Appearance
Review β Auth expansion Phase 1 (feature/auth-expansion-phase1) β
Date: 2026-07-15 Β· Scope: master (9dfa444)..HEAD β 25 commits Spec: docs/superpowers/specs/2026-07-14-auth-expansion-design.md Β· Plan: docs/superpowers/plans/2026-07-14-auth-expansion-phase1.md Β· Tracker: docs/tracking/auth-expansion-phase1.mdProcess: subagent-driven execution β fresh implementer per task, per-task spec+quality review, adversarial final whole-branch review, fix rounds re-reviewed.
Deterministic gate β
| Check | Result |
|---|---|
nx lint/test/build web | β green |
nx test web --configuration=coverage | β 83.95% lines (baseline 83.83%) |
nx lint/test/build api (live-DB router tests incl. new fail-closed cases) | β green |
nx e2e web-e2e (live stack: signupβmailβverifyβpending, member sign-in, full reset) | β 5/5 |
nx lint web-e2e | β green |
| Live RLS probe (psql, JWT claims) | β Pending = 0 rows on member tables; member = full read |
Findings and resolutions β
π΄ Blocking β all fixed before this record β
- Pending users could reach member data via the Go API's non-CRUD routes (
router.goβ pulse/okrs/skills/votes/notifications mounted with onlyRequireAuth; services query as table owner, bypassing RLS). A self-served Pending JWT could readGET /pulse/:id/results(aggregate member sentiment), write pulse responses/OKRs/skills. β Fixed (db107fe): member-roleRequireRolegroup on those five mounts;/meandadminsunchanged by design. Fail-closed tests: Pendingβ403, no-claimβ401, memberβ200 on/pulse/activeand/okrs. - (found mid-branch, Task 14) The new
is_member()restrictive RLS silently emptied all CRUD reads through the API β the engine's RLS context carried onlysub, notmembership_role. β Fixed (8f512f1): verified JWT claim threaded into the samerequest.jwt.claimsGUC, defaultPending(fail closed), regression tests for explicit-Pending and empty-claim callers (proven load-bearing by reverting the fix).
π‘ Should-fix β all fixed before this record β
memberGuardfailed open on a null role (profile fetch failure β full member access). β fail-closed: null role parks on/pending(35f3225).- Spec Β§4.3 drift: signed-in users weren't redirected off
/login,/signup,/reset-password. βauthPagesGuardadded (not on/reset-password/updateβ recovery links must reach the form). Redirect-graph traced across all roleΓMFA states: no cycles, β€2 hops. - MFA was advisory (URL-bar bypass during the challenge). β client-side AAL enforcement in
authGuard/memberGuardviaAuthService.mfaSatisfied();/login?mfa=1shows the challenge panel directly. Server-side AAL is NOT enforced (API/RLS ignoreaal) β recorded as an explicit Phase 2 gap in the tracker. docs/auth-setup.mdstill documented the Workspace domain gate. β rewritten (External consent screen, nohd, Pending profiles, GitHub OAuth app setup, email confirmations).- Task-7/8/12 per-task review rounds: login a11y labels + submit re-entrancy; signup resend silent-failure; MFA QR returned unusable raw SVG (now a proper
data:image/svg+xmlURI) and silent factor-removal failures. All fixed and re-reviewed in their rounds.
π’ Follow-ups (accepted, not blocking) β
/settings/securityhas no nav entry (scaffold; reachable by URL).- Signup with an already-confirmed email shows "check your email" and nothing arrives (GoTrue anti-enumeration; consider hedged copy).
handle_new_useraccepts an empty-string metadata name (cosmetic;nullif(trim(β¦),'')later).pendingGuarddoesn't itself check AAL (no member data on/pending; API fail-closes independently).- MFA panel has no back-to-password escape; a few AuthService helpers lack direct unit tests (e2e-covered).
Verdict β
Green β ready to push/PR after user sign-off. Every blocking and should-fix finding is fixed, re-reviewed, and covered by tests; the deterministic gate is fully green; remaining items are recorded follow-ups. Reminder of the deliberate scope seams: org create/join/invites, per-org LoginPolicy/SAML, and server-side AAL enforcement are Phase 2 (see spec Β§5 and the tracker's Known gaps). Ops prerequisites before the first deploy of this branch: Google consent screen β External, GitHub OAuth apps (+ hosted provider config), SMTP on hosted Supabase (tracker ops checklist).