The backend had never been run through rustfmt. Doing it in one mechanical pass (134 files)
so no future functional diff is buried under formatting churn, then gating `cargo fmt
--check` in checks.yml so it stays clean.
Formatting only — no logic, SQL, or behaviour changed. Verified after the reformat:
cargo test 56 passed, clippy --all-targets -D warnings clean, cargo fmt --check clean.
This is the deferred cleanup noted when CI's Format step was first left out.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
CI ran Playwright (chromium-desktop) + the dependency audit and nothing else. cargo test,
clippy, the frontend vitest suite, svelte-check and the e2e typecheck were all green on a
developer's machine and gated NOTHING.
checks.yml (new): cargo test (with a Postgres service; --test-threads bounded so the
sqlx per-test DBs can't exhaust connections) + clippy; vitest + svelte-check; e2e tsc.
e2e.yml: also run the chromium-mobile project — 22 tests (focus traps, touch targets,
safe-area, viewport reflow) that never ran in CI on a phone-first app.
playwright.config: widen webkit-iphone beyond @smoke (2 specs) to the core guest journeys
(auth/upload/feed) — iOS Safari is the PRIMARY browser here; and retries 2 → 0.
retries:0 is deliberate and against the usual advice: this repo's real bugs are races, a
race is indistinguishable from a flake from outside, and a retry resolves that ambiguity
toward "flake" every time — it took a real 3%-flaky product bug from 1-in-33 to 1-in-37000,
green. A flake here is a bug report.
Not gated: cargo fmt (the tree has never been rustfmt'd — a 112-file reformat would bury
every real diff; do it separately). WebKit widening is unverified locally (needs libavif16
via sudo), so its first CI run may surface real iOS bugs.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Three deploy-readiness gaps, none of them in the export invariant itself.
1. The escape hatch was unreachable. `POST /host/export/rebuild` was added as the fix
for "a failed export is terminal", but nothing in the frontend called it — so recovery
required a terminal, the API docs and a valid JWT. The host page instead told the host
to reopen uploads and re-release, which is the destructive act the endpoint exists to
avoid (it unlocks the gallery to every guest and retracts the release). The failed
state now offers "Erneut versuchen"; a ready keepsake can be rebuilt behind a confirm,
since a rebuild makes it briefly undownloadable.
2. Migration 014 had never been run against anything. It is the repo's first destructive
migration and its backfill has to carry the old notion of "downloadable" across exactly
— get it wrong and a released event's keepsake silently 404s, on data that cannot be
re-created. backend/scripts/rehearse-014.sh proves it on a throwaway postgres, against
a real pg_dump or a synthetic DB covering every pre-014 state, asserting up, down and
up-again all preserve downloadability. Verified non-vacuous: retiring nothing (ELSE -1
-> ELSE e.export_epoch) fails it, naming the three keepsakes it would resurrect.
It also surfaced that the down migration is an inverse UP TO DRIFT: a ready flag that
disagreed with its job row comes back FALSE. That heals corruption rather than
restoring it, and costs nothing (no file_path to serve), so the assertion checks what
actually matters — no genuinely downloadable keepsake loses its flag — and reports the
normalisation instead of failing on it.
3. No advisory scanning. cargo audit + npm audit, in .github/workflows/ because Gitea
Actions scans it too and e2e.yml already resolves actions/* from GitHub. The runner is
not assumed to have cargo. RUSTSEC-2023-0071 (rsa/Marvin) is ignored SPECIFICALLY, not
globally: it is unreachable here (HS256 + bcrypt, Postgres only) and unpatched, so
failing on it would mean a permanently red pipeline everyone learns to ignore.
Tests: e2e pins that a failed keepsake recovers via rebuild while the event stays
released and uploads stay locked — so a future refactor implementing rebuild as an
internal reopen+re-release fails — and that rebuild cannot publish an unreleased gallery.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>