diashow only subscribed to SSE events but never called connectSse(), so a kiosk/projector opening /diashow directly (not via /feed) never opened the EventSource — the showcase display got a one-time /feed snapshot and no live updates, showing "Noch keine Beiträge" forever when turned on before any photos. Open the stream in onMount (idempotent) and close it in onDestroy, mirroring the feed page. Raise the default upload_rate_per_hour from 10 to 100 (migration 015, scoped to installs still on the old default so admin overrides are preserved). Guests routinely upload bursts of 10-20 photos; the old default throttled the first burst. Also update the code fallback and the test-mode reseed. Both verified end-to-end against the docker test stack. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Migrations
SQLx-managed Postgres migrations. Each NNN_topic.up.sql has a matching
NNN_topic.down.sql. Run by sqlx::migrate!() at app start.
Rules
- Never edit a shipped migration. If a column needs to change or a fix needs to land, write a new migration. Production has already applied the old one and SQLx tracks each by checksum — editing in place will fail to apply on existing databases.
- Always pair
.up.sqlwith a.down.sql. Reverts may not be perfect (data loss is sometimes unavoidable) but the file must exist and do the best it can. - Prefer additive changes. New columns, new tables, new keys in
config. Drop / rename only when there is no alternative. - No business logic in migrations. Schema + seeds only. Anything that needs Rust code goes in a one-off binary, not a migration file.
- One concern per migration. Easier to revert. Easier to read in
git log.
Numbering
Zero-padded three digits, monotonically increasing. The next free number lives at the bottom of the directory listing — pick that.
Seed-only migrations
When you only need to add config keys (feature flags, defaults), use
INSERT … ON CONFLICT DO NOTHING so existing operator overrides survive. See
009_feature_toggles.up.sql for the canonical shape.