docs: the dotfile list gains .seen, and names the shape a new one should copy

Held until the merge deliberately: this file describes what is deployed, and
writing it while the code sat on another agent's branch would have made our
canonical convention document describe a service that was not running.

Also records a latent bug the R2 work surfaced in code it did not touch.
.blurred stores one stripped rel per line, so a rel carrying a leading space or
a newline does not round-trip and blurring ' a.png' can blur 'a.png'. .seen was
written as a JSON array for that reason, and additionally opens O_NOFOLLOW |
O_NONBLOCK with an S_ISREG check so a planted symlink is refused and a FIFO
cannot hang the read — the outage this repo has already paid for once. New
dotfiles inherit .seen's shape, not .blurred's.
This commit is contained in:
vh
2026-09-23 10:28:52 -07:00
parent 1ddd1c5654
commit 225570623d
+13 -1
View File
@@ -63,12 +63,24 @@ No database. `ls ~/booth-data` tells you everything the service knows.
Per-booth operator state is a **dotfile inside the booth**: `.forever` (keep), Per-booth operator state is a **dotfile inside the booth**: `.forever` (keep),
`.viewed` (last deliberate look — U4's "viewing is activity"), `.blurred` (one `.viewed` (last deliberate look — U4's "viewing is activity"), `.blurred` (one
rel per line), `.marks.json` + `.marks.lock` (judgment), `.pins` (link-board pin rel per line — ⚠ see below), `.seen` (R2: rels looked at full size, a JSON
ARRAY), `.marks.json` + `.marks.lock` (judgment), `.pins` (link-board pin
ids), `.uploaded` (upload-booth marker). `booth_items()` skips `name.startswith(".")`, so a new ids), `.uploaded` (upload-booth marker). `booth_items()` skips `name.startswith(".")`, so a new
dotfile costs nothing in item counts, galleries or zips. That skip is why the dotfile costs nothing in item counts, galleries or zips. That skip is why the
dotfile is the right shape for new operator state — use it rather than dotfile is the right shape for new operator state — use it rather than
inventing a sidecar-per-item. inventing a sidecar-per-item.
⚠ **`.seen` is a JSON array where `.blurred` is one stripped rel per line, and
the difference is a latent bug in the older one.** A rel may carry a leading
space or a newline; line-stripped storage does not round-trip it, so blurring
`" a.png"` can blur `a.png` instead. `.seen` was written as JSON for exactly
that reason (design-dev, R2), and it also opens `O_NOFOLLOW | O_NONBLOCK` with
an `S_ISREG` check — a planted symlink is refused and a FIFO cannot hang the
read, which is the outage in
`persistent-memory.d/2026-09-22-size-cap-opened-a-hang.md`. **Any new dotfile
inherits that shape, not `.blurred`'s.** `.blurred` itself is unfixed and
pre-existing.
### 3. One resolver for item facts ### 3. One resolver for item facts
`booth.items.booth_items(booth)` is the only place a file is classified, a `booth.items.booth_items(booth)` is the only place a file is classified, a