new-site/api/migrations/065_crypto_payment_jobs.sql
justin f8cd37ac8c Initial commit — Performance West telecom compliance platform
Includes: API (Express/TypeScript), Astro site, Python workers,
document generators, FCC compliance tools, Canada CRTC formation,
Ansible infrastructure, and deployment scripts.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-27 06:54:22 -05:00

67 lines
3.7 KiB
SQL

-- 065: Crypto payment orchestrator jobs + Relay deposit source tagging
--
-- `crypto_payment_jobs` is the worker's mutable state machine (one row
-- per crypto-paid order). `crypto_payment_ledger` is immutable audit;
-- `crypto_payment_jobs` is where the worker records state transitions.
--
-- Also adds `source_kind` to `relay_deposits` so the matcher can tell
-- "this $X deposit was our Coinbase Prime offramp" vs "this was a
-- Stripe ACH batch" vs "something else — operator review".
CREATE TABLE IF NOT EXISTS crypto_payment_jobs (
order_id TEXT PRIMARY KEY,
order_type TEXT NOT NULL,
state TEXT NOT NULL DEFAULT 'received'
CHECK (state IN (
'received', -- SHKeeper webhook in, job enqueued
'sizing', -- computing vendor_obligations
'offramping', -- Coinbase Prime sell + wire initiated
'funds_at_relay', -- USD landed in RelayFi account
'ready', -- Playwright filing flow can now charge the card
'settled', -- reservation spent, order complete
'failed', -- attempt_count exhausted
'manual' -- admin intervention required
)),
coin TEXT NOT NULL,
amount_coin NUMERIC(36,18) NOT NULL,
amount_usd_cents BIGINT NOT NULL, -- SHKeeper balance_fiat at receipt
needed_usd_cents BIGINT, -- sizer output: filing + 10% + commission
offramp_provider TEXT DEFAULT 'coinbase_prime',
offramp_ref TEXT, -- Coinbase Prime order id / transfer id
relay_deposit_id INT REFERENCES relay_deposits(id),
target_card_id TEXT DEFAULT 'RELAY_FILING_CARD_ID',
last_error TEXT,
attempt_count INT NOT NULL DEFAULT 0,
next_retry_at TIMESTAMPTZ,
idempotency_key TEXT UNIQUE, -- "shkeeper-settle:<order>:<first-txid>"
received_at TIMESTAMPTZ,
sized_at TIMESTAMPTZ,
offramping_at TIMESTAMPTZ,
funds_at_relay_at TIMESTAMPTZ,
settled_at TIMESTAMPTZ,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX IF NOT EXISTS idx_cpj_active
ON crypto_payment_jobs (state)
WHERE state NOT IN ('settled','failed');
CREATE INDEX IF NOT EXISTS idx_cpj_retry
ON crypto_payment_jobs (next_retry_at)
WHERE state NOT IN ('settled','failed','manual') AND next_retry_at IS NOT NULL;
-- ── Extend relay_deposits for source tagging ──────────────────────────
-- Parsed from the Relay deposit notification email body/sender. Values:
-- 'stripe_ach' — Stripe customer payments batched to Relay
-- 'offramp_coinbase_prime' — our own Coinbase Prime → Relay wire/RTP
-- 'internal_transfer' — between our own accounts
-- 'unknown' — operator review required
ALTER TABLE relay_deposits ADD COLUMN IF NOT EXISTS source_kind TEXT;
ALTER TABLE relay_deposits ADD COLUMN IF NOT EXISTS memo TEXT;
-- memo captures the beneficiary memo field (e.g., 'PW-ORDER-FO-2026-0042')
-- so the matcher can find the corresponding crypto_payment_jobs row.
CREATE INDEX IF NOT EXISTS idx_relay_deposits_unmatched_offramp
ON relay_deposits (detected_at DESC)
WHERE source_kind = 'offramp_coinbase_prime' AND processed = FALSE;