diff --git a/workplans/DISCTL-WP-0003-railiance-backup-governance.md b/workplans/DISCTL-WP-0003-railiance-backup-governance.md new file mode 100644 index 0000000..977d53f --- /dev/null +++ b/workplans/DISCTL-WP-0003-railiance-backup-governance.md @@ -0,0 +1,169 @@ +--- +id: DISCTL-WP-0003 +type: workplan +title: "Railiance backup lane governance integration" +domain: infotech +repo: disaster-control +status: ready +owner: grok +topic_slug: custodian +created: "2026-07-07" +updated: "2026-07-07" +--- + +# Railiance backup lane governance integration + +Codify the **existing** `railiance-backup` tooling practices into the +Resilience Control Plane: registers, policy, RTO/RPO targets, cross-repo +pickup tracking, and the first evidence trail entry. + +This is a focused slice of `DISCTL-WP-0002` (tasks T02, T04, T06, T08). When +tasks here complete, mark the corresponding WP-0002 tasks `done` as well. + +**Inputs:** + +| Source | What it contributes | +| --- | --- | +| `history/2026-07-04-forgejo-backup-strategy-assessment.md` | Layer inventory, gaps, pickup queue items 1–6 | +| `railiance-cluster/docs/backup-restore.md` | Dev-workstation `railiance-backup` practices (age, Nextcloud, preflight, cron) | +| `railiance-cluster/tools/cmd/railiance-backup-s2` | S2 k3s runtime backup (local, age, 7-day prune) | +| `railiance-infra/tools/cmd/railiance-backup-s1` | S1 OS config backup (local, age, 7-day prune) | +| `the-custodian/docs/forgejo-production-decisions.md` | Backup decision Option A (2026-07-09): Nextcloud WebDAV, daily schedule, retention | +| `railiance-infra/docs/forgejo-restore-drill-evidence.md` | T09 restore drill evidence to import | + +**Scope boundary:** documents and tracks backup governance here; implementation +(CNPG ScheduledBackup, scheduled `forgejo dump`, platform tool restoration) stays +in `railiance-platform`, `railiance-apps`, and `railiance-infra`. + +## Seed registers with railiance-backup tool family (R2, R9) + +```task +id: DISCTL-WP-0003-T01 +status: todo +priority: high +``` + +Write initial `AssetRegister.yaml` and `DataRegister.yaml` seeded with the +backup lanes discovered in the July assessment. At minimum, record: + +| Stream | Tool | Owner repo | Tier | Backup mechanism | Destination | Schedule | Status | +| --- | --- | --- | --- | --- | --- | --- | --- | +| Dev workstation | `railiance-backup` | `railiance-cluster` | T1 | pg_dump + config tar, age | Nextcloud WebDAV | daily cron 02:00 | operational | +| S1 OS config | `railiance-backup-s1` | `railiance-infra` | T2 | OS config tar, age | `/opt/backup/railiance/infra/` local | manual (`make backup`) | operational | +| S2 k8s runtime | `railiance-backup-s2` | `railiance-cluster` | T1 | k3s state.db + helm values + kubeconfig, age | `/opt/backup/railiance/cluster/` local | manual (`make backup`) | operational | +| S3 platform | `railiance-backup` | `railiance-platform` | T1 | pg_dump (intended) | Nextcloud WebDAV (intended) | TBD | **missing tool** | +| Forgejo production | scheduled `forgejo dump` | `railiance-apps` | T1 | dump zip + CNPG logical | Nextcloud WebDAV (decided) | daily (intended) | not wired | +| Gitea canonical | `gitea dump` / mirror | `railiance-infra` | T1 | manual dump | none automated | pre-cutover only | at risk | + +Every entry must declare: `owner`, `recovery_method`, `backup_schedule`, +`rto`, `rpo`, and honest `status` (operational / manual-only / missing). +Mark the platform `railiance-backup` gap and missing off-cluster upload for +S1/S2 explicitly — do not paper over gaps. + +Feeds `DISCTL-WP-0002-T02`. + +## Write BackupPolicy.md codifying existing practices (R3, R9) + +```task +id: DISCTL-WP-0003-T02 +status: todo +priority: high +``` + +Write `BackupPolicy.md` translating live `railiance-backup` practices into +policy with verification steps: + +1. **3-2-1 + immutable/offline model** — per `specs/ResilienceControlSetup.md` §4 +2. **Per-stream mechanisms** — table keyed to register entries from T01 +3. **Encryption standard** — age for all artifacts; key custody rules + (operational key + password-manager recovery copy) +4. **Retention** — 7-copy local prune (S1/S2); 14 daily + 4 weekly for + Forgejo/platform lane per 2026-07-09 decision +5. **Destination** — Nextcloud WebDAV file drop for off-node lanes; local + `/opt/backup/railiance/{infra,cluster}/` for S1/S2 until upload is wired +6. **Credential separation** (R3) — backup-storage credentials must not live + on production hosts with delete permission; verify with named check +7. **Monitoring** (R9) — backup job success + repository integrity checks on a + defined schedule; `.last-backup` stamp freshness; preflight gate before + infrastructure changes; named alerting owner + +Record the 2026-07-09 Forgejo backup decision (Option A: extend platform +backup lane) as the adopted standard for Forgejo + CNPG `forgejo-db` until +superseded. + +Feeds `DISCTL-WP-0002-T04`. + +## Draft RTO-RPO matrix for backup lanes (R1, R6) + +```task +id: DISCTL-WP-0003-T03 +status: todo +priority: high +``` + +Write `RTO-RPO-Matrix.md` with explicit per-system targets. Start from the +assessment draft and the 2026-07-09 adopted targets: + +| System | RPO | RTO | Evidence basis | +| --- | --- | --- | --- | +| Forgejo git + packages | 24h | 4h | Decision #7 (2026-07-09); T09 drill | +| Gitea (canonical until cutover) | 24h | 4–8h | Assessment §suggested targets | +| `forgejo-db` CNPG | 24h (Phase 1 logical dump) | 4h | Decision #7 | +| k3s cluster state (S2) | 24h | 4–8h | `railiance-backup-s2` local retention | +| S1 OS config | 24h | 4–8h | Manual backup; no schedule yet | +| Dev workstation custodian DB | 24h | 4h | Daily cron; T09-era preflight | + +Mark each row `adopted` or `draft` until operator confirms. Link to register +entries and BackupPolicy streams. + +Feeds `DISCTL-WP-0002-T03` (partial — ResiliencePolicy.md remains in WP-0002). + +## Cross-repo pickup queue status board (R2, R9) + +```task +id: DISCTL-WP-0003-T04 +status: todo +priority: medium +``` + +Create `BackupPickupQueue.md` tracking closure of assessment items 1–6. Each row: +item, owner repo, blocker, status (`open` / `in_progress` / `done`), last +checked date, and link to implementation evidence when closed. + +| # | Item | Owner | Initial status | +| --- | --- | --- | --- | +| 1 | Backup destination + retention decision | `railiance-infra` / T02 | **done** — Option A 2026-07-09 | +| 2 | CNPG `ScheduledBackup` on `forgejo-db` | `railiance-platform` | open | +| 3 | Scheduled `forgejo dump` → age → upload | `railiance-apps` | open | +| 4 | Restore `tools/cmd/railiance-backup` to platform | `railiance-platform` | open (relocation cancelled) | +| 5 | Gitea pre-cutover snapshot runbook + evidence | `railiance-infra` / `railiance-apps` | open | +| 6 | `apps-pg` backup coverage | `railiance-platform` | open | + +Update register and BackupPolicy as each item lands. Review queue monthly or +when a cross-repo workplan closes. + +Feeds `DISCTL-WP-0002-T08`. + +## Import Forgejo drill evidence and define evidence template (R2) + +```task +id: DISCTL-WP-0003-T05 +status: todo +priority: high +``` + +Establish the evidence loop: + +1. Create `TestEvidence/` directory +2. Write `TestEvidence/restore-drill-2026-07-04-forgejo.md` — copy or link + `railiance-infra/docs/forgejo-restore-drill-evidence.md` with measured + RTO/RPO, result, issues found, and follow-up actions +3. Write `TestEvidence/README.md` — evidence file naming convention, required + fields (date, system, RPO achieved, RTO achieved, operator, result, + follow-ups), and quarterly drill cadence + +Define the next untested restore target (Gitea dump decrypt, secret vault cold +restore, or S2 `railiance-backup-s2` decrypt) as a follow-up action — do not +block this task on running it. + +Feeds `DISCTL-WP-0002-T06` (partial — next drill execution remains in WP-0002). \ No newline at end of file