feat(booth): upload-for-pickup with human-readable ids (v0.1.1)

Add a reverse direction to the Booth: the operator (or any client via `curl -F`)
can upload files through the browser and pick them up by a human-readable id.

- POST /upload — streams files to a new booth named with a human-readable id
  (e.g. 4-wombat / star-84), 303-redirects to /b/<id>/ (id in the Location
  header so curl clients can read it). Uploads reuse the whole booth machinery
  (render, per-file download links, 24h TTL sweep, delete).
- Human-readable ids: word+number in either order, collision-checked, from a
  curated 140-word friendly list; secrets-based selection.
- Safety: filenames reduced to a safe basename (no traversal), streaming size
  cap (BOOTH_MAX_UPLOAD_MB, default 1024) + file-count cap (BOOTH_MAX_FILES,
  default 50), partial-write cleanup on any failure.
- UI: Australis-themed upload/drop panel (drag-drop, progressive-enhancement JS,
  degrades to a native file input), a "⬆ pickup" badge on upload booths, a
  pickup banner, and a ⬇ download link on every gallery item.
- python-multipart dependency; homepage tile description updated; 9 new tests
  (24 total, all green).
This commit is contained in:
vh
2026-07-20 14:44:21 -07:00
parent eaece794d7
commit 775e9804cd
8 changed files with 347 additions and 22 deletions
+1 -1
View File
@@ -24,7 +24,7 @@
href: http://10.100.10.50:8090/
icon: mdi-filmstrip
siteMonitor: http://10.100.10.50:8090/healthz
description: Ephemeral media drop — CC-session A/B & smoke results (nh3-dev, 24h TTL)
description: Ephemeral media drop + upload-for-pickup (human-readable ids) — nh3-dev, 24h TTL
# The AI tab is fully Docker-auto-discovered. Each inference service carries
# a homepage.group=AI - <role> label on its compose file (AI - Inference,