From a192c9abfcd836e8283945d68fdc70c3020c49f2 Mon Sep 17 00:00:00 2001 From: tegwick Date: Sat, 31 Oct 2026 13:40:07 +0100 Subject: [PATCH] Record native reset authority rehearsal and remaining admission scope Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a18e2d-f513-7742-b8e7-12af0b744ff3 --- WORK-RECORDS.md | 3 +- .../native-matrix.json | 265 ++++++++++++++++++ .../NK-WP-0054-service-identity-policy.md | 46 ++- 3 files changed, 312 insertions(+), 2 deletions(-) create mode 100644 docs/evidence/2026-10-31-reset-authority/native-matrix.json diff --git a/WORK-RECORDS.md b/WORK-RECORDS.md index a80a97d..2857458 100644 --- a/WORK-RECORDS.md +++ b/WORK-RECORDS.md @@ -320,7 +320,8 @@ | task | NK-WP-0054-T07 | progress | — | workplans/NK-WP-0054-service-identity-policy.md | | task | NK-WP-0054-T08 | done | — | workplans/NK-WP-0054-service-identity-policy.md | | task | NK-WP-0054-T09 | done | — | workplans/NK-WP-0054-service-identity-policy.md | -| task | NK-WP-0054-T10 | todo | — | workplans/NK-WP-0054-service-identity-policy.md | +| task | NK-WP-0054-T10 | progress | — | workplans/NK-WP-0054-service-identity-policy.md | +| task | NK-WP-0054-T11 | done | — | workplans/NK-WP-0054-service-identity-policy.md | | task | NK-WP-0055-T01 | done | — | workplans/NK-WP-0055-security-platform-production-readiness.md | | task | NK-WP-0055-T02 | wait | — | workplans/NK-WP-0055-security-platform-production-readiness.md | | task | NK-WP-0055-T03 | wait | — | workplans/NK-WP-0055-security-platform-production-readiness.md | diff --git a/docs/evidence/2026-10-31-reset-authority/native-matrix.json b/docs/evidence/2026-10-31-reset-authority/native-matrix.json new file mode 100644 index 0000000..fddbf7e --- /dev/null +++ b/docs/evidence/2026-10-31-reset-authority/native-matrix.json @@ -0,0 +1,265 @@ +{ + "schema": "coulomb.native-reset-authority-matrix.v1", + "observed_at": "2026-10-31T12:37:24.533367+00:00", + "data": "synthetic", + "status": "native_authority_matrix_verified", + "images": { + "lldap": "sha256:9e605a66c02514bfcffd1b67cafb1e98d50992216bb2871d7ae44622047dd09d", + "authelia": "sha256:bd97cff4fcbf715b5ff1f9ae286afbe6033afce385302520b0368122d43a6f54", + "client": "sha256:512819463a1902b43a615beee14be7bf97e6a05e016385082b9380692ad1a8cd" + }, + "production_access": false, + "provider_smtp_contacted": false, + "owner_runtime_or_permission_change_performed": false, + "no_ports_host_mounts_or_external_routes": true, + "backend_container_flags_verified_before_fixture_import": true, + "source_manifest_sha256": "c982e3a47d9e3aec5095a3c11fea7260fd4f5cb6db57b827b915988b432a18d0", + "target_classes": { + "alice": "ordinary user", + "bob": "other ordinary user", + "operator": "lldap_admin member", + "appoperator": "application-admins member, not lldap_admin", + "svc-other": "other service, lldap_strict_readonly" + }, + "findings": { + "scenarios": [ + { + "bind_role": "lldap_strict_readonly", + "directory_writes": { + "positive_controls": 7, + "refused_mutations": [ + "create_user", + "edit_other_user", + "delete_user", + "create_group", + "delete_group", + "self_promote_admin", + "remove_admin_membership" + ], + "directory_metadata_unchanged": true + }, + "direct_password_changes": [ + { + "target": "alice", + "password_changed": false, + "old_password_accepted": true, + "new_password_accepted": false + }, + { + "target": "bob", + "password_changed": false, + "old_password_accepted": true, + "new_password_accepted": false + }, + { + "target": "operator", + "password_changed": false, + "old_password_accepted": true, + "new_password_accepted": false + }, + { + "target": "appoperator", + "password_changed": false, + "old_password_accepted": true, + "new_password_accepted": false + }, + { + "target": "svc-other", + "password_changed": false, + "old_password_accepted": true, + "new_password_accepted": false + } + ], + "authelia_resets": [ + { + "target": "alice", + "status": "reset_refused", + "only_loopback_interface": true, + "external_routes_absent": true, + "old_password_initially_accepted": true, + "new_password_initially_refused": true, + "native_first_factor": true, + "interactive_service_login_refused": true, + "reset_http_status": 200, + "reset_response_status": "KO", + "native_identity_finish": true, + "reset_without_verified_challenge_refused": true, + "consumed_identity_token_replay_refused": true, + "old_password_accepted_after": true, + "new_password_accepted_after": false + }, + { + "target": "bob", + "status": "reset_refused", + "only_loopback_interface": true, + "external_routes_absent": true, + "old_password_initially_accepted": true, + "new_password_initially_refused": true, + "native_first_factor": true, + "interactive_service_login_refused": true, + "reset_http_status": 200, + "reset_response_status": "KO", + "native_identity_finish": true, + "reset_without_verified_challenge_refused": true, + "consumed_identity_token_replay_refused": true, + "old_password_accepted_after": true, + "new_password_accepted_after": false + }, + { + "target": "operator", + "status": "reset_refused", + "only_loopback_interface": true, + "external_routes_absent": true, + "old_password_initially_accepted": true, + "new_password_initially_refused": true, + "native_first_factor": true, + "interactive_service_login_refused": true, + "reset_http_status": 200, + "reset_response_status": "KO", + "native_identity_finish": true, + "reset_without_verified_challenge_refused": true, + "consumed_identity_token_replay_refused": true, + "old_password_accepted_after": true, + "new_password_accepted_after": false + }, + { + "target": "appoperator", + "status": "reset_refused", + "only_loopback_interface": true, + "external_routes_absent": true, + "old_password_initially_accepted": true, + "new_password_initially_refused": true, + "native_first_factor": true, + "interactive_service_login_refused": true, + "reset_http_status": 200, + "reset_response_status": "KO", + "native_identity_finish": true, + "reset_without_verified_challenge_refused": true, + "consumed_identity_token_replay_refused": true, + "old_password_accepted_after": true, + "new_password_accepted_after": false + } + ] + }, + { + "bind_role": "lldap_password_manager", + "directory_writes": { + "positive_controls": 7, + "refused_mutations": [ + "create_user", + "edit_other_user", + "delete_user", + "create_group", + "delete_group", + "self_promote_admin", + "remove_admin_membership" + ], + "directory_metadata_unchanged": true + }, + "direct_password_changes": [ + { + "target": "alice", + "password_changed": true, + "old_password_accepted": false, + "new_password_accepted": true + }, + { + "target": "bob", + "password_changed": true, + "old_password_accepted": false, + "new_password_accepted": true + }, + { + "target": "operator", + "password_changed": false, + "old_password_accepted": true, + "new_password_accepted": false + }, + { + "target": "appoperator", + "password_changed": true, + "old_password_accepted": false, + "new_password_accepted": true + }, + { + "target": "svc-other", + "password_changed": true, + "old_password_accepted": false, + "new_password_accepted": true + } + ], + "authelia_resets": [ + { + "target": "alice", + "status": "reset_completed", + "only_loopback_interface": true, + "external_routes_absent": true, + "old_password_initially_accepted": true, + "new_password_initially_refused": true, + "native_first_factor": true, + "interactive_service_login_refused": true, + "reset_http_status": 200, + "reset_response_status": null, + "native_identity_finish": true, + "reset_without_verified_challenge_refused": true, + "consumed_identity_token_replay_refused": true, + "old_password_accepted_after": false, + "new_password_accepted_after": true + }, + { + "target": "bob", + "status": "reset_completed", + "only_loopback_interface": true, + "external_routes_absent": true, + "old_password_initially_accepted": true, + "new_password_initially_refused": true, + "native_first_factor": true, + "interactive_service_login_refused": true, + "reset_http_status": 200, + "reset_response_status": null, + "native_identity_finish": true, + "reset_without_verified_challenge_refused": true, + "consumed_identity_token_replay_refused": true, + "old_password_accepted_after": false, + "new_password_accepted_after": true + }, + { + "target": "operator", + "status": "reset_refused", + "only_loopback_interface": true, + "external_routes_absent": true, + "old_password_initially_accepted": true, + "new_password_initially_refused": true, + "native_first_factor": true, + "interactive_service_login_refused": true, + "reset_http_status": 200, + "reset_response_status": "KO", + "native_identity_finish": true, + "reset_without_verified_challenge_refused": true, + "consumed_identity_token_replay_refused": true, + "old_password_accepted_after": true, + "new_password_accepted_after": false + }, + { + "target": "appoperator", + "status": "reset_completed", + "only_loopback_interface": true, + "external_routes_absent": true, + "old_password_initially_accepted": true, + "new_password_initially_refused": true, + "native_first_factor": true, + "interactive_service_login_refused": true, + "reset_http_status": 200, + "reset_response_status": null, + "native_identity_finish": true, + "reset_without_verified_challenge_refused": true, + "consumed_identity_token_replay_refused": true, + "old_password_accepted_after": false, + "new_password_accepted_after": true + } + ] + } + ], + "cleanup_verified": true + } +} diff --git a/workplans/NK-WP-0054-service-identity-policy.md b/workplans/NK-WP-0054-service-identity-policy.md index 191f8fa..99d0c4a 100644 --- a/workplans/NK-WP-0054-service-identity-policy.md +++ b/workplans/NK-WP-0054-service-identity-policy.md @@ -457,7 +457,7 @@ T05 remains done for its original scope. T10 owns the newly explicit reset retur ```task id: NK-WP-0054-T10 -status: todo +status: progress priority: high assignee: codex depends_on: [NK-WP-0054-T09] @@ -485,3 +485,47 @@ checks refuse, MFA/TLS/directory boundaries are preserved, and the current archi configuration restores the same supported behavior. Retain secret-free evidence and explicit productive verdict; hand the result to CSOC-WP-0015-T06. Existing personal reset acceptance remains historical evidence, not a post-split return. + + +2026-10-31 T10 preparation checkpoint: the matrix in T11 establishes the proposed +role's actual scope on the pinned binaries. Password-manager refuses LLDAP admins +but can change non-LDAP-admin service and application-admin passwords. Therefore +no one-line role promotion is an execution-ready remedy. Next: value-free current +membership/subject classification, owner review of the service write grant and +an explicit supported directory-admin recovery path, then the guarded packet. +No existing identity grant, declaration, helper or runtime was changed. + +## Rehearse native password-reset authority and unrelated write limits + +```task +id: NK-WP-0054-T11 +status: done +priority: high +assignee: codex +depends_on: [NK-WP-0054-T09] +``` + +Completed 2026-10-31. Ten direct password-change cases and eight native Authelia +reset flows cover strict-readonly/password-manager against ordinary users, an +LLDAP admin, an application-admin outside that group, and another service account +(the service case uses the direct directory API). Password-manager changes all +non-LLDAP-admin targets; the LLDAP admin refuses. Strict-readonly refuses all. +Actual old/new authentication verifies each result; first factor, unverified +reset and consumed-link refusal remain checked. No production account is mapped +to a synthetic class by this result. + +Both roles refuse seven unrelated writes with seven successful admin controls: +user create/delete/other-profile edit, group create/delete, self-promotion and +removal of another admin's membership. User/group metadata remains unchanged. +Authelia excludes interactive service login; direct LLDAP access and password +API scope remain distinct. This is a bounded operation matrix, not an exhaustive +rights audit or productive acceptance. All containers use disposable loopback +confinement with no host mounts, ports, external routes or provider SMTP. + +Evidence: docs/evidence/2026-10-31-reset-authority/native-matrix.json, produced by +coulomb-social/scripts/rehearse-reset-authority.py with source manifest retained in +that repository's docs/release/reset-authority-matrix-2026-10-31.sources.txt. +Consumer validation binds the full gate (546 passed, no failures/errors/skips), +both original native reset cases and three CLI refusal checks. T10 retains current +membership observation, complete grant/recovery design, admission, supervised +execution and native backup/restore acceptance; none is closed by this rehearsal.