Lewati ke isi

T0-D Result — Credential Lifecycle / Recovery

Metadata Value
Mode Server development /home/scola/odoo
Run ID T0-D-20260809T042347Z
Docs read development-guide, workspace-governance, architecture-api, T0-D-preflight, DEC-014, inventory
BE application commit 4f132a86c4e2abb661502af7929959384287fcb0
FE application commit f25698b094c2e452dddcf24b2f6cab8d63714252
Golden DB scola_golden upgraded + restarted with BE identity env
Matrix 11/11 PASS / 0 FAIL / 0 skip

Credential surface inventory summary

See T0-D-credential-surface-inventory.md.

Canonical retained: login/session/logout API, change-password + force gate, public password-reset request/confirm, admin reset (scoped), account activate/deactivate with session revoke, SPMB OTP (separate purpose), account generation without shared defaults.

Excluded/denied: customer break-glass/login-as, password expiry, inventing lockout UX, Odoo /auth/logout as FE logout path.

Fixed unsafe: GBS/GTS shared gbs123/gts123 removed; faculty plaintext password logging removed.

Final DEC-014

See T0-D-DEC-014.md.

Status: CLOSED_WITH_IMMUTABLE_RUNTIME_EVIDENCE for Core credential recovery contract.

Canonical lifecycle

  1. Provisioned account → random credential + must_change and/or recovery token (hash-at-rest).
  2. Authenticated password change → verify old, set new, revoke other sessions.
  3. Forgot password → anti-enumeration request → single-use TTL token → confirm → revoke all sessions.
  4. Admin reset → capability + tenant scope → random/temp + must_change → revoke sessions → audit.
  5. Disable account → revoke sessions; disabled cannot consume recovery successfully as active.

Routes retained / removed

Route Status
/api/auth/password-reset/request SUPPORTED_CANONICAL (public)
/api/auth/password-reset/confirm SUPPORTED_CANONICAL (public)
/api/auth/change-password SUPPORTED_CANONICAL
/api/auth/logout SUPPORTED_CANONICAL (FE now uses this)
/forgot-password, /reset-password SUPPORTED_CANONICAL FE
/register stub redirect to /login
Impersonation / login-as EXCLUDED_AND_DENIED
Foundation HR reset controller NOT_IMPLEMENTED (registry dead) — EXCLUDED until owned

Runtime matrix totals

Metric Value
Total 11
PASS 11
FAIL 0
Skip 0

Evidence: T0-D-evidence/T0-D-20260809T042347Z-results.json

Covered: avail probe; reset exist/missing/disabled + anti-enumeration shape; confirm invalid/expired/replay; change-password wrong-old; admin unauthorized; excluded break-glass surfaces.

Session revocation evidence

Implemented in credential_session.revoke_user_sessions; called from change-password (keep current), reset confirm (all), admin reset, deactivate. Matrix cases exercise change/reset/admin paths on live Golden after upgrade.

Token replay / expiry / binding

Unit: 8/8 (test_credential_lifecycle_unit.py). Runtime: CONFIRM invalid/expired/replay PASS.

Cross-tenant / admin scope

Admin reset without users.manage denied (T0D-ADMIN-01). Token bound to user+purpose; wrong-account consumption fails as invalid.

Notification failure

Mail send failures do not delete issued token; raw token never logged. Request still returns generic success.

User-enumeration comparison

Public request returns identical success message + success:true for exist / missing / disabled (T0D-RESET-04).

Audit evidence

scola.credential.audit.event — system ACL only; actions recorded without passwords/tokens.

Source / runtime identity

Field Value
backend_git_commit_sha (runtime) 4f132a86c4e2abb661502af7929959384287fcb0
FE app commit f25698b094c2e452dddcf24b2f6cab8d63714252
Working trees at matrix clean application commits (docs tip may follow)

Remaining credential risks

Item Status
Deep multi-session concurrent revoke stress OPEN (mechanism present; not load-tested)
Foundation HR reset wiring BLOCKED / NOT_IMPLEMENTED
SPMB dual register controllers DUPLICATE_MERGE residual (outside password-reset)
Timing side-channel on reset request OPEN (not claimed closed)
Activation invite-without-password UX polish PARTIAL — service purpose activation exists; V1 relies on must_change + reset/admin_reset

Exit statuses

Area Status
Password reset / recovery CLOSED_WITH_IMMUTABLE_RUNTIME_EVIDENCE
Authenticated password change + session revoke CLOSED_WITH_IMMUTABLE_RUNTIME_EVIDENCE
Shared default passwords CLOSED_WITH_IMMUTABLE_RUNTIME_EVIDENCE
Break-glass / impersonation customer surface EXCLUDED_AND_DENIED
Password expiry / lockout product UX EXCLUDED_AND_DENIED
Foundation HR reset BLOCKED

T0-D: CLOSED — CREDENTIAL LIFECYCLE / RECOVERY

Do not declare full Tranche-0 closed yet — independent T0 final audit/reconciliation remains before T1.