Following the reference_numbers fix, audited every active (non .skip) migration for the same failure shape — ALTER/CREATE TRIGGER against lead_requests, tracecoin_wallets, tracecoin_ledger, or job_applications without ever creating them — since this codebase has a repeated pattern of table-creation migrations getting silently disabled (renamed .skip) after the code that depends on them was already written. Found three more, ALL already pushed to origin, meaning they've likely been breaking the migration chain since the date each was deployed: - 20260317195000_profession_specific_profiles.up.sql (Mar 17) — ALTERs lead_requests twice. Earliest failure point found for the lead_requests chain. Now self-creates a minimal lead_requests table first (no FK to `leads`, which isn't created until June 10 — well after this migration). - 20260318233000_tracecoin_ledger_immutable.up.sql (Mar 18) — creates immutability triggers ON tracecoin_ledger, assuming it exists. Now self-creates tracecoin_wallets/tracecoin_ledger first, matching the column names (transaction_type/reference_type) the Rust code actually uses — the only schema that ever existed for these tables (in a disabled .skip migration) used stale names (type/reason). - 20260425000000_ai_usage.up.sql (Apr 25) — ALTERs job_applications inside a BEGIN/COMMIT block, so this failure was also rolling back company_ai_usage/job_seeker_ai_usage creation in the same file. Now self-creates job_applications first. Each later migration that also touches these tables (this session's customer/job-seeker/lead_requests fixes) now uses ADD COLUMN IF NOT EXISTS instead of assuming its own CREATE TABLE ran, so the schema converges to the same end state regardless of which migration actually created the table first. Every touched migration uses IF NOT EXISTS / idempotent guards throughout, so this is safe to apply whether or not any of these tables already exist in the real database.
55 lines
2.5 KiB
PL/PgSQL
55 lines
2.5 KiB
PL/PgSQL
-- 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();
|