diff --git a/WORK-RECORDS.md b/WORK-RECORDS.md index 8176dc2..3021ce0 100644 --- a/WORK-RECORDS.md +++ b/WORK-RECORDS.md @@ -75,6 +75,6 @@ | task | RAILIANCE-WP-0016-T03 | todo | — | workplans/RAILIANCE-WP-0016-apps-pg-resource-evidence.md | | task | RAILIANCE-WP-0016-T01 | done | — | workplans/RAILIANCE-WP-0016-architecture-cleanup-backlog.md | | task | RAILIANCE-WP-0016-T02 | done | — | workplans/RAILIANCE-WP-0016-architecture-cleanup-backlog.md | -| task | RAILIANCE-WP-0016-T03 | todo | — | workplans/RAILIANCE-WP-0016-architecture-cleanup-backlog.md | +| task | RAILIANCE-WP-0016-T03 | done | — | workplans/RAILIANCE-WP-0016-architecture-cleanup-backlog.md | | task | RAILIANCE-WP-0016-T04 | todo | — | workplans/RAILIANCE-WP-0016-architecture-cleanup-backlog.md | | task | RAILIANCE-WP-0016-T05 | todo | — | workplans/RAILIANCE-WP-0016-architecture-cleanup-backlog.md | diff --git a/workplans/RAILIANCE-WP-0016-architecture-cleanup-backlog.md b/workplans/RAILIANCE-WP-0016-architecture-cleanup-backlog.md index 0d71f5f..94d75a8 100644 --- a/workplans/RAILIANCE-WP-0016-architecture-cleanup-backlog.md +++ b/workplans/RAILIANCE-WP-0016-architecture-cleanup-backlog.md @@ -61,8 +61,10 @@ reliable numbers here, because nobody has scoped them yet. | 6 | `rapp.yaml` schema + family declaration validator | `railiance-master` | 8 | 5 | 7 | 3 | **6.7** | | 7 | Reconcile hub capability attribution (C1) | `railiance-master` | 5 | 4 | 6 | 3 | **5.0** | | 8 | Deployable coverage check: every deployable → one rapp | `railiance-master` | 7 | 4 | 7 | 4 | **4.5** | -| 9 | Telemetry MVP: metrics + alerting for one real expectation | `railiance-telemetry` | 9 | 6 | 8 | 5 | **4.6** | -| 10 | Conformance loop MVP: declared-vs-live firewall check | `railiance-telemetry` / Q7 owner | 8 | 6 | 9 | 5 | **4.6** | +| 9a | Telemetry: minimal metrics collection on railiance01 | `railiance-telemetry` | 8 | 5 | 5 | 4 | **4.5** | +| 9b | Telemetry: one expectation-based alert (needs 10b) | `railiance-telemetry` | 8 | 5 | 2 | 2 | **7.5** | +| **10a** | **Run `make verify`; tighten the UFW assertion to check the allowlist** | `railiance-infra` | 8 | 7 | 9 | 1–2 | **12.0** | +| 10b | Schedule verification; route failures where they are seen | `railiance-infra` / Q7 owner | 7 | 6 | 8 | 3 | **7.0** | | 11 | Consolidate the bootstrap path; sort inherited S2 content | `railiance-bootstrap` | 5 | 3 | 4 | 4 | **3.0** | | 12 | Forge migration: `rapp-forgejo` + S4 layer transfer | `railiance-forge` / S4 | 6 | 4 | 4 | 5 | **2.8** | | 13 | Prove a restore end to end | `railiance-platform` | 9 | 5 | 9 | 8 | **2.9** | @@ -85,11 +87,12 @@ run. ratifications in `railiance-master` block items 6, 7, 8, 12 and parts of 9 and 10. It is a day of decisions that unblocks a quarter of the backlog. -**Items 9 and 10 are the strategic core** despite mid-table WSJF. They are Q2 -and Q7 — the two halves of the self-evidencing thread that five layers -independently asked for. Their size scores are guesses. Scoping them into -smaller slices would likely move both up sharply, and **that rescoping is itself -worth doing before committing to the order below them.** +**Items 9 and 10 are the strategic core** — Q2 and Q7, the two halves of the +self-evidencing thread five layers independently asked for. They were rescoped +on 2026-08-12 (see below) and item 10 turned out to be badly mis-sized: the +conformance checker already exists in `railiance-infra` and has simply not run +since 2026-03-09. **Slice 10a is now the highest-value item after the +ratifications** at WSJF 12.0. **Item 13 is blocked, not deprioritized.** Proving a restore needs the object storage decision (`9c21c0e0`), which is escalated and awaiting human approval on @@ -100,6 +103,89 @@ the family, but it is large, and item 12 gives S4 a smaller first responsibility to prove delivery on. Building the portal before the forge transfer would be starting at the hard end. +## Rescoping items 9 and 10 (2026-08-12) + +### What was assumed + +That Q2 Observability and Q7 Governance were both greenfield builds of +comparable size (5), sitting mid-table at WSJF 4.6. + +### What is actually there + +`railiance-infra` already has: + +- `goss/baseline.yaml` — a host baseline assertion suite +- `ansible/roles/goss` + `ansible/playbooks/verify.yaml` — the runner +- `make verify` — runs it against all hosts, **commits TAP reports to git**, and + exits non-zero on failure +- `reports/*.tap` — an evidence trail, last written **2026-03-09** + +So a check-and-evidence mechanism exists and is wired. Two things are wrong with +it, and neither is a build: + +1. **Nothing runs it.** Five months of silence. A verification suite that is not + scheduled is a verification suite that does not exist. +2. **Its firewall assertion is too loose in exactly the place that mattered.** + It asserts `/6443\/tcp.*ALLOW/` — that the port is allowed. It does not + assert *from whom*. That regex passes identically whether 6443 is restricted + to one operator address or open to the entire internet, which is precisely + the drift that went undetected. + +It would, however, have caught the *other* finding: it asserts +`Status: active`, and UFW is entirely inactive on `CoulombCore`. + +### The rescoped slices + +**Item 10 — conformance loop** + +| Slice | Work | Size | +| --- | --- | --- | +| 10a | Run `make verify` against both hosts; tighten the UFW assertion to compare the live allowlist against `k3s_api_allowed_sources` rather than matching any ALLOW; fix what it surfaces | **2** | +| 10b | Schedule it, and route failures somewhere a human or agent actually sees | 3 | +| 10c | Extend to declaration conformance — rapp/rail/reef schema validation | blocked on item 6 | +| 10d | Deployable coverage: every live deployable maps to exactly one rapp | blocked on item 8 | + +**Item 9 — telemetry** + +| Slice | Work | Size | +| --- | --- | --- | +| 9a | Minimal metrics collection on `railiance01` | 4 | +| 9b | One expectation-based alert on the 10b path | 2 | +| 9c | Retention sufficient to prove a restore or rollout held | 3 | +| 9d | Dashboards and agent-queryable surfaces | 4 | + +### The shared dependency worth naming + +**10b and 9b are the same plumbing.** Both are "a check failed — now make that +visible to someone who can act." Building an alert path twice would be waste, +and building either of 9 or 10 *without* it produces logs nobody reads. That +path is the real first dependency for both, and it is small. + +It also has an obvious candidate already in the fleet: the Goss suite commits +TAP evidence to git, and State Hub takes progress events. Neither is an alert, +but the gap between them is narrow. + +### Revised positions + +| Item | Old WSJF | New WSJF | Effect | +| --- | --- | --- | --- | +| 10a run + tighten Goss | 4.6 (as part of 10) | **12.0** (V8 TC7 RR9 / size 2) | rises to 4th overall | +| 10b schedule + alert path | — | **7.0** (V7 TC6 RR8 / size 3) | rises above ArgoCD | +| 9b one real alert | — | **7.5** (V8 TC5 RR2 / size 2) | depends on 10b | +| 9a metrics collection | 4.6 | **4.5** (unchanged) | stays mid-table | + +**Conclusion: item 10a should be done next, immediately after the ratifications.** +It is two points of effort, it directly closes the hole that produced this +session's security finding, and it converts an existing but dormant asset into a +working control. Item 9 is correctly mid-table and genuinely is a build. + +### The lesson worth keeping + +The original size-5 estimate for item 10 was wrong because nobody looked. The +gap analysis correctly identified "no conformance loop" as a *capability* gap, +but the capability was two-thirds built and unrun. **Before sizing a gap as a +build, check whether it is actually an abandonment.** + ## Tasks ```task @@ -140,16 +226,22 @@ items — and that this workplan closes once adopted. ```task id: RAILIANCE-WP-0016-T04 -status: todo +status: done priority: medium state_hub_task_id: "aac02de1-6367-4767-b7ee-c980577e778f" ``` Rescope items 9 and 10 (telemetry MVP, conformance loop MVP) into deliverable slices before committing to their position. Their size scores are the least -reliable on the list, and both are strategically central. A first slice of item -10 could be as small as a Goss check comparing declared UFW state to live state -on one host. +reliable on the list, and both are strategically central. + +**Done 2026-08-12, and the answer changes the order.** See "Rescoping items 9 +and 10" below. The headline: item 10 was mis-sized by a wide margin, because the +conformance checker **already exists** — `railiance-infra` has a Goss baseline +suite with a `make verify` target that runs it against all hosts and commits TAP +reports to git. It has not run since **2026-03-09**, five months. The work is not +to build a loop; it is to run what exists, tighten two assertions, and schedule +it. ```task id: RAILIANCE-WP-0016-T05