The file carried an identifier minted by the retired local hub while central held a different record for the same file — ADR-010's same-filename, different-UUID duplicate-registration class. Central is authoritative (ADR-010 decision 1) and decision 6 says to mitigate by changing the repository file rather than editing central, so the file adopts central's id. The cache-side id dies with the cache. Refs CUST-WP-0068 Assistant: claude-code Assistant-Model: opus Assistant-Process: 2583210@bnt-lap001 Assistant-Session: f2bff2d5-e9b2-4338-92ca-10282a927006
5.6 KiB
| id | type | title | domain | repo | status | owner | topic_slug | created | updated | state_hub_workstream_id |
|---|---|---|---|---|---|---|---|---|---|---|
| DISCTL-WP-0002 | workplan | Resilience foundation: registers, policy, first tested restore | infotech | disaster-control | finished | grok | custodian | 2026-07-04 | 2026-07-07 | 73d2ecb3-e594-4a7c-920d-8753198eb6ec |
Resilience foundation: registers, policy, first tested restore
Stand up the minimum viable Resilience Control Plane for Coulomb Social / Helix Forge: know what exists (registers), what must survive (policy, RTO/RPO), how it comes back (runbook, panic sheet), and prove it once (drill + evidence).
Driven by history/2026-07-04-initial-risk-analysis.md — priority order R2
(untested restores), R9 (silent backup failure), R3 (backup-deleting breach),
R4/R5 (identity & secret recovery), R10 (control plane single-homed), R1
(full server loss). Design source: specs/ResilienceControlSetup.md.
The same-day Forgejo/Railiance assessment
(history/2026-07-04-forgejo-backup-strategy-assessment.md) proved the Forgejo
restore path (RAIL-HO-WP-0005-T09) and handed this repo a pickup queue: its
items 7–8 are T03/T04/T06 below; its cross-repo items are tracked by T08.
Mirror disaster-control off the primary Gitea (R10)
id: DISCTL-WP-0002-T01
status: done
priority: high
state_hub_task_id: "0d7e27f6-1290-45da-b76a-407b7b039e95"
This repo must survive the disasters it describes. Add at least one mirror on infrastructure independent of CoulombCore/Gitea (e.g. GitHub private mirror or secondary machine), document the mirror location in README, and note how the mirror is refreshed.
Asset and data registers with Tier-0 recovery paths (R4, R7, R8, R12)
id: DISCTL-WP-0002-T02
status: done
priority: high
state_hub_task_id: "59f04771-25cf-4bde-adf0-8a1cd418dc1f"
Write AssetRegister.yaml and DataRegister.yaml seeded with the current
stack: domains/DNS/registrar, email, Stripe, Bubble.io, OpenRouter, Gitea,
CoulombCore content, k3s, databases, backup storage, secrets/OpenBao. Every T0
entry must record its recovery path (backup admin, MFA recovery, break-glass).
Every T1 entry must name its source of truth and backup mechanism (or mark it
backup: none honestly). Use the tier model from the spec (§2).
ResiliencePolicy and RTO/RPO matrix (R1, R6)
id: DISCTL-WP-0002-T03
status: done
priority: high
state_hub_task_id: "8c119835-0c97-4556-ab98-42267688e432"
Write ResiliencePolicy.md (operating principle, tier definitions, drill
cadence, evidence requirement) and RTO-RPO-Matrix.md with explicit per-system
targets, starting from the spec's suggested values (§3): RPO ≤ 24h everywhere,
RTO ≤ 1 day full recovery, RTO ≤ 4–8h for code/content/control plane.
BackupPolicy with credential separation and monitoring (R3, R9)
id: DISCTL-WP-0002-T04
status: done
priority: high
state_hub_task_id: "d6b9b621-c901-48c0-be4c-7bc98245de99"
Write BackupPolicy.md: 3-2-1 + immutable/offline model, per-stream mechanisms
(gitea dump + mirrors, restic, k3s etcd snapshots, Bubble/Stripe exports,
SOPS/age secret vault), and two hard rules with verification steps —
(a) backup-storage credentials never live on the production host with delete
permission; (b) backup job success and repository integrity are checked on a
defined schedule with a named alerting path.
Full-server-loss restore runbook and panic sheet (R1, R11)
id: DISCTL-WP-0002-T05
status: done
priority: medium
state_hub_task_id: "c413734b-7a17-4164-bf72-0de18fd509c4"
Write RestoreRunbooks/01-full-server-loss.md (new machine → Ansible → secret
recovery → data restore → k3s redeploy → validate → DNS cutover → evidence
report) and the one-page panic sheet: where backups are, who has access, how to
rebuild, how to rotate secrets, how to switch DNS — written so a competent
stranger could execute it.
First restore drill with evidence file (R2)
id: DISCTL-WP-0002-T06
status: done
priority: high
state_hub_task_id: "c816efa0-bbc2-4612-9a8f-a03bd83ca7c0"
The 2026-07-04 Forgejo drill (evidence in railiance-infra) proved that path;
this task covers the next untested system: restore one Gitea repo/dump or
decrypt the secret vault from cold, onto a clean target. Write
TestEvidence/restore-drill-2026-MM-DD.md with measured RTO/RPO, result,
issues found, and follow-up actions; also copy or link the Forgejo drill
evidence so this repo holds the complete evidence trail. Define the recurring
drill cadence (pickup item 7). This task is the exit criterion for the
workplan: no drill evidence here, not finished.
Incident playbooks (R3, R4, R5, R6, R7)
id: DISCTL-WP-0002-T07
status: done
priority: medium
state_hub_task_id: "ee7254a8-5adf-4913-bb47-bf94e59c88ec"
Write the five playbooks under IncidentPlaybooks/: ransomware/hostile access,
credential leak, accidental delete / data corruption, provider outage
(Bubble/Stripe/OpenRouter/DNS/email), loss of admin identity. Keep each to one
page of numbered steps per the spec (§6).
Track cross-repo backup pickup queue (R2, R9)
id: DISCTL-WP-0002-T08
status: done
priority: medium
state_hub_task_id: "af9ae2ca-5af8-45af-9301-8c28e78ea32a"
Drive closure of the cross-repo items from the Forgejo assessment's pickup
queue (items 1–6: backup destination decision #7, CNPG ScheduledBackup,
scheduled forgejo dump, railiance-backup tool, Gitea pre-cutover snapshot,
apps-pg coverage). Implementation lives in railiance-platform /
railiance-apps / railiance-infra; this repo tracks status and records the
outcome in the registers and BackupPolicy as each item lands.