user-engine/docs/account-journeys.md
tegwick 560cdeed46
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 3s
Build and Publish Container Image / build-and-push (push) Successful in 19s
Account journey acceptance / journeys (push) Successful in 8s
Show an existing NetKingdom sign-in before the account site continues it.
The account site said "Not signed in" while Authelia still had a session, and Sign in reused that identity. Ask Authelia who the session cookie is, show that name, and send a fresh sign-in only when a different identity is requested.

Assistant: grok
Assistant-Session: 01a0d25d-d358-7e13-b84a-d007fbb7e34f
2026-09-27 00:21:34 +02:00

17 KiB

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. U01, U09 and U10 were revised on 2026-09-26. 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 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; 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 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 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 Reauthentication handoff is the only tenant switch; 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; 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 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 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 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.