NK-WP-0049-T19: done; founder ran the isolated existing-token MFA check on the actual backup
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s

Restored LLDAP, database and original keys in one network-free namespace; archived
resolver repointed to the restored directory in the disposable copy. By user and
realm through /validate/check: wrong key refused (error 907), wrong code refused,
the founder's TOTP PIN+code accepted. Loopback only; cleanup verified. Does not
prove the KeyCape consumer login chain or production token validity.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: sonnet
Assistant-Process: 328925@bnt-lap001
Assistant-Session: 14b795fd-c632-4c01-8d28-e7e490c7b0ed
This commit is contained in:
tegwick 2026-10-24 18:49:33 +02:00
parent 5008e34f1a
commit a9f68fc8a2
6 changed files with 116 additions and 9 deletions

View file

@ -268,7 +268,7 @@
| task | NK-WP-0049-T16 | done | — | workplans/NK-WP-0049-bootstrap-secret-free-recovery-handoff.md |
| task | NK-WP-0049-T17 | done | — | workplans/NK-WP-0049-bootstrap-secret-free-recovery-handoff.md |
| task | NK-WP-0049-T18 | wait | — | workplans/NK-WP-0049-bootstrap-secret-free-recovery-handoff.md |
| task | NK-WP-0049-T19 | wait | — | workplans/NK-WP-0049-bootstrap-secret-free-recovery-handoff.md |
| task | NK-WP-0049-T19 | done | — | workplans/NK-WP-0049-bootstrap-secret-free-recovery-handoff.md |
| task | NK-WP-0049-T20 | done | — | workplans/NK-WP-0049-bootstrap-secret-free-recovery-handoff.md |
| task | NK-WP-0049-T21 | wait | — | workplans/NK-WP-0049-bootstrap-secret-free-recovery-handoff.md |
| task | NK-WP-0049-T22 | wait | — | workplans/NK-WP-0049-bootstrap-secret-free-recovery-handoff.md |

View file

@ -0,0 +1,59 @@
{
"schema": "netkingdom.isolated-privacyidea-mfa.v1",
"status": "isolated_privacyidea_mfa_verified",
"production_contacted": false,
"secret_values_exported": false,
"existing_token_mfa_proven": true,
"user_to_token_resolver_proven": true,
"container_cleanup_verified": true,
"temporary_plaintext_cleanup_verified": true,
"source_sha256": "d55c5f93c085907be6ae19b0eba6ef360fe863ef8922aa5b6ec205f4837efa16",
"reused_source_sha256": {
"isolated-privacyidea.py": "4df7196678aac1ad594f32abf45c68dc21a9d2760d9e8a536a215a4a3c5d277f",
"isolated-lldap.py": "35bfa8411186ad936a199bd450c7e18c2ad51059301a6db9650e6bd055ab1b81",
"identity-bundle.py": "524a03c065db4307fcde83d33af39503f3de19cb6ef3a8ca72c991d4a8c08ee6",
"verify-identity.py": "039864d0141b552887752bf17cfdcf1bef4bdc9126f946a9c0533e4fd54ebf4f",
"retrieve-identity-offline.py": "3421dbb3f3280a001d33ea2deb12ab609404a0b4254cd43c21518d77d166f972"
},
"target": {
"engine_id": "74f93783-6cef-43a8-a3c4-f62586cd3bc1",
"engine_name": "bnt-lap001",
"images": [
{
"reference": "docker.io/lldap/lldap@sha256:9e605a66c02514bfcffd1b67cafb1e98d50992216bb2871d7ae44622047dd09d",
"image_id": "sha256:9e605a66c02514bfcffd1b67cafb1e98d50992216bb2871d7ae44622047dd09d"
},
{
"reference": "ghcr.io/gpappsoft/privacyidea-docker@sha256:af7841adad262f129e0c1d4f553af13f21cb2f4dc713533f316cfe43ed0b4473",
"image_id": "sha256:af7841adad262f129e0c1d4f553af13f21cb2f4dc713533f316cfe43ed0b4473"
},
{
"reference": "postgres@sha256:ff23cdce56cac62ada6f66013e1a50864c0abbe79d132d40b6e05bd80f378a70",
"image_id": "sha256:ff23cdce56cac62ada6f66013e1a50864c0abbe79d132d40b6e05bd80f378a70"
}
],
"production_contacted": false,
"network_mode": "none",
"host_ports_published": false
},
"ciphertext_sha256": "7117b3fe1e4840c86b301c94c85e6b16709e5626bb0884bd0580bde630e30e30",
"manifest_file_count": 36,
"all_manifest_hashes_verified": true,
"ldap_resolvers_rewritten_to_loopback": 1,
"container_isolation_verified_before_private_import": true,
"user_resolved_through_restored_resolver_and_directory": true,
"selected_user_sha256": "2868946f999c23cc527736fa53c6e35ca7960cf01d06b33ea792e1e164aabcc1",
"user_token_count": 1,
"user_usable_token_count": 1,
"user_usable_token_types": [
"totp"
],
"wrong_key_refused": true,
"wrong_key_refusal": "error_907",
"wrong_code_refused": true,
"wrong_code_refusal": "wrong_value",
"existing_token_native_check_accepted": true,
"only_loopback_interface_verified": true,
"external_routes_absent": true,
"finished_at": "2026-10-24T16:48:44.390108+00:00"
}

View file

@ -0,0 +1,31 @@
{
"schema": "netkingdom.actual-isolated-privacyidea-mfa-review.v1",
"status": "verified",
"accepted_at": "2026-10-24T16:48:44+00:00",
"receipt": "actual-isolated-privacyidea-mfa-recovery.json",
"source_commit": "5008e34",
"source_sha256_matches_committed_file": true,
"reused_source_sha256_match_committed_files": true,
"known_recovered_ciphertext_matches": "7117b3fe1e4840c86b301c94c85e6b16709e5626bb0884bd0580bde630e30e30",
"exact_local_target_matches": true,
"checks_passed": [
"ldap_resolver_repointed_to_restored_directory",
"user_resolved_through_restored_resolver_and_directory",
"wrong_key_refused",
"wrong_code_refused",
"existing_token_native_check_accepted"
],
"token_type_checked": "totp",
"usable_tokens_for_user": 1,
"wrong_key_refusal": "error_907",
"wrong_code_refusal": "wrong_value",
"container_and_plaintext_cleanup_verified": true,
"agent_received_private_credentials": false,
"earlier_attempt": "A first run of a serial-based design stopped at ResolverError on all checks (receipt retained in /tmp, not in Git); the acceptance gate correctly claimed no proof and the stage was rebuilt.",
"not_proven": [
"KeyCape consumer login through Authelia, LLDAP and privacyIDEA together",
"event handlers or policies that call outside the isolated namespace",
"tokens of users other than the one named",
"current production token PIN or code validity"
]
}

View file

@ -2,7 +2,7 @@
NK-WP-0049-T15. Prepared 2026-10-16. **Actual LLDAP recovery accepted at
18:37 UTC; native privacyIDEA token-material/audit recovery accepted at
19:10 UTC; native Authelia recovery accepted 2026-10-24 at 15:24 UTC. Existing-token MFA and the KeyCape consumer run remain unexecuted.**
19:10 UTC; native Authelia recovery accepted 2026-10-24 at 15:24 UTC; existing-token MFA accepted 2026-10-24 at 16:48 UTC. The KeyCape consumer run remains unexecuted.**
Accountable preparer: codex. Execution/acceptance: Railiance Platform and the
LLDAP, Authelia, KeyCape and privacyIDEA service owners.
@ -257,8 +257,9 @@ Existing-token MFA remains T19; event completeness is not claimed.
## Prepared owner step: isolated existing-token MFA (T19)
Prepared and fixture-tested 2026-10-24 under T42; not yet run on the actual
backup. Execute in your own terminal with a verified transfer receipt (the T23
Prepared and fixture-tested 2026-10-24 under T42. The actual owner run passed the
same day (16:48 UTC); evidence is in `docs/evidence/2026-10-24-nk49-t19-privacyidea-mfa/`.
T19 is done. The procedure below remains for a future drill. Execute in your own terminal with a verified transfer receipt (the T23
procedure) and your authenticator ready:
```bash
@ -330,6 +331,6 @@ the one user you name, not for every user.
- Service-owner acceptance of network/config translations and all required
grants. New grants or production effects require their own owner decisions.
Until resolved, T15 stays in progress and T18–T19 remain waiting; T16, T17, T20 and T31 are done. Production
Until resolved, T15 stays in progress and T18 remains waiting; T16, T17, T19, T20 and T31 are done. Production
cutover, full-host/OpenBao restoration and application database recovery are
separate owner procedures.

View file

@ -43,7 +43,7 @@ T42). After the age key it asks for your login name, then the PIN+code you would
`isolated-privacyidea-mfa.py` restores LLDAP, the database and the original keys into one network-free
namespace, repoints the archived LDAP resolver to the restored directory in the disposable copy only, and calls
`/validate/check` by user and realm, as KeyCape does: wrong key refused, wrong code refused, your code accepted.
It reuses `isolated-privacyidea.py` and `isolated-lldap.py` unedited. Fixture tests pass; the actual owner run is still open.
It reuses `isolated-privacyidea.py` and `isolated-lldap.py` unedited. Fixture tests and the actual owner run (2026-10-24) passed; T19 is done.
`run-isolated-privacyidea.sh TRANSFER_RECEIPT` is the token-material/audit recovery step.
It asks only for the existing backup age key. `isolated-privacyidea.py` restores

View file

@ -563,11 +563,10 @@ production password validity.
```task
id: NK-WP-0049-T19
status: wait
status: done
priority: high
assignee: codex
depends_on: [NK-WP-0049-T15, NK-WP-0049-T16, NK-WP-0049-T31, NK-WP-0049-T42]
blocking_reason: "LLDAP T16, token-material T31 and audit T20 passed; T42 stage prepared and fixture-tested 2026-10-24 and rebuilt after the first run (resolver/directory now restored; checks run by user and realm). Await the founder-attended run: run-isolated-privacyidea-mfa.sh with a verified transfer receipt, the age key, a login name and a token PIN+code."
state_hub_task_id: "6f8af1a7-2a3f-5fa8-8202-83103ebd55b2"
```
@ -590,6 +589,23 @@ wrong-code/wrong-key authentication refusal. Internal decryption or padding
success does not authenticate a user. No MFA code is needed for T20/T31; the
selected user's private factor input and exact isolated MFA adapter remain T19.
Completed 2026-10-24 at 16:48 UTC. The founder ran `run-isolated-privacyidea-mfa.sh`
privately on the independently retrieved generation (ciphertext `7117b3fe…0e30`, all 36
manifest hashes verified). Restored LLDAP, the database and the original keys ran in one
network-free namespace; the archived LDAP resolver was repointed to the restored
directory in the disposable copy only. The named user was found through the restored
resolver and directory (hashed in the receipt) and had one usable TOTP token. Through
`POST /validate/check` by user and realm: a wrong encryption key was refused (privacyIDEA
error 907), a wrong code was refused, and the founder's PIN and code were accepted with
the original key and retained token material. Only loopback existed; containers and tmpfs
staging were cleaned. No production endpoint was contacted and the agent received no
secret. Evidence: `actual-isolated-privacyidea-mfa-recovery.json` and
`actual-isolated-privacyidea-mfa-review.json` in
`docs/evidence/2026-10-24-nk49-t19-privacyidea-mfa/`. Not proven: the KeyCape consumer
login through all four services, event handlers or policies that call outside the
namespace, other users' tokens, and current production token validity. An earlier
serial-based attempt stopped at `ResolverError` and claimed no proof; see T42.
## Prove historical and new privacyIDEA audit-signature continuity
```task
@ -633,7 +649,7 @@ status: wait
priority: high
assignee: codex
depends_on: [NK-WP-0049-T15, NK-WP-0049-T16, NK-WP-0049-T19, NK-WP-0049-T32, NK-WP-0049-T33, NK-WP-0049-T40]
blocking_reason: "T33/T40 done. Issuer-side attempt verified 2026-10-23 (receipt 16d72f7c); original OpenBao restored in isolation 2026-10-24 (RPF-WP-0064, receipt 4e048dee). Await the live consumer login: RPF-WP-0064 phase B network plus the SECRETS-WP-0015-T04 consumer run, each founder-admitted, and T19 retained-factor MFA."
blocking_reason: "T33/T40 done. Issuer-side attempt verified 2026-10-23 (receipt 16d72f7c); original OpenBao restored in isolation 2026-10-24 (RPF-WP-0064, receipt 4e048dee). T19 retained-factor MFA passed 2026-10-24. Await the live consumer login: RPF-WP-0064 phase B network plus the SECRETS-WP-0015-T04 consumer run, each founder-admitted."
state_hub_task_id: "141dd773-c1fa-56c1-a852-bbe2372e5125"
```