--- id: NK-WP-0025 type: workplan title: "Provide NetKingdom self-registration and application first-login provisioning" domain: infotech repo: net-kingdom status: active owner: codex topic_slug: netkingdom created: "2026-08-09" updated: "2026-08-13" depends_on: - NK-WP-0024 - USER-WP-0022 - KEY-WP-0008 - CSOC-WP-0003 state_hub_workstream_id: "1638183b-e2cb-4da2-92b8-d39592d62e86" --- # NK-WP-0025 - public registration and application JIT provisioning ## 2026-08-13 completion review This workplan was blocked at review time. Source-side registration, provider recovery, application JIT, registration entry points, and client MFA selection now exist, but the live user-engine still has `USER_ENGINE_PUBLIC_REGISTRATION=false` and no verification or delivery credentials. Case B and the negative matrix have therefore not run through the deployed path. The durable audit receiver is now deployed and the user-engine event/mail credential split is implemented and tested. The remaining upstream gate in NK-WP-0024 is custody delivery plus activation of the fail-closed runtime. Then enable registration with the email-connect verification endpoint, the `coulomb-social` client/tenant allow-lists, and the identity-provisioner password-setup origin. Final closure requires disposable live users plus an attended MFA/isolation check; `tegwick` remains reserved for the attended positive acceptance test. Provide two safe entry paths for ordinary users of NetKingdom-enabled applications, beginning with coulomb.social: 1. an existing LLDAP user signs in through KeyCape and receives an application-local profile on first successful login; and 2. a new person self-registers through a NetKingdom-owned flow, verifies the address, establishes an LLDAP login, then continues through the same application first-login path. The design is additive to coulomb.social's local-account model. NetKingdom owns authentication and identity lifecycle; coulomb.social/helix-forge owns its application profile, preferences, content, and application authorization. An OIDC subject is linked to an application profile, not merged with an unverified email-only local account. ## T01 - Ratify identity and account-linking semantics ```task id: NK-WP-0025-T01 status: done priority: high state_hub_task_id: "523d5894-6ab6-4097-a28c-0f77880744b1" ``` Record the source-of-truth split, stable key `(issuer, subject)`, optional verified-email matching rules, explicit-link requirements for pre-existing local accounts, unlink/recovery behavior, username/display-name handling, and collision policy for `tegwick` and `bernd.worsch@gmail.com`. Done when email alone cannot silently take over an existing application account and the standalone application-account decision remains intact. Implemented by coulomb.social's unique `(issuer, subject)` Member binding and idempotent first-login creation. Email and username remain mutable profile attributes and are not account-link keys. ## T02 - Provide secure LLDAP self-registration orchestration ```task id: NK-WP-0025-T02 status: wait priority: high state_hub_task_id: "bc220e2b-4cd1-4dcf-b107-12ef3595fe14" ``` Expose a NetKingdom registration service behind user-engine. Validate and normalize username/email, verify mailbox control, create the LLDAP identity through the existing privileged provisioning adapter, establish password via a one-time provider-owned handoff, assign only the ordinary baseline group, and support idempotent resume/expiry/cleanup. Browsers and user-engine must never receive LLDAP admin credentials. Done when an unknown user can reach a normal KeyCape login without operator provisioning and without acquiring tenant-admin or platform authority. Implementation resumed with `docs/public-registration-orchestration-contract.md`. The contract fixes the anonymous/verified actor boundary, non-enumerating start response, durable verification request, digest-only single-use verification state, baseline group provisioning, provider-owned password setup, and fresh OIDC handoff. The user-engine registration domain already requires verified factors and uses the privileged provisioning adapter; the next implementation slice is the persisted intent and verification-port API. Source implementation now includes allow-listed, non-enumerating anonymous start and purpose-bound verification consumption. Verification attaches an email factor only after client/tenant/username binding checks and deliberately stops before user or LLDAP creation. The remaining slice is resumable completion, baseline provisioning, provider-subject linking, and password-setup handoff. The source happy path now completes those transitions: one user-engine user, one idempotent provisioning request with only the baseline `user` role, a KeyCape issuer/subject link, and an allow-listed HTTPS provider password-setup redirect. The full user-engine suite passes 126 tests with 3 environment-dependent skips. Remaining before T02 completion: implement and deploy the verification issuer/mail receiver, add automated recovery for a provider failure after local completion, and run disposable live conformance. ## T03 - Integrate registration entry points and return flow ```task id: NK-WP-0025-T03 status: wait priority: high state_hub_task_id: "3ec4a9a0-cbce-4c63-8ed8-db36f4cae0fb" ``` Publish a NetKingdom registration URL and allow applications to provide `return_to`, client, and tenant hints through a signed/allow-listed state envelope. Add "Create account" beside "Sign in" on the coulomb.social landing page. After registration, start a fresh OIDC authorization-code/PKCE flow; never treat the registration browser session as application authentication. Done when direct NetKingdom registration and coulomb.social-initiated registration converge on the same verified identity flow without open redirects or client confusion. ## T04 - Apply optional MFA policy safely ```task id: NK-WP-0025-T04 status: wait priority: high state_hub_task_id: "cf2e4d05-fd07-4bc3-92ff-b2a5ade97846" ``` Replace global mandatory MFA for this consumer with the KeyCape policy from KEY-WP-0008. Ordinary coulomb.social login is password-only unless the application profile, requested action, tenant policy, or risk/assurance rule requires step-up. Platform administration and other existing high-assurance clients remain MFA protected. Done when lowering assurance for this application cannot lower assurance for OpenBao, platform administration, or another client. Source implementation adds a per-client minimum override and honors explicit `acr_values=aal2`; only the coulomb-social static registration selects AAL1. Other clients retain provider-driven mandatory MFA. Live rollout remains. ## T05 - Prove both cases end to end ```task id: NK-WP-0025-T05 status: wait priority: high state_hub_task_id: "5d13f9f6-16b1-44c9-8e1d-4630cfe60a7b" ``` Test an existing LLDAP identity with no coulomb.social profile, a completely new registrant, repeated callback/JIT, existing-email collision, expired and replayed verification, duplicate username, provider outage and compensation, cross-tenant attempts, optional MFA, profile-requested step-up, unlink, and offboarding. Use `tegwick` only for the attended positive acceptance test; automated tests use disposable identities. Done when both user journeys work on railiance01 and all negative cases leave no orphaned privileged identity or duplicate application profile.