Repository navigation
M1 State
Paolo Veronelli edited this page Aug 25, 2026
·
2 revisions
Updated: 2026-08-25 UTC
Outcome: 9.12.3 server on 2018 gruppi; the 2018 binary and a pre-v1 gruppi/ stay bootable until a responsabile publish is proven on the live URL.
Legend: ✅ done · 🟡 active/next · ⏳ queued · ⛔ blocked · ❓ unknown
flowchart LR
subgraph F["#37 freeze + baseline"]
I26["#26 freeze, integrity-check,<br/>boot, record 2018 baseline"]
I41["#41 parse-probe frozen stato<br/>with 9.12.3 Read"]
I26 --> I41
end
subgraph B["#38 9.12.3 binary — 3 PRs, 3 gates"]
I28["#28 sqlite v1<br/>values + refuses prod"]
I29["#29 SCGI via separate<br/>nginx block"]
I30["#30 RSA-1.0 unlock<br/>+ CI gate"]
I28 --> I29 --> I30
end
subgraph C["#39 copy probe"]
I31["#31 clone from freeze,<br/>checksum-verified"]
I32["#32 migrate + boot;<br/>values = baseline"]
I33["#33 live responsabile<br/>types own password"]
I31 --> I32 --> I33
end
subgraph X["#40 cut-over — copy-and-switch"]
I34["#34 runbook + timed<br/>rehearsal incl. rollback"]
I42["#42 fresh re-freeze<br/>inside the window"]
I35["#35 switch live URL<br/>to gruppi.v1"]
I36["#36 responsabile publish<br/>+ values = baseline"]
I34 --> I42 --> I35 --> I36
end
I26 --> I31
I30 --> I32
I31 --> I34
I33 --> I35
F --> C
B --> C
C --> X
I36 --> T["live URL 9.12.3 · publish proven · freeze still boots"]
#41 hangs off the freeze, not the probe epic, so the milestone's largest unknown — whether 9.12.3 can Read years of live Eventi constructors — is answered the day the freeze lands, in parallel with #38, instead of at position 8 of 11.
- 🟡 #37 Freeze + baseline + parse probe — next: #26. Absorbs the old #27.
- 🟡 #38 9.12.3 binary — local branch has the code as two commits; it is re-cut into three PRs with three gates (#28, #29, #30). Now genuinely parallel with #37: #28 no longer needs live data.
- ⏳ #39 copy probe — blocked by #37 and #38. #33 is gated on a person, not on code.
- ⏳ #40 cut-over — blocked by #39. Copy-and-switch, fresh re-freeze in the window, same-window rollback if #36 fails.
| # | Ticket | State |
|---|---|---|
| #26 | Freeze, integrity-check, boot, record the 2018 baseline | 🟡 next |
| #41 | Parse-probe frozen stato with the 9.12.3 Read parser | ⛔ by #26 |
| #28 | sqlite v1 — values asserted, refuses production root | 🟡 ready |
| #29 | SCGI through a separate nginx block | ⛔ by #28 |
| #30 | RSA-1.0 Segreto unlock + golden-keys/migrate-selftest in ci.yaml
|
⛔ by #29 |
| #31 | Clone live gruppi from the freeze, checksum-verified | ⛔ by #26 |
| #32 | Migrate + boot the copy; saldi/totals equal the baseline | ⛔ by #30, #31 |
| #33 | Live responsabile publishes on the copy, typing their own password | ⛔ by #32 |
| #34 | Copy-and-switch runbook + timed rehearsal including rollback | ⛔ by #31 |
| #42 | Fresh re-freeze of production inside the cut-over window | ⛔ by #34 |
| #35 | Switch the live URL to 9.12.3 on gruppi.v1
|
⛔ by #33, #34, #42 |
| #36 | Responsabile publish on the live URL; values still match | ⛔ by #35 |
| #27 | ✅ closed, merged into #26 |
Review of the milestone found the shape right — freeze first, prove on a copy, cut over last — but the proofs too weak to conclude "9.12.3 runs old gruppi", and the rollback stale by construction. Applied:
-
#26 + #27 merged. Booting the freeze was the only cheap chance to capture the 2018 baseline while 2018 is still the truth. Freeze now means: quiesce → copy (sqlite first,
stato.*last) →PRAGMA integrity_check+ row-count compare vs live → read-only → boot → record per-user saldi and per-group totals. #27 closed as duplicate. - Values, not counts. #32 and #36 now require 9.12.3's saldi and totals to equal the recorded 2018 baseline, value by value. Previously a migration could preserve every row count, corrupt every amount, and pass all 15 tickets green.
- #42 re-freeze added. Rollback used to restore a freeze taken days of live publishes before the switch. A fresh consistency-checked freeze is now taken inside the maintenance window, before any migrate.
-
Cut-over is copy-and-switch. #34/#35: stop 2018 → fresh freeze →
cp -a gruppi gruppi.v1→ migrategruppi.v1→ 9.12.3 ongruppi.v1.gruppi/stays v0, so rollback is a process restart, and the partial-migration.bakdeadlock can never happen on the live path. - #41 parse probe added, under #37, runnable the day the freeze lands.
-
Two routes to taking down
:8000closed. #28:migrate-sqlitemust refuse the production root unless explicitly flagged, asserted by a test. #29: SCGI proven through a separate nginx block, with config backup,nginx -t, and a re-check that the live URL is still 2018. -
#30 puts the gates in CI.
just golden-keysandjust migrate-selftestrun in.github/workflows/ci.yaml— which today runs onlycabal build all, fourmolu and hlint, so the milestone's central proof had zero regression protection. - Playwright ACs replaced with operator-observed + screenshot on the issue. The repo has no Playwright config or spec; an unenforceable gate is worse than an honest observation.
- #34 can now fail: accepted only after a timed end-to-end rehearsal including rollback, and the window is sized from those numbers.
-
#35 gets provenance and supervision: production binary is
nix build .#defaultat the merged commit (build-artifacts.yamlalready does this — the gap was a tagged, durable release, not a reproducible build), hash and store path recorded, copy archived beside the freeze. Notdist-newstyle. Plus: same supervisor as today, or one is added, and it survives a unit restart. - Same-window rollback written into #35 and #36: if the publish does not pass, roll back before leaving.
-
#38 ∥ #37 is now true. #28's live-
tarogasrow-count AC moved to #32, so the binary epic needs no live data. -
Scope resolved: production holds exactly one group,
tarogas. Baseline comparison is "every group in the freeze", and #26 records the actual inventory rather than assuming it.
- Board Status is unset on all items and the parent/child links are prose, not native GitHub sub-issues, so the board's "Sub-issues progress" column stays blank. This page is the tracker.
- Data-loss policy: #42 states the window and who tells the responsabili — it is answered there, at the window, not in advance.
- What the 2018 binary does when started on a v1 sqlite is still ❓; #34's rehearsal must establish it, because that answer decides whether a failed cut-over is recoverable or terminal.
- Whether 9.12.3's
stato.correntecan be read back by the 2018 binary is still ❓; #34 must state it. - Whether Segreti exist written by binaries older than the 2018 one is still ❓. #41 will surface it if the parser chokes.
Milestone: https://github.com/paolino/reactivegas/milestone/1