The electorate is a Discord server
Discord is the identity provider and the membership gate. A
four-branch account-matching ladder handles OAuth edge cases; a bot
re-verifies stale memberships every 24h — daily batch plus lazy
per-request refresh — and treats 200 / 404 / 5xx distinctly, so
someone who leaves the server loses the ballot without ever seeing
a login screen.
Two music catalogues, one interface
Nomination search runs through a MetadataResolver
interface with per-category resolvers — Spotify track, album,
artist; YouTube video — so forms and dedup stay provider-agnostic.
Spotify’s bearer token is cached for 59 minutes of its 60-minute
life. A YouTube search costs 100 quota units, so results are
enriched with one batched 1-unit call instead of per-video lookups.
When a provider dies or the quota burns out, the UI collapses to a
URL-paste fallback and nominations keep flowing.
Caching that can’t serve stale
Read paths are cache-aside on Redis with versioned keys:
invalidation is a single counter increment fired by model
observers — no key scans, no wildcard deletes, a one-hour safety
TTL as the net. External API responses cache 24h for real hits,
10 minutes for empty results, and errors are never cached — a
momentary Spotify outage can’t freeze “no results” for a day.
Duplicates, in a language full of diacritics
Fuzzy dedup runs in Postgres — pg_trgm trigram similarity over
unaccent-normalized text (Edavārdi ≈ Edavardi) on a GIN
index, one query. A soft threshold powers the live “did you mean”
hint; a hard threshold blocks the submit. The public hint endpoint
only ever surfaces approved entries, so anonymous probes can’t
read the pending queue.
One ballot, no races
Ballot submission takes a Postgres advisory lock per user and
category, re-checks everything inside it — phase, ballot size,
nomination validity, already-voted — and backs it with a unique
index. Votes denormalize category and cycle so tallies are one
indexed aggregation; reveals snapshot results into an immutable
table read by the archive.
The server fetches what users paste
Text nominations auto-fill page titles from pasted URLs — a
classic SSRF hole, closed: private, loopback, and cloud-metadata
ranges blocked, DNS rebinding checked by resolving before fetching,
every redirect hop re-validated, all on a 4-second / 4-redirect /
512 KB budget.
Proof it holds
449 Pest test cases — OAuth flows, cache
invalidation, dedup behavior against a real Postgres with pg_trgm,
voting guards, admin authorization — running in CI on every push.
Production is six Docker services behind Caddy with
Cloudflare-locked ingress, nightly rotated backups, and
opcache-safe deploys.