ops(recovery): verify full archive recovery and activate protected backup timers
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s

Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a13eab-1e6a-7b33-9c37-372e90ada3a2
This commit is contained in:
tegwick 2026-10-16 09:38:31 +02:00
parent 17a8fa1495
commit 1de6deaf0a
9 changed files with 196 additions and 10 deletions

View file

@ -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.

View file

@ -0,0 +1,3 @@
{
"status": "timers_active_after_independent_recovery"
}

View file

@ -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
}

View file

@ -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"
}

View file

@ -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
}

View file

@ -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"
}

View file

@ -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
}

View file

@ -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

View file

@ -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"
```