-- Durable economic idempotency for match completion. -- -- One economic effect per (profile_id, match_identity), independent of any HTTP -- receipt idempotency the game host/adapter layers on top. A sequential replay, -- a restart replay, a concurrent duplicate, or a conflicting re-report of the -- same match all collide on this UNIQUE and are refused BEFORE any coins, XP, -- statistics, objectives, or achievements are applied — the first completion is -- the one canonical result, the rest are idempotent no-ops. -- -- `match_identity` is opaque to Core: the game adapter/host derives a stable -- per-match token (e.g. the FIFA17 match-create id). Core never parses it. CREATE TABLE match_completions ( id TEXT PRIMARY KEY NOT NULL, profile_id TEXT NOT NULL REFERENCES profiles(id), match_identity TEXT NOT NULL, result TEXT NOT NULL, -- canonical: win | draw | loss | dnf | no_contest coins_awarded INTEGER NOT NULL DEFAULT 0, xp_awarded INTEGER NOT NULL DEFAULT 0, match_id TEXT NOT NULL REFERENCES matches(id), completed_at TEXT NOT NULL, UNIQUE(profile_id, match_identity) ); CREATE INDEX idx_match_completions_profile ON match_completions(profile_id); -- W/D/L already live on `statistics`; add the DNF (abandon/quit) bucket so the -- four match outcomes are mutually-exclusive counters. A did-not-finish is -- economically a loss but is tallied here, not in `matches_lost`. ALTER TABLE statistics ADD COLUMN matches_dnf INTEGER NOT NULL DEFAULT 0;