ops: record native tenant success and prepare attended identity repair

Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a07ff8-19d0-7820-b4d0-1353833cb7fc
This commit is contained in:
tegwick 2026-09-11 21:41:26 +02:00
parent 6f9cfe3dfd
commit 6a0773bcfa
6 changed files with 369 additions and 3 deletions

View file

@ -36,4 +36,27 @@ Local validation: Flex Auth make test (including race tests), 27 policy tests an
User Engine make test: 169 tests, 3 optional integration skips, layer check passed;
regression proves authority 403 reaches the browser as redacted 403 without
creating an administrator. Source fixes: flex-auth dd8dd51, user-engine 3c85e56.
CI publication/live promotion are pending; these are not live success claims.
CI succeeded: Flex Auth smoke 159/image 160, User Engine smoke 116/image 117.
Tenant PDP Helm revision 3 now serves
sha256:05a03a8790c2210c48ea92391441c77ddf640d0cd32f5ec09838f5393171fcbd.
User Engine now serves
sha256:9369d6709269395751a8db301820dd8d04160d7126c3c8f509a70341d409fde8.
Both are ready at their prior 25m and 50m requests. Nine live checks from the
Tenant Engine consumer confirm intended allow/deny outcomes and missing-token
401. Native User Engine adapter readback returns demo-company not found, so the
failed form submission left no tenant. A fresh native operator login was opened
for the continued tenant onboarding in RAPPS-WP-0014-T02.
At 19:03:18 UTC the operator's second native tenant-form submission returned 200.
Native operator readback and the deployed User Engine adapter confirm
`tenant:trial:demo-company`, display `demo-company`, lifecycle active, version 1.
The tenant administration page confirms the chosen first administrator exists
with invited account status. No private contact address is recorded here.
Ordinary demo users, application deployment and onboarding remain RAPPS-WP-0014.
The observation helper mistakenly collected full browser storage every five
seconds; Playwright opened temporary pages for previously visited origins.
After the operator reported the repeated page activity, the helper was stopped
and changed to cookie-only persistence. The confirmed tenant submission was not
repeated. This was helper-induced UI disruption, not evidence of a tenant failure.

View file

@ -0,0 +1,68 @@
# Repair the identity provisioner's stored LLDAP credential
NK-WP-0036-T04, 2026-09-11. Prepared and tested; live apply has not run.
The native User Engine Create login request reaches identity-provisioner, whose
LLDAP admin login returns HTTP 401 before identity creation. Reloading the
existing lldap-secrets reference did not fix it. The tenant and user-domain
records are independent and remain intact. Root portal login is working.
This is a proposed attended consumer-reference reconciliation. It does not
rotate the LLDAP account, change signing keys, restore an exposed predecessor,
read a Secret payload, or rebuild KeyCape's configuration. The operator must
supply the currently working LLDAP `admin` password from existing custody through
a hidden terminal prompt. The platform-root portal password is a different input.
No value belongs in chat, shell arguments or work records. Do not fetch values
through the unresolved warden pointer lane or a Kubernetes Secret export.
The owner contract is warden route net-kingdom-lldap-bind-credential, with
railiance-platform custody and the NetKingdom attended procedure. Operator
acceptance of this narrow repair is required before its explicit apply command;
the older full-bundle incident approval is not reused. If the current working
credential is unavailable, stop at the custody-owner recovery boundary.
The helper is sso-mfa/k8s/lldap/identity-provisioner-reconcile.py. Run inspect
first; it emits only the exact Secret UID/resourceVersion and rejects controller
ownership or the wrong cluster:
```sh
python3 sso-mfa/k8s/lldap/identity-provisioner-reconcile.py inspect
python3 sso-mfa/k8s/lldap/identity-provisioner-reconcile.py check
```
`check` requires an interactive terminal and a hidden current-password prompt.
It authenticates the existing admin against the pinned in-cluster LLDAP URL and
performs a directory read. It changes no provider or consumer state.
After explicit operator acceptance, use the UID/resourceVersion from inspect:
```sh
python3 sso-mfa/k8s/lldap/identity-provisioner-reconcile.py apply --expected-uid c6a9e6be-5bb5-47e6-9faa-06b8d72afec3 --expected-resource-version 51345775
```
The helper validates the candidate against the provider before any write, server
dry-runs a JSON patch, then updates only lldap-secrets/LLDAP_LDAP_USER_PASS with
UID/resourceVersion tests. Values travel only in child stdin/process memory;
there is no temporary credential file, Secret export or full-manifest output.
It restarts only identity-provisioner, waits for readiness and verifies the
reloaded credential through the consumer. Failure after a successful field
update is reported as incomplete verification; the rejected old value is never
restored. Other login services and the LLDAP provider are not restarted.
Seven synthetic tests cover exact patch scope, stale metadata and controller
refusal, candidate rejection before writes, check-only behavior, stdin-only
value handling, redaction of child errors and the apply/reload/proof sequence.
The live metadata-only inspect succeeds. Live check/apply requires operator
input and is not claimed by those tests.
After success, retry Create login only for the existing intended user, inspect
the returned password-setup page and record the native identity linkage.
Password setup links are private, short-lived and must not enter evidence.
User Engine's display name is not necessarily its directory username: the
current provider derives a name from email unless preferred_username is sent.
Keep the requested demo login-name mapping explicit before provisioning.
Follow-up remains necessary for credential custody/publication and a functional
provisioner preflight: the current /healthz confirms process health while the
directory connection is broken. The HTTP handler also fails to catch the
upstream HTTPError. These are tracked in NK-WP-0036-T05.