diff --git a/docs/bootstrap-recovery-ceremony.md b/docs/bootstrap-recovery-ceremony.md index 5065868..14acab6 100644 --- a/docs/bootstrap-recovery-ceremony.md +++ b/docs/bootstrap-recovery-ceremony.md @@ -1,8 +1,11 @@ # NK-WP-0049 recovery ceremony and closure packet -Status: actual off-host privacyIDEA database drill passed; full identity backup -coverage remains in preparation. This document grants no credential export, -provider access, revocation, rotation, root retrieval or production bootstrap. +Status: the actual full off-host identity bundle was independently retrieved and +recovered with the human-held age key. Daily backup/retention and hourly health +timers are active. Full native service authentication, token decryption, audit +continuity and current/legacy caller acceptance remain open for NK-WP-0049. +Approved execution is recorded in decisions40bfae40 and5edd5203; this document +records their scope and evidence. ## What has been established @@ -438,7 +441,7 @@ conversion/property/version/reader bindings. The disabled node units were replaced with exact previous-packet/content guards, timers verified disabled and inactive, and preserved rollback bytes; source release `758ba4d170ba5ed4b6c563d3a379e496c5f81e8bff28c45d142a6bacbfaa21bf` -is installed.56 focused checks passed, including native synthetic full-archive +is installed. 56 focused checks passed, including native synthetic full-archive PostgreSQL recovery. The task-only disabled-upgrade source and packet are in the live evidence folder; this is not permission for an unchecked active-job upgrade. @@ -457,3 +460,39 @@ artifact. No age private key was used in capture/upload. The first independent owner retrieval and human hidden-key archive proof follow; both timers remain disabled until the actual proof is reviewed. Full directory/issuer/MFA/token and audit-continuity acceptance remains distinct from archive recovery. + + +## Actual independent full recovery and activation — 2026-10-16 + +The attended Backup-account download succeeded and its owner session self-revoked. +The independently fetched 109738344-byte ciphertext was rehashed locally against +the exact published digest. The operator then ran the hidden-key ceremony through +`railiance-bootstrap/bin/railiance identity-recovery`. The original independent +backup key matched the declared recipient; an unrelated key was refused; all 36 +manifest files/hashes, original key pairs and SQLite integrity checked; the native +networkless disposable PostgreSQL 16.14 restore read back 5 tokens/2 resolvers/2 realms. +The checker source SHA256 and exact artifact/digest were reviewed, plaintext and +container cleanup passed, and no NK49 Docker containers remain. The agent +received no age private key or restored secret values. + +Safe evidence: `independent-owner-transfer.json`, `actual-full-archive-recovery.json` +and `actual-full-recovery-review.json` in the October16 live evidence directory. +This proves actual archive/file/native-database recovery, with full-service +authentication/token decryption/audit-continuity fields explicitly false. + +The accepted receipt was copied as root-private state and bound to the exact +successful node off-site receipt. The approved installer activation succeeded; +both timers are enabled and active. Next backup:2026-10-17T03:47:39Z (05:47CEST, +including the configured jitter). Next hourly health run:2026-10-16T08:00:00Z +(10:00CEST). The actual health unit completed with Result=success/ExecMainStatus=0. +A live retention preview listed the recovered artifact as protected, selected no +expiry candidates and deleted nothing; unknown objects remain untouched. No +capture/retention failure marker or pending event outbox remains. Runtime cadence +is daily 03:45 UTC plus up to 5 minutes jitter, hourly health and 25-hour freshness; +the recorded next times are observations, not permanent calendar values. + +`activation-result.json` and `activation-review.json` record the actual state. +The verified first generation stays pinned until a separately reviewed owner +change. Both archive creation/retrieval/recovery and the backup job setup are now +complete. NK49 remains active because broader native service/caller and legacy +custody acceptance are separate open closure criteria. diff --git a/docs/evidence/2026-10-16-identity-backup-live/activation-result.json b/docs/evidence/2026-10-16-identity-backup-live/activation-result.json new file mode 100644 index 0000000..31cd4af --- /dev/null +++ b/docs/evidence/2026-10-16-identity-backup-live/activation-result.json @@ -0,0 +1,3 @@ +{ + "status": "timers_active_after_independent_recovery" +} diff --git a/docs/evidence/2026-10-16-identity-backup-live/activation-review.json b/docs/evidence/2026-10-16-identity-backup-live/activation-review.json new file mode 100644 index 0000000..1c34b33 --- /dev/null +++ b/docs/evidence/2026-10-16-identity-backup-live/activation-review.json @@ -0,0 +1,32 @@ +{ + "schema": "netkingdom.identity-activation-review.v1", + "timers": [ + { + "NextElapseUSecRealtime": "Sat 2026-10-17 03:47:39 UTC", + "ActiveState": "active", + "UnitFileState": "enabled", + "name": "net-kingdom-identity-backup.timer" + }, + { + "NextElapseUSecRealtime": "Fri 2026-10-16 08:00:00 UTC", + "ActiveState": "active", + "UnitFileState": "enabled", + "name": "net-kingdom-identity-backup-health.timer" + } + ], + "retention_preview": { + "status": "retention_preview", + "started_at": "2026-10-16T07:35:53.483785+00:00", + "protected": "net-kingdom-identity-20261016T063159Z-5882771aa2ce.tar.age", + "keep": [ + "net-kingdom-identity-20261016T063159Z-5882771aa2ce.tar.age" + ], + "candidates": [], + "deleted": [], + "unknown_objects_untouched": true + }, + "accepted_recovery_artifact": "net-kingdom-identity-20261016T063159Z-5882771aa2ce.tar.age", + "capture_marker_present": false, + "retention_blocked": false, + "pending_event_outbox": 0 +} diff --git a/docs/evidence/2026-10-16-identity-backup-live/actual-full-archive-recovery.json b/docs/evidence/2026-10-16-identity-backup-live/actual-full-archive-recovery.json new file mode 100644 index 0000000..fa1145d --- /dev/null +++ b/docs/evidence/2026-10-16-identity-backup-live/actual-full-archive-recovery.json @@ -0,0 +1,39 @@ +{ + "schema": "netkingdom.identity-recovery.v1", + "status": "identity_archive_verified", + "started_at": "2026-10-16T07:33:14.591607+00:00", + "production_contacted": false, + "secret_values_exported": false, + "container_cleanup_verified": true, + "temporary_plaintext_cleanup_verified": true, + "source_sha256": "039864d0141b552887752bf17cfdcf1bef4bdc9126f946a9c0533e4fd54ebf4f", + "ciphertext_sha256": "7117b3fe1e4840c86b301c94c85e6b16709e5626bb0884bd0580bde630e30e30", + "artifact": "net-kingdom-identity-20261016T063159Z-5882771aa2ce.tar.age", + "registered_recipient_match": true, + "wrong_key_refused": true, + "checks": { + "sqlite_integrity_passed": true, + "privacyidea_key_format_and_pair_passed": true, + "keycape_signing_key_format_passed": true, + "policy_json_present": true, + "database_custom_format_present": true, + "native_identity_recovery_proven": false + }, + "manifest_file_count": 36, + "all_manifest_hashes_verified": true, + "profile_sha256": "40f9e5b5bb957e5b23e03b31701702b850502d16a92a0fa0ebf92618cc3f18a1", + "database_restore": { + "image": "postgres@sha256:ff23cdce56cac62ada6f66013e1a50864c0abbe79d132d40b6e05bd80f378a70", + "image_id": "sha256:ff23cdce56cac62ada6f66013e1a50864c0abbe79d132d40b6e05bd80f378a70", + "pg_restore_version": "pg_restore (PostgreSQL) 16.14 (Debian 16.14-1.pgdg13+1)", + "aggregate_row_counts": { + "token": 5, + "resolver": 2, + "realm": 2 + } + }, + "full_service_authentication_proven": false, + "existing_token_decryption_proven": false, + "audit_signature_continuity_proven": false, + "finished_at": "2026-10-16T07:33:37.778319+00:00" +} diff --git a/docs/evidence/2026-10-16-identity-backup-live/actual-full-recovery-review.json b/docs/evidence/2026-10-16-identity-backup-live/actual-full-recovery-review.json new file mode 100644 index 0000000..9960a11 --- /dev/null +++ b/docs/evidence/2026-10-16-identity-backup-live/actual-full-recovery-review.json @@ -0,0 +1,18 @@ +{ + "status": "actual_independent_archive_recovery_verified", + "artifact": "net-kingdom-identity-20261016T063159Z-5882771aa2ce.tar.age", + "ciphertext_sha256": "7117b3fe1e4840c86b301c94c85e6b16709e5626bb0884bd0580bde630e30e30", + "source_sha256_matches": true, + "independent_ciphertext_rehashed": true, + "manifest_file_count": 36, + "no_remaining_nk49_containers": true, + "wrong_key_refused": true, + "all_manifest_hashes_verified": true, + "original_key_pairs_and_sqlite_integrity_verified": true, + "native_pg_restore_verified": true, + "plaintext_and_container_cleanup_verified": true, + "full_service_authentication_proven": false, + "existing_token_decryption_proven": false, + "audit_signature_continuity_proven": false, + "activation_under_previously_approved_packet": true +} diff --git a/docs/evidence/2026-10-16-identity-backup-live/independent-owner-transfer.json b/docs/evidence/2026-10-16-identity-backup-live/independent-owner-transfer.json new file mode 100644 index 0000000..c5e1d54 --- /dev/null +++ b/docs/evidence/2026-10-16-identity-backup-live/independent-owner-transfer.json @@ -0,0 +1,25 @@ +{ + "status": "readback_verified", + "source_sha256": "ec123d47a07305253570dacab7e103f8c193a23f20c9fc87466ea4a95ae0ec13", + "schema": "netkingdom.identity-offsite.v1", + "observed_at": "2026-10-16T06:32:39.402297+00:00", + "provider": "Storage Share", + "folder": "Backup/railiance-backups/net-kingdom-identity", + "artifact": "net-kingdom-identity-20261016T063159Z-5882771aa2ce.tar.age", + "ciphertext_sha256": "7117b3fe1e4840c86b301c94c85e6b16709e5626bb0884bd0580bde630e30e30", + "ciphertext_bytes": 109738344, + "fetched_path": "/tmp/nk49-identity-fetched-z9rd3c4w/net-kingdom-identity-20261016T063159Z-5882771aa2ce.tar.age", + "etag": "\"28ec1f7014e492de4c40e1ae75502f08\"", + "quota_available_before": 3643309771, + "new_object_created": true, + "downloaded_digest_verified": true, + "verified_index_published": true, + "index_name": "net-kingdom-identity-20261016T063159Z-5882771aa2ce.tar.age.receipt.json", + "age_private_key_used": false, + "secret_values_exported": false, + "retained_objects_deleted": false, + "native_identity_recovery_proven": false, + "independent_owner_retrieval_verified": true, + "caller_entity_id": "4a1f663c-0621-0483-edd0-f852274f4b6b", + "downloaded_at": "2026-10-16T07:32:28.276274+00:00" +} diff --git a/docs/evidence/2026-10-16-identity-backup-live/rollout-review.json b/docs/evidence/2026-10-16-identity-backup-live/rollout-review.json index d6ee8ea..76e9935 100644 --- a/docs/evidence/2026-10-16-identity-backup-live/rollout-review.json +++ b/docs/evidence/2026-10-16-identity-backup-live/rollout-review.json @@ -1,5 +1,5 @@ { - "status": "actual_full_bundle_readback_verified_independent_recovery_pending", + "status": "actual_independent_archive_recovery_verified_timers_active", "observed_at": "2026-10-15T23:56:00.293983+00:00", "approval_decision": "40bfae40-6108-4e51-8613-073339f5345f", "approved_platform_source_commit": "69a792c", @@ -29,7 +29,7 @@ "Bind actual runtime host hostname and machine identity rather than SSH alias", "Keep unapproved-CCR negative tests proposed independently of actual owner approval status" ], - "identity_timers_enabled": false, + "identity_timers_enabled": true, "scope_change_owner_decision": "5edd5203-fae7-461b-8775-5d22b7873971", "approved_provider_masks": { "publisher": 21, @@ -51,5 +51,11 @@ "actual_provider_boundary_and_native_delivery_verified": true, "actual_ciphertext_bytes": 109738344, "actual_ciphertext_sha256": "7117b3fe1e4840c86b301c94c85e6b16709e5626bb0884bd0580bde630e30e30", - "actual_independent_key_recovery_pending": true + "actual_independent_key_recovery_pending": false, + "actual_independent_key_recovery_verified": true, + "retention_recovered_point_protection_verified": true, + "retention_deletions": 0, + "health_service_result": "success", + "health_service_exit": 0, + "native_full_service_authentication_proven": false } diff --git a/registry/capabilities/capability.security.bootstrap-recovery.md b/registry/capabilities/capability.security.bootstrap-recovery.md index aab94ee..da03ee2 100644 --- a/registry/capabilities/capability.security.bootstrap-recovery.md +++ b/registry/capabilities/capability.security.bootstrap-recovery.md @@ -89,6 +89,8 @@ evidence: - tools/custody-record/README.md - docs/bootstrap-recovery-ceremony.md - workplans/NK-WP-0049-bootstrap-secret-free-recovery-handoff.md + - docs/evidence/2026-10-16-identity-backup-live/actual-full-recovery-review.json + - docs/evidence/2026-10-16-identity-backup-live/activation-review.json tests: - tests/test_identity_bundle.py - tests/test_identity_offsite.py @@ -110,8 +112,10 @@ consumer_guidance: or autonomous bare-VM restore is established. - Actual first full identity bundle captured, sealed and Storage Share readback verified on2026-10-16; both scoped readers passed native identity/namespace/audience/ESO - checks. Independent human-key full archive proof and complete service authentication - remain pending.56 focused implementation checks pass. + checks. Independent human-key full archive recovery passed and daily backup/hourly + health are active. Complete service authentication/token decryption/audit continuity + and an unattended full-estate rebuild remain unproven. 56 focused implementation + checks pass. --- # Guarded bootstrap and recovery preparation diff --git a/workplans/NK-WP-0049-bootstrap-secret-free-recovery-handoff.md b/workplans/NK-WP-0049-bootstrap-secret-free-recovery-handoff.md index 2bbb69e..f0a54ba 100644 --- a/workplans/NK-WP-0049-bootstrap-secret-free-recovery-handoff.md +++ b/workplans/NK-WP-0049-bootstrap-secret-free-recovery-handoff.md @@ -575,6 +575,26 @@ Independent owner retrieval/human-key recovery is next; both timers remain disabled. Full native service/token/audit/caller and legacy credential acceptance remain open; T02 progress/T03 wait. +2026-10-16 full archive proof and backup activation complete: independently +retrieved the exact 109738344-byte ciphertext through attended Backup custody and +rehashed it. The operator ran the hidden-key command via railiance-bootstrap's +identity-recovery handoff. Reviewed the actual receipt against exact checker +source/artifact: recipient match, wrong-key denial, all 36 manifest files/hashes, +original key pairs, SQLite integrity and native disposable PostgreSQL restore +passed (5 tokens/2 resolvers/2 realms). Plaintext/container cleanup verified; no NK49 +Docker containers remain. The agent received no age key or restored values. + +Activated only after this actual proof, under the already approved packet and +root-private artifact-bound accepted receipt. Daily backup/retention and hourly +health timers are enabled/active; actual health service succeeded. Next observed +backup 03:47:39 UTC Oct17; health 08:00 UTC Oct16. Live retention preview protects the +recovered generation, candidates/deletions empty; no failure marker/outbox. +Backup coverage setup is complete, but whole NK49 is not: full native directory/ +issuer/MFA, retained token decryption, audit continuity, current callers and T02 +legacy credential dispositions remain open. T02 progress/T03 wait retained. +Evidence: actual archive recovery/review, independent transfer and activation +receipts in `docs/evidence/2026-10-16-identity-backup-live/`. + ## Verify owner-approved recovery and current native callers ```task @@ -582,7 +602,7 @@ id: NK-WP-0049-T03 status: wait priority: high depends_on: [NK-WP-0049-T02] -blocking_reason: "Both new scoped readers passed native identity and ESO delivery acceptance. The first full identity bundle was captured and Storage Share readback verified with helper/plaintext cleanup. Independent owner download and attended human-key archive recovery remain pending; both timers are disabled. Full directory/issuer/MFA/token/audit continuity plus current caller and T02 legacy credential acceptance remain open. No root fallback or deferred exposure rotation is authorized." +blocking_reason: "Actual full off-host archive recovery passed with the independently held key, complete manifest, original key pairs, SQLite integrity and disposable native PG restore; cleanup verified. Daily backup/retention and hourly health timers are active with the recovered generation pinned. Full native directory/issuer/MFA authentication, retained token decryption, audit continuity and current/T02 legacy caller acceptance remain open. No root fallback or deferred exposure rotation is authorized." state_hub_task_id: "d68cd4d3-1ba3-530e-88f9-26ebb8dd6eac" ```