Prepare independent outage recovery and Storage Share documentation
Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a13eab-1e6a-7b33-9c37-372e90ada3a2
This commit is contained in:
parent
2a3800e7f1
commit
1764f40b43
12 changed files with 1050 additions and 22 deletions
|
|
@ -7,6 +7,12 @@ 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.
|
||||
|
||||
**Outage quick start:** [Storage Share disaster recovery guide](disaster-recovery-storage-share.md).
|
||||
The independently prompted provider download and offline tools ZIP are prepared;
|
||||
actual outage-path retrieval and guide publication are separately tracked in
|
||||
T23/T26. The [isolated service restore packet](identity-service-restore-packet.md)
|
||||
contains the draft native-service sequence and remaining T15 admission inputs.
|
||||
|
||||
## What has been established
|
||||
|
||||
On 2026-10-15 the operator identified Scaleway and Storage Share as the off-host
|
||||
|
|
|
|||
136
docs/disaster-recovery-storage-share.md
Normal file
136
docs/disaster-recovery-storage-share.md
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
# NetKingdom disaster recovery — start here
|
||||
|
||||
Updated 2026-10-16. Owner: NetKingdom with Railiance Platform and the individual
|
||||
identity service owners. This guide covers the identity backup, not whole-host,
|
||||
OpenBao, Forgejo, User Engine or application recovery.
|
||||
|
||||
## If the identity services are down
|
||||
|
||||
1. Use a trusted recovery workstation. Obtain Storage Share access independently
|
||||
from your password safe/offline custody, and the independently held
|
||||
`railiance-backup` age private key. Never paste either into chat or a ticket.
|
||||
The private key must match this **public** recipient:
|
||||
`age1zvryunvjhvpkmasskauga2heeg0ztnte9ymgppvjge36ekumk50syr3tsz`.
|
||||
The provider password and encryption key are separate requirements.
|
||||
2. Open <https://nx4069.your-storageshare.de> using the independent provider
|
||||
account, not NetKingdom SSO. In the Backup account, navigate to
|
||||
`railiance-backups/net-kingdom-identity/`. Recovery documentation and a small
|
||||
versioned recovery-tools ZIP are placed beside the encrypted archives.
|
||||
Keep a copy of this guide and ZIP outside Storage Share as well.
|
||||
3. Choose an intact recovery generation. The full identity filename starts
|
||||
`net-kingdom-identity-` and ends `.tar.age`. A `privacyidea_db-*.dump.age`
|
||||
database-only backup cannot replace the matching service keys and configs.
|
||||
Each generation has a `.receipt.json` index. Preserve the original objects.
|
||||
4. Check timestamp, size and SHA256 against a separately trusted receipt. The
|
||||
index is useful metadata, not a signed independent trust anchor. For the
|
||||
first actually recovered, protected generation the trusted values are:
|
||||
|
||||
- Artifact: `net-kingdom-identity-20261016T063159Z-5882771aa2ce.tar.age`
|
||||
- Bytes: `109738344`
|
||||
- SHA256: `7117b3fe1e4840c86b301c94c85e6b16709e5626bb0884bd0580bde630e30e30`
|
||||
- Strong ETag at publication: `"28ec1f7014e492de4c40e1ae75502f08"`
|
||||
|
||||
This is a known good fallback, not a claim that it is the latest backup.
|
||||
For a newer generation, reconcile its index with the independently retained
|
||||
publisher receipt before constructing a new download input. Never edit a
|
||||
receipt just to make a failed integrity check pass. ETag changes require
|
||||
owner reconciliation even if the filename is unchanged.
|
||||
5. On Linux with Python 3, unpack the recovery-tools ZIP into a private working
|
||||
directory and enter it. Verify its `SHA256SUMS` against a trusted repository
|
||||
copy or independently held kit digest before executing code. A checksum
|
||||
stored only alongside the download detects damage, not a malicious provider.
|
||||
Alternatively use an independently available trusted net-kingdom checkout.
|
||||
|
||||
```bash
|
||||
python3 tools/bootstrap-recovery/retrieve-identity-offline.py \
|
||||
--source-receipt docs/evidence/2026-10-16-identity-backup-live/actual-offsite.json \
|
||||
--auth account --receipt /tmp/nk49-outage-transfer.json
|
||||
```
|
||||
|
||||
In your own terminal, enter the independently held **Backup** account app
|
||||
password at the hidden prompt. The fixed account name is `Backup`.
|
||||
If your independently held credential is a read-capable public share token
|
||||
for this exact identity folder, use `--auth folder-share` instead. An
|
||||
upload-only token, another account's password or a share for the backup root
|
||||
is insufficient for this command. A 401/403/404 stops; do not widen permissions
|
||||
or substitute another token silently. Download performs only HEAD/GET against
|
||||
the fixed provider, rejects redirects/proxies, and verifies ETag/size/hash.
|
||||
Failure removes its incomplete local download. Success leaves ciphertext
|
||||
in a private `/tmp/nk49-identity-fetched-*` directory named in the receipt.
|
||||
6. Verify and decrypt through the existing hidden key helper. Requirements:
|
||||
`age`, `age-keygen`, `openssl`, Python 3 and Docker; the following PostgreSQL
|
||||
image must already be present on the recovery host:
|
||||
`postgres@sha256:ff23cdce56cac62ada6f66013e1a50864c0abbe79d132d40b6e05bd80f378a70`.
|
||||
Stage and verify this image before a drill. The tools ZIP contains no images.
|
||||
Allow enough private disk and RAM for a roughly 110 MB ciphertext, a bounded
|
||||
512 MiB archive and the disposable PostgreSQL container (2 GiB memory limit).
|
||||
|
||||
```bash
|
||||
bash sso-mfa/bootstrap/sops-custody-unlock.sh \
|
||||
--expected-recipient age1zvryunvjhvpkmasskauga2heeg0ztnte9ymgppvjge36ekumk50syr3tsz \
|
||||
--prompt -- \
|
||||
python3 tools/bootstrap-recovery/verify-identity.py \
|
||||
--transfer-receipt /tmp/nk49-outage-transfer.json \
|
||||
--receipt /tmp/nk49-outage-archive-recovery.json
|
||||
```
|
||||
|
||||
Use new receipt names on every run. The helper removes its temporary private
|
||||
key on exit. The verifier checks the encrypted manifest and all file hashes,
|
||||
original key pairs, SQLite integrity, wrong-key refusal and an isolated
|
||||
PostgreSQL restore. It removes decrypted staging and the disposable database.
|
||||
It deliberately does not install restored secrets or alter production.
|
||||
7. Preserve the sanitized receipts and original ciphertext. Remove your local
|
||||
downloaded ciphertext directory when no longer needed. If the verifier fails,
|
||||
stop and check the bounded receipt with the service owner; do not regenerate
|
||||
encryption/signing keys, reset user passwords or delete the provider backup.
|
||||
|
||||
## What the backup contains
|
||||
|
||||
| Component | Recovery material |
|
||||
| --- | --- |
|
||||
| LLDAP | Native SQLite snapshot, remaining durable data, deployment and referenced secrets |
|
||||
| Authelia | Native SQLite snapshot, encryption/session/OIDC material, current configuration and referenced secrets |
|
||||
| KeyCape | Original signing/configuration material, client configuration, authentication policies and receipts |
|
||||
| privacyIDEA | Fresh PostgreSQL dump, original encryption key, matching original audit RSA key pair, current configuration and required durable files |
|
||||
|
||||
The encrypted manifest records exact files and capture intervals. This is not
|
||||
a global atomic snapshot of all services. Historical backups and selected
|
||||
notification/log files are excluded as documented by the capture profile.
|
||||
The backup contains sensitive service credentials; only ciphertext belongs on
|
||||
ordinary persistent recovery media. The age private key is never in the bundle.
|
||||
|
||||
## Restoring working services
|
||||
|
||||
**Archive recovery passed on 2026-10-16. Full restored-service acceptance remains
|
||||
open.** The archive verifier deletes its plaintext and is not a service importer.
|
||||
Follow `docs/identity-service-restore-packet.md` with service owners before an
|
||||
isolated service drill. Its pending target and image fields must be resolved.
|
||||
|
||||
Restore the exact matching data/config/original keys into an isolated recovery
|
||||
environment first. Keep production ingress, public DNS, notifications, external
|
||||
provider writes and real consumer traffic disconnected. Establish directory and
|
||||
database readiness; prove LLDAP existing-user authentication; then privacyIDEA
|
||||
retained-token MFA/audit continuity, Authelia storage/OIDC, and KeyCape/current
|
||||
consumer continuity according to their actual dependencies. Existing user/MFA
|
||||
inputs stay in operator custody. Public issuer identity must be preserved while
|
||||
test traffic is routed privately; do not change production DNS for a drill.
|
||||
|
||||
Only after owner acceptance of native positive/negative tests should the owners
|
||||
approve a production cutover, including target identity, rollback, DNS/ingress,
|
||||
current consumers, credential dispositions and monitoring. This guide does not
|
||||
authorize a production restore or automatic credential rotation.
|
||||
|
||||
## Schedule, protection and limits
|
||||
|
||||
Daily capture is scheduled at 03:45 UTC with up to five minutes jitter. Hourly
|
||||
host-local checks flag a backup older than 25 hours. Retention protects the
|
||||
independently recovered pinned generation, newest generation, seven distinct
|
||||
daily and two weekly points; unknown/unindexed objects are not auto-deleted.
|
||||
|
||||
At this revision the full identity backup has one provider copy on Storage Share.
|
||||
Existing Scaleway database backups do not establish a second full identity copy.
|
||||
Host-local health cannot report a dead host. Full service login/MFA/audit proofs,
|
||||
an independently executed outage-path retrieval drill, a second provider copy
|
||||
and external host-loss monitoring must not be assumed from an upload or this
|
||||
guide. Track remaining acceptance in NK-WP-0049; current task state lives in the
|
||||
repository and may be newer than this offline guide.
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
{
|
||||
"schema": "netkingdom.identity-recovery-image-observation.v1",
|
||||
"observed_at": "2026-10-16T15:56:10.384927+00:00",
|
||||
"cluster_uid": "a553c742-0115-43d4-99a4-a5ca56fe0786",
|
||||
"read_only": true,
|
||||
"secret_values_read": false,
|
||||
"archive_generation_match_proven": false,
|
||||
"independent_image_availability_proven": false,
|
||||
"pods": [
|
||||
{
|
||||
"namespace": "sso",
|
||||
"pod": "authelia-7f57c4c4fc-mk5hb",
|
||||
"pod_uid": "7678e756-0af9-4eb9-bc25-c8b09ca490fc",
|
||||
"owners": [
|
||||
{
|
||||
"kind": "ReplicaSet",
|
||||
"name": "authelia-7f57c4c4fc",
|
||||
"uid": "de04027d-ebff-45bc-8aff-73583907b57e"
|
||||
}
|
||||
],
|
||||
"containers": [
|
||||
{
|
||||
"name": "authelia",
|
||||
"image_id": "docker.io/authelia/authelia@sha256:bd97cff4fcbf715b5ff1f9ae286afbe6033afce385302520b0368122d43a6f54",
|
||||
"ready": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"namespace": "sso",
|
||||
"pod": "keycape-5fc5dd9b7f-zv5xm",
|
||||
"pod_uid": "bf0d4674-cbe4-4e44-b105-b799eb4c124e",
|
||||
"owners": [
|
||||
{
|
||||
"kind": "ReplicaSet",
|
||||
"name": "keycape-5fc5dd9b7f",
|
||||
"uid": "8d862e2d-532c-4f1f-b510-cbe489ec579b"
|
||||
}
|
||||
],
|
||||
"containers": [
|
||||
{
|
||||
"name": "keycape",
|
||||
"image_id": "forgejo.coulomb.social/coulomb/key-cape@sha256:cdec9dd7c515f7e0a6169fc3fa560ee2cc47bf40d899755dec808c362f5ce010",
|
||||
"ready": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"namespace": "sso",
|
||||
"pod": "lldap-f6df76764-jjp97",
|
||||
"pod_uid": "b05329a6-8b9d-45d6-a573-c03c04e667be",
|
||||
"owners": [
|
||||
{
|
||||
"kind": "ReplicaSet",
|
||||
"name": "lldap-f6df76764",
|
||||
"uid": "306a97b4-a5f7-421f-971d-36a3dd5fbc47"
|
||||
}
|
||||
],
|
||||
"containers": [
|
||||
{
|
||||
"name": "lldap",
|
||||
"image_id": "docker.io/lldap/lldap@sha256:9e605a66c02514bfcffd1b67cafb1e98d50992216bb2871d7ae44622047dd09d",
|
||||
"ready": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"namespace": "mfa",
|
||||
"pod": "privacyidea-86b695c88c-9kh7g",
|
||||
"pod_uid": "2a44aa01-84e0-4778-a7c3-d0597b192259",
|
||||
"owners": [
|
||||
{
|
||||
"kind": "ReplicaSet",
|
||||
"name": "privacyidea-86b695c88c",
|
||||
"uid": "7db5316a-0b89-431e-a678-a5dad372fc9c"
|
||||
}
|
||||
],
|
||||
"containers": [
|
||||
{
|
||||
"name": "factor-recovery",
|
||||
"image_id": "ghcr.io/gpappsoft/privacyidea-docker@sha256:af7841adad262f129e0c1d4f553af13f21cb2f4dc713533f316cfe43ed0b4473",
|
||||
"ready": true
|
||||
},
|
||||
{
|
||||
"name": "privacyidea",
|
||||
"image_id": "ghcr.io/gpappsoft/privacyidea-docker@sha256:af7841adad262f129e0c1d4f553af13f21cb2f4dc713533f316cfe43ed0b4473",
|
||||
"ready": true
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"knowledge": {
|
||||
"version": "0.2.6",
|
||||
"package_digest": "8d1d6a9d4d07fec7b619618de7dfe2be2254c1790f85f4198c7fe19db9751c02",
|
||||
"source_status": "withheld; current SECURITY-COMPANION and owner route sources reviewed directly; orientation only"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
{
|
||||
"schema": "netkingdom.identity-outage-preparation.v1",
|
||||
"date": "2026-10-16",
|
||||
"status": "source_fixture_verified_owner_execution_pending",
|
||||
"tests": {
|
||||
"command": "NK49_RUN_DISPOSABLE_POSTGRES_TEST=1 python3 -m pytest -q tests/test_identity_offline_recovery.py tests/test_identity_offsite.py tests/test_identity_bundle.py tests/test_privacyidea_offhost_recovery.py",
|
||||
"passed": 65,
|
||||
"failed": 0,
|
||||
"skipped": 0
|
||||
},
|
||||
"kit_preview": {
|
||||
"schema": "netkingdom.recovery-kit.v1",
|
||||
"status": "built",
|
||||
"secret_values_exported": false,
|
||||
"new_grants_created": false,
|
||||
"files": [
|
||||
{
|
||||
"name": "net-kingdom-recovery-62b9464609b8e0fd-START-HERE.md",
|
||||
"bytes": 8381,
|
||||
"sha256": "1531675f2e7d3713a3a7fc28a5143fb24f201b19cd05d14c59ee485a0bc11e61"
|
||||
},
|
||||
{
|
||||
"name": "net-kingdom-recovery-62b9464609b8e0fd.zip",
|
||||
"bytes": 34527,
|
||||
"sha256": "62b9464609b8e0fde2c05527fc79eff742ee3f626262d847df8fb579548a9470"
|
||||
},
|
||||
{
|
||||
"name": "net-kingdom-recovery-62b9464609b8e0fd.zip.sha256",
|
||||
"bytes": 108,
|
||||
"sha256": "55e375291b27c2977049b89a5deddaed5e39c7ee9179013ce73d2ad43f2fb308"
|
||||
}
|
||||
],
|
||||
"finished_at": "2026-10-16T15:56:50.813341+00:00"
|
||||
},
|
||||
"sources": [
|
||||
{
|
||||
"path": "tools/bootstrap-recovery/retrieve-identity-offline.py",
|
||||
"sha256": "80e9f755b2304c222822b49ab563600832b9452c0c387a0523f4323e591e6270"
|
||||
},
|
||||
{
|
||||
"path": "tools/bootstrap-recovery/recovery-kit.py",
|
||||
"sha256": "55df6283898fadae316b89304bacf485dec88459b35ea2b9599c5d387c44ca8c"
|
||||
},
|
||||
{
|
||||
"path": "tools/bootstrap-recovery/run-offline-recovery.sh",
|
||||
"sha256": "0e3cfe8cc66d63b91a5c3f90912ce700c648c55b685ac11151631d22d87b40fd"
|
||||
},
|
||||
{
|
||||
"path": "docs/disaster-recovery-storage-share.md",
|
||||
"sha256": "1531675f2e7d3713a3a7fc28a5143fb24f201b19cd05d14c59ee485a0bc11e61"
|
||||
},
|
||||
{
|
||||
"path": "docs/identity-service-restore-packet.md",
|
||||
"sha256": "34f90e0ee1425083b26a763777b0150241e1cd5fb7dbdf8917f7a7a99482376d"
|
||||
},
|
||||
{
|
||||
"path": "tests/test_identity_offline_recovery.py",
|
||||
"sha256": "d88a752fd862983e3c01ebe6aea4baffa4168802d8ec616db161585a80c65f62"
|
||||
}
|
||||
],
|
||||
"actual_outage_retrieval_verified": false,
|
||||
"actual_storage_share_guide_publication_verified": false,
|
||||
"service_restore_executed": false,
|
||||
"new_grants_created": false,
|
||||
"secret_values_exported": false
|
||||
}
|
||||
97
docs/identity-service-restore-packet.md
Normal file
97
docs/identity-service-restore-packet.md
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
# Isolated identity service restore packet
|
||||
|
||||
NK-WP-0049-T15. Prepared 2026-10-16; **draft, not admitted or executed**.
|
||||
Accountable preparer: codex. Execution/acceptance: Railiance Platform and the
|
||||
LLDAP, Authelia, KeyCape and privacyIDEA service owners.
|
||||
|
||||
## Fixed starting point
|
||||
|
||||
Use the actual recovered artifact and receipt in
|
||||
`docs/evidence/2026-10-16-identity-backup-live/actual-offsite.json`, with matching
|
||||
original keys and manifest. The completed archive recovery verified 36 file
|
||||
hashes, SQLite integrity, RSA pairs and native PostgreSQL restore. It did not
|
||||
prove service authentication or audit-signature continuity. A newer generation
|
||||
needs equivalent provenance and archive checks before replacing this input.
|
||||
|
||||
## Targets and image admission still required
|
||||
|
||||
No execution target has been admitted. Select a disposable host/context and
|
||||
record its immutable identity, operator, private endpoints, maximum lifetime,
|
||||
resource limits and exact owned cleanup inventory. Never select the production
|
||||
context or reuse live PVCs. Use fresh private storage; no production host mounts,
|
||||
service-account tokens, ingress controller or external DNS update credentials.
|
||||
|
||||
The October 16 read-only pod observation is recorded in
|
||||
`docs/evidence/2026-10-16-identity-outage-recovery/image-observation.json`.
|
||||
These are candidate inputs, not confirmation of the images in the selected archive:
|
||||
|
||||
| Component | Candidate reference | Admission gap |
|
||||
| --- | --- | --- |
|
||||
| PostgreSQL | `postgres@sha256:ff23cdce56cac62ada6f66013e1a50864c0abbe79d132d40b6e05bd80f378a70` | Passed archive DB restore; stage independently of failed registry |
|
||||
| LLDAP | `docker.io/lldap/lldap@sha256:9e605a66c02514bfcffd1b67cafb1e98d50992216bb2871d7ae44622047dd09d` | Actual running digest resolved; compare selected archive/runtime lineage and stage it |
|
||||
| Authelia | `docker.io/authelia/authelia@sha256:bd97cff4fcbf715b5ff1f9ae286afbe6033afce385302520b0368122d43a6f54` | Compare selected archive deployment and stage image |
|
||||
| KeyCape | `forgejo.coulomb.social/coulomb/key-cape@sha256:cdec9dd7c515f7e0a6169fc3fa560ee2cc47bf40d899755dec808c362f5ce010` | Compare selected archive; require independent image availability |
|
||||
| privacyIDEA | `ghcr.io/gpappsoft/privacyidea-docker@sha256:af7841adad262f129e0c1d4f553af13f21cb2f4dc713533f316cfe43ed0b4473` | Actual main and sidecar digest observed separately; compare archive/runtime lineage and stage it |
|
||||
|
||||
Record image archive digests and offline load/inspect results. Resolve mutable
|
||||
references from trusted runtime/image metadata rather than pulling today's tag.
|
||||
The encrypted archive deployment records must be compared privately; do not
|
||||
export literal environment values, Secret payloads or arbitrary configs.
|
||||
|
||||
## Restore order and containment
|
||||
|
||||
1. Freeze the selected artifact/manifest/image/target references. The owner
|
||||
supplies existing-user credentials and an existing retained MFA token through
|
||||
private inputs. Agree time synchronization and test identities without
|
||||
exposing passwords, seed material, client secrets or user records.
|
||||
2. Establish an isolated network with default-deny external egress, no published
|
||||
ports, no host networking and no production DNS/ingress. Permit only named
|
||||
internal service links. The test browser, if needed, must use a separately
|
||||
reviewed local route and hosts mapping. Preserve issuer/client identity while
|
||||
keeping all test traffic private. Verify denied external connection attempts.
|
||||
3. Import manifest-checked data and original keys into fresh private storage.
|
||||
Do not apply archived Kubernetes objects wholesale: metadata UIDs, mounts,
|
||||
service accounts, endpoints and sidecars require explicit translation. Keep
|
||||
notification/provider credentials sealed and unused; disable sending paths.
|
||||
4. Restore the linked privacyIDEA database with native PostgreSQL first; restore
|
||||
LLDAP data/config and verify directory readiness. Run directory authentication
|
||||
before dependent provider checks. Restore privacyIDEA with its original enckey
|
||||
and audit pair against the isolated database/directory. Restore Authelia with
|
||||
original storage/OIDC keys and private directory routes. Restore KeyCape with
|
||||
original signing/config/policies and private MFA/directory dependencies.
|
||||
5. Run the individual acceptance checks below; do not start provisioning,
|
||||
enrollment, rotation, scheduled jobs or production consumers automatically.
|
||||
An unsupported dependency is a named gap, never an implicit production route.
|
||||
6. Remove only the named disposable containers/network/storage and temporary
|
||||
plaintext/key files. Confirm absence and production resources unchanged;
|
||||
retain sanitized receipts, original ciphertext and independently held keys.
|
||||
|
||||
## Acceptance matrix
|
||||
|
||||
| Task / owner lane | Positive check | Negative check | Safe evidence |
|
||||
| --- | --- | --- | --- |
|
||||
| T16 / LLDAP | Preserved user/group/membership identities; existing-user bind/login | Wrong password rejected | Image/target IDs, aggregate comparisons and booleans |
|
||||
| T17 / Authelia | Native storage decryption; same signing identity/client configs; isolated authentication | Wrong credentials or unregistered client refused | Public key thumbprint, test outcome, notification suppression |
|
||||
| T19 / privacyIDEA MFA | Existing retained token decrypts internally and actual existing-token MFA succeeds | Wrong enckey and invalid code refused in disposable copies | Token material never exported; bounded outcomes only |
|
||||
| T20 / privacyIDEA audit | Verify historical signatures; create and verify one isolated entry with original key | Mismatched public key/tampered disposable record rejected | Signature counts, continuity result, cleanup |
|
||||
| T18 / KeyCape | Same issuer/JWKS, registry/policy/receipt continuity; named current consumer authenticates | Wrong secret and denied scope rejected | Public fingerprints, owner-selected test IDs and outcomes |
|
||||
|
||||
Do not silently reset credentials or re-enroll tokens to pass. Historical audit
|
||||
verification failures must be reported, not hidden with replacement keys.
|
||||
|
||||
## Unresolved inputs before execution
|
||||
|
||||
- Named immutable disposable target, approved private browser route if required,
|
||||
resource limits, cleanup inventory and operator window.
|
||||
- Confirm archive/runtime lineage for the observed image digests and stage all
|
||||
images independently of production and the failed registry.
|
||||
- A retained user and MFA token available in private owner custody; exact native
|
||||
verification commands reviewed against the chosen service versions.
|
||||
- T02 current-caller ledger and T21 per-caller owner admission, including legacy
|
||||
token, diagnostic, resolver and LDAP-group boundaries.
|
||||
- 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 T16–T20 remain waiting. Production
|
||||
cutover, full-host/OpenBao restoration and application database recovery are
|
||||
separate owner procedures.
|
||||
Loading…
Add table
Add a link
Reference in a new issue