SCRUM-210 — admin-auth unit and integration tests¶
Plan ref: AA-11 (docs/11-admin-plane-plan.md). Stacked on SCRUM-208.
What exists¶
services/admin_auth/TESTING.md maps every AA-1..AA-10 acceptance criterion and the
D2/D3/D5 rules to the tests that cover them. Gaps filled by this ticket:
| Area | Test |
|---|---|
| D3 role-grant matrix | one table-driven HTTP test: actor ∈ {root, admin, live_ops, viewer} × 8 actions (invite viewer/live_ops/admin, grant admin, change own roles, disable root, disable self, disable another admin) |
| Password hashing | salt uniqueness; Dummy() verify time comparable to a real verify (interleaved samples, ratio bound) |
| Login indistinguishability | unknown email vs wrong password: same status and body (minus request id); median of 20 timings, |Δ| < 25 ms (skipped under -short) |
| Lockout | success resets the failure count |
| Refresh rotation under concurrency | 10 simultaneous refreshes with one token → exactly one rotation (one new session, one new cookie), the rest served by the 30 s grace path with no new cookie; with grace disabled → exactly one 200, the rest 401 |
No production code changed; no bug found.
How to verify¶
cd services/admin_auth
ADMIN_AUTH_TEST_DATABASE_URL=postgres://auth_rw:pw@127.0.0.1:5433/admin_auth_test?sslmode=disable \
go test -race -count=2 ./...
Results at time of writing¶
go test -race -count=2with the DB: pass; the timing and concurrency tests also passed 3 more times in a row under-race.- Coverage measured across packages (
-coverpkg=./..., the HTTP tests exerciseapiandstorefrominternal/server): 70.7 % of statements overall.
How it was built¶
DeepSeek run scoped (Landlock) to services/admin_auth (408 s, ~36k output tokens,
reasoning effort low). Claude review: re-ran the timing-sensitive tests repeatedly
and measured merged coverage; no changes needed.