5 Commits

Author SHA1 Message Date
d70ee8b63c Fix N7/N8: human session fingerprint epoch; drop duplicate view_ttl
resolve() now requires sess_fp == live_fp for every session that carries
a fingerprint (including human_via_agent), so a redeem-vs-rekey race
cannot leave a view:read bearer alive. Drop the duplicate view_ttl key
in issue_code's return dict. Regression tests cover both.
2026-10-06 06:28:01 +08:00
b4d9cbe5f8 Fix N3: dedicated rekey rate-limit bucket; charge only on failure
enrol_rekey shared the enrol: bucket and metered before auth, so junk
calls could lock out incident-response rekey. Use a separate rekey:
bucket and charge it only after a bad bootstrap secret, so a valid seed
always proceeds.
2026-10-06 06:28:01 +08:00
558d313783 Fix N1: resolve re-checks agent; codes bind key fingerprint
In-flight verify/issue_code could insert a session or code after revoke
or rekey. sessions.resolve now refuses if the agent is revoked, has no
live key, or (agent sessions) the fingerprint no longer matches.
View codes store the issuing fingerprint and redeem refuses after
rekey/wipe; issue_code re-checks agent state. DESIGN matches the choke
point. Regression tests plant race-surviving sessions and stale codes.
2026-10-06 06:28:01 +08:00
16ed04caea Fix R6/R7/R8: claim_code expiry CAS, rate-limit rekey, delete spent bootstrap
claim_code now requires redeem_expires_at > now in the CAS UPDATE.
enrol_rekey shares the enrol: rate-limit bucket. spend_bootstrap and
sibling clear delete rows instead of retaining spent hashes, matching
the schema comment.
2026-10-06 06:28:01 +08:00
910ddfde42 Harden Sigil: tests/test_hardening.py 2026-10-06 06:28:01 +08:00