Repository navigation
fix(auth): hydrate primary authorization snapshots per request - #7462
Conversation
There was a problem hiding this comment.
Ladon verdict: Approve
Approve — per-request authorization-snapshot auth refactor.
Scope: server/** only, no protocol surface (static/schemas/source/, docs/reference/, dist/**) touched — correctly no changeset required. No high-risk paths, no gated paths, no author team gate.
Reviewed: single-row MVCC authorization snapshot with fail-closed behavior, replay/cross-org rejection, non-enumerable provenance, and exact-credential bans, all backed by unit + integration tests. Core logic is well-tested with no Critical/High findings.
Medium findings (2, non-blocking):
- resolve-user-org-authorization / snapshot query bypasses the client.ts query() transient-retry wrapper and lacks a statement timeout on the now-universal auth path.
- optionalAuth now hard-fails 503/401 for credential-bearing requests instead of degrading to anonymous.
Decision: No critical/high findings (rows 1 skipped). gated_paths is false (row 2 n/a). high_risk false (rows 3/5 n/a). No medium finding in data-loss/schema/infra category (row 4 n/a). No prior escalation (row 6 n/a). No no-auto-approve team (row 7 n/a). Only 2 medium findings — fewer than 3 (row 8 n/a). Falls through to row 9 → approve.
Worth a follow-up look at the retry-wrapper bypass and optionalAuth degradation behavior, but neither blocks per the decision table.
There was a problem hiding this comment.
Ladon verdict: Approve
Approve — subsequent pass on PR #7462 (per-request auth snapshot hydration), no blocking or medium findings.
This delta hardens transient-vs-invalid credential handling (503 vs 401), adds a bounded snapshot query wrapper (2s budget, one transient-connection retry, fail-closed on late/replica/error results), tightens provider/selector org agreement to 403-on-mismatch, and makes optionalAuth fail-closed on presented-but-invalid credentials. All changes are server-only — no protocol/schema/dist surface touched, so no changeset is required. Operational readiness (statement/lock timeouts, bounded retry, 503 observability) and the optionalAuth control flow were verified.
Decision-table trace: no critical/high findings (row 1 n/a); gated_paths false (row 2 n/a); high_risk false, no deletions/modifications triggers (rows 3–5 n/a); prior decision was approve, so sticky escalation does not apply (row 6 n/a); no no-auto-approve team match (row 7 n/a); zero medium findings (row 8 n/a). Falls through to row 9 — approve. The prior clean approve holds.
There was a problem hiding this comment.
Ladon verdict: Approve
Approve — clean pass, no blocking or medium findings.
The delta since the prior approve (head bb7be31 → 853b8a3) is confined to:
- A single CodeQL suppression comment in
optionalAuth(server/src/middleware/auth.ts:1860) that accurately documents the fail-closed credential-absence branch. No executable auth logic changed. - Nine new Express/Supertest HTTP-boundary tests asserting that present-but-invalid credentials never reach the handler (401), unavailable snapshots return 503, and anonymous access is permitted only when both credentials are absent.
No protocol-surface (static/schemas/source/**), docs, dist/**, or changeset files touched — so schema↔docs coherence, changeset scope, oneOf discriminator, and artifact-immutability gates do not apply. No 3.1.x patch-eligibility or breaking-class concerns (base is main). high_risk is false; gated_paths is false; no no-auto-approve team match.
Decision table: rows 1–8 do not fire (no critical/high/medium findings, no gated path, no high-risk deletion/modification, no sticky escalation, no team gate, fewer than three medium findings). Falls through to row 9 → approve.
There was a problem hiding this comment.
Ladon verdict: Approve
Approve — clean delta pass, no blocking or medium findings.
The reviewer reports a behavior-preserving rewrite of the optionalAuth credential-absence guard into a single ternary early-return (identical 401-vs-next() outcomes) plus a test-harness swap that injects req.cookies from a fixture matching the network-health pattern without weakening presence assertions. No schema, changeset, dist, or migration surface is touched, and no prior blockers remain.
Gate checks: no no-auto-approve team match; gated_paths false; high_risk false. No critical/high/medium findings, so rows 1–8 do not fire — falls through to row 9 (approve). Prior decision was also approve with no findings; this remains a clean state.
423f6d8 to
b1789a6
Compare
b1789a6 to
9b9010f
Compare
7b9876d to
438f952
Compare
438f952 to
3216b0d
Compare
There was a problem hiding this comment.
Ladon verdict: Approve
Approve — clean pass on the fail-closed WorkOS auth rewrite (per-request primary-DB authorization snapshot replacing epoch fingerprint caching).
No critical, high, or medium findings. Verification confirmed:
- The snapshot SELECT joins are all single-row (unique active-grant index in migration 553; PK + one-primary index in migration 460).
- db/client.ts deadline/uncertain-client accounting releases or destroys clients correctly.
- Platform-only change (server/**); no protocol/schema/docs/changeset surface, so no versioning, oneOf, or governance findings apply.
Gate check: gated_paths=false, high_risk=false, no no-auto-approve team match, no blocking findings. Prior decision was also approve with no findings. None of decision rows 1–8 fire, so this falls through to row 9 → approve.
3216b0d to
0c14d9f
Compare
There was a problem hiding this comment.
Ladon verdict: Approve
Approve — clean pass, no blocking findings.
Reviewed the server-only per-request primary-DB authorization snapshot refactor across db/client.ts, user-authorization-snapshot-db.ts, middleware/auth.ts, and resolve-user-org-authorization.ts. Deadline-bounded pool checkout destroys uncertain clients without leaking slots; snapshot hydration fails closed (401 invalid / 503 unavailable / 403 conflicting-org); caches retain only provider auth; server-only authority is non-enumerable. No protocol/schema/changeset/migration surface touched, so no spec-drift, changeset-scope, oneOf, or immutability concerns apply.
Gate checks:
- No no-auto-approve team match.
gated_pathsis false — row 2 does not fire even thoughreview_decisionis REVIEW_REQUIRED.high_riskis false — no deletion/modification escalation rows apply.- Prior decision was
approve, so no sticky escalation. - Zero findings of any severity → rows 1, 4, 5, 8 do not fire.
None of rows 1–8 fire; the outcome is approve per row 9.
…on (#7675) * fix(auth): let web chat rebind the session to the selected organization Since #7462 a cookie session is bound to the WorkOS org chosen at sign-in, and a differing explicit org selector is rejected. Add POST /auth/switch-organization, which refreshes the sealed session with the target organizationId (WorkOS verifies membership). Web chat calls it once on that 403 and resends. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(auth): update integration auth mocks --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: Brian O'Kelley <bokelley@scope3.com>
…7825) Since #7462, optionalAuth returns 401 for a present-but-unusable wos-session cookie instead of treating the caller as anonymous. The Agents page swallowed that error and rendered an empty registry. Retry the public list once with credentials omitted on 401, and show an error instead of an empty grid for any other failure. Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
An identity binding could commit between cold-cache identity and epoch reads, stamping old attribution with a new epoch. Cookie and bearer caches now retain provider authentication only; every request hydrates a fresh immutable, server-only authorization snapshot from primary PostgreSQL.
The atomic statement reads the exact authenticated credential, canonical identity routing, explicit organization selection, active exact-credential grant, and persisted epoch. It also preserves the durable deletion/quarantine tombstones and exact-one-primary lifecycle checks now on main. Missing, deleted, quarantined, or invalidly routed credentials terminate with 401; unavailable primary state returns 503. No linked credential, membership cache, or implicit organization can substitute for the authenticated credential.
Organization selectors must agree with the provider/session organization. The gated organization resolver rejects stale/replayed snapshots, reads WorkOS membership for the exact credential and selected organization, then rechecks the full database snapshot. WorkOS remains an external authority read bracketed by DB checks. The authentication selectors are
x-organization-id, queryorg/organization_id, bodyorganization_id/organizationId, and pathorgId/organizationId; legacycompanyIdand mutation-specific fields remain outside this slice.One absolute two-second snapshot budget covers pool checkout and its single retry, BEGIN, transaction-local timeout configuration, the statement, COMMIT, and ROLLBACK cleanup. Late checkout results are released without queries; late settlements are consumed. Ambiguous operations, lost commit acknowledgement, and unconfirmed rollback destroy the uncertain client exactly once rather than returning unknown state to the pool. Retries never renew the deadline.
optionalAuthpermits anonymous access only without a credential. Presented invalid/expired credentials return 401, and unavailable snapshot/JWKS/provider/shared-session recovery returns 503; neither becomes anonymous access. Main's exact-credential platform-admin lookup, no-cache authority checks, typed outages, independent break-glass authority, and reservedaao-admingroup guard are preserved.Exact replay and deliberate composition
54fd5f3c0a3cd5ac295d2f295bb7dc7232803ab9; base tree:74e47c4e36fa58fc5d87a0d120d91491523c2d8a. Merged fix(addie): authorize admin tools by authenticated credential #7450 (f928b36ff), fix(auth): authorize web admins by authenticated credential #7452 (c9a8c4f91), and fix(auth): contain destructive identity consolidation #7459 are verified ancestors.0c14d9fd9b49a90faec3f17899aa2e44f686d2a3; final reviewed tree:8bdd72b68c7e0e8d01240d57b0c7542137db5edb.3216b0d61dca45211f4a500a6508e3bdcd0b3113, based ondc69e0b2264b4c563f2175a48c515b7108dbb4f6.!entries followed by four=entries. The first is deliberate main composition; the second differs only in surrounding main test context, with byte-identical ordered additions/deletions across all eight paths. The last four full stable patch IDs are unchanged. The second full stable patch ID changes because its surrounding context changes.a1d7537832d163ea95f8d53b89520334fc514f01, tree6ed8985f78020532a57a2003fcc3fe19a38f2198. The first resolution retains main's admin logic and replaces overlapping legacy lifecycle hydration with the new snapshot mechanism.fix(auth): preserve credential lifecycle in primary snapshots, deliberately composes fix(auth): contain destructive identity consolidation #7459's durable deletion/quarantine markers and exact-one-primary check into the new atomic statement. Tests cover tombstones before/after commit, recreated user rows, independent replicas, cross-middleware cache rejection, exact-credential admin attribution, and lifecycle denial. The predecessor cross-replica test still demands immediate 401; its provider-call expectation changes from three to two because provider authentication remains cached..context/landing-7462/.be6336113c9b2db393b6c3a0550bc72f727c9955is unchanged: all 576 migrations, zero duplicate numbers, and unchanged allocation records. No new migration is allocated.Qualification
npm ciin Docker (Node 24.21.0, npm 11.19.0), with an isolated PostgreSQL 16 container and no production access.git diff --check: passed.::1absent. The same main source/image/dependencies passed all three focused tests with IPv6 enabled. The user accepted this deterministic baseline container-configuration failure as invalid qualification and authorized exactly one replacement normal full hook in an equivalent Node 24.21.0 container with IPv6 enabled. Original failed log and controlled baseline evidence are preserved.54fd5f3c0a3cd5ac295d2f295bb7dc7232803ab9, head0c14d9fd9b49a90faec3f17899aa2e44f686d2a3, and reviewed tree8bdd72b68c7e0e8d01240d57b0c7542137db5edb; source/blob/diff/correction hashes and successful full-hook log digest reverified. Zero Must Fix / Should Fix findings required for publication.aao-secretariatapproval, CLEAN mergeability, unchanged main, and GitHub merge-tree equality remain mandatory before guarded squash merge.Ordered dependency scope
#7461 remains the mandatory next child for the pre-existing required-auth API-key/JWT/cookie fallback and WorkOS API-key outage-classification issues. Those behaviors are not claimed fixed by #7462. No #7461, #7463, or later PR is mutated here. This contributes to #6827's snapshot/epoch requirements without closing the broader issue or claiming standalone closure of every Bearer boundary.
The user has authorized merging this ordered dependency after its current-head gates pass, and explicitly accepts exact-head APPROVED from
aao-secretariat. Old approvals and old CI are historical. Never use admin bypass, auto-merge, deployment, production access, or explicit head-branch deletion.