fix(blur): writes are strict, so a set the writer cannot read is never overwritten
groa's late retry on the blur bug-hunt, adjudicated against the landed code. Its four bugs were already fixed, but a robustness note (mkstemp's 0600 locks out a reader under another uid, which then "sees nothing and replaces it") pointed at a real gap. set_blurred built on read_blurred, the renderer's lenient reader, which turns an unreadable, oversized or malformed `.blurred.json` into an empty set. The writer then replaced the file, and whatever it held was gone. This is the `.marks.json` wipe of 2026-09-21 in a new module, and it shipped for a night. - `_load` is the one parse with two postures. read_blurred maps its refusal to "nothing blurred" (a damaged file costs the blur, never the page). set_blurred lets it raise BlurUnwritable, which the route answers with 409 and the CLI with exit 3, and changes nothing. - It refuses only for a REGULAR file it cannot read. A link, a directory or a FIFO at either name holds no set anyone wrote, so it reads as empty, and the postcondition judges whether the write can land: a link is replaced, a directory refused. - The file is 0644 again, as the line-format writer left it (fchmod after mkstemp). The open flags in `_read_capped` became a second layer behind the new lstat check, and the mutation run caught their rows VACUOUS through the public API. They are now held to account by direct tests, because they still close the lstat-to-open race. blur_storage.toml: 25/25. No second panel was run: this folds one reviewer note plus the repo's own recorded lesson, with a test and a proved row for each behaviour.
This commit is contained in:
@@ -48,7 +48,11 @@ _As of 2026-09-23:_
|
||||
`a..b.png` and refuses an empty path, and a missing package fails closed.
|
||||
Declined: the `Item` positional-constructor break (booth_items is the only
|
||||
constructor, INV-1), the fdopen fd leak, the short read, and
|
||||
unreadable-reads-as-revealed (the `.seen` posture). `Item.blurred_self` came
|
||||
unreadable-reads-as-revealed (the `.seen` posture). ⚠ **groa's late retry
|
||||
exposed that the WRITER was building on the lenient reader**: an unreadable,
|
||||
oversized or malformed `.blurred.json` read as empty and was then
|
||||
overwritten, which is the `.marks.json` wipe. Fixed 2026-09-24: writes are
|
||||
strict (`_load`), and the file is 0644 again, not mkstemp's 0600. `Item.blurred_self` came
|
||||
along, so blur state has one reader (invariant 3). **Still ours, not done:**
|
||||
"off" means ON for /blur and /blurbooth but OFF for /flag (forms only send
|
||||
0/1), and the CLI's `.blurbooth` `touch` still follows a symlink where the
|
||||
|
||||
Reference in New Issue
Block a user