docs(m181): rollback carries no migrate step, and the daemon now enforces why
M176 changed what an older binary does when it meets a database a newer one
migrated: it used to delete the versions it did not recognise and carry on, and
it now refuses with UZ-STARTUP-005, naming the version, having changed nothing.
That is a cutover-time fact, and cutover is M181's. Recorded where the operator
swapping binaries will read it rather than left in a PR review thread.
Three consequences, written into the spec:
- Invariant 1 said rollback needs no schema or data migration, enforced by
the family rule. The DAEMON enforces it now as well, which is a stronger
claim than a rule nobody's code checks. The invariant also gains its own
expiry: it is cheap only while the family rule holds, and the first release
after cutover that adds a migration turns a rollback across that boundary
into a schema decision rather than a binary swap.
- §4's rollback path carries NO `migrate` invocation. Rollback serves an
older binary against a ledger it already understands; a `migrate` there is
at best a no-op and at worst the one command that can refuse mid-incident,
which is the worst moment to meet it. `probes.sh` asserts the absence
rather than trusting the runbook's prose — Dimension 4.4.
- A Failure Modes row for the case itself, so an operator who trips it reads
what it means (a rollback that crossed a migration boundary) instead of
debugging an exit code.
M176's Files Changed gains `docs/v2/pending/M181_001_*.md`, because rubric row
R6 requires the diff to stay inside that table and a note recorded by quietly
stepping outside it would be a poor advertisement for a milestone about not
silently corrupting things.
The SQL half of this — `schema/110_roles_and_privileges.sql` forgiving a
concurrent CREATE ROLE — Indy reviews with api-dev at cutover.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> K
Kishore Kumar committed
8a4e6c501050d483cefb580a02a1348afaf613e7
Parent: 11a3bcf