Skip to content

auth(setup): first-run setup, sessions, and password recovery - #5

Merged
TusanHomichi merged 1 commit into
mainfrom
claude/repo-setup-complete-y2qmmk
Aug 28, 2026
Merged

auth(setup): first-run setup, sessions, and password recovery#5
TusanHomichi merged 1 commit into
mainfrom
claude/repo-setup-complete-y2qmmk

Conversation

@TusanHomichi

@TusanHomichiTusanHomichi commented Aug 28, 2026

Copy link
Copy Markdown
Member

Primary Issue

Closes#4

Problem And Outcome

The operable shell had no way to initialize an installation or authenticate anyone. After merge, an empty installation completes the full Milestone 1 authentication lifecycle with no external services: setup code → first administrator → cookie session → administrator-issued reset → offline sole-administrator recovery.

Changes

  • Migration 0002: agency, user, capability_grant, session, setup_code, password_reset_code, audit_event (append-only, enforced by database triggers)
  • Capability-based authorization from the start: manage_users gates reset-code issuance; the Administrator role is a grant bundle applied at creation (manage_users, manage_programs, assign_training, export_records), never a name compared at decision time
  • First-run setup: hashed 15-minute setup code emitted by serve on start and by consolebook setup-code; POST /api/setup creates agency + administrator + grants and consumes the code in one transaction; 409 after initialization
  • Sessions: 256-bit opaque tokens stored as SHA-256 digests, HttpOnlySameSite=Strict cookies, 12-hour absolute expiry, immediate revocation on logout and reset; login timing equalized against a dummy hash and identical failure bodies so responses don't reveal account existence
  • Passwords: Argon2id PHC strings; 12–512 byte policy shared by setup and reset
  • Reset: POST /api/auth/reset-codes (capability-checked) → POST /api/auth/reset rotates the password, marks the code used, revokes all sessions, and audits — one transaction
  • Recovery: consolebook recover --username ... requires OS access to the data directory, refuses non-administrator targets, records a distinct audit event
  • doctor now reports initialization state and administrator count
  • ADR 0004 records the decisions and deliberate gaps (no rate limiting yet; Secure cookie flag deferred to deployment hardening — both flagged for pre-pilot work)

Scope

Verification

  • Listed the exact verification commands run below
  • Added or updated tests when behavior changed — 15 new integration tests (setup validity/expiry/single-use, login enumeration resistance, session expiry/revocation, reset lifecycle, capability gating, recovery refusals, audit append-only)
  • Added or updated an ADR when a durable decision changed — ADR 0004
  • All fixtures and examples are invented; no real agency data (Example County Communications, avery.admin, taylor.trainee)
- cargo fmt --check
- cargo clippy --workspace --all-targets -- -D warnings
- cargo test --workspace (25 passed: 15 auth + 10 shell)
- end-to-end against the real binary: setup-code → POST /api/setup →
login → session → recover → reset (204) → old session 401 →
new password 200 → setup-code refused after init

Review And Merge Notes

  • Review focus: the setup and reset transactions in setup.rs / users.rs (atomicity claims), and ADR 0004's deliberate gaps
  • User or operator impact: an installation is now actually initializable and operable; two new CLI commands (setup-code, recover)

Implement the Milestone 1 authentication scope (docs/architecture.md):
- migration 0002: agency, user, capability_grant, session, setup_code,
password_reset_code, and audit_event (append-only via triggers)
- capability-based authorization from the start; the Administrator role
is a grant bundle applied at creation, never a name checked at
decision time
- first-run setup: short-lived hashed setup code emitted by serve and
the setup-code command; POST /api/setup creates agency, first
administrator, and grants and consumes the code in one transaction;
unavailable after initialization
- sessions: 256-bit opaque tokens stored as SHA-256 digests, HttpOnly
SameSite=Strict cookies, 12-hour absolute expiry, immediate
revocation on logout and password reset; login timing equalized for
unknown usernames and failure responses identical
- passwords: Argon2id PHC strings, 12-512 byte policy shared by setup
and reset
- reset: manage_users-gated code issuance over the API; using a code
rotates the password, revokes all sessions, and audits, atomically
- recovery: consolebook recover --username issues a reset code for an
administrator with OS access to the data directory only, refusing
non-administrator targets, with a distinct audit event
- doctor reports initialization state and administrator count
- 15 new integration tests covering the flows and their failure paths
- ADR 0004 records the decisions and the deliberate gaps (no rate
limiting yet, Secure cookie flag deferred to deployment hardening)
Closes#4
@TusanHomichi
TusanHomichi merged commit d4fca7c into mainAug 28, 2026
1 check passed
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Milestone 1: first-run setup, administrator accounts, sessions, and password recovery

2 participants

@TusanHomichi@claude