Data Model & Database Design
The authoritative schema is defined in packages/db/src/schema/index.ts and versioned through Drizzle migrations.
Core Principles
- Wallet and audit domains are append-only where integrity matters.
- Tenant isolation is encoded in schema and reinforced in middleware.
- Deduplication is enforced by DB constraints, not only in memory.
- Historical explainability is preserved through versioned rules and linked reward events.
Domain Tables
Identity and tenancy
userstenantstenant_users
POS integration
pos_connectionspos_webhook_events_raw
Transactions and rewards
transactionsreward_rulesreward_events
Wallets and financial trail
walletswallet_ledger
Governance and reliability
idempotency_keysadmin_audit_logs
High-Value Constraints
Transaction dedup
transactions has unique key:
(tenant_id, provider, provider_transaction_id)
This is a critical idempotency guard for webhook and poll replays.
Single wallet per user per tenant
wallets has unique key:
(tenant_id, user_id)
Ledger invariants
wallet_ledger includes checks:
entry_type IN ('credit', 'debit')points > 0
Balance direction is represented by entry type, not signed values.
Migration Progression
Current sequence:
0000_puzzling_proudstar.sql- baseline schema0001_lovely_patch.sql- onboarding fields on tenants0002_tired_cannonball.sql- Square poll watermark on pos connections
ER Snapshot
Operational Notes
users.idis mapped to Supabase user UUID and is not auto-generated by app logic.- OAuth tokens are stored encrypted in
pos_connections. - Raw webhook payload storage supports debugging and replay-safe processing.
Deep Dive
See Data Model and Migrations for implementation-level detail.
Written byDhruv Doshi