feat(booth): close the keep round trip, and add cosmetic per-item blur
Two operator requests.
KEEP, BOTH DIRECTIONS. The kept lane could already release a booth back to
ephemeral, but an ephemeral booth could only be promoted from a shell -- so the
round trip was closed only if you had ssh. The /keep route and the `booth keep`
verb both already existed; only the button was missing. Adds ★ to the ephemeral
card, mirroring × on the other shoulder.
BLUR. Per-item cosmetic censoring: `booth blur <name> <file>...`, a ◌/◉ toggle
in each caption row, and 👁 click-to-reveal. State is `.blurred` in the booth
dir, one booth-relative path per line -- the same filesystem-is-the-state idiom
as .pins and .forever. An empty set deletes the marker rather than leaving a
zero-byte file, so `ls -a` tells the truth.
⚠ BLUR IS NOT ACCESS CONTROL, and the code, the docs and a test all say so on
purpose. A blurred item is still served at its own URL, still in the zip, still
on disk. The Booth has no auth by design. test_blur_is_cosmetic_the_file_is_
still_served asserts the 200 deliberately: if someone later "hardens" this into
a 403 that test fails, and it should, because half-implemented access control is
more dangerous than none.
Reveal is per-viewer and never persisted; a reload re-hides. With JS off an item
stays blurred, which is the safe direction to fail in.
Two things the first pass got wrong, both caught by checking rather than
assuming:
* The cover thumb. index.html has IDENTICAL markup in the kept and ephemeral
lanes, so a single-occurrence replace patched only the kept one and the
ephemeral front page happily displayed the thing someone had hidden. The
test that caught it was itself wrong first -- it matched the bare string
"blurred-thumb", which is in base.html's stylesheet on every page and so
passed in both states. It now asserts the attribute.
* Inline docs render through their own <figure> branch and were left
unblurred -- the branch that puts readable text straight on the page, so it
needed blur more than images do. The suite passed; a live curl caught it.
165 tests pass (154 pre-existing, unchanged).
This commit is contained in:
@@ -39,6 +39,41 @@ rsync -a ./out/ nh3-dev:booth-data/my-run/
|
||||
|
||||
Then hand the operator `http://10.100.10.50:8090/b/my-run/`.
|
||||
|
||||
## Blurring an item (cosmetic censoring)
|
||||
|
||||
⚠⚠ **Blur is NOT access control.** A blurred item is still served at its own
|
||||
URL, still included in the zip, still on disk. It hides a thing from a *glance*
|
||||
— a shoulder, a screen-share, a scroll past something you did not want
|
||||
full-size — and nothing else. The Booth has no auth by design: **if a thing must
|
||||
not be SEEN by whoever can reach port 8090, it must not be in a booth.**
|
||||
|
||||
```bash
|
||||
booth blur <name> <file>... # hide from a glance
|
||||
booth unblur <name> <file>...
|
||||
```
|
||||
|
||||
Or the ◌ / ◉ toggle in each item's caption row on the booth page.
|
||||
|
||||
- **State** is `.blurred` in the booth dir — one booth-relative item path per
|
||||
line, the same filesystem-is-the-state idiom as `.pins` and `.forever`. An
|
||||
empty set deletes the file rather than leaving a zero-byte one, so `ls -a`
|
||||
tells the truth about whether anything here is blurred.
|
||||
- **Reveal is per-viewer and never persisted.** Click 👁 reveal; a reload
|
||||
re-hides. With JS off it stays blurred, which is the safe direction to fail.
|
||||
- **Covers inherit it.** If a booth's cover image is blurred, the index card's
|
||||
thumb is blurred too — otherwise the front page undoes the censoring.
|
||||
- **Inline docs are blurred too**, not just images and video. That branch puts
|
||||
readable text straight on the page, so it needs this more than a picture does.
|
||||
|
||||
## Keeping a booth (round trip, both directions)
|
||||
|
||||
`★` on an ephemeral card promotes it to the kept lane; `release` in the kept
|
||||
lane sends it back. Equivalent CLI: `booth keep <name>` / `booth unkeep <name>`.
|
||||
|
||||
⚠ Until 2026-09-19 the UI only went one way — the kept lane could release, but
|
||||
an ephemeral booth could only be kept from a shell. The `/keep` route and the
|
||||
CLI verb both already existed; only the button was missing.
|
||||
|
||||
## Kept boards — the one exception to the 24h rule
|
||||
|
||||
A booth containing a **`.forever`** dotfile is **never swept**, and renders in
|
||||
|
||||
Reference in New Issue
Block a user