dashboard: make credential lifecycle audit events transactionally durable
#2,482 opened on Jul 12, 2026
Repository metrics
- Stars
- (4,293 stars)
- PR merge metrics
- (PR metrics pending)
Description
Summary
Make dashboard credential mutations, session invalidation, and their security audit event durable as one recoverable operation.
Audited current-main behavior (2026-07-15)
- Dashboard auth is implemented under
dashboard/backend/auth/using SQLite. - Administrator password reset calls
Store.UpdatePasswordinstore.go, then callswriteAuditfrom the handler. writeAuditcallsAddAuditLogafter the mutation and discards the returned error.- The current administrator reset path does not revoke all existing sessions for the target user.
- There is no
dashboard/backend/auth/password_store.goon currentmain. - Self-service password change is not a current supported handler, so it must not be described as already transactionally updating password and sessions.
A database or request failure can therefore leave a changed credential without a durable audit event, and previously issued target-user sessions may remain active.
Expected contract
Use one SQLite transaction for the credential mutation, target-user session revocation, and either:
- the final typed audit row; or
- a durable outbox row for bounded idempotent delivery.
The handler succeeds only after that durable state commits.
Scope
- Define typed credential lifecycle events for administrator reset and any future self-service change/recovery flow.
- Add store-level transaction methods; do not coordinate SQL transactions in HTTP handlers.
- Revoke all target-user sessions when password/credential state changes.
- Preserve actor, target, action, outcome, timestamp, and correlation/idempotency key without credential material.
- Make retries/delivery idempotent and bounded if an outbox is used.
- Add retention/pruning and terminal-failure metrics/content-free logs.
- Ensure cancellation semantics do not report success after an ambiguous commit.
Acceptance criteria
- Successful administrator reset atomically persists the new hash, revokes target sessions, and persists an audit/outbox record.
- Failure rolls back all three effects; no false success event is written.
- Existing target-user sessions are rejected after commit.
- Duplicate retry cannot apply a second semantic mutation or duplicate the event.
- Audit/outbox payload never contains passwords, hashes, tokens, cookies, authorization headers, or raw bodies.
- Full-disk, lock/busy, canceled context, insert failure, post-commit response failure, retry, and restart tests exist.
- A future self-service path must use the same store transaction contract.
Likely change surfaces
dashboard/backend/auth/store.go, session_store.go, audit_store.go, schema.go, admin_meta_handlers.go, tests, metrics/docs, and possibly a narrowly scoped outbox store.
Validation entrypoint
make agent-report ENV=cpu CHANGED_FILES="dashboard/backend/auth/store.go dashboard/backend/auth/session_store.go dashboard/backend/auth/audit_store.go dashboard/backend/auth/admin_meta_handlers.go"
cd dashboard/backend && go test -race ./auth ./router
Follow the nearest dashboard AGENTS.md and the harness-reported gates.