feat: per-host credential revocation and optional max-age #19

Closed
opened 2026-07-03 13:16:32 +00:00 by a73x · 1 comment
a73x commented 2026-07-03 13:16:32 +00:00 (Migrated from git.a73x.sh)

[claude 2026-07-03] Fixes 9f98faa4 (P1). Credential v2 host_id.generation.issued_unix.hmac; hosts.cred_generation with guarded ALTER migration; generation checked at Hello AND per report tick (revoke kills a live session within ~10s); POST /api/v1/hosts/{id}/revoke-credential (admin, audited, 404 unknown); optional credential_max_age config (off by default — no auto-renewal channel; revocation primary). Runbook docs/credential-revocation.md covers single-cred leak, host_secret leak, upgrade note (breaking: v1 two-part creds rejected, one-time re-enroll). TDD: hosttoken v2 round-trip/tamper/legacy tests; store gen lifecycle; syncsvc stale-gen + max-age rejection (mutation-checked after a tooling mishap masked the behavioral RED); api endpoint + v2-mint tests; hosttoken at 100% coverage. make ci green.


Migrated from git-collab patche 1dfd975568faaf93a6e7e41f68164766ed591e7b.

Original author: a73x dev@a73x.sh.

Fixes git-collab issue 9f98faa4

Historical merged patch. The original head and merge commits were not recorded. Forgejo cannot display a pull request without a head commit, so this record is preserved as a closed issue. The original diff is unavailable; no commit was guessed.

Original branches: fix/credential-revocation → main.

[claude 2026-07-03] Fixes 9f98faa4 (P1). Credential v2 host_id.generation.issued_unix.hmac; hosts.cred_generation with guarded ALTER migration; generation checked at Hello AND per report tick (revoke kills a live session within ~10s); POST /api/v1/hosts/{id}/revoke-credential (admin, audited, 404 unknown); optional credential_max_age config (off by default — no auto-renewal channel; revocation primary). Runbook docs/credential-revocation.md covers single-cred leak, host_secret leak, upgrade note (breaking: v1 two-part creds rejected, one-time re-enroll). TDD: hosttoken v2 round-trip/tamper/legacy tests; store gen lifecycle; syncsvc stale-gen + max-age rejection (mutation-checked after a tooling mishap masked the behavioral RED); api endpoint + v2-mint tests; hosttoken at 100% coverage. make ci green. --- Migrated from git-collab patche `1dfd975568faaf93a6e7e41f68164766ed591e7b`. Original author: a73x <dev@a73x.sh>. Fixes git-collab issue `9f98faa4` **Historical merged patch.** The original head and merge commits were not recorded. Forgejo cannot display a pull request without a head commit, so this record is preserved as a closed issue. The original diff is unavailable; no commit was guessed. Original branches: `fix/credential-revocation` → `main`.
a73x commented 2026-07-03 13:24:37 +00:00 (Migrated from git.a73x.sh)

Original review: comment (revision not recorded)

[claude 2026-07-03] Fresh-context reviewer: not-mergeable-as-is on one Critical + two Important; all fixed in amended d84c933. CRITICAL: the squash (git reset --soft against a moved main) had silently reverted the freshly-merged web error-banner work — restored byte-identical to main (git diff main -- web/ is empty). IMPORTANT-2: per-report GetHost failure no longer conflates transient store errors with revocation (closes code 0 -> normal 5s agent backoff; CodeAuthRejected reserved for real mismatch/expiry). IMPORTANT-3: migration test added (old-schema DB without cred_generation -> Open migrates, rows read gen 1, bump works). Minors applied: max-age now enforced mid-session too (new TestMaxAgeEnforcedMidSession, truncation-aware timing — Mint stores second-granular issued_unix; verified stable -count=5 -race); revoke audit moved INSIDE the bump tx; hosttoken synopsis self-contained + shape regenerated. Reviewer verified the crypto (raw-string HMAC avoids canonicalization gap; RandHex IDs cannot contain dots; constant-time compare) and per-report DB load acceptability. make ci green. Merging per session goal.

**Original review: comment** (revision not recorded) [claude 2026-07-03] Fresh-context reviewer: not-mergeable-as-is on one Critical + two Important; all fixed in amended d84c933. CRITICAL: the squash (git reset --soft against a moved main) had silently reverted the freshly-merged web error-banner work — restored byte-identical to main (git diff main -- web/ is empty). IMPORTANT-2: per-report GetHost failure no longer conflates transient store errors with revocation (closes code 0 -> normal 5s agent backoff; CodeAuthRejected reserved for real mismatch/expiry). IMPORTANT-3: migration test added (old-schema DB without cred_generation -> Open migrates, rows read gen 1, bump works). Minors applied: max-age now enforced mid-session too (new TestMaxAgeEnforcedMidSession, truncation-aware timing — Mint stores second-granular issued_unix; verified stable -count=5 -race); revoke audit moved INSIDE the bump tx; hosttoken synopsis self-contained + shape regenerated. Reviewer verified the crypto (raw-string HMAC avoids canonicalization gap; RandHex IDs cannot contain dots; constant-time compare) and per-report DB load acceptability. make ci green. Merging per session goal.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
a73x/eitri#19
No description provided.