2.9 KiB
2.9 KiB
Database Migrations
This directory contains SQL migrations that enforce ledger correctness boundaries.
Migration Order
Run migrations in this order:
001_ledger_idempotency.sql- Add unique constraint for idempotency002_dual_ledger_outbox.sql- Create outbox table003_outbox_state_machine.sql- Enforce state machine constraints004_balance_constraints.sql- Enforce balance integrity (apply after data cleanup)005_post_ledger_entry.sql- Create atomic posting function006_sal_positions_fees.sql- SAL extension: positions (asset x chain), fees, reconciliation snapshots
Running Migrations
Option 1: Direct SQL execution
# Set your database connection
export DATABASE_URL="postgresql://user:password@host:port/database"
# Run migrations in order
psql $DATABASE_URL -f db/migrations/001_ledger_idempotency.sql
psql $DATABASE_URL -f db/migrations/002_dual_ledger_outbox.sql
psql $DATABASE_URL -f db/migrations/003_outbox_state_machine.sql
psql $DATABASE_URL -f db/migrations/004_balance_constraints.sql
psql $DATABASE_URL -f db/migrations/005_post_ledger_entry.sql
psql $DATABASE_URL -f db/migrations/006_sal_positions_fees.sql
Option 2: Prisma migrate (if using Prisma migrations)
These SQL files can be added to a Prisma migration:
npx prisma migrate dev --name add_ledger_correctness_boundaries
Then copy the SQL into the generated migration file.
Important Notes
Column Naming
These migrations assume snake_case column names in the database (Prisma default).
If your database uses camelCase, adjust the SQL accordingly:
ledger_id→ledgerIddebit_account_id→debitAccountId- etc.
Balance Constraints
The balance constraints in 004_balance_constraints.sql will fail if you have existing inconsistent data.
Before applying:
- Audit existing balances
- Fix any inconsistencies
- Then apply the constraints
Testing
After applying migrations, verify:
-- Check idempotency constraint exists
SELECT constraint_name
FROM information_schema.table_constraints
WHERE table_name = 'ledger_entries'
AND constraint_name LIKE '%reference%';
-- Check outbox table exists
SELECT COUNT(*) FROM dual_ledger_outbox;
-- Test posting function
SELECT * FROM post_ledger_entry(
'Test'::TEXT,
'account1'::TEXT,
'account2'::TEXT,
100::NUMERIC,
'USD'::TEXT,
'fiat'::TEXT,
'Type_A'::TEXT,
'test-ref-123'::TEXT,
NULL::NUMERIC,
NULL::JSONB
);
Rollback
These migrations are designed to be additive. To rollback:
- Drop the function:
DROP FUNCTION IF EXISTS post_ledger_entry(...); - Drop the outbox table:
DROP TABLE IF EXISTS dual_ledger_outbox CASCADE; - Remove constraints:
ALTER TABLE ledger_entries DROP CONSTRAINT IF EXISTS ledger_entries_unique_ledger_reference; - Remove balance constraints:
ALTER TABLE bank_accounts DROP CONSTRAINT IF EXISTS ...;