diff --git a/AssetRegister.yaml b/AssetRegister.yaml index 067323d..d8388d7 100644 --- a/AssetRegister.yaml +++ b/AssetRegister.yaml @@ -3,7 +3,7 @@ # Backup lanes: DISCTL-WP-0003-T01. Stack assets (T0/T4): DISCTL-WP-0002-T02. schema_version: "0.2" -updated: "2026-07-07" +updated: "2026-10-23" register_scope: backup_lanes_and_stack tier_definitions: @@ -214,6 +214,46 @@ backup_streams: - history/2026-07-04-forgejo-backup-strategy-assessment.md - specs/ResilienceControlSetup.md + - id: backup-netkingdom-identity + name: NetKingdom identity stack (LLDAP, privacyIDEA, KeyCape client registry) + tool: net-kingdom identity backup profile + tool_path: null + owner_repo: net-kingdom + operator: Bernd + tier: T0 + host: railiance01 + backup_mechanism: >- + LLDAP directory; privacyIDEA database, token material and audit; KeyCape + client registry archive; age encrypt; upload to one off-host provider. + Profile and restore tooling owned by net-kingdom; backup account and + custody owned by railiance-platform. + destination: + primary: Storage Share (single off-host provider) + offsite: Storage Share (same provider — no second off-host copy) + backup_schedule: "daily 03:45 UTC (+<=5 min jitter); hourly on-host health check, 25h freshness bound" + retention: "per net-kingdom identity backup profile" + encryption: age + recovery_method: >- + Isolated identity restore per net-kingdom/docs/identity-restore-drill.md + (NK-WP-0053). Prior one-off proofs: NK-WP-0049-T16 (LLDAP), T31 + (privacyIDEA token material), T20 (audit). + rpo: 24h + rto: TBD (to be measured by first NK-WP-0053 drill) + status: operational + gaps: + - "G1 (accepted until 2027-01-31): single off-host provider" + - "G2 (accepted until 2027-01-31): freshness detection on-host only; outside-node watchdog owed by RAPP-TELEMETRY-WP-0001-T04" + - "Quarterly isolated restore drill not yet run — first due by 2027-01-31 (NK-WP-0053); component proofs only so far" + evidence: + restore_tested: false + last_drill: null + evidence_ref: net-kingdom/docs/evidence/-identity-restore-drill/ + references: + - net-kingdom NK-WP-0049-T14 (activation evidence, 2026-10-16) + - net-kingdom/docs/identity-restore-drill.md + - net-kingdom/workplans NK-WP-0049, NK-WP-0053 + - workplans/DISCTL-WP-0004-netkingdom-identity-backup-lane.md + assets: # ── T0 Identity / trust / money ────────────────────────────────────────────── @@ -472,7 +512,10 @@ related_streams: host: railiance01 backup_schedule: daily CronJobs on railiance01 status: operational - note: "Only scheduled backup CronJobs found on cluster as of 2026-07-04 assessment" + note: >- + Only scheduled backup CronJobs found on cluster as of 2026-07-04 assessment. + Since 2026-10-23 LLDAP and privacyIDEA are governed as backup_streams + backup-netkingdom-identity (DISCTL-WP-0004); Authelia coverage unchanged here. - id: backup-apps-pg name: apps-pg shared CloudNativePG cluster diff --git a/BackupPolicy.md b/BackupPolicy.md index 80ee1e1..0761181 100644 --- a/BackupPolicy.md +++ b/BackupPolicy.md @@ -1,7 +1,7 @@ # Backup Policy **Status:** adopted (initial) -**Updated:** 2026-07-07 +**Updated:** 2026-10-23 **Owner:** Bernd **Scope:** Coulomb Social / Helix Forge — Railiance backup lanes **Register:** `AssetRegister.yaml` (stream inventory) · `DataRegister.yaml` (data classes) @@ -47,6 +47,7 @@ Target model (per `specs/ResilienceControlSetup.md` §4): | S3 platform | — | — | — | Tool missing | | Forgejo production | ✗ (prod + drill /tmp only) | partial | intended | Automation not wired | | Gitea canonical | ✗ | ✗ | ✗ | Manual pre-cutover only | +| NetKingdom identity | ✓ (prod + on-host + Storage Share) | ✓ (disk + cloud) | ✓ (single provider) | Operational since 2026-10-16 (NK-WP-0049-T14); single off-host provider accepted until 2027-01-31 (G1) | --- @@ -133,10 +134,11 @@ Canonical inventory: `AssetRegister.yaml`. Summary: | `backup-s3-platform` | `railiance-backup` | TBD | Nextcloud (intended) | **missing** | | `backup-forgejo-production` | `forgejo dump` + `pg_dump` | Daily (intended) | Nextcloud (adopted) | **not_wired** | | `backup-gitea-canonical` | `gitea dump` / mirror | Pre-cutover manual | None automated | **at_risk** | +| `backup-netkingdom-identity` | net-kingdom identity profile (LLDAP, privacyIDEA DB/token material/audit, KeyCape client registry archive) | Daily 03:45 UTC (+≤5 min jitter) | Storage Share (single off-host provider), age | operational | **Related streams** (tracked, not yet full policy coverage): -- `backup-adjacent-sso` — daily CronJobs (`privacyidea-backup`, `authelia-backup`, `lldap-backup`) on railiance01 +- `backup-adjacent-sso` — daily CronJobs (`privacyidea-backup`, `authelia-backup`, `lldap-backup`) on railiance01; LLDAP and privacyIDEA are governed as `backup-netkingdom-identity` since 2026-10-23 (DISCTL-WP-0004) - `backup-apps-pg` — CNPG `apps-pg`; no ScheduledBackup CR **Not in git backups:** Git repos are protected by push-to-Gitea remotes. Preflight @@ -221,6 +223,8 @@ that host. Mitigation: wire offsite upload for S1/S2 (tracked in pickup queue). | M-4 | Preflight gate | Before infra change | `bin/railiance preflight` exits 0 | Bernd | | M-5 | Restore drill | Quarterly per T1 stream | Dated evidence in `TestEvidence/` | Bernd | | M-6 | Register review | Monthly | `AssetRegister.yaml` statuses updated; gaps unchanged or closed | Bernd | +| M-7 | NetKingdom identity lane freshness | Hourly (on-host) | Latest identity backup < 25h old; on-host only until outside-node watchdog (RAPP-TELEMETRY-WP-0001-T04) lands (G2) | net-kingdom | +| M-8 | NetKingdom identity restore drill | Quarterly; first by 2027-01-31 | Isolated restore per `net-kingdom/docs/identity-restore-drill.md` (NK-WP-0053); evidence under `net-kingdom/docs/evidence/-identity-restore-drill/`, linked from `TestEvidence/` | net-kingdom | ### Preflight gate (mandatory before infrastructure work) @@ -269,6 +273,8 @@ RPO measured, issues, follow-up actions. | `apps-pg` no ScheduledBackup | App data unprotected | CNPG ScheduledBackup CR | `railiance-platform` | | No immutable weekly offline copy | R3 residual risk | Add offline/append-only copy (Phase 2) | TBD | | Cold decrypt not evidenced | R5 residual risk | Quarterly cold decrypt drill (M-3 extended) | `disaster-control` | +| Identity lane single off-host provider (G1) | Identity backups lost if Storage Share fails or is compromised | **Accepted until 2027-01-31** (decision e4c288d9); review in DISCTL-WP-0004-T04 | `railiance-platform` / `net-kingdom` | +| Identity lane on-host-only freshness detection (G2) | Silent backup failure if railiance01 itself is down | **Accepted until 2027-01-31**; outside-node watchdog owed by RAPP-TELEMETRY-WP-0001-T04 | `rapp-telemetry` | Track closure in `BackupPickupQueue.md` (DISCTL-WP-0003-T04). @@ -283,4 +289,5 @@ Track closure in `BackupPickupQueue.md` (DISCTL-WP-0003-T04). - `history/2026-07-04-initial-risk-analysis.md` — R3, R9 risk context - `railiance-cluster/docs/backup-restore.md` — dev lane operational procedures - `the-custodian/docs/forgejo-production-decisions.md` — Option A adoption -- `railiance-infra/docs/forgejo-restore-drill-evidence.md` — T09 restore proof \ No newline at end of file +- `railiance-infra/docs/forgejo-restore-drill-evidence.md` — T09 restore proof +- `net-kingdom/docs/identity-restore-drill.md` — quarterly isolated identity restore drill (NK-WP-0053) \ No newline at end of file diff --git a/DataRegister.yaml b/DataRegister.yaml index 52b8d21..adfa0ad 100644 --- a/DataRegister.yaml +++ b/DataRegister.yaml @@ -3,7 +3,7 @@ # Stack data classes (T0/T4): DISCTL-WP-0002-T02. Backup lanes: DISCTL-WP-0003-T01. schema_version: "0.2" -updated: "2026-07-07" +updated: "2026-10-23" register_scope: backup_lanes_and_stack data_classes: @@ -278,6 +278,59 @@ data_classes: owner: Bernd status: operational + - id: data-netkingdom-lldap-directory + name: NetKingdom LLDAP user directory + tier: T0 + source_of_truth: LLDAP on railiance01 + description: >- + Users, groups and memberships behind NetKingdom SSO — identity trust + boundary asset + backup_stream: backup-netkingdom-identity + backup: daily age-encrypted backup to Storage Share (net-kingdom identity profile) + recovery_method: >- + Isolated identity restore per net-kingdom/docs/identity-restore-drill.md; + one-off restore proven in NK-WP-0049-T16 + rpo: 24h + rto: TBD (to be measured by first NK-WP-0053 drill) + owner: Bernd + status: operational + gaps: + - "Single off-host provider (G1, accepted until 2027-01-31)" + + - id: data-netkingdom-privacyidea + name: NetKingdom privacyIDEA database, token material and audit + tier: T0 + source_of_truth: privacyIDEA on railiance01 + description: >- + MFA token enrolments and token material, privacyIDEA configuration + database and audit trail — loss forces re-enrolment of every factor + backup_stream: backup-netkingdom-identity + backup: daily age-encrypted backup to Storage Share (net-kingdom identity profile) + recovery_method: >- + Isolated identity restore per net-kingdom/docs/identity-restore-drill.md; + one-off proofs NK-WP-0049-T31 (token material) and T20 (audit) + rpo: 24h + rto: TBD (to be measured by first NK-WP-0053 drill) + owner: Bernd + status: operational + gaps: + - "Single off-host provider (G1, accepted until 2027-01-31)" + + - id: data-keycape-client-registry + name: KeyCape client registry archive + tier: T0 + source_of_truth: KeyCape on railiance01 + description: OIDC client registrations served by KeyCape — needed to restore relying-party login + backup_stream: backup-netkingdom-identity + backup: daily age-encrypted archive to Storage Share (net-kingdom identity profile) + recovery_method: Isolated identity restore per net-kingdom/docs/identity-restore-drill.md + rpo: 24h + rto: TBD (to be measured by first NK-WP-0053 drill) + owner: Bernd + status: operational + gaps: + - "Single off-host provider (G1, accepted until 2027-01-31)" + status_legend: operational: "Backup mechanism exists and has run successfully" manual_only: "Restore path exists but backup is operator-triggered only" diff --git a/RTO-RPO-Matrix.md b/RTO-RPO-Matrix.md index 77ba1fe..53c8dc5 100644 --- a/RTO-RPO-Matrix.md +++ b/RTO-RPO-Matrix.md @@ -1,6 +1,6 @@ # RTO / RPO Matrix -**Updated:** 2026-07-07 +**Updated:** 2026-10-23 **Owner:** Bernd **Scope:** Backup lanes — initial seed (DISCTL-WP-0003-T03) **Related:** `AssetRegister.yaml` · `BackupPolicy.md` · `DataRegister.yaml` @@ -34,7 +34,8 @@ Global baseline (from `specs/ResilienceControlSetup.md` §3): **RPO ≤ 24h ever | Dev workstation operator config | `backup-dev-workstation` | 24h | 4h | draft | Daily cron 02:00; preflight gate | Operational — meets target if cron healthy | | S3 platform PostgreSQL | `backup-s3-platform` | 24h | 4h | **adopted** | Decision #7 (extends platform lane) | **degraded** — tool missing | | `apps-pg` CNPG | `backup-apps-pg` | 24h | 4–8h | draft | `railiance-platform/docs/apps-pg.md` | **degraded** — no ScheduledBackup CR | -| Adjacent SSO/MFA stack | `backup-adjacent-sso` | 24h | 4–8h | draft | Daily CronJobs on railiance01 | Operational — scheduled daily | +| Adjacent SSO/MFA stack | `backup-adjacent-sso` | 24h | 4–8h | draft | Daily CronJobs on railiance01 | Operational — scheduled daily; LLDAP/privacyIDEA now under `backup-netkingdom-identity` | +| NetKingdom identity (LLDAP, privacyIDEA, KeyCape client registry) | `backup-netkingdom-identity` | 24h | TBD (first NK-WP-0053 drill) | **adopted** (RPO) | Founder decision e4c288d9 (2026-10-23); NK-WP-0049-T14 activation; component proofs NK-WP-0049-T16/T31/T20 | Operational — daily 03:45 UTC, 25h freshness bound; G1/G2 accepted until 2027-01-31 | --- @@ -45,7 +46,7 @@ Global baseline (from `specs/ResilienceControlSetup.md` §3): **RPO ≤ 24h ever | 2026-07-04 | Forgejo (isolated restore, manual dump) | Point-in-time of manual `forgejo dump` | ~3–5 min (isolated namespace) | success | `TestEvidence/restore-drill-2026-07-04-forgejo.md` | | 2026-07-07 | Forgejo (automated backup decrypt) | ~47 min (backup 18:08Z, drill 18:55Z) | 7 sec (decrypt + validate) | success | `TestEvidence/restore-drill-2026-07-07-forgejo-automated.md` | -Next drills: S2 k8s decrypt, dev workstation cold restore, Gitea dump (see `TestEvidence/README.md`). Next drills should produce +Next drills: NetKingdom identity isolated restore (NK-WP-0053, due by 2027-01-31), S2 k8s decrypt, dev workstation cold restore, Gitea dump (see `TestEvidence/README.md`). Next drills should produce dated files under `TestEvidence/` (DISCTL-WP-0003-T05). --- diff --git a/TestEvidence/README.md b/TestEvidence/README.md index a70ba4a..59b1935 100644 --- a/TestEvidence/README.md +++ b/TestEvidence/README.md @@ -55,4 +55,9 @@ Next targets: 2. **S2 k3s runtime** — decrypt `railiance-backup-s2` on railiance01 3. **Dev workstation cold restore** — password-manager key only 4. **Gitea dump** — before next migration wave -5. **Secret vault cold decrypt** — SOPS/age recovery material (R5) \ No newline at end of file +5. **Secret vault cold decrypt** — SOPS/age recovery material (R5) +6. **NetKingdom identity isolated restore** — quarterly, first due by + 2027-01-31; run by `net-kingdom` NK-WP-0053 per + `net-kingdom/docs/identity-restore-drill.md`. Canonical evidence lives under + `net-kingdom/docs/evidence/-identity-restore-drill/`; link it here as + `restore-drill--netkingdom-identity.md` (DISCTL-WP-0004-T03). \ No newline at end of file diff --git a/workplans/DISCTL-WP-0004-netkingdom-identity-backup-lane.md b/workplans/DISCTL-WP-0004-netkingdom-identity-backup-lane.md new file mode 100644 index 0000000..59abaa2 --- /dev/null +++ b/workplans/DISCTL-WP-0004-netkingdom-identity-backup-lane.md @@ -0,0 +1,91 @@ +--- +id: DISCTL-WP-0004 +type: workplan +title: "Adopt the NetKingdom identity backup lane" +domain: infotech +repo: disaster-control +status: active +owner: claude +topic_slug: custodian +created: "2026-10-23" +updated: "2026-10-23" +--- + +# Adopt the NetKingdom identity backup lane + +Bring the NetKingdom identity backup lane on railiance01 under +disaster-control governance, as requested by net-kingdom (State Hub message +`ef2bf2a9`; founder decision `e4c288d9`, resolved 2026-10-23). This repo +tracks and evidences the lane; implementation and restore tooling stay in +`net-kingdom`, backup account and custody in `railiance-platform`. + +**Lane facts (non-secret):** + +| Item | Value | +| --- | --- | +| Scope | LLDAP; privacyIDEA (database, token material, audit); KeyCape client registry archive | +| Owner | `net-kingdom` (profile, restore tooling); `railiance-platform` (backup account / custody) | +| Backup | Daily 03:45 UTC (+≤5 min jitter), age-encrypted, ONE off-host provider (Storage Share) | +| Monitoring | Hourly on-host health check; 25-hour freshness bound | +| RPO | 24h | +| Activation evidence | `net-kingdom` NK-WP-0049-T14 (2026-10-16) | +| Accepted residual risk G1 | Single off-host provider — accepted until 2027-01-31 | +| Accepted residual risk G2 | On-host-only freshness detection — accepted until 2027-01-31; linked to the outside-node watchdog owed by RAPP-TELEMETRY-WP-0001-T04 | +| Restore proof | Quarterly isolated identity restore drill, `net-kingdom` NK-WP-0053, procedure `net-kingdom/docs/identity-restore-drill.md`; first due by 2027-01-31; evidence under `net-kingdom/docs/evidence/-identity-restore-drill/` | +| Prior one-off proofs | NK-WP-0049-T16 (LLDAP), T31 (privacyIDEA token material), T20 (audit) | + +## Register the lane in AssetRegister and DataRegister + +```task +id: DISCTL-WP-0004-T01 +status: done +priority: high +``` + +Add `backup-netkingdom-identity` to `AssetRegister.yaml` → `backup_streams` +(T0) with the schedule, destination, freshness bound, accepted residual risks +G1/G2 as `gaps`, and prior one-off proofs. Point the older +`related_streams` → `backup-adjacent-sso` entry at the new stream. Add +`DataRegister.yaml` data classes for the LLDAP directory, privacyIDEA +database/token material/audit, and the KeyCape client registry archive. + +## Update BackupPolicy, RTO-RPO matrix and TestEvidence cadence + +```task +id: DISCTL-WP-0004-T02 +status: done +priority: high +``` + +Add the lane to the `BackupPolicy.md` 3-2-1 compliance table, the per-stream +mechanisms table, the monitoring checks, and the open-gaps table (G1/G2 with +their acceptance expiry). Add an RTO-RPO matrix row and list the quarterly +identity drill under `TestEvidence/README.md` next targets. + +## Import the first quarterly identity restore drill evidence + +```task +id: DISCTL-WP-0004-T03 +status: wait +priority: high +``` + +Waits on `net-kingdom` NK-WP-0053: when the first isolated identity restore +drill runs (due by 2027-01-31), add +`TestEvidence/restore-drill--netkingdom-identity.md` linking the +canonical evidence under `net-kingdom/docs/evidence/-identity-restore-drill/`, +record measured RPO/RTO in `RTO-RPO-Matrix.md`, and set the register +`evidence.last_drill`. + +## Review accepted residual risks G1/G2 at expiry + +```task +id: DISCTL-WP-0004-T04 +status: wait +priority: medium +``` + +By 2027-01-31, confirm whether a second off-host provider (G1) and the +outside-node freshness watchdog from RAPP-TELEMETRY-WP-0001-T04 (G2) have +landed. Close the gaps in the registers and `BackupPolicy.md`, or route a +founder decision to re-accept or escalate them.