fix(admin): per-request allowlist enforcement on the cookie path (revocation takes effect next request)#49
Merged
Conversation
…evocation) The NIP-98 API path already re-checked allowlist membership on every request, but the browser COOKIE-session path (whoami) checked membership only at login/elevation — so removing an identity from the committed allowlist would not revoke a live browser session until it expired (up to the 8h absolute bound). The governance model requires revocation (commit + deploy) to take effect on the identity's NEXT request. Add resolveAllowlistedAdmin(): the single per-request enforcement choke point for cookie-authenticated admin routes. It resolves the session (idle/absolute bounds, as before) AND re-checks the identity against the current allowlist, DESTROYING the session if the identity has been de-listed. whoami's browser path now routes through it; future privileged cookie routes (Phases 5/6) must too — never resolveAdminSessionId alone. No stored membership/role snapshot to go stale: ADMIN_SESSIONS holds identity only, so the check is always live. Logout stays de-escalation-only (a revoked admin may still clear its cookie). Tests: mid-session revocation for both methods — a live session whose identity is removed from the allowlist gets 401 on its next request AND is destroyed (the original allowlist can't resurrect it). Closes the gap that had no coverage before. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LVPyHAtQ1cdK76RpFasafP
Deploying with
|
| Status | Name | Latest Commit | Updated (UTC) |
|---|---|---|---|
| ✅ Deployment successful! View logs |
wecanjustbuildthings | 1e7882d | Jul 04 2026, 07:18 AM |
MartinMontero
marked this pull request as ready for review
July 4, 2026 07:55
This was referenced Jul 4, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What does this PR do?
Closes the one gap in per-request allowlist enforcement, so revocation (remove an identity → commit → deploy) takes effect on that identity's next request, per the governance model. This is the precondition hardening that lands BEFORE any real identities are committed.
Task B verdict (the read-only enforcement audit that prompted this)
whoamiPath 2)isAllowedNostrPubkeyon every request (was already correct)whoamiPath 1)ADMIN_SESSIONScontentssubject,method,createdAt,lastSeen) — no membership/role snapshot to go stale, so a live re-check is the correct fixVerdict: per-request enforcement ABSENT on the cookie path → smallest hardening + tests, this PR, merges before identities.
The fix
resolveAllowlistedAdmin()— the single per-request enforcement choke point for cookie-authenticated admin routes. It resolves the session (idle/absolute bounds, unchanged) and re-checks the identity against the current allowlist, destroying the session if the identity was de-listed.whoami's browser path routes through it; future privileged cookie routes (Phases 5/6) must too — neverresolveAdminSessionIdalone. Logout stays de-escalation-only (a revoked admin may still clear its own cookie).Because a session stores no membership snapshot, revocation is a live lookup — no cache to invalidate. No behavior change for a still-allowlisted admin.
Tests
Two new mid-session revocation cases (Nostr + Bluesky): a live, in-bounds session whose identity is removed from the allowlist gets 401 on its next request and is destroyed (re-supplying the original allowlist can't resurrect it).
verify:allgreen;enforcegreen; 289 tests, 0 fail.Type of change
Required checks
npm run check· [x]npm run enforce· [x]npm test(289) · [x]npm run buildDeploy semantics
Merging IS a production deploy. It changes only the cookie-path enforcement (the allowlist is still committed-empty, so the live surface remains fails-closed-for-everyone). No new bindings, no schema change, no new deps.
Draft on purpose — do not mark ready-for-review, do not merge; merge is yours alone. This is the enforcement precondition; the identities PR (with the genesis role schema) is separate and fires only on your explicit
identities: go.🤖 Generated with Claude Code
https://claude.ai/code/session_01LVPyHAtQ1cdK76RpFasafP
Generated by Claude Code