Row 178 gave the Console --proof-header NAME --proof-file PATH, but on the pinned stack only
activate --tester-port could write a new Console flag into the pointer. A hand install of the pair
would make every later activate, pm-on and rollback refuse unit-flags-drift. activate now takes
the pair, which replaces any pair in the pointer, and --no-proof, which drops it. The pair goes
after the preview flags and before --send and --tester-port, the order webui-service.sh render
writes and flags_drift compares. With neither flag, a target Console that takes --proof-header
carries the pair; a rollback to one that doesn't drops it and says so, and an activate to one
refuses proof-target unless --no-proof is given.
An activate may name the pointer's copy only when it sets a pair or drops one with --no-proof, so
Part B's B3 and its corrected rollback line B-R1 (activate <live copy> --pm --no-proof) can run;
every other activate of the live copy still refuses already-active. Before anything stops, the run
refuses proof-needs-preview, proof-header-invalid (proofOptions' own rules) and proof-file-invalid:
not absolute, a character the unit can't carry, a symlink, missing, not a regular file, inside the
repository or the copies, mode other than 600 or 400, or another owner. The file gets lstat, stat
and realpath only; the script never opens it and no line it writes holds the value. --plan prints
one proof: line. docs/TOOLS.md "Pinned stack update" lists the flags and describes the pair.
stack-release.test.mjs adds T53, eleven subtests. Each ends with a scan of every written file and
output for the proof file's sentinel and an inotify watch that counts no open or read of it. The
five brief mutants and Darkwing's two are killed. Filbert's M8 (a carried pair skips the checks)
and M9 (the repository case dropped) survive T53; both are follow-ups on P19, with a stale comment
in proof_for_target and the stale row 178 paragraph in docs/TOOLS.md.
This is step A0 of mos-0928 Part B and builds the tool only; nothing turns the proof on for the
live Console. Filbert approved round 1 on #1685.
activate --plan printed the backup line whenever the store file existed. But run_steps rolls back
with store-newer or migration-needs-flag before backup_store, so in those two cases the plan said
both that the run rolls back and that it backs up the store. The plan now prints
"backup: none; the run rolls back before the backup" there. The no-store line comes first, since
with no store file the run skips the whole store block. When S_CHANGED is set the plan keeps the
backup line: a wrong backup line costs nothing, a wrong none line hides the directory a --restore
needs. run_steps, backup_store, refusals, exit codes and flags are unchanged; the diff to
stack-release.sh is inside plan only. docs/TOOLS.md "Pinned stack update" step 3 names the
backup line. These are Filbert's N1 and N2 on row 185 (P19 404).
stack-release.test.mjs updates T26's not-given case and adds T52, six activate cases that plan,
check the one backup line and that nothing was written, then run and check the backup exists
exactly when the plan said so. The three brief mutants are killed, and so is Filbert's M7 (an
S_CHANGED read counted as early, by T29). Filbert's M6 (the early test ahead of the no-store test)
survives, since no test plans a missing store with an out-of-chain pointer schema; that is a
bounded follow-up with the store-unclean reading, on P19 404.
Filbert approved round 1 in #1684 comment 29419, with two non-blocking notes.
NEW moves from the 9f5153deb candidate to 490e2771d, which lands row 185 (#1683), 52 commits past
89af38a83. The tool blob at NEW is f8051d81cc. P5 now checks that REPO's four service scripts
match NEW instead of HEAD equal to NEW, since record commits after NEW move HEAD. Sage's SESSIONS
line for the row 185 landing.
stack-release.sh activate now backs up the stopped store under its activation id on every run
with a store file, before any migration. Before this, backup_store ran only when the schemas
differed, so a same-schema activate took no backup and rollback --restore had nothing to name.
store-newer and migration-needs-flag still roll back before the backup, since those runs never
touch the store, and a missing store takes no backup.
BACKUP and TAKEN now mean two things. BACKUP is set by every backup, so the log line names it and
from_log backup finds it. TAKEN is set only right before a migration, so a gate failure after a
same-schema activate puts back the units and the wrapper and leaves the store as the failed run
left it. activate --plan prints a backup line, or "backup: none" with no store file. Rollback and
pm-on are unchanged; a same-schema rollback --restore already works through the row 181 guard.
docs/TOOLS.md "Pinned stack update" steps 5-7 say so.
stack-release.test.mjs updates T5, T11, T26 and T29 and adds T47-T51, with one fixture fault
(start-writes-row-<copy>). The three brief mutants are killed, and Filbert's two more (the backup
ahead of the schema checks, the plan line on a rollback) are killed by T6, T9 and T50.
This is the precondition for mos-0928 Part A, the re-pin from 89af38a83.
Filbert approved round 1 in #1683 comment 29404, with two non-blocking notes.
A same-schema activate takes no store backup: backup_store runs only when
the schemas differ, and the two live backups (3f, 3h) don't match 3i, so
rollback --restore refuses both. Row 185 makes every activate back up the
stopped store before any migration and keeps the in-run restore
migration-only. Part A of the mos-0928 plan (re-pin 89af38a83 to the
refactor head) needs it first. Part B, the row 178 proxy proof
activation, is drafted for Jason and runs nothing.
Sweeps Dewey's uncommitted SESSIONS line for the row 184 rebase and in-review, and adds
Sage's line for the mos-0870 assignment (rows 177, 178, 180 and 181 and follow-ups 182-184).
Additions only. No existing line changes.
mosaic thread create|open|read and threads take --tester and run as the tester through
tester-cli.mjs. talk --thread and follow --thread take --tester too, and the row 177 refusal of
--thread with --tester is gone. The bus already checks thread ownership (thread-not-owned), so
the CLI adds no rule of its own, and every verb it sends as the tester is in TESTER_VERBS. follow
already receives with message.receive, so a tester reply arrives without polling inbox.
docs/TOOLS.md and packages/cli/README.md list the new flags.
The new tester-threads.test.mjs runs an in-process Broker. It covers create, list, open, send,
read and follow on a tester thread; thread-not-owned on a human thread both ways; and the human
forms unchanged with no tester transport call. A real-process test runs scripts/mosaic as the
tester. thread-cli.test.mjs and tester-reads.test.mjs drop the argvs that pinned the old
refusal. Brief mutants (talk sent as the human, follow without the thread filter) are killed.
Filbert approved round 1 in #1682 comment 29396 with no findings or notes. Their run on 3da362982,
with row 182 in the broker, added one more mutant (no thread read before the first receive in
follow), and it was killed.
Sweeps lines the seats appended but didn't commit: Darkwing's SESSIONS lines for rows 180, 181
and 182, and Rocko's SESSIONS and BUILD-LOG lines for rows 138, 164, 171, 176 and 178. Additions
only, as the seats wrote them. No existing line changes.
webui serve takes --proof-header NAME --proof-file PATH, only with the --public-host preview flags.
Before listen it reads the file once through O_NOFOLLOW and fstat: a regular file owned by the
Console uid, mode 0400 or 0600, at least 32 base64url bytes with one optional final LF. Any file
problem gives one fixed refusal that names neither the path nor the contents. The header name can't
collide with Host, Origin, auth or tester names.
On a public Host the guard runs before any auth header is read. It needs exactly one proof header
and compares equal-length buffers with timingSafeEqual. Missing, wrong and repeated proofs get the
same fixed 401. A proof header on another Host or on the tester listener gets 403. The existing
auth, Origin, Fetch Metadata and human write checks are unchanged.
webui-service.sh renders both flags and checks the file's metadata and canonical location without
opening it, and the send-status regex accepts the proof pair. stack-release.sh only gains a comment:
it already carries Console flags through re-pin and rollback, and new tests pin that.
This is a partial fix. Same-uid seats can still read the proof file. Activation (middleware, unit
flags, restart, smoke) is a separate Mos-checked window and isn't part of this commit.
Dewey approved round 2 in #1676 comment 29386, candidate 9300a670. Round 1 changes were in 29374.
COUNTED, next to STORE_JS, lists the 11 tables a bus writer fills without an event in the same
transaction (role_claims through usage_records, in schema order). STORE_JS count and heldcount
return events after STAMP plus each listed table after STAMP from the same open as before. A
listed table the store lacks counts 0, and one that exists but can't be read refuses
restore-mismatch.
rollback --restore refuses post-backup-events unless the total is 0 or --events equals it, and
the message names each table with rows. The in-run recount compares the same total. An
events-only store prints the old text. T46 reads every table in schema.sql and fails on a table
in no list or in two.
Filbert approved round 1 in #1679 comment 29372. Follow-ups F1 (task_comment_cursors) and F2
(the refusal text at stack-release.sh:909) are recorded in agents/darkwing/work/queue-181/BUILD.md.