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