coulomb-social/docs/release/native-password-reset-review-2026-10-30.md
tegwick d5adc4b998
Some checks failed
Use-case regression gate / usecase-regressions (push) Failing after 6m14s
Review reset authority transition and same-process role refresh
Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a18e2d-f513-7742-b8e7-12af0b744ff3
2026-10-31 14:26:17 +01:00

20 KiB

Native password-reset bind prerequisite

WP-0015-T06 owns the remaining native authority return. An isolated native Authelia/LLDAP test identifies a directory permission prerequisite before the full UC-009 browser journey can be accepted. It does not change the existing personal reset acceptance, prove the currently installed bind's privileges or authorize any live permission change.

The inspected NetKingdom source assigns svc-authelia to lldap_strict_readonly in sso-mfa/k8s/lldap/bind-split.py. The Authelia ConfigMap binds as that account. The owner rehearsal checks first-factor login, which succeeds under this role. Password reset needs a separate write operation; first-factor success cannot establish recovery readiness.

scripts/rehearse-native-password-reset.py now runs the actual pinned Authelia 4.39.28 and LLDAP 0.6.2 binaries against a fresh synthetic directory. It tests the read-only role and then the password-manager role on a dedicated fixture account, with a fresh Authelia store for each case. No owner checkout is changed.

Check Strict read-only bind Password-manager bind
Human first-factor login Succeeds Succeeds
Native reset notification generated Yes Yes
Valid reset-link identity verification Succeeds Succeeds
Password change Refused; HTTP 200 with status: KO Succeeds; HTTP 200 with empty body
Old directory password afterward Still accepted Refused
Replacement directory password afterward Refused Accepted
Consumed reset-link replay Refused Refused
Reset without verified challenge Refused Refused
Interactive Authelia login as service bind Refused by the service-account filter Refused by the same filter
Directory group creation using the service identity Refused Refused

The test checks native response status and actual directory authentication. An HTTP 200 alone would misclassify the read-only failure. Usable handles, cookies, passwords and notification text remain private and are absent from the public receipt. The password-manager result concerns an ordinary synthetic human; it does not establish privileged-account recovery or every directory right.

Authelia's LLDAP integration documentation requires the bind to support password changes when reset is desired. The pinned native reset handler performs that update after identity verification. These native test results confirm the boundary without relying on a protocol double.

Isolation and repetition

python3 scripts/rehearse-native-password-reset.py \
  --output /tmp/fresh-native-reset-receipt.json

The command requires the three retained image digests named in its source; it never pulls. The product image supplies only the Python standard-library probe; its application entrypoint and Django are not started. The test uses the default local Unix Docker socket, a unique network-none directory container, and Authelia/probes sharing only that container's loopback namespace. Backend containers are inspected before fixture import: read-only root, nonroot UID, dropped capabilities, no new privileges, bounded CPU/memory, no published ports, no devices and exclusively private tmpfs mounts. The probe also checks that only loopback exists and no external IPv4 routes exist.

Only generated synthetic credentials are delivered through pipes into tmpfs. There is no live configuration, production data, key custody, SMTP provider, external DNS reachability, host mount, persistent volume or network bridge. Native notifications use Authelia's private filesystem notifier, not an SMTP/inbox delivery claim. The API probe emulates the local proxy's forwarded headers and secure-cookie transport; it is not browser or TLS verification. All backend/probe containers are removed and their absence checked, including on failures. Failed fixture startup leaves only a private redacted diagnostic on the workstation.

Retain the JSON receipt with its adjacent .sources.txt manifest. The JSON binds that manifest's hash; the manifest contains only canonical filename/content digests. Existing outputs refuse. Assertions must be enabled. Negative CLI checks prove that optimized assertions and either existing output refuse without overwriting evidence. Ruff and the native rehearsal pass. The full make check gate was also rerun:396 passed, zero failures/errors/skips, including required browsers.

Required owner return and remaining journey

Keep the bind's read and password-reset responsibilities explicit. NetKingdom must review a supported narrow reset authority or another supported recovery path under its existing NK-WP-0054-T05 bind-split work, including any privileged account limits. Do not silently promote the production bind to directory admin or infer that the synthetic password-manager grant is approved for production. The source-role mismatch is retained on the existing WP-0015-T04; it is not a new credential request or a duplicated provider implementation task.

After that owner return, complete isolated native browser reset/expiry/replay, local mail-sink delivery, KeyCape/client/tenant isolation and real app login. The current test proves the native reset prerequisite only. It proves no OIDC issuance, MFA ceremony, TLS/browser flow, application session or productive runtime/permission acceptance. UC-009 remains established: false.

October31 follow-through: the separate native browser gate now exercises SMTP, expiry/replay, KeyCape, user-engine HTTP and the actual app callback using an explicit synthetic password-manager bind. See native-recovery-browser-review-2026-10-31.md. That new proof does not grant production reset authority or rewrite this API-only receipt's scope.

Owner return assessed on October 31

The bind split and its post-split restore drill are now complete under NK-WP-0054-T05. Their checks cover sign-in and MFA, not password replacement. The founder receipt records svc-authelia as strict-readonly. Current read-only metadata finds that bind in the ConfigMap and both deployed images exactly match this isolated proof. No current directory membership or production reset was queried, so this is an unresolved reset-authority return rather than a live failure claim. See reset-owner-return-assessment-2026-10-31.json.

The same owner workplan now carries T09 (completed evidence assessment) and T10 (supported reset authority, reviewed execution and native/recovery acceptance). CSOC-WP-0015-T06 consumes T10. T05 remains complete for its original migration scope. Previous personal reset acceptance does not establish behavior after the bind changed; no new grant is inferred from either the old approval or the synthetic password-manager success. Preparation may proceed independently of the pending application image and backup installation.

Native authority matrix — October 31

scripts/rehearse-reset-authority.py extends the synthetic investigation without changing the application, canonical bind helper, declaration or live directory. It uses the same pinned native images and network-none loopback confinement. Run with --output naming a fresh local JSON receipt; adjacent source manifest and receipt refuse overwrite. Disabled assertions refuse before Docker access.

Synthetic target Strict-readonly Password-manager
Two ordinary users Reset refused Reset succeeds
Member of lldap_admin Reset refused Reset refused
Application-admin group member, outside lldap_admin Reset refused Reset succeeds
Other read-only service account, direct directory password API Refused Password changes

The first four user cases are tested through actual Authelia reset/link flows and direct directory password changes. Old/replacement password authentication confirms every outcome; HTTP 200 is insufficient. Unverified requests and consumed link replay refuse. Service interactive login through Authelia is excluded by the filter in every scenario. This does not prohibit direct LLDAP web login, and that filter does not constrain a compromised bind credential's directory password API.

For each role, seven valid directory mutations refuse: create/delete user, edit another user's profile, create/delete group, self-promote to directory admin, and remove another administrator's membership. Matching admin controls succeed, and complete user/group metadata remains unchanged after the denied operations. This bounds the tested operations; it does not enumerate every API right.

The LLDAP-admin restriction agrees with the pinned upstream LLDAP v0.6.2 integration guidance. The application-admin and service results matter to admission: a password-manager role is not restricted to Coulomb users or to human accounts. It must not be presented as restoring all prior reset behavior. No actual account's current classification has been inferred from these fixtures.

Owner T11 records this completed rehearsal; T10 retains the supported runtime path. Before an executable proposal, obtain owner-authorized, value-free classification of the intended reset subjects and current bind memberships. Review a service-owned password-write grant against SI-3 and its complete non-LLDAP-admin reach, and, if the accepted subject is a directory administrator, a supported recovery route for that subject. Preserve the existing human-admin separation and MFA requirements. A role change alone is not a complete proposal, and no runtime grant or policy exception is approved here.

Evidence: reset-authority-matrix-2026-10-31.json and its source manifest; reset-authority-validation-2026-10-31.json. Ten direct password cases, eight native Authelia flows, fourteen unrelated-write denials and fourteen matching admin controls pass. All disposable containers are removed. Both original native reset scenarios still pass; the full make check gate passes 546 tests with zero failures/errors/skips. These checks add neither productive acceptance nor a current membership observation. Existing expiry/browser/app proof retains its separate scope; this matrix does not retest the complete issuer/MFA journey.

Current-role observation for the accepted account

The October6 acceptance record names tegwick (history/20261006T185411Z-personal-workspace-acceptance.md). Decision 8770d4ea-8538-4f88-a9f8-8bcfb0542603 corrects the earlier inference that a new route for all directory administrators must precede this consumer's remedy. Check tegwick's current membership first. If it is an LLDAP administrator, its supported recovery path is required; otherwise retain the administrator exclusion under existing NetKingdom recovery ownership. The admitted password-write scope still requires explicit review. This preserves the accepted workflow and adds no grant.

The fixed-subject observer is prepared and tested (owner T12); actual observation is owner T13. Run these commands in your own workstation terminal:

install -d -m 700 /home/worsch/.local/state/net-kingdom/reset-authority
python3 /home/worsch/net-kingdom/sso-mfa/k8s/lldap/reset-authority-observe.py \
  --receipt /home/worsch/.local/state/net-kingdom/reset-authority/roles-20261031.json

Enter the human admin account's password at the hidden prompt. The tool already selects tegwick, svc-authelia and admin; it asks for no username, token or backup credential. Do not paste the password into chat. Return only its JSON result. The existing NetKingdom bind helper uses this human-held input for authenticated reads; the new observer reuses its bounded transport without credential discovery.

Expected status is current_reset_roles_observed. It creates a mode0600 local receipt, signs in as admin and performs three read queries. It changes no group, password, declaration or deployment, sends no reset email, and grants nothing. TLS failures and unexpected/missing users refuse; do not bypass verification. An existing receipt refuses without overwrite. A successful result proves current role metadata only, not Authelia reset success, app authorization or acceptance.

Evidence: reset-observer-preparation-2026-10-31.json. The observer and shared transport pass92 checks; four native owner cases pass and the final observer node passes with unchanged directory metadata and verified fixture cleanup. Production observation has not been performed during preparation.

Attended observation received

The founder completed the read at12:57:44Z on October31. Independent local receipt verification confirms its private custody, exact subject/endpoint and all four prepared source hashes. svc-authelia has only strict-readonly and no additional groups. tegwick has no built-in directory privilege role and one other group. Thus the directory-admin exclusion does not block the accepted personal flow on this observed state. Owner T13 is complete; T10 prepares the reviewed transition, including the full non-admin reach established by the native matrix. No grant, reset, app authorization or productive acceptance is contained in this receipt. Do not rerun the completed observer command. Evidence: reset-role-observation- 2026-10-31.json and reset-role-return-verification-2026-10-31.json.

Reviewed role-transition proposal — 2026-10-31

Prepared, not admitted or executed. Owner preparation is NK-WP-0054-T14; founder admission/execution is T15; declaration alignment and productive reset plus fresh identity restore acceptance are T16. T10 and CSOC-WP-0015-T06 remain open.

Proposal: sha256:753f50f139a0d090a8b64ba15174f2a7e8b0e639eb0dd01d17783476b5a3759f. Exact controller and plan are /home/worsch/net-kingdom/sso-mfa/k8s/lldap/reset-role-transition.py and reset-role-plan.json. The digest binds the controller, existing transport and observer sources, current role observation, native rights matrix, pinned runtime identities/configuration and final validation. No new resources or recurring capacity are requested; no credential rotation, service rename or restart is included. Both pinned workloads were Ready when observed.

Decision and scope

The proposed change replaces only svc-authelia's strict-readonly membership with lldap_password_manager. This restores the native password-write capability needed by the accepted tegwick recovery flow. The role can change passwords for all non-LLDAP-admin directory identities, including other service accounts and application administrators outside lldap_admin. It is not limited to Coulomb or to human accounts. LLDAP administrators are excluded. Seven tested unrelated writes remain refused; this is not an exhaustive rights audit. Both roles already permit own-profile/password operations in the pinned LLDAP access-control source.

The same dedicated SERVICE account and single Authelia consumer remain. The plan contains the proposed declaration: directory read USE plus narrowly described password ADMINISTER scope, without the read-only bind convention. SI-3 permits a service-owned write account with its narrowest working scope. The canonical read-only declaration has not been changed to imply approval. Following a verified grant, T16 must align it and existing bind verification/repair expectations. Do not rerun the historical read-only bind migration as reset verification.

Rollback limit: membership rollback restores fresh Authelia reset denial, but it does not revoke previously issued HTTP tokens or undo changed user passwords. A native test proves a token obtained during the grant can still change an eligible password after membership rollback; a freshly issued token cannot. The pinned LLDAP token implementation embeds groups in a token with a one-day expiry. Treat retained token authority as lasting up to 24 hours unless separately revoked. This packet includes no token revocation or incident-containment operation. Admission includes this limitation.

Execution and recovery

Run in the founder's workstation terminal only after accepting the scope above:

python3 /home/worsch/net-kingdom/sso-mfa/k8s/lldap/reset-role-transition.py \
  --execute --expect-digest sha256:753f50f139a0d090a8b64ba15174f2a7e8b0e639eb0dd01d17783476b5a3759f

The hidden prompt requires the human admin password. Never paste it into chat. After reviewing the printed scope, enter exactly:

GRANT sha256:753f50f139a0d090a8b64ba15174f2a7e8b0e639eb0dd01d17783476b5a3759f

The controller checks the exact live cluster/namespace/deployment identities, images and Authelia configuration before private authentication and again after confirmation. It rechecks the human admin role, tegwick's non-admin classification and svc-authelia's exact baseline before writing. The old role is removed before the new one is added; a brief directory lookup failure is possible. Every effect has a durable intent record. All user IDs and group memberships are compared after each step; unknown concurrent changes fail verification. Profile fields/passwords are not copied into the receipt or claimed as independently compared.

Success is password_manager_role_verified. Paste only the returned JSON; Codex will verify the durable mode0600 receipt in ~/.local/state/net-kingdom/reset-authority/753f50f139a0d090a8b64ba15174f2a7e8b0e639eb0dd01d17783476b5a3759f/journal.json. An existing attempt refuses replay. Do not delete its state or repeat the grant. If the operation is interrupted or reports uncertain status, restore read-only membership with this separate attended recovery:

python3 /home/worsch/net-kingdom/sso-mfa/k8s/lldap/reset-role-transition.py \
  --recover --expect-digest sha256:753f50f139a0d090a8b64ba15174f2a7e8b0e639eb0dd01d17783476b5a3759f

Confirm RECOVER sha256:753f50f139a0d090a8b64ba15174f2a7e8b0e639eb0dd01d17783476b5a3759f. For an already completed successful grant, use --rollback instead of --recover and confirm ROLLBACK sha256:753f50f139a0d090a8b64ba15174f2a7e8b0e639eb0dd01d17783476b5a3759f. Both restore only the role and retain previous journal versions. They preserve unrelated subsequent memberships and user password changes. Recovery tolerates workload unready status but still requires pinned identities, images and configuration; runtime drift requires review, not a bypass. If the directory itself is unreachable, recovery cannot claim completion until the owner restores access. These are role restoration commands with the token limitation above, not full credential revocation.

Evidence and remaining acceptance

25 unit checks and four native controller checks pass with no skips/failures. The native checks include real process termination immediately after removal and addition, successful recovery without replay, and the retained-token boundary. A separate confined native rehearsal uses one running Authelia process through read-only → password-manager → read-only: reset refuses, succeeds, then refuses; old/new passwords and consumed challenge denial are checked each time. No restart is needed in this tested configuration. Synthetic fixtures and generated passwords are removed; no provider SMTP or productive password reset was used.

Evidence: reset-transition-validation-2026-10-31.json, reset-role-refresh-2026-10-31.json and its source manifest. A successful role receipt still leaves T16: source alignment, productive tegwick reset/app/MFA and fresh identity backup/restore evidence. It does not complete the four goal workplans.

The final consumer make check gate passes546 tests (zero failures/skips;69 existing warnings). Receipt: reset-transition-consumer-gate-2026-10-31.json.