net-kingdom/workplans/NK-WP-0042-workload-mfa-step-up.md
tegwick 257c810709
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 2s
NK-WP-0042-T02: record user-engine's pilot proposal (coulomb-social)
The message dependency is cleared; T02 waits on the founder under
decision cef97ccd for the pilot choice and journey acceptance.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 469893@bnt-lap001
Assistant-Session: 49296f15-2171-4137-b972-2443bab95edb
2026-10-09 11:47:34 +02:00

7.3 KiB

id type title domain repo status flavor owner topic_slug created updated related state_hub_workstream_id
NK-WP-0042 workplan Let workloads require MFA for all or part of their features infotech net-kingdom blocked planning claude-code netkingdom 2026-09-23 2026-10-09
NK-ADR-0016
NK-WP-0037
3f702215-704b-5788-8ca0-b8b9ba2dd3f8

ADR-0016 makes MFA a user preference by default and lets a workload require it for all or some of its features. This workplan defines how a workload states that requirement and how the flow enforces it. It does not require MFA anywhere; the enrollment and recovery usability gate in ADR-0016 still applies first.

Specify the workload-requested step-up contract

id: NK-WP-0042-T01
status: done
priority: medium
state_hub_task_id: "d66a6347-b714-5cca-aeb5-7121328f4dec"

Define how a workload requests AAL2: per client registration for the whole feature set, or per request as a step-up when a protected feature is used. Specify:

  • which OIDC parameter the request uses (acr_values, max_age, or both);
  • what KeyCape must return when a user has no factor (a clean refusal and an enrollment route, never silent AAL1);
  • how the resulting assurance.level reaches flex-auth.

Record it as an IAM Profile amendment. key-cape owns the implementation.

Done 2026-09-27. Drafted as canon/standards/iam-profile_v0.4.md (status proposed, supersedes v0.3, which stays accepted and normative until this is accepted). The new "Workload-Requested Step-Up (proposed)" section specifies acr_values carrying an assurance.level value (aal2/aal3) as the step-up request, max_age as an optional additive freshness request that must never stand in for strength alone, the two conforming no-factor refusal shapes (inline enrollment detour or an explicit error=mfa_required-class refusal, never silent AAL1), and that flex-auth keeps reading the issued assurance.level with no new claim. The exact enrollment/recovery UX is left to T02, which this section names explicitly.

Agree the user-facing step-up and enrollment journey

id: NK-WP-0042-T02
status: wait
needs_human: true
decision_id: cef97ccd-4ee7-40fe-859e-1df9c9360ecb
blocking_reason: "user-engine's pilot proposal (coulomb-social) is in; the pilot choice, the AAL2 switch-on and user-perspective acceptance are the founder's (decision cef97ccd)."
priority: medium
state_hub_task_id: "4e51585d-2b57-56d4-84c1-314041d26bcf"

With user-engine (U06, factor recovery) and one pilot workload, agree what a user sees when a feature needs MFA and they have none. That includes the enrollment detour, the return to the feature, and recovery. It must be accepted from a user's perspective before any workload turns the requirement on.

Waiting 2026-09-27. Routed to user-engine via State Hub message 892fd489-113d-4108-8048-727f4b0ed048, referencing the T01 contract and asking for a proposed pilot workload and U06 touchpoints. This is a UX/product agreement across two repos and a pilot workload owner; NetKingdom cannot decide it unilaterally.

2026-10-03: human gate routed to hub decision cef97ccd-4ee7-40fe-859e-1df9c9360ecb (D10: Identity record and MFA: accept NK-ADR-0017, choose the record read surface, agree the MFA user experience) by CUST-WP-0075; resolving that decision raises C-40 here.

2026-10-03 (CUST-WP-0075 inbox sweep): gate re-checked, unchanged. The unread user-engine message of 2026-10-03 (db1b7d6e, USER-WP-0026-T03) was about the workload catalogue/admission and access-decision owner, not this journey; it was answered (reply 19a0cbcd: access-engine owns decisions, grants, revocation and the protected-system registry; the catalogue is the onboarding binding of access-engine protected system, key-cape OIDC client and user-engine application record; NetKingdom only orchestrates). It does not settle T02. Our 2026-09-27 request 892fd489 (pilot workload, U06 touchpoints) is still unread by user-engine, so blocked_on: message-from:user-engine stays real, and the founder's acceptance under decision cef97ccd stays the human gate. The reply reminds user-engine of 892fd489.

2026-10-09: user-engine answered 892fd489 (message a459e8a6), as a proposal; the pilot choice and the AAL2 switch-on stay founder decisions:

  • Pilot workload: coulomb-social (the current registration/onboarding client, owner of application action step-up). One non-privileged feature behind acr_values=aal2. Precedent: the user-engine portal's administration step-up ("Verify with MFA" -> /login?recovery=1&return_path=..., P06 recent-MFA guard, deployed).
  • Refusal shape: inline enrollment detour at the issuer; factor screens stay on the IdP and user-engine never collects an OTP or reads a seed. Fallback on an mfa_required-class refusal: link to the public user-engine /security page. Return means the workload re-requests with acr_values; a return URL is never proof of enrollment.
  • U06 touchpoints reused: /security; My account -> Sign-in security -> provider management (USER_ENGINE_MFA_MANAGEMENT_URL, deliberately unset until attended KEY-WP-0035 self-service checks pass); U07 lost device and U08 replace/remove (replacement verified before removal, no bypass link; P04 operator-assisted recovery); P06 policy preview/rollback so switching on does not lock out unenrolled users.
  • Constraint: user-engine's attended real-factor U05-U08 run (USER-WP-0027-T03 / USER-WP-0028-T03) is pending, and route net-kingdom-privacyidea-admin-token is still resolvable: false (railiance-platform). user-engine proposes running the pilot's user-perspective acceptance in that same attended session (enrollment detour -> return -> lost-factor recovery, end to end once).

NetKingdom's reading: the proposal fits the T01 contract (issuer owns factor screens, workload enforces issued assurance, return is not evidence). The message dependency is cleared; T02 stays wait on the founder under decision cef97ccd: choose the pilot, then accept the journey in the combined attended session. Note that coulomb.social fits oidc-browser-relying-party 1.0 only partly (NK-WP-0048 README fit table), so the pilot's KeyCape acr_values handling is checked on its existing registration.

Infrastructure review — 2026-09-28

Build T02 on the already completed USER-WP-0033 and KEY-WP-0035 P06 work. Their September 14 release evidence records optional-after-enrollment policy for user-engine-portal and vergabe-demo-company, privileged MFA guards, confirmed enrollment/cancellation and old-session checks. Do not rebuild those capabilities or interpret this plan as the first delivery of MFA policy.

The residual is workload-level interoperability and an accepted pilot journey: agree the pilot owner, reuse U06 recovery, prove no-factor enrollment and return to the protected action, and test stale AAL1, refusal and provider unavailability. Existing scoped policy does not prove arbitrary-client acr_values support or acceptance of IAM v0.4. KeyCape owns issuer enforcement; user-engine owns the journey; the workload and flex-auth enforce the issued assurance at the protected action. T02 remains wait for that agreement and actual-user acceptance, coordinated with KEY-WP-0034 / USER-WP-0028 / VERGABE-WP-0019, without reopening their completed provider work.

Evidence and cross-plan priorities: estate review.