These workplans exist only in the retired local hub. Their random pre-ADR-007 identifiers are refused by C-06 as stale references, so they cannot be registered. Deriving from the canonical record id takes no identity from anything: central does not hold them and the old ids die with the cache. Records central already holds were deliberately left untouched. Refs CUST-WP-0068-T06 Assistant: claude-code Assistant-Model: opus Assistant-Process: 2583210@bnt-lap001 Assistant-Session: f2bff2d5-e9b2-4338-92ca-10282a927006
218 lines
10 KiB
Markdown
218 lines
10 KiB
Markdown
---
|
|
id: NK-WP-0025
|
|
type: workplan
|
|
title: "Provide NetKingdom self-registration and application first-login provisioning"
|
|
domain: infotech
|
|
repo: net-kingdom
|
|
status: finished
|
|
owner: codex
|
|
topic_slug: netkingdom
|
|
created: "2026-08-09"
|
|
updated: "2026-08-14"
|
|
depends_on:
|
|
- NK-WP-0024
|
|
- USER-WP-0022
|
|
- KEY-WP-0008
|
|
- CSOC-WP-0003
|
|
state_hub_workstream_id: "2412a251-d6b5-5f05-8082-3eb7697c51dc"
|
|
---
|
|
|
|
# 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: "f6fba00e-1fb6-59be-9b9a-242aed991892"
|
|
```
|
|
|
|
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: done
|
|
priority: high
|
|
state_hub_task_id: "b0d7ac51-54ae-508b-b62d-8ac8dff34497"
|
|
```
|
|
|
|
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: done
|
|
priority: high
|
|
state_hub_task_id: "ed93741b-8bb7-5b37-b5c5-a06e7f826735"
|
|
```
|
|
|
|
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.
|
|
|
|
Done 2026-08-14: public registration is enabled only for client
|
|
`coulomb-social` and `tenant:coulomb`; the password handoff permits only the
|
|
HTTPS `kc.coulomb.social` origin. The user-engine `/register` page is live.
|
|
railiance-apps commit `963de9c` publishes
|
|
`NETKINGDOM_REGISTRATION_URL=https://users.92-205-62-239.nip.io/register`, and
|
|
the live coulomb.social `/auth/register/` returns a 302 to that exact URL.
|
|
Unknown-client and unknown-tenant API requests both return 400 before any mail
|
|
request. The fresh OIDC flow remains provider-owned after password setup.
|
|
|
|
## T04 - Apply optional MFA policy safely
|
|
|
|
```task
|
|
id: NK-WP-0025-T04
|
|
status: done
|
|
priority: high
|
|
state_hub_task_id: "2b9a60cc-44a2-5874-8e7e-21db96da88f0"
|
|
```
|
|
|
|
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.
|
|
|
|
2026-08-14 rollout: public registration is live with a scoped verification
|
|
token. An authenticated malformed consume request reaches email-connect and
|
|
returns 400 rather than 401, proving the caller credential without exposing
|
|
it. Repeated invalid opaque handles return the same redacted 400 response.
|
|
Client and tenant allow-list negatives also fail before mail issuance.
|
|
|
|
## T05 - Prove both cases end to end
|
|
|
|
```task
|
|
id: NK-WP-0025-T05
|
|
status: done
|
|
priority: high
|
|
state_hub_task_id: "68bf6fe7-7b68-5189-ad1c-4ba5e0d0ad6e"
|
|
```
|
|
|
|
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.
|
|
|
|
2026-08-14 live evidence: Case B reached anonymous start, disposable mailbox
|
|
verification, baseline LLDAP provisioning, allow-listed provider password
|
|
handoff, and password completion with statuses 202, 303, and 200. The identity
|
|
had `tenant:coulomb:users` and not `tenant:coulomb:admins`; it and the two
|
|
partial diagnostic identities were deprovisioned. No verification handle,
|
|
setup token, generated password, or privileged credential was printed or
|
|
persisted. The live KeyCape configuration has
|
|
`coulomb-social.mfaRequired=false`, while every other client was verified not
|
|
to have that lowering override; KeyCape rolled successfully.
|
|
|
|
T02 and T04 are complete. T05 remains in progress for the attended browser
|
|
OIDC callback/JIT check for both an existing identity and a new registrant,
|
|
repeated callback behavior, and attended AAL1/AAL2 isolation. The reserved
|
|
`tegwick` identity was not used by automation.
|
|
|
|
Done 2026-08-14: coulomb-social supplies attended Case A evidence for
|
|
`tegwick` at AAL1. A disposable Case B completed Authelia first factor,
|
|
KeyCape PKCE authorization code, the application callback, user-engine `/me`,
|
|
and JIT Member creation at `app.coulomb.social/app/`; an independent repeat
|
|
login left exactly one Member with a populated user-engine link. The run fixed
|
|
ordinary-user `me.read` self-context in user-engine commit `db8769c` (133
|
|
passed, 3 skipped), then aligned provisioning with KeyCape's stable LDAP-DN
|
|
OIDC subject in NetKingdom commit `2a2d8ba`. The deployed canonical-subject
|
|
contract was verified directly. Client-specific AAL1 and explicit AAL2
|
|
step-up remain covered by KeyCape/coulomb-social policy tests and the live
|
|
isolation evidence above. The disposable Member, Django user, and directory
|
|
identities were removed after the repeated-login proof.
|