user-engine/docs/account-journeys.md

127 lines
15 KiB
Markdown
Raw Normal View History

# Account and access journeys
Owner: user-engine, with KeyCape/NetKingdom for sign-in and factors,
tenant-engine for tenant lifecycle, and applications for workload admission.
Acceptance work: USER-WP-0027; OTP dependency: KEY-WP-0035 and NK-WP-0033.
Reviewed against the portal on 2026-09-13. This is the browser acceptance contract;
headless capability alone does not mean a journey is usable or verified live.
## Common interaction rules
- The header states the verified portal identity, or “Not signed in to this
portal.” A valid portal session shows Log out; an absent/expired session shows
Sign in. Never infer identity from URL parameters or an existing provider tab.
- The portal cannot observe every application or shared-provider session. Explain
this once in sign-out confirmation or expandable identity-switch help, not as
competing login/logout actions everywhere. “Use another account” remains
reachable when a wrong shared identity prevents portal login.
- Log out opens a confirmation with the scope made explicit. GET never signs out.
Invalid confirmation leaves the current session intact. Do not claim global
sign-out when only the portal session ended.
- Name the person, selected tenant, and application separately. Platform
administration is not tenant membership and does not imply application access.
- Every action has a visible result and a useful next step. Failure is not success;
unknown provider state is not “disabled.” Keep recovery reachable before login.
- Use one primary action per step, familiar wording, labelled fields and errors,
keyboard-visible focus, and layouts usable on a phone. Preserve safe form input
after validation failure; never redisplay secrets or trust unverified returns.
- A status change requires authoritative confirmation. A sent message is not
delivered mail; an invitation is not a login; opening a setup link is not OTP
activation; recorded membership is not guaranteed workload admission.
## User perspective
| ID / intent | Success | Failure and recovery | Current support / acceptance |
|---|---|---|---|
| U01 — Know whether I am signed in | Header names my verified account; exactly the appropriate Sign in or Log out control | Expired/unknown cookie shows signed-out state; sign in again | Implemented; automated anonymous/expired/member/operator tests |
| U02 — Sign in to my company application | Personal login lands in the intended tenant and application | Wrong credentials stay on provider; denied membership leads to account help with identity switching | Recovery deployed previously; actual fresh-user acceptance waiting on OTP |
| U03 — Accept an invitation | Confirm intended tenant/role, accept once, then see next setup step | Expired/used/wrong-person invitation explains next step; admin reissues without duplicates | Service/browser routes exist; live delivery and full browser acceptance pending |
| U04 — Set or recover my password | Use actual login name, complete single-use setup, return to sign-in | Missing mail or expired link offers admin-assisted new setup link | Password setup reported successful; email delivery unresolved; display-name/login-name clarity needs work |
| U05 — Use password-only access before optional OTP enrollment | Ordinary application permits login when provider confirms no activated factor | Provider unavailable gives recovery, never silently bypasses enrolled OTP | KEY-WP-0035 source tested; live credential/policy gate unresolved |
| U06 — Turn on authenticator codes voluntarily | My account → Sign-in security → provider; confirm identity, scan QR, verify current code, see activation confirmed, test fresh login | Bad code retries; cancellation does not report enabled; interruption can resume safely; support reachable without portal login | Help and configurable provider handoff implemented; provider activation/cancel semantics and live enrollment unverified |
| U07 — Sign in with an enrolled authenticator | Current code completes login; existing AAL1 session cannot skip OTP | Invalid code explains retry; lost device has a recovery route | Issuer policy tested; real-user enrolled/recovery acceptance pending |
| U08 — Replace or remove my authenticator | Provider reauthenticates; replacement verified before old factor removed; status and recovery instructions clear | Lost old factor triggers verified recovery, not a bypass link; policy-required MFA cannot be disabled | Required provider journey; not verified/available from portal yet |
| U09 — See my tenants and usable applications | Account page lists allowed tenants and launchable applications with the current context | Empty membership explains request-access route; unavailable/stale access is labelled and refreshable | Personal membership display exists; authoritative application catalogue/request-access journey pending USER-WP-0026-T03 |
| U10 — Change tenant or account | Explicit tenant switch confirms new authority; account switch ends relevant sessions and lets me choose identity | Denied tenant leaves a clear recovery route; stale shared identity can be cleared | Tenant reauthentication and shared sign-out implemented; real multi-identity acceptance pending |
| U11 — Sign out | Confirmation states scope; portal session ends; correct signed-out controls appear | CSRF rejection retains session; shared-provider failure explains remaining scope and retry | Portal automated tests; prior shared logout browser checks; current real-user acceptance pending |
| U12 — Recover from denied access or service outage | Plain explanation, reference for support, and account/help navigation | No automatic login loop; no private claims/codes echoed; safe retry only | HTML browser denial/recovery implemented; JSON API semantics retained |
| U13 — Update my profile and finish onboarding | Saved values and required steps are confirmed; external steps reflect provider evidence | Validation keeps safe input; provider-owned steps cannot be manually faked complete | Existing routes; form-preservation and external completion UX acceptance pending |
## Tenant administrator perspective
| ID / intent | Success | Failure and recovery | Current support / acceptance |
|---|---|---|---|
| T01 — Enter the right tenant administration | Header shows identity; managed tenant is explicit; only permitted admin navigation | Non-admin/cross-tenant request denied with account recovery | Existing authorization/navigation tests; broader browser matrix pending |
| T02 — Invite someone with the right role | Review name, email, tenant and role; show invitation state and next action | Duplicate, wrong address, expired invite: inspect, correct/reissue or expire without making a second account | Invitation routes and checks exist; delivery/preview usability pending |
| T03 — Prepare an account that can actually log in | Distinguish profile, directory login name, invitation, password setup, and tenant access; admin can give the correct login name | Partial provisioning shows what exists and retry reconciles it; never show display name as login implicitly | Create-login/setup-link routes exist; plain login-name presentation and lifecycle state view pending |
| T04 — Help someone who cannot sign in | Identify affected tenant/account; distinguish password, OTP, membership, and outage; give safe recovery step | No access to passwords, OTP seed or current codes; provider failure has support reference/escalation | Password setup and help page exist; verified lost-factor recovery/provider status pending |
| T05 — Grant/change/revoke application access | Review exact tenant/application/role; apply authorized change; confirm effective result | Policy denial or stale version explains reason and refresh; no silent broad grant | Service capabilities vary; consolidated browser application-access management pending |
| T06 — Suspend/reactivate/remove a tenant account | Confirm target and scope; show resulting state and whether access propagation is pending | Stale or failed operation leaves truthful state; retry after readback; shared identity in other tenants preserved | Existing lifecycle routes; confirmation/propagation UX and cross-tenant browser drills pending |
| T07 — Track incomplete onboarding | See invited, identity missing, password pending, OTP problem, and access denied as distinct actionable states | Stale/unknown provider state is labelled; administrator gets the correct owner/action | Headless diagnostics exist; consolidated browser status and retry workflow pending |
| T08 — Manage admin succession and audit | Grant the next admin only with authority; preserve an accountable admin; review who changed what | Prevent loss of last administrator or provide platform recovery; no self-escalation | Required journey; last-admin guard and browser audit acceptance need review |
## Platform administrator perspective
| ID / intent | Success | Failure and recovery | Current support / acceptance |
|---|---|---|---|
| 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 |
| 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 | Current incident: rejected factor-read credential; custody/renewal and mail delivery unresolved |
| 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 |
| P08 — Review audit and service recovery | Follow correlation reference without exposing secrets; see actor, tenant, action and result; prove rollback | Missing telemetry or unknown state visible; no success until authoritative readback | Existing service events/references; unified browser audit/support workflow pending |
## OTP activation state contract
The provider owns credential material and proof of possession. The portal owns
explanation, navigation, and handoff; it never collects OTP seeds or codes.
| State | What the user sees | Allowed next step | Required evidence |
|---|---|---|---|
| Unknown / unavailable | “We cannot confirm your authenticator status”; setup unavailable when no verified handoff is configured | Help; provider management only when operator-configured and verified | Do not infer off from lookup failure or AAL1 session |
| Not enrolled | Optional setup, plus continue without OTP where policy permits | Start enrollment | Authoritative factor absence and applicable client policy |
| Enrollment pending | QR/code confirmation at provider; no success badge yet | Confirm, retry, cancel or resume | Pending token cannot accidentally lock normal login |
| Enabled | Confirmation and recovery instructions | Test fresh sign-in; later manage device | Provider verifies possession and reports activated factor |
| Replacement pending | Old factor remains usable until replacement confirmed | Confirm replacement or cancel | No gap allowing MFA bypass |
| Recovery required | Clear lost-device recovery instructions | Verified recovery with audit | Provider proof/authorized recovery, never tenant membership alone |
Deployment gate: verify the live provider's activation, cancellation, realm mapping,
scoped factor-read credential and renewal contract before enabling optional policy
or setting USER_ENGINE_MFA_MANAGEMENT_URL. Both successful and empty token queries
must be tested against controlled accounts; self-service credentials are not an
administrative lookup credential. The portal help page is reachable before login
so OTP-required login does not hide recovery.
## Executable implementation status
Implementation workplans: USER-WP-0028 (users), USER-WP-0029 (tenant admins),
USER-WP-0030 (platform admins), USER-WP-0031 (automated suites), and NK-WP-0038
(scoped provider lifecycle). The original review column above records the starting
gaps. For the current per-journey implementation state and executable tests, use
`tests/journey-coverage.json` and `make test-journeys`; the report never equates
provider-boundary tests with real OTP or mail acceptance.
Now implemented: actual login-name handoff, profile validation/retry, scoped
provider lifecycle, role succession, cross-connection last-admin protection,
confirmation/stale-state checks, first-admin bootstrap rollback/retry, invitation
delivery readout, onboarding follow-up, tenant audit, and platform delivery retry.
## Acceptance and remaining work
USER-WP-0027 tracks the matrix and role-based usability gaps. KEY-WP-0035 tracks
OTP policy/provider rollout. USER-WP-0026 retains authoritative workload catalogue
work. Do not close these based solely on this document or a unit-test pass.
Run every journey with an ordinary member, tenant admin, and platform operator as
applicable, plus an anonymous/expired session. For each capture: initial state,
visible controls, action, authoritative result, failure, recovery, and cross-tenant
isolation. Use synthetic identities in stored evidence. Include keyboard-only and
narrow-screen checks; never store passwords, QR images or OTP values in evidence.
Automated portal coverage: test_account_clarity.py, test_account_recovery.py,
test_portal_navigation.py and existing test_web.py authorization/lifecycle tests.
Automated issuer coverage: KEY-WP-0035 optional MFA tests. Actual provider OTP,
notification delivery and multi-user workload acceptance remain separate evidence.