Reusable signing flow: service handler generates document → inserts esign_records row → emails JWT link → client reviews PDF + signs → API stores signature + resumes pipeline. Works for RMD, CPNI, CALEA, 499-A engagement, discontinuance, CRTC, and any future doc types. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
48 lines
2.2 KiB
SQL
48 lines
2.2 KiB
SQL
-- 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');
|