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>
This commit is contained in:
commit
f8cd37ac8c
1823 changed files with 145167 additions and 0 deletions
104
api/migrations/017_identity_verifications.sql
Normal file
104
api/migrations/017_identity_verifications.sql
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
-- 017_identity_verifications.sql
|
||||
-- Stripe Identity verification sessions for director KYC.
|
||||
--
|
||||
-- Every CRTC order director is verified via Stripe Identity BEFORE the order is
|
||||
-- saved and before any payment is collected. The verification session extracts
|
||||
-- name and date of birth from the ID document, which are compared against what
|
||||
-- the customer entered on the order form.
|
||||
--
|
||||
-- Applies to ALL payment methods (card, ACH, Klarna, crypto).
|
||||
--
|
||||
-- Match result tiers:
|
||||
-- name_match: exact | fuzzy_pass | fuzzy_warn | mismatch
|
||||
-- dob_match: exact | no_dob_on_id | mismatch
|
||||
-- overall: verified | pending | needs_review | failed
|
||||
--
|
||||
-- 'needs_review' orders are held in a manual queue — payment is NOT collected
|
||||
-- until an admin clears them. This is a hard gate.
|
||||
|
||||
BEGIN;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS identity_verifications (
|
||||
id SERIAL PRIMARY KEY,
|
||||
|
||||
-- Stripe Identity
|
||||
stripe_session_id TEXT NOT NULL UNIQUE,
|
||||
stripe_report_id TEXT, -- verification_report id once complete
|
||||
stripe_status TEXT, -- 'requires_input' | 'processing' | 'verified' | 'canceled'
|
||||
|
||||
-- What customer typed on the form
|
||||
form_director_name TEXT NOT NULL,
|
||||
form_director_dob DATE, -- null if customer didn't enter DOB
|
||||
|
||||
-- What Stripe extracted from the ID document
|
||||
id_first_name TEXT,
|
||||
id_last_name TEXT,
|
||||
id_full_name_extracted TEXT, -- first + last concatenated
|
||||
id_dob_year INTEGER,
|
||||
id_dob_month INTEGER,
|
||||
id_dob_day INTEGER,
|
||||
id_doc_type TEXT, -- 'driving_license' | 'passport' | 'id_card'
|
||||
id_issuing_country TEXT,
|
||||
id_expiry_year INTEGER,
|
||||
id_expiry_month INTEGER,
|
||||
id_expiry_day INTEGER,
|
||||
id_number TEXT, -- redacted after comparison
|
||||
|
||||
-- Comparison results
|
||||
name_match_score NUMERIC(5,2), -- 0-100 fuzzy score
|
||||
name_match TEXT -- 'exact' | 'fuzzy_pass' | 'fuzzy_warn' | 'mismatch' | 'pending'
|
||||
CHECK (name_match IN ('exact','fuzzy_pass','fuzzy_warn','mismatch','pending')),
|
||||
dob_match TEXT -- 'exact' | 'no_dob_on_id' | 'mismatch' | 'pending'
|
||||
CHECK (dob_match IN ('exact','no_dob_on_id','mismatch','pending')),
|
||||
doc_expired BOOLEAN DEFAULT FALSE,
|
||||
|
||||
-- Overall gate result
|
||||
overall_result TEXT NOT NULL DEFAULT 'pending'
|
||||
CHECK (overall_result IN ('pending','verified','needs_review','failed')),
|
||||
|
||||
-- Admin review
|
||||
reviewed_by TEXT,
|
||||
review_notes TEXT,
|
||||
reviewed_at TIMESTAMPTZ,
|
||||
admin_override BOOLEAN DEFAULT FALSE, -- admin manually cleared needs_review
|
||||
|
||||
-- Linkage
|
||||
order_number TEXT, -- set once order is created
|
||||
order_type TEXT DEFAULT 'canada_crtc',
|
||||
customer_email TEXT,
|
||||
|
||||
-- Audit
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
verified_at TIMESTAMPTZ,
|
||||
ip_address TEXT,
|
||||
user_agent TEXT
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_iv_session ON identity_verifications (stripe_session_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_iv_order ON identity_verifications (order_number);
|
||||
CREATE INDEX IF NOT EXISTS idx_iv_result ON identity_verifications (overall_result, created_at);
|
||||
CREATE INDEX IF NOT EXISTS idx_iv_needs_review ON identity_verifications (overall_result)
|
||||
WHERE overall_result = 'needs_review' AND admin_override = FALSE;
|
||||
|
||||
-- Add identity_session_id to CRTC orders so the order route can gate on it
|
||||
ALTER TABLE canada_crtc_orders
|
||||
ADD COLUMN IF NOT EXISTS identity_session_id TEXT
|
||||
REFERENCES identity_verifications(stripe_session_id) ON DELETE SET NULL;
|
||||
|
||||
ALTER TABLE canada_crtc_orders
|
||||
ADD COLUMN IF NOT EXISTS identity_result TEXT
|
||||
CHECK (identity_result IN ('verified','needs_review','failed','pending'));
|
||||
|
||||
-- Admin view: sessions awaiting review
|
||||
CREATE OR REPLACE VIEW identity_pending_review AS
|
||||
SELECT
|
||||
iv.*,
|
||||
o.order_number AS linked_order,
|
||||
o.customer_email AS order_email
|
||||
FROM identity_verifications iv
|
||||
LEFT JOIN canada_crtc_orders o ON o.identity_session_id = iv.stripe_session_id
|
||||
WHERE iv.overall_result = 'needs_review'
|
||||
AND iv.admin_override = FALSE
|
||||
ORDER BY iv.created_at DESC;
|
||||
|
||||
COMMIT;
|
||||
Loading…
Add table
Add a link
Reference in a new issue