Separate, clearly-labeled commit for observation set (vi) from the #910 review.
The HMAC-verify half is a non-trivial blast radius (emit must sign, record must
verify-and-bind), so it is isolated here rather than expanding the installer diff.
Both changes are additive and backward-compatible (the legacy unsigned path and
emit_ts fallback are preserved when no key is configured).
(vi-a) Monitor-side ingested_ts: `record` stamps the monitor's own receive-time,
and `check` computes staleness from ingested_ts (falling back to emit_ts
only for a legacy record). A host shipping a far-future emit_ts to defer
its own staleness can no longer fool the off-host dead-man clock.
(vi-b) Beacon HMAC-verify at record: when a key name is configured
(WAKE_BEACON_HMAC_KEY_NAME / WAKE_HMAC_KEY_NAME), `emit` signs the beacon
core via the existing sign.sh sign-digest path and `record` verifies via
sign.sh verify AND binds the envelope to this beacon (content_hash ==
sha256(core), seq/emit_ts match). A spoofed or unsigned beacon is REJECTED
fail-loud and never advances the received clock. Key is by-name only —
beacon.sh inlines no key material.
test-wake-beacon.sh extended with B11 (ingested_ts staleness) and B12 (HMAC-verify
+ spoof/unsigned rejection); test-wake-install.sh gains I7/I8 for the same
invariants. Both harnesses shown red-first under targeted mutation, then green.
Part of #892
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0158NZqN2n2ymKFeJAZ4GUCb
Framework install machinery for the wake component (EPIC #892 W7, the last
build slice). ADDITIVE per #869: adds an `install.sh --component wake` early
dispatch that never enters the full-framework sync, never alters
framework-manifest ownership behavior, and touches nothing the #869
install-ordering-guard covers (no runtime-asset linking, no lease-enforcement
hook wiring).
(i) Idempotent component-manifest install + Gate A (wake-install.sh install):
the wake manifest.txt is VERSION METADATA ONLY; the component file set is
INTERSECTED-AND-VALIDATED against the single SSOT framework-manifest.txt.
A candidate the SSOT does not own is REFUSED fail-closed with no partial
write. Re-running writes zero files (no diff).
(ii) systemd/user/mosaic-wake.service — the long-lived detector daemon
(detector.sh run). Per-class SLO lives inside the daemon, not a systemd
interval; it is a SERVICE not a timer, so blank-reset does not apply.
(iii) blank-reset idiom on the legacy mosaic-heartbeat@<agent>.timer cadence
drop-in during the §5 overlap->retire lifecycle (empty OnUnitActiveSec=
reset before the new value => exactly one OnUnitActiveUSec), with a
reset->verify->retire acceptance path (retire LAST, only on §4-vector pass).
(iv) snapshot-guard — a reap/clean-checkout of a deployed unit is REFUSED
without a prior snapshot (the deployed-from-uncommitted failure class).
(v) fail-closed alarm-target + HMAC-key install-validation (G1/G2a): the
operator W6 alarm sink must be configured + reachable and the W3/W7 HMAC
key must resolve BY NAME; missing/unreachable => FAIL LOUD. The installer
ships/writes NO endpoint value and NO secret, and echoes neither.
Red-first harness test-wake-install.sh (6 groups) wired into test:framework-shell;
Gate-A parity extended to prove bash+TS both resolve the wake component paths
framework-owned. wake component manifest bumped 0.5.0 -> 0.6.0.
Part of #892
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0158NZqN2n2ymKFeJAZ4GUCb
Part of #869
Mos (id-11) Gate-16 merge: independent APPROVE @b6f36564 (8/8, verified vs real production settings template), author id2 != approver id11, clean mosaic-coder author, CI green wp1988.
Co-authored-by: jason.woltje <jason@diversecanvas.com>
Co-committed-by: jason.woltje <jason@diversecanvas.com>
Part of #869
Mos (id-11) Gate-16 merge: independent APPROVE @75235ef8 (9/9, no live host mutation), author id2 != approver id11, CI green wp1971.
Co-authored-by: jason.woltje <jason@diversecanvas.com>
Co-committed-by: jason.woltje <jason@diversecanvas.com>
Part of #869
Mos (id-11) Gate-16 merge: independent 3-round APPROVE @c5a2bcc5, author id2 != approver id11, CI green wp1973.
Co-authored-by: jason.woltje <jason@diversecanvas.com>
Co-committed-by: jason.woltje <jason@diversecanvas.com>
GLPI helpdesk workflow skills written against the portable
tools/glpi/ tooling (session-init.sh, ticket-list.sh, ticket-create.sh),
cross-linked via [[glpi-*]]:
- glpi-solve — close a ticket by setting status Solved (5); GLPI auto-closes
- glpi-followup — add a followup via the top-level /ITILFollowup endpoint
- glpi-sweep — read-only hunt for done-but-open tickets needing Solve
- glpi-list — query tickets by status/recency
- glpi-create — open a new ticket
Core rule encoded: completing work means setting status Solved, not just
posting a resolution followup (a followup documents; only Solved auto-closes).
Note: illustrative examples in the bodies are USC-flavored (M2M / helpdesk
ticket numbers) and can be genericized in review if preferred.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019GjBgrb9tHgvq414Fqj37c