Skip to content

fix(hosts): audit only liveness transitions, not every heartbeat - #107

Merged
wstein merged 5 commits into
fix/88-pubsub-close-orderfrom
fix/101-liveness-audits
Oct 16, 2026
Merged

wstein merged 5 commits into
fix/88-pubsub-close-orderfrom
fix/101-liveness-audits

Conversation

@wstein

@wstein wstein commented Oct 16, 2026

Copy link
Copy Markdown
Owner

Implements #101 (owner decision H57:a): audit only liveness transitions, not every heartbeat.

  • Audited, each exactly once per transition: host_connected (authenticated socket open), host_connection_replaced (inside the replacement transaction), host_connection_unknown (stale, disconnect, identity invalid, other close), host_heartbeat_refused (rate-limit close), host_connection_reset (restart).
  • Accepted heartbeats update hosts.last_seen/lease and set the slot to connected, with no audit row.
  • Replacement is detected from the slot row inside the transaction; a clean close clears connection_id.
  • host-enrollment.md lists the audited events. The first authenticated heartbeat audit follows in fix(hosts): audit the first authenticated heartbeat of a connection #105.

Every new test fails without the code it protects. Review: CLEAR (Opus 5.5) on b0d363a after three rounds; carried to this rebased head by identical range-diff. Final make check after the stack merges (H61). Stacked on #103 (#88).

🤖 Generated with Claude Code

@wstein
wstein force-pushed the fix/101-liveness-audits branch from 037889c to a018980 Compare October 16, 2026 11:33
@wstein

wstein commented Oct 16, 2026

Copy link
Copy Markdown
Owner Author

Restacked onto main e82167b after #96/#91 merged; range-diff identical, review carries to a018980.

@wstein
wstein added this pull request to stack #108 October 16, 2026 12:04
wstein and others added 5 commits October 16, 2026 14:04
Every accepted heartbeat wrote an undeletable audit row (about 8,640 per host per day).
Heartbeats now only renew the connection row. Replacement is audited once as
host_connection_replaced inside the replacement transaction, since the old close no
longer matches the slot; a rate-limit close is audited as host_heartbeat_refused.

Refs: #101
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The contract said 'slot/unknown audit as for any close' and 'audit every heartbeat
mutation', which is ambiguous after the replacement and heartbeat changes. List the
audited liveness events and update the acceptance IDs to the real test names.

Refs: #101
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…rites

replacing? came from in-memory state, so a failed close write dropped the entry but left
the slot's connection_id, and the next open overwrote it without the replaced audit.
Read the slot inside the transaction and clear connection_id on a clean close. The
steady-heartbeat test now asserts hosts last_seen/lease and slot state move.

Refs: #101
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
host_connected is written at authenticated socket open, not hello, and heartbeats update
hosts last_seen/lease plus slot state rather than a connection row.

Refs: #101
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Clean close clears connection_id so a later open is not audited as a replacement and a
restart writes no reset; no test failed without it. The steady-heartbeat test also never
asserted the slot returns to connected.

Refs: #101
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@wstein
wstein force-pushed the fix/101-liveness-audits branch from a018980 to 3322b21 Compare October 16, 2026 12:04
@wstein
wstein merged commit 1cb22c2 into main Oct 16, 2026
1 of 2 checks passed
@wstein
wstein deleted the fix/101-liveness-audits branch October 16, 2026 12:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant