diff --git a/docs/account-journeys.md b/docs/account-journeys.md index 6fe239d..3978454 100644 --- a/docs/account-journeys.md +++ b/docs/account-journeys.md @@ -67,7 +67,7 @@ headless capability alone does not mean a journey is usable or verified live. | P01 — Administer platform without joining every tenant | Platform console reachable with platform role; personal memberships remain truthful | Opening a workload as platform admin can be denied; account console remains reachable | Existing platform navigation/authority tests; full workload denial journey acceptance pending | | P02 — Create tenant and first administrator | Confirm tenant identifier/type/name and first admin; show tenant created versus admin onboarding pending | Conflict/partial failure readback avoids duplicate tenant; resume only missing stages | Existing platform creation/result routes; live end-to-end drill pending | | P03 — Find and inspect a tenant | Search exact identifier or disambiguate matching names; clearly state selected scope | Unknown/ambiguous name presents choices without guessing authority | Existing tests for unknown/ambiguous names and tenant selection | -| P04 — Recover a tenant administrator | Verify request and affected scope; audited, bounded account/factor recovery returns control | Insufficient proof denies; provider outage yields pending state and named owner | Identity-recovery route exists; lost-factor recovery and audited browser acceptance pending | +| P04 — Recover a tenant administrator | Verify request and affected scope; audited, bounded account/factor recovery returns control | Insufficient proof denies; provider outage yields pending state and named owner | Implemented: recent-MFA platform recovery, exact-factor confirmation, durable provider audit/readback/retry and replacement possession; see evidence/2026-09-13-p04-recovery.md | | P05 — Operate sign-in, factor and notification services | See degraded component and impacted journeys; renew scoped credentials; verify recovery | Expired factor-read credential blocks assurance decision; missing mail uses explicit assisted setup; no hidden MFA bypass | Factor-read custody, automatic renewal and mounted delivery verified (RPF-WP-0040); provider expiry/revocation drills and mail delivery remain open | | P06 — Set authentication policy | Distinguish optional-after-enrollment, mandatory, and application step-up; preview impact and rollback | Unsupported/ambiguous policy rejected; avoid locking out unenrolled users or weakening privileged actions | KeyCape optional policy source tested; scoped rollout and privileged-portal policy acceptance pending | | P07 — Suspend/retire/reactivate tenant | Confirm blast radius and resulting tenant lifecycle; applications reflect effective policy | Stale version or partial propagation provides readback/retry; recovery retains audit | Existing tenant lifecycle APIs; browser confirmation/propagation drill pending | diff --git a/docs/evidence/2026-09-13-p04-recovery.md b/docs/evidence/2026-09-13-p04-recovery.md new file mode 100644 index 0000000..35cc7c9 --- /dev/null +++ b/docs/evidence/2026-09-13-p04-recovery.md @@ -0,0 +1,63 @@ +# P04 administrator recovery release — 2026-09-13 + +P04 is implemented and deployed. Entry: https://users.coulomb.social/platform/factor-recovery. +A platform operator signs in with MFA within five minutes, enters the exact +directory login and support reference, reviews one factor and shared-identity +scope, and attests that the person's ownership was verified through the support +process. A missing attestation denies the operation; the software does not +pretend a checkbox independently proves ownership. + +Recovery disables one selected factor and preserves password, directory identity, +tenant access and other factors. Provider audit persists before mutation; stale +state, changed ownership and conflicting references are rejected. PostgreSQL +advisory locking serializes recovery requests; row locking protects the selected +factor and a final fingerprint protects readback. Retries reconcile completion. +Check recovery result by support reference if the page or response was lost; +the original administrator can obtain a fresh confirmation for an interrupted +operation. A completed receipt is rechecked against current provider state. + +The private provider-side service independently verifies RS256 signature, exact +KeyCape issuer and portal audience, human platform-operator role and fresh AAL2 +assurance. Actor comes from the signed subject. Confirmation tickets bind actor, +target, version, realm, support reference and expiry. Portal sessions retain the +signed ID token server-side; it is never rendered into HTML or receipts. The +portal receives no provider credentials or Kubernetes permissions. Network policy +permits the recovery endpoint only from portal pods. Public signing-key access +is separately scoped. No OpenBao owner handoff is needed for routine recovery. + +The user then signs in to https://pink-account.coulomb.social with their own +password, enrolls a replacement TOTP, proves possession and tests a fresh +application login. The live `keycape-confirm-totp-enrollment` policy requires +possession confirmation for new TOTP enrollments in coulomb. Existing factors +were not changed. KeyCape already requires confirmed enrollment and OTP evidence +before AAL2. Recovery does not automatically relax application MFA policy. + +## Release and verification + +- Portal source: 11dfaf5 (including 58e07dd). +- Portal image: forgejo.coulomb.social/coulomb/user-engine@sha256:86112f2f0bb6388344d0260a3611da2a19c609b8f08bd79858d51e1a271e5fa6. +- Provider service source: key-cape d15f4dd (including cb51584). +- Immutable service code: mfa/factor-recovery-626517ff9acb0ef7. +- Provider image: ghcr.io/gpappsoft/privacyidea-docker@sha256:af7841adad262f129e0c1d4f553af13f21cb2f4dc713533f316cfe43ed0b4473. +- net-kingdom deployment procedure: sso-mfa/k8s/privacyidea/deploy-factor-recovery.py; + possession policy: enable-factor-confirmation.py. Cluster and deployment UID + checks plus resource-version preconditions protect rollout targets. +- 219 portal regression tests passed with disposable PostgreSQL, no skips. +- 15 recovery core/service tests passed, including lost-confirmation reconciliation. +- 19 isolated Chromium checks passed, including P04 role denial, scope/proof + confirmation, completion receipt and replacement instructions. +- Installed-provider Job provider-p04-contract-02 passed signed administrator + recovery, wrong role/audience, stale MFA, unsigned requests, unknown-user + isolation, tampered confirmation, durable audit, retry, reference readback, + replacement possession and authentication. Its databases, identities, JWT + signing key and OTP seeds were disposable fixtures, not production accounts. +- Exact source CI passed: KeyCape run60; portal runs161/162/163. +- Both deployments completed rollout. Live portal health/readiness returned 200; + anonymous recovery page returned 403 with sign-in recovery navigation. Native + portal-to-provider health returned 200; missing/invalid authentication returned + 403. Provider signing-key access and policy readback passed. + +No real user's authenticator was disabled for testing. Production authenticated +recovery was not exercised against a real account; positive mutation and browser +acceptance used disposable fixtures. P05 service operations and P06 broader +policy/self-service work remain USER-WP-0030-T03; P04 is removed from that gap. diff --git a/docs/platform-admin-acceptance.md b/docs/platform-admin-acceptance.md index c8706c1..c0023df 100644 --- a/docs/platform-admin-acceptance.md +++ b/docs/platform-admin-acceptance.md @@ -9,7 +9,7 @@ administrators cannot read cross-tenant platform support records. | P01 Platform entry | Role-aware navigation and tenant-independent console; member denial | Existing provider sign-in acceptance still applies | | P02 Tenant and first admin | Authority readback, local bootstrap rollback and retry without duplicate admin | Real first-admin sign-in depends on provider | | P03 Tenant inspection | Exact identifier, ambiguous-name handling and selected scope | No new implementation gap | -| P04 Administrator recovery | Tenant account restoration, scoped directory readback, confirmation and operator-only preview | Identity proof and lost-factor recovery require provider recovery contract | +| P04 Administrator recovery | Tenant restoration and recent-MFA lost-factor preview, proof attestation, signed scope confirmation, audited disable/readback/retry and replacement enrollment | Implemented and deployed; evidence: evidence/2026-09-13-p04-recovery.md | | P05 Service operations | Capability availability, delivery failure/retry/readback, assisted setup guidance | Live factor credential renewal, provider health and actual mail receipt | | P06 Authentication policy | Existing KeyCape optional/mandatory/step-up source tests; no portal policy-write control | Verified factor lookup, owner-approved effective policy rollout and rollback | | P07 Tenant lifecycle | Authority version/confirmation, stale-state rejection and recovery | Application propagation must be verified at the application | @@ -43,13 +43,13 @@ make test-browser-journeys make test-journeys JOURNEY_ARGS="--role platform_admin --require-complete" ``` -The platform selection currently runs 19 tests; the full regression suite runs -216 with seven opt-in PostgreSQL skips. The isolated Chromium suite runs 16 -checks. The final completeness command intentionally fails while P04/P05/P06 +The platform selection includes the P04 recovery tests; the full regression suite runs +219 tests (all pass when disposable PostgreSQL is enabled). The isolated Chromium suite runs 19 +checks. The final completeness command intentionally fails while P05/P06 retain external dependencies. The machine-readable matrix is `tests/journey-coverage.json`; passing portal tests is not live factor acceptance. -## Provider handoff needed +## Historical provider handoff (superseded for P04) KEY-WP-0035/NK-WP-0033 and USER-WP-0030-T03 retain the provider gap. The registered `net-kingdom-privacyidea-admin-token` route was rechecked and remains @@ -59,3 +59,8 @@ repair must not be assumed to be the correct ongoing realm-scoped factor-read credential. The owner must establish the consumer contract and verify its exact permissions and renewal before policy or recovery rollout. No secrets belong in this document, support references, chat or activity records. + +P04 recovery now uses the signed platform session and private provider service. +Use Authenticator recovery for exact-login preview and support-reference readback. +No provider credential or OpenBao login is requested from the operator. +See evidence/2026-09-13-p04-recovery.md for the implemented boundary and acceptance. diff --git a/tests/journey-coverage.json b/tests/journey-coverage.json index 403093f..93b8ed0 100644 --- a/tests/journey-coverage.json +++ b/tests/journey-coverage.json @@ -243,12 +243,15 @@ { "id": "P04", "role": "platform_admin", - "implementation": "external-blocked", + "implementation": "implemented", "tests": [ "test_journey_roles.PlatformAdminJourneys.test_recovery_uses_tenant_access_and_keeps_global_identity_operations_unused", - "test_platform_support.PlatformSupportJourneys.test_recovery_denied_before_preview_and_operator_sees_factor_boundary" + "test_platform_support.PlatformSupportJourneys.test_recovery_denied_before_preview_and_operator_sees_factor_boundary", + "test_factor_recovery_journey.FactorRecoveryJourney.test_role_csrf_and_freshness_denied_before_provider", + "test_factor_recovery_journey.FactorRecoveryJourney.test_preview_cancel_apply_retry_and_secret_not_rendered", + "test_factor_recovery_journey.FactorRecoveryJourney.test_stepup_requests_fresh_mfa_and_binds_return" ], - "remaining": "Tenant identity recovery is scoped; verified OTP/account-ownership recovery remains provider-owned." + "remaining": "" }, { "id": "P05", diff --git a/workplans/USER-WP-0030-platform-admin-journeys.md b/workplans/USER-WP-0030-platform-admin-journeys.md index f3c4c17..6c48fa9 100644 --- a/workplans/USER-WP-0030-platform-admin-journeys.md +++ b/workplans/USER-WP-0030-platform-admin-journeys.md @@ -97,3 +97,11 @@ provider's isolated database/audit contract passed. railiance-platform supplies an attended platform-admin wrapper and runbook with actor-denial tests. Native wrapper acceptance and authenticated portal/browser integration remain live KEY-WP-0036-T02/T03 tasks. No real account was modified; P04 remains incomplete. + +2026-09-13 P04 completed: KEY-WP-0036 delivers the recent-MFA platform browser +journey, signed exact-factor confirmation, provider-derived actor, durable audit, +safe retry and support-reference reconciliation. Production service/portal are +rolled out and replacement TOTP possession confirmation is active. Evidence: +docs/evidence/2026-09-13-p04-recovery.md. Positive recovery uses disposable-provider +acceptance; no real user's factor was disabled. T03 remains in progress only for +P05 and P06 scope; routine P04 no longer needs an OpenBao owner handoff.