user-engine/docs/account-journeys.md
tegwick eca7c54748
Some checks are pending
CI Smoke / host-smoke (push) Waiting to run
CI Smoke / container-smoke (push) Waiting to run
Account journey acceptance / journeys (push) Successful in 10s
Close recovery acceptance and reconcile blocked workplans
Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a0e38e-e5bb-7b50-968d-a738a0294997
2026-09-27 17:54:47 +02:00

144 lines
18 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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/0028; provider implementation: KEY-WP-0035 (finished).
Reviewed against the portal on 2026-09-13. U01, U09 and U10 were revised on
2026-09-26; acceptance dependencies were reconciled on 2026-09-27. This is the browser acceptance contract;
headless capability alone does not mean a journey is usable or verified live.
## Common interaction rules
- The header is titled NetKingdom Identity. An account-site session says
“Signed in as” the verified identity and offers Log out. With no account-site
session, the header says “Not signed in” and offers Sign in. When the browser
already sent a NetKingdom session cookie, the account site asks the sign-in
service which identity that cookie is and shows “NetKingdom sign-in is” that
confirmed name, with “This account site has no session yet.” Continue reuses
that identity. “Use a different identity” starts a fresh NetKingdom sign-in.
A URL parameter does not name the visitor. If the sign-in service does not
answer, the page stays “Not signed in” and does not invent a name. A one-time
code raises the security level of the NetKingdom sign-in and is not another
sign-in.
- 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 and the home page say “Signed in as” the verified identity when an account-site session exists. With no account-site session they say “Not signed in,” unless the sign-in service confirms an existing NetKingdom identity, which is then named before the account site continues. An application may keep its own session. A one-time code is a higher security level, not another sign-in | Expired/unknown cookie shows signed-out state; a query does not invent a session; a failed identity lookup stays signed out; sign in again, or use a different identity | Implemented; automated anonymous/expired/member/operator tests, including the home identity section and a confirmed NetKingdom sign-in with no account-site session |
| 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 | Fresh application login confirmed on September 24; second-user, setup-to-welcome and company-workflow acceptance remain VERGABE-WP-0019-T06 |
| 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; login name and sign-in address now named at handoff and in the user entry (2026-09-23 run, USER-WP-0035-T01); email delivery unresolved (USER-WP-0035-T02) |
| 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 | Renewable factor-reader and optional policy deployed (KEY-WP-0035/RPF-WP-0040); installed-provider checks pass; attended full U05–U08 acceptance remains USER-WP-0028-T03 |
| 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 | Installed-provider activation/cancellation checks pass (P06); real-user enrollment and verified portal handoff remain USER-WP-0028-T03 |
| 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 | P04 recovery and P06 replacement guards deployed and verified with disposable provider fixtures; real-person recovery/replacement acceptance remains USER-WP-0028-T03 |
| U09 — See my tenants and usable applications | Account page and home show login state, the tenants and privileges active on this sign-in, and allowed memberships separately. An ordinary sign-in has one active tenant. An administrator, vendor, or multi-hire sign-in may show more than one active tenant when the verified token lists them. A recorded workload membership is an allowed record | An empty allowed list says nothing is recorded. A tenant account or the token tenant is not shown as a membership. A missing catalogue decision is not checked, which is neither access nor a denial | Login state, active sign-in, and allowed memberships are shown (USER-WP-0036). Allow, deny, and unavailable workload decisions remain USER-WP-0026-T03 and USER-WP-0028-T02 |
| U10 — Change tenant or account | Explicit reauthentication confirms the new tenant. Other allowed tenants stay inactive until that sign-in. Switching does not claim to end sessions an application already has | Denied tenant leaves a clear recovery route; stale shared identity can be cleared. A portal control does not mark a second tenant active by itself | Account switching confirmed by the founder on September 24 with fresh issuer sequences (USER-WP-0026-T02); multi-user workload acceptance remains VERGABE-WP-0019-T06 |
| 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 | Automated scope/CSRF tests, live shared-logout checks and September 24 attended account-switch receipt complete USER-WP-0026-T02; existing application JWTs are not revoked |
| 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; login name and sign-in address presented in the user entry (USER-WP-0035-T01); 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 | P04 recovery and provider status implemented/deployed; tenant admins escalate to authorized platform recovery; real-person lost-factor acceptance remains USER-WP-0028-T03 |
| 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 | 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 | Implemented and deployed (USER-WP-0032): checked services, confirmed single-delivery recovery, durable uncertain-send guard; SMTP/IMAP retry and provider expiry/permission/rotation acceptance pass; live checks send no email |
| 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 | Implemented and deployed: issuer-owned scoped policy, recent-MFA preview/apply/rollback, privileged portal guards and installed-provider browser acceptance; see P06 evidence |
| 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
completed OTP policy/provider rollout; USER-WP-0028-T03 retains attended OTP
acceptance. Credential custody is no longer a blocker. 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.
September 27 reconciliation: the credential/policy deployment gate above passed
under RPF-WP-0040 and P06; it is still a prerequisite for any future handoff
configuration. KEY-WP-0034 and the September 24 attended receipt close the prior
account-switch wait. Mail infrastructure is available, but provider setup-link
delivery and invited-person receipt remain USER-WP-0035-T02. See
[evidence review](evidence/2026-09-27-loose-ends-review.md) for the exact evidence
and remaining owner dependencies.