Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions migrations/20260601000000_create_cbdc_gateways.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
-- migrate:up
-- CBDC Network Gateway Registry (Issue #499)
-- Tracks permissioned central bank DLT node endpoints, connection profiles,
-- mTLS certificate footprints, and operational status.

CREATE TABLE IF NOT EXISTS cbdc_gateways (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name TEXT NOT NULL,
description TEXT,
dlt_system TEXT NOT NULL CHECK (dlt_system IN ('Hyperledger Besu', 'Corda', 'Quorum', 'Hyperledger Fabric')),
network_type TEXT NOT NULL DEFAULT 'sandbox' CHECK (network_type IN ('sandbox', 'staging', 'production')),
rpc_endpoint TEXT NOT NULL,
ws_endpoint TEXT,
chain_id BIGINT,
mtls_certificate_footprint TEXT,
mtls_ca_cert_pem TEXT,
mtls_client_cert_pem TEXT,
node_identity TEXT,
connection_timeout_ms INTEGER NOT NULL DEFAULT 5000,
max_retries INTEGER NOT NULL DEFAULT 3,
retry_backoff_ms INTEGER NOT NULL DEFAULT 1000,
rate_limit_rps INTEGER NOT NULL DEFAULT 10,
is_active BOOLEAN NOT NULL DEFAULT TRUE,
last_health_check_at TIMESTAMPTZ,
last_healthy_at TIMESTAMPTZ,
health_status TEXT DEFAULT 'unknown' CHECK (health_status IN ('healthy', 'degraded', 'unreachable', 'unknown')),
metadata JSONB DEFAULT '{}'::jsonb,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE INDEX IF NOT EXISTS idx_cbdc_gateways_dlt_system ON cbdc_gateways(dlt_system);
CREATE INDEX IF NOT EXISTS idx_cbdc_gateways_status ON cbdc_gateways(health_status);
CREATE INDEX IF NOT EXISTS idx_cbdc_gateways_active ON cbdc_gateways(is_active) WHERE is_active = TRUE;

COMMENT ON TABLE cbdc_gateways IS 'CBDC Network Gateway Registry — permissioned central bank DLT node endpoints';
COMMENT ON COLUMN cbdc_gateways.dlt_system IS 'Enterprise DLT platform type: Hyperledger Besu, Corda, Quorum, or Hyperledger Fabric';
COMMENT ON COLUMN cbdc_gateways.mtls_certificate_footprint IS 'SHA-256 fingerprint of the mTLS client certificate for node authentication';
COMMENT ON COLUMN cbdc_gateways.health_status IS 'Current gateway health status as determined by the background health checker';
COMMENT ON COLUMN cbdc_gateways.metadata IS 'Flexible JSONB metadata for network-specific configuration and vendor extensions';

CREATE TRIGGER update_cbdc_gateways_updated_at
BEFORE UPDATE ON cbdc_gateways
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();

-- migrate:down
DROP TRIGGER IF EXISTS update_cbdc_gateways_updated_at ON cbdc_gateways;
DROP TABLE IF EXISTS cbdc_gateways;
90 changes: 90 additions & 0 deletions migrations/20260601000001_create_cbdc_swap_records.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
-- migrate:up
-- CBDC Cross-Rail Swap Records (Issue #499)
-- Immutable audit trail mapping on-chain Stellar transaction hashes to
-- corresponding central bank ledger block IDs for atomic cross-rail swaps.

CREATE TABLE IF NOT EXISTS cbdc_swap_records (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
swap_type TEXT NOT NULL CHECK (swap_type IN ('mint', 'burn', 'cross_rail_settlement')),
status TEXT NOT NULL DEFAULT 'pending' CHECK (status IN (
'pending', 'prepared', 'committed_cbdc', 'committed_stellar',
'completed', 'failed', 'held_for_reconciliation', 'reversed'
)),

-- Stellar leg
stellar_transaction_hash TEXT,
stellar_asset_code TEXT NOT NULL,
stellar_asset_issuer TEXT,
stellar_amount NUMERIC(36, 18) NOT NULL,
stellar_source_account TEXT,
stellar_destination_account TEXT,
stellar_trustline TEXT,
stellar_sequence_number BIGINT,
stellar_ledger BIGINT,

-- CBDC leg
cbdc_gateway_id UUID REFERENCES cbdc_gateways(id),
cbdc_transaction_id TEXT,
cbdc_block_id TEXT,
cbdc_block_number BIGINT,
cbdc_confirmations INTEGER DEFAULT 0,
cbdc_sender TEXT,
cbdc_recipient TEXT,
cbdc_amount NUMERIC(36, 18) NOT NULL,
cbdc_currency TEXT NOT NULL,
cbdc_raw_payload JSONB,

-- 2PC state
two_phase_state TEXT NOT NULL DEFAULT 'none' CHECK (two_phase_state IN (
'none', 'preparing', 'prepared', 'committing', 'committed', 'rolling_back', 'rolled_back'
)),
two_phase_lock_id TEXT,
two_phase_prepared_at TIMESTAMPTZ,
two_phase_committed_at TIMESTAMPTZ,

-- AML / Compliance
aml_screening_id TEXT,
aml_screening_result TEXT CHECK (aml_screening_result IN ('pass', 'fail', 'pending', 'escalated')),
compliance_metadata JSONB DEFAULT '{}'::jsonb,

-- Settlement worker tracking
worker_id TEXT,
worker_attempts INTEGER NOT NULL DEFAULT 0,
worker_last_error TEXT,
worker_scheduled_at TIMESTAMPTZ,
worker_completed_at TIMESTAMPTZ,

-- Multi-sig signatory approvals
required_approvals INTEGER NOT NULL DEFAULT 1,
current_approvals INTEGER NOT NULL DEFAULT 0,
approval_threshold_met BOOLEAN NOT NULL DEFAULT FALSE,

-- Audit trail
error_message TEXT,
error_code TEXT,
idempotency_key TEXT UNIQUE NOT NULL,
reversal_of UUID REFERENCES cbdc_swap_records(id),
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE INDEX IF NOT EXISTS idx_cbdc_swap_status ON cbdc_swap_records(status);
CREATE INDEX IF NOT EXISTS idx_cbdc_swap_stellar_hash ON cbdc_swap_records(stellar_transaction_hash);
CREATE INDEX IF NOT EXISTS idx_cbdc_swap_cbdc_tx ON cbdc_swap_records(cbdc_transaction_id);
CREATE INDEX IF NOT EXISTS idx_cbdc_swap_gateway ON cbdc_swap_records(cbdc_gateway_id);
CREATE INDEX IF NOT EXISTS idx_cbdc_swap_two_phase ON cbdc_swap_records(two_phase_state) WHERE two_phase_state != 'none';
CREATE INDEX IF NOT EXISTS idx_cbdc_swap_idempotency ON cbdc_swap_records(idempotency_key);
CREATE INDEX IF NOT EXISTS idx_cbdc_swap_created ON cbdc_swap_records(created_at);

COMMENT ON TABLE cbdc_swap_records IS 'Immutable cross-rail swap audit trail linking Stellar transactions to CBDC ledger operations';
COMMENT ON COLUMN cbdc_swap_records.two_phase_state IS 'Current state within the Two-Phase Commit (2PC) protocol lifecycle';
COMMENT ON COLUMN cbdc_swap_records.reversal_of IS 'References the original swap record if this entry is a reversal';
COMMENT ON COLUMN cbdc_swap_records.idempotency_key IS 'Unique idempotency key to guarantee exactly-once processing of swap requests';

CREATE TRIGGER update_cbdc_swap_records_updated_at
BEFORE UPDATE ON cbdc_swap_records
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();

-- migrate:down
DROP TRIGGER IF EXISTS update_cbdc_swap_records_updated_at ON cbdc_swap_records;
DROP TABLE IF EXISTS cbdc_swap_records;
53 changes: 53 additions & 0 deletions migrations/20260601000002_create_cryptographic_signatory_vault.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
-- migrate:up
-- Cryptographic Signatory Vault (Issue #499)
-- Tracks multi-sig approval states required for sovereign-tier token exchanges
-- with strict data residency and partitioning rules.

CREATE TABLE IF NOT EXISTS cryptographic_signatory_vault (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
swap_record_id UUID NOT NULL REFERENCES cbdc_swap_records(id) ON DELETE CASCADE,
signatory_type TEXT NOT NULL CHECK (signatory_type IN (
'central_bank_official', 'treasury_controller', 'compliance_officer',
'platform_admin', 'auditor', 'hsm_module'
)),
signatory_identity TEXT NOT NULL,
signing_key_id TEXT,
signing_algorithm TEXT NOT NULL DEFAULT 'ECDSA-P256' CHECK (signing_algorithm IN (
'ECDSA-P256', 'ECDSA-P384', 'ED25519', 'RSA-2048', 'RSA-4096',
'PKCS11-HSM'
)),
signature_value TEXT,
signature_payload TEXT,
signature_hash TEXT,
approval_action TEXT NOT NULL CHECK (approval_action IN ('approve', 'reject', 'abstain')),
approval_order INTEGER NOT NULL,
is_required BOOLEAN NOT NULL DEFAULT TRUE,
approved_at TIMESTAMPTZ,
rejected_at TIMESTAMPTZ,
rejection_reason TEXT,
expiry_at TIMESTAMPTZ,
data_residency_region TEXT NOT NULL DEFAULT 'ng-1' CHECK (data_residency_region IN (
'ng-1', 'ng-2', 'gh-1', 'ke-1', 'za-1', 'eu-1', 'us-1', 'sg-1'
)),
audit_metadata JSONB DEFAULT '{}'::jsonb,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE INDEX IF NOT EXISTS idx_signatory_vault_swap ON cryptographic_signatory_vault(swap_record_id);
CREATE INDEX IF NOT EXISTS idx_signatory_vault_status ON cryptographic_signatory_vault(approval_action);
CREATE INDEX IF NOT EXISTS idx_signatory_vault_residency ON cryptographic_signatory_vault(data_residency_region);
CREATE INDEX IF NOT EXISTS idx_signatory_vault_expiry ON cryptographic_signatory_vault(expiry_at) WHERE expiry_at IS NOT NULL;

COMMENT ON TABLE cryptographic_signatory_vault IS 'Multi-sig approval vault for sovereign-tier CBDC token exchanges with regional data residency enforcement';
COMMENT ON COLUMN cryptographic_signatory_vault.signatory_type IS 'Role category of the approving authority';
COMMENT ON COLUMN cryptographic_signatory_vault.signing_algorithm IS 'Cryptographic algorithm used for signature generation (supports PKCS#11 HSM)';
COMMENT ON COLUMN cryptographic_signatory_vault.data_residency_region IS 'Regional data residency zone for sovereign compliance (e.g., ng-1 for Nigeria)';

CREATE TRIGGER update_signatory_vault_updated_at
BEFORE UPDATE ON cryptographic_signatory_vault
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();

-- migrate:down
DROP TRIGGER IF EXISTS update_signatory_vault_updated_at ON cryptographic_signatory_vault;
DROP TABLE IF EXISTS cryptographic_signatory_vault;
41 changes: 41 additions & 0 deletions migrations/20260601000003_create_cbdc_2pc_locks.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
-- migrate:up
-- 2PC Lock Manager Persistence (Issue #499)
-- Database-backed Two-Phase Commit lock records for crash recovery.
-- The primary lock state is held in Redis for fast atomic operations;
-- this table provides durability and recovery after worker restarts.

CREATE TABLE IF NOT EXISTS cbdc_2pc_locks (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
lock_key TEXT NOT NULL UNIQUE,
swap_record_id UUID NOT NULL REFERENCES cbdc_swap_records(id),
gateway_id UUID REFERENCES cbdc_gateways(id),
lock_state TEXT NOT NULL CHECK (lock_state IN (
'preparing', 'prepared', 'committing', 'committed', 'rolling_back', 'rolled_back'
)),
lock_holder TEXT NOT NULL,
lock_acquired_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
lock_expires_at TIMESTAMPTZ NOT NULL,
prepared_payload JSONB,
commit_payload JSONB,
rollback_payload JSONB,
node_failure_count INTEGER NOT NULL DEFAULT 0,
last_heartbeat_at TIMESTAMPTZ,
recovered_at TIMESTAMPTZ,
error_detail TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE INDEX IF NOT EXISTS idx_2pc_locks_state ON cbdc_2pc_locks(lock_state);
CREATE INDEX IF NOT EXISTS idx_2pc_locks_expiry ON cbdc_2pc_locks(lock_expires_at) WHERE lock_state NOT IN ('committed', 'rolled_back');

COMMENT ON TABLE cbdc_2pc_locks IS 'Persistent Two-Phase Commit lock records for crash recovery and disaster recovery';
COMMENT ON COLUMN cbdc_2pc_locks.lock_state IS 'Current 2PC protocol phase — used to resume interrupted transactions after worker restart';

CREATE TRIGGER update_cbdc_2pc_locks_updated_at
BEFORE UPDATE ON cbdc_2pc_locks
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();

-- migrate:down
DROP TRIGGER IF EXISTS update_cbdc_2pc_locks_updated_at ON cbdc_2pc_locks;
DROP TABLE IF EXISTS cbdc_2pc_locks;
Loading