--- id: NK-WP-0042 type: workplan title: "Let workloads require MFA for all or part of their features" domain: infotech repo: net-kingdom status: blocked flavor: planning owner: claude-code topic_slug: netkingdom created: "2026-09-23" updated: "2026-09-28" related: [NK-ADR-0016, NK-WP-0037] state_hub_workstream_id: "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 ```task 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 ```task id: NK-WP-0042-T02 status: wait 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. ## 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](../history/2026-09-28-open-workplan-infrastructure-review.md).