Add /admin/uploads HTML page and JSON API backed by the upload_files
DB index. The page lists file_id, name, size (KB), uploaded_at, and
sha256 with client-side search by name, column sort, and per-row delete.
DELETE /admin/uploads/:id removes the DB index row and the on-disk
data file plus .meta.json sidecar. Admin deletes are written to the
audit log.
Wire the new dependencies through admin.Mount and main.go, and run
the backfill step on startup so pre-existing sidecars are indexed.
Tests cover auth, HTML rendering, JSON search, delete removing all
artifacts, and audit entry creation.
Co-Authored-By: Claude <noreply@anthropic.com>
Sweep() used to run synchronously at startup without any time bound.
On a large uploads directory this can block the server for 30s or more,
keeping /healthz returning 503 while the reaper works. Add a context
timeout so startup continues if the sweep cannot finish within budget.
The timeout is set to 5 seconds: long enough to clear typical leftover
state, short enough that a stuck sweep will not meaningfully delay
health checks or startup readiness.
Change Store.Sweep to accept a context.Context and check ctx.Err() at
the top of each iteration. If the context is cancelled or times out,
Sweep returns the files deleted so far and ctx.Err().
Add TestStore_Sweep_HonorsContextCancel to ensure a cancelled context
causes Sweep to exit early instead of running to completion.
Deliberately unchanged: there is still no periodic reaper. The server
only sweeps once at startup; this change just bounds that single sweep.
Co-Authored-By: Claude <noreply@anthropic.com>