-- Internal credit ledger foundation; no public payment or credit-grant route. CREATE TABLE IF NOT EXISTS opt_credit_accounts ( tenant_id text PRIMARY KEY CHECK (length(tenant_id) > 0), available bigint NOT NULL DEFAULT 0 CHECK (available >= 0 AND available <= 9007199254740991), reserved bigint NOT NULL DEFAULT 0 CHECK (reserved >= 0 AND reserved <= 9007199254740991) ); CREATE TABLE IF NOT EXISTS opt_credit_reservations ( tenant_id text NOT NULL REFERENCES opt_credit_accounts(tenant_id), reservation_id text NOT NULL CHECK (length(reservation_id) > 0), amount bigint NOT NULL CHECK (amount > 0 AND amount <= 9007199254740991), status text NOT NULL CHECK (status IN ('reserved', 'settled', 'released')), settled_amount bigint CHECK (settled_amount >= 0 AND settled_amount <= amount), PRIMARY KEY (tenant_id, reservation_id) ); CREATE TABLE IF NOT EXISTS opt_credit_events ( event_id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY, tenant_id text NOT NULL REFERENCES opt_credit_accounts(tenant_id), idempotency_key text NOT NULL CHECK (length(idempotency_key) > 0), kind text NOT NULL CHECK (kind IN ('verified_payment', 'reserve', 'settle', 'release')), amount bigint NOT NULL CHECK (amount >= 0 AND amount <= 9007199254740991), reference text NOT NULL CHECK (length(reference) > 0), created_at timestamptz NOT NULL DEFAULT now(), UNIQUE (tenant_id, idempotency_key) ); -- A single external payment cannot fund multiple tenants or grants. CREATE UNIQUE INDEX IF NOT EXISTS opt_credit_verified_payment_reference ON opt_credit_events(reference) WHERE kind = 'verified_payment'; -- Server-owned price snapshot. Never read price or credits from PAY0 metadata. CREATE TABLE IF NOT EXISTS opt_credit_purchases ( tenant_id text NOT NULL CHECK (length(tenant_id) > 0), purchase_id text NOT NULL CHECK (length(purchase_id) > 0), checkout_session_id text NOT NULL UNIQUE CHECK (length(checkout_session_id) > 0), amount_minor bigint NOT NULL CHECK (amount_minor > 0 AND amount_minor <= 9007199254740991), currency text NOT NULL CHECK (currency ~ '^[A-Z]{3}$'), credits bigint NOT NULL CHECK (credits > 0 AND credits <= 9007199254740991), created_at timestamptz NOT NULL DEFAULT now(), PRIMARY KEY (tenant_id, purchase_id) );