Gate schema mutation of the operator's store on provenance and consent - #179
Merged
Merged
Conversation
Every build migrated any database it opened as a side effect of opening it, which is how an unreleased migration from a worktree once landed on real data (#417 made that detectable; this prevents it). The operator's store now carries a `protected` marker in a `store_meta` table — in the file, so it survives a symlink, a moved data directory, or a restored copy — and a protected store with pending migrations never migrates silently. The TUI asks at launch, on plain stdin before the terminal is taken, so reading the yes back is itself the proof a human is present; every CLI verb refuses, naming the new `voro migrate` verb; and `voro migrate --yes` consents from a script, recorded in the journal's `applied_by` so even the override leaves a trace. A fresh install still creates its database with no ceremony, and unprotected stores — dev, scratch, in-memory — migrate on open exactly as before. The task proposed routing by build provenance instead, so release artifacts kept migrating invisibly. Dropped after discussion: the CI stamp lives in a workflow cargo-dist regenerates and would silently vanish, and it bought one keypress per release. DESIGN.md §5 records the policy and the reversal. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ThKpEECj8gR1xD167gAyKz
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Every build migrated any database it opened as a side effect of opening it —
the mechanism behind the #417 incident, where a worktree's
cargo runinherited
VORO_DBand applied an unreleased migration to real data. Theoperator's store now never migrates without consent.
What changed. Migration 0020 adds a
store_metatable, and aprotectedmarker is written there on any open at the production path — in the file
itself, so the property survives a symlink, a moved data directory, or a
restored copy. A protected store with pending migrations refuses to open:
the terminal is taken. Reading the yes back is itself the proof a human is
present — a headless bare
voro(the incident's exact shape) cannot answerand is refused.
explicitly tells an agent to stop and tell the operator.
voro migrateis the explicit spelling: asks at a terminal, takes--yesfrom a script, and either consent route is recorded in the journal'sapplied_by("via voro migrate --yes" / "confirmed at the TUI prompt"), soeven the override leaves a trace.
A fresh install (schema 0) creates its database silently, and unprotected
stores — dev.db, scratch
--db, in-memory — migrate on open exactly as before.voro-coregained no process I/O: the gate is a pure check inside open, andall terminal interaction lives in the voro crate's main, before ratatui
initialises.
Deviation from the task body, agreed in-session: the proposed
build-provenance routing (release artifact → silent migrate) was dropped. The
CI stamp would live in a workflow cargo-dist regenerates and could silently
vanish — turning releases into prompting from-source builds for everyone — and
it bought one keypress per release. A release upgrade now costs one y/N at the
next TUI start. Both "worth deciding" questions dissolve with it: main-vs-
released has nothing left to decide, and the dev-store default keeps its job
unchanged. DESIGN.md §5 records the policy and the reversal; the "deferred to
its own change" note is gone. CHANGELOG updated.
Verification. Five new schema_guard tests (refusal leaves the store
untouched and unsnapshotted; consent applies and journals the route; the
marker travels with a renamed file; fresh production store creates silently
and marked; scratch stores migrate silently). Full live smoke against a
schema-19 store built by replaying migrations 1–19: CLI refusal, headless
bare-voro refusal, headless migrate refusal, interactive decline (pty),
interactive accept (pty),
--yes, journal trace, snapshot in backups/, andthe nothing-pending report.
cargo test --workspace(888 tests) and clippy-D warnings clean; rebased onto origin/main (no migration-number collision).