-- 076: Generic eSign records — stores signatures for any document type. -- -- Instead of adding esign columns to every order table, this table -- stores one row per signature event, linked by order_number. -- -- Supports: RMD, CPNI, CALEA SSI, 499-A engagement, discontinuance, -- CRTC, and any future document types. -- -- The portal token carries { order_id (= order_number), order_type, email }. -- order_type tells us which table/service the document belongs to. CREATE TABLE IF NOT EXISTS esign_records ( id SERIAL PRIMARY KEY, order_number TEXT NOT NULL, -- e.g. CO-ABCD1234 document_type TEXT NOT NULL, -- rmd, cpni, calea, 499a-engagement, discontinuance, crtc, etc. document_title TEXT NOT NULL DEFAULT '', -- human-readable title shown to signer entity_name TEXT NOT NULL DEFAULT '', -- company name shown on signing page -- Document reference document_minio_key TEXT, -- MinIO key for the PDF to sign document_metadata JSONB DEFAULT '{}', -- any extra data (FRN, order details, etc.) -- Signature signature_type TEXT CHECK (signature_type IN ('drawn', 'typed')), signature_data TEXT, -- base64 PNG (drawn) or typed name signer_email TEXT, signer_ip TEXT, signer_user_agent TEXT, -- Perjury declaration requires_perjury BOOLEAN DEFAULT FALSE, perjury_agreed BOOLEAN DEFAULT FALSE, -- Status status TEXT NOT NULL DEFAULT 'pending' CHECK (status IN ('pending', 'signed', 'expired', 'revoked')), signed_at TIMESTAMPTZ, expires_at TIMESTAMPTZ, -- Audit created_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW() ); CREATE INDEX IF NOT EXISTS idx_esign_order ON esign_records(order_number); CREATE INDEX IF NOT EXISTS idx_esign_status ON esign_records(status) WHERE status = 'pending'; CREATE UNIQUE INDEX IF NOT EXISTS idx_esign_order_doc ON esign_records(order_number, document_type) WHERE status IN ('pending', 'signed');