-- Enforce immutable tracecoin ledger: no UPDATE/DELETE allowed. -- -- This migration assumed tracecoin_wallets/tracecoin_ledger already existed -- (they were meant to come from an earlier migration that was later disabled -- via .skip, with no active replacement) — so `CREATE TRIGGER ... ON -- tracecoin_ledger` below has been failing with "relation tracecoin_ledger -- does not exist" on any environment where those tables were never created, -- which blocks every migration after this one in the chain. Self-creating -- both tables here (idempotent, matching the schema -- crates/db/src/models/tracecoin_wallet.rs actually reads/writes) makes this -- migration correct on its own regardless of what ran before it. CREATE TABLE IF NOT EXISTS tracecoin_wallets ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE UNIQUE, balance INTEGER NOT NULL DEFAULT 0, reserved INTEGER NOT NULL DEFAULT 0, updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE TABLE IF NOT EXISTS tracecoin_ledger ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), wallet_id UUID NOT NULL REFERENCES tracecoin_wallets(id), transaction_type VARCHAR(20) NOT NULL, amount INTEGER NOT NULL, reference_type VARCHAR(50), reference_id UUID, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); -- Defensive fallback in case tracecoin_ledger already existed under the -- older, stale column names (`type`/`reason`) from the disabled migration. ALTER TABLE tracecoin_ledger ADD COLUMN IF NOT EXISTS transaction_type VARCHAR(20); ALTER TABLE tracecoin_ledger ADD COLUMN IF NOT EXISTS reference_type VARCHAR(50); CREATE INDEX IF NOT EXISTS idx_tracecoin_ledger_wallet_id ON tracecoin_ledger(wallet_id); CREATE INDEX IF NOT EXISTS idx_tracecoin_ledger_reference_id ON tracecoin_ledger(reference_id); CREATE OR REPLACE FUNCTION prevent_tracecoin_ledger_mutation() RETURNS trigger AS $$ BEGIN RAISE EXCEPTION 'tracecoin_ledger is immutable; % is not allowed', TG_OP; END; $$ LANGUAGE plpgsql; DROP TRIGGER IF EXISTS trg_prevent_tracecoin_ledger_update ON tracecoin_ledger; CREATE TRIGGER trg_prevent_tracecoin_ledger_update BEFORE UPDATE ON tracecoin_ledger FOR EACH ROW EXECUTE FUNCTION prevent_tracecoin_ledger_mutation(); DROP TRIGGER IF EXISTS trg_prevent_tracecoin_ledger_delete ON tracecoin_ledger; CREATE TRIGGER trg_prevent_tracecoin_ledger_delete BEFORE DELETE ON tracecoin_ledger FOR EACH ROW EXECUTE FUNCTION prevent_tracecoin_ledger_mutation();