Add full monorepo: virtual-banker, backend, frontend, docs, scripts, deployment
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
167
docs/specs/banking/account-ledger.md
Normal file
167
docs/specs/banking/account-ledger.md
Normal file
@@ -0,0 +1,167 @@
|
||||
# Account & Ledger Specification
|
||||
|
||||
## Overview
|
||||
|
||||
This document specifies the customer ledger system using double-entry bookkeeping principles for banking operations.
|
||||
|
||||
## Double-Entry Ledger Schema
|
||||
|
||||
### Ledger Entry
|
||||
|
||||
```sql
|
||||
CREATE TABLE ledger_entries (
|
||||
id UUID PRIMARY KEY,
|
||||
customer_id UUID NOT NULL,
|
||||
transaction_id UUID NOT NULL,
|
||||
entry_type VARCHAR(20) NOT NULL, -- 'debit', 'credit'
|
||||
account_type VARCHAR(50) NOT NULL, -- 'cash', 'crypto', 'fiat', etc.
|
||||
amount NUMERIC(78, 0) NOT NULL,
|
||||
currency VARCHAR(10) NOT NULL,
|
||||
description TEXT,
|
||||
reference_id VARCHAR(255), -- External transaction reference
|
||||
created_at TIMESTAMP DEFAULT NOW(),
|
||||
FOREIGN KEY (customer_id) REFERENCES customers(id),
|
||||
FOREIGN KEY (transaction_id) REFERENCES transactions(id)
|
||||
);
|
||||
```
|
||||
|
||||
### Transaction Table
|
||||
|
||||
```sql
|
||||
CREATE TABLE transactions (
|
||||
id UUID PRIMARY KEY,
|
||||
customer_id UUID NOT NULL,
|
||||
transaction_type VARCHAR(50) NOT NULL, -- 'deposit', 'withdrawal', 'transfer', etc.
|
||||
status VARCHAR(20) NOT NULL, -- 'pending', 'completed', 'failed'
|
||||
amount NUMERIC(78, 0) NOT NULL,
|
||||
currency VARCHAR(10) NOT NULL,
|
||||
from_account UUID,
|
||||
to_account UUID,
|
||||
blockchain_tx_hash VARCHAR(66), -- If blockchain transaction
|
||||
created_at TIMESTAMP DEFAULT NOW(),
|
||||
completed_at TIMESTAMP,
|
||||
FOREIGN KEY (customer_id) REFERENCES customers(id)
|
||||
);
|
||||
```
|
||||
|
||||
### Double-Entry Rule
|
||||
|
||||
**Constraint**: Sum of debits = Sum of credits for each transaction
|
||||
|
||||
**Implementation**: Two entries per transaction (debit and credit)
|
||||
|
||||
## Wallet Mapping
|
||||
|
||||
### Customer-Wallet Mapping
|
||||
|
||||
```sql
|
||||
CREATE TABLE customer_wallets (
|
||||
id UUID PRIMARY KEY,
|
||||
customer_id UUID NOT NULL,
|
||||
chain_id INTEGER NOT NULL,
|
||||
address VARCHAR(42) NOT NULL,
|
||||
wallet_type VARCHAR(20) NOT NULL, -- 'external', 'custodial'
|
||||
verified BOOLEAN DEFAULT false,
|
||||
verified_at TIMESTAMP,
|
||||
created_at TIMESTAMP DEFAULT NOW(),
|
||||
UNIQUE (customer_id, chain_id, address),
|
||||
FOREIGN KEY (customer_id) REFERENCES customers(id)
|
||||
);
|
||||
```
|
||||
|
||||
### Wallet Verification
|
||||
|
||||
**Process**:
|
||||
1. Customer provides address
|
||||
2. Request signature verification
|
||||
3. Verify signature matches address
|
||||
4. Link address to customer account
|
||||
5. Mark as verified
|
||||
|
||||
## Reconciliation Jobs
|
||||
|
||||
### Reconciliation Process
|
||||
|
||||
**Purpose**: Ensure ledger matches actual blockchain/custodial balances
|
||||
|
||||
**Frequency**: Daily or real-time (depending on account type)
|
||||
|
||||
**Steps**:
|
||||
1. Query actual balances (blockchain or custodial wallet)
|
||||
2. Calculate expected balance from ledger
|
||||
3. Compare and identify discrepancies
|
||||
4. Create reconciliation entries if needed
|
||||
5. Alert on discrepancies
|
||||
|
||||
### Reconciliation Schema
|
||||
|
||||
```sql
|
||||
CREATE TABLE reconciliations (
|
||||
id UUID PRIMARY KEY,
|
||||
customer_id UUID NOT NULL,
|
||||
account_type VARCHAR(50) NOT NULL,
|
||||
currency VARCHAR(10) NOT NULL,
|
||||
expected_balance NUMERIC(78, 0) NOT NULL,
|
||||
actual_balance NUMERIC(78, 0) NOT NULL,
|
||||
discrepancy NUMERIC(78, 0) NOT NULL,
|
||||
status VARCHAR(20) NOT NULL, -- 'matched', 'discrepancy', 'resolved'
|
||||
reconciled_at TIMESTAMP DEFAULT NOW(),
|
||||
resolved_at TIMESTAMP,
|
||||
FOREIGN KEY (customer_id) REFERENCES customers(id)
|
||||
);
|
||||
```
|
||||
|
||||
## Audit Trails
|
||||
|
||||
### Audit Log Schema
|
||||
|
||||
```sql
|
||||
CREATE TABLE audit_logs (
|
||||
id UUID PRIMARY KEY,
|
||||
customer_id UUID,
|
||||
action VARCHAR(100) NOT NULL,
|
||||
resource_type VARCHAR(50) NOT NULL,
|
||||
resource_id VARCHAR(255),
|
||||
old_value JSONB,
|
||||
new_value JSONB,
|
||||
actor_id UUID NOT NULL, -- User/system that performed action
|
||||
ip_address VARCHAR(45),
|
||||
user_agent TEXT,
|
||||
created_at TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
```
|
||||
|
||||
### Immutable Log Storage
|
||||
|
||||
**Storage**: Append-only log (immutable)
|
||||
**Retention**: Per regulatory requirements (typically 7 years)
|
||||
**Access**: Audit team only
|
||||
**Integrity**: Cryptographic hashing for tamper detection
|
||||
|
||||
## Balance Calculations
|
||||
|
||||
### Account Balance
|
||||
|
||||
**Formula**: Sum of credits - Sum of debits for account
|
||||
|
||||
**Implementation**:
|
||||
```sql
|
||||
SELECT
|
||||
SUM(CASE WHEN entry_type = 'credit' THEN amount ELSE 0 END) -
|
||||
SUM(CASE WHEN entry_type = 'debit' THEN amount ELSE 0 END) AS balance
|
||||
FROM ledger_entries
|
||||
WHERE customer_id = ? AND account_type = ? AND currency = ?;
|
||||
```
|
||||
|
||||
### Real-Time Balance
|
||||
|
||||
**Caching**: Cache balances with TTL
|
||||
**Updates**: Invalidate on new ledger entries
|
||||
**Accuracy**: Reconcile with actual balances periodically
|
||||
|
||||
## References
|
||||
|
||||
- Identity & Compliance: See `identity-compliance.md`
|
||||
- Payment Rails: See `payment-rails.md`
|
||||
- Database Schema: See `../database/postgres-schema.md`
|
||||
|
||||
Reference in New Issue
Block a user