Open-Audit now includes a comprehensive Reconciliation Worker that:
- Detects Data Gaps — Identifies missing events due to network failures, database deadlocks, or maintenance windows
- Verifies Data Integrity — Compares local database events with the authoritative Stellar RPC source
- Auto-Repairs — Automatically reindexes missing or corrupted events (optional)
- Maintains Audit Trail — Records all reconciliation actions for compliance and oversight
- Runs Automatically — Executes on a configurable daily cron schedule or on-demand
┌─────────────────────────────────────────────────────────────┐
│ Open-Audit System │
├─────────────────────────────────────────────────────────────┤
│ │
│ PostgreSQL Database │
│ ├── events (persisted with reconciliation metadata) │
│ ├── reconciliation_jobs (job history & status) │
│ ├── audit_logs (complete audit trail) │
│ └── reconciliation_config (configuration) │
│ │
│ Redis + Bull Queue │
│ └── Async job processing & retry logic │
│ │
│ Reconciliation Engine │
│ ├── Comparator (DB vs RPC comparison) │
│ ├── Auditor (audit trail recording) │
│ └── Scheduler (cron-based job triggering) │
│ │
│ API Endpoints │
│ ├── /api/health (system health) │
│ ├── /api/reconciliation/status (job status) │
│ ├── /api/reconciliation/trigger (manual trigger) │
│ ├── /api/reconciliation/config (configuration) │
│ ├── /api/reconciliation/history (job history) │
│ └── /api/reconciliation/report/[jobId] (detailed reports) │
│ │
└─────────────────────────────────────────────────────────────┘
All necessary packages are already added to package.json:
npm installKey packages:
@prisma/client— ORM for databasebull— Redis-based job queueioredis— Redis clientnode-cron— Cron schedulingpino— Structured logging
# Update .env.local
DATABASE_URL=postgresql://user:password@localhost:5432/openaudit
# Run migrations
npm run db:migrate# Update .env.local
DATABASE_URL=file:./dev.db
# Run migrations
npm run db:migrate# Start Redis locally
redis-server
# Or using Docker
docker run -d -p 6379:6379 redis:latest
# Update .env.local
REDIS_URL=redis://localhost:6379npm run db:seedThis creates the default reconciliation configuration.
# Development with hot reload
npm run dev
# Production
npm run build
npm startEdit reconciliation settings in the database or via the API:
# Via API (GET current config)
curl http://localhost:3000/api/reconciliation/config
# Via API (UPDATE config)
curl -X PUT http://localhost:3000/api/reconciliation/config \
-H "Content-Type: application/json" \
-d '{
"cronSchedule": "0 2 * * *",
"lookbackDays": 7,
"autoFix": false,
"alertThreshold": 0.1
}'| Option | Default | Description |
|---|---|---|
cronSchedule |
0 2 * * * |
Cron schedule for daily reconciliation (2 AM UTC) |
batchSize |
1000 |
Number of events to process per batch |
lookbackDays |
7 |
Number of days to reconcile |
autoFix |
false |
Automatically reindex missing events |
alertThreshold |
0.1 |
Alert if discrepancies > 0.1% |
enabled |
true |
Enable/disable reconciliation |
curl http://localhost:3000/api/healthResponse:
{
"status": "healthy",
"database": {
"connected": true,
"totalEvents": 45230,
"verifiedEvents": 45215,
"pendingVerification": 15,
"verificationRate": "99.97%"
},
"indexer": {
"lastLedger": 50000000
},
"timestamp": "2026-06-19T14:32:00Z"
}curl http://localhost:3000/api/reconciliation/statuscurl -X POST http://localhost:3000/api/reconciliation/trigger \
-H "Content-Type: application/json" \
-d '{
"startLedger": 49500000,
"endLedger": 50000000,
"autoFix": false
}'curl "http://localhost:3000/api/reconciliation/history?limit=10&offset=0"curl "http://localhost:3000/api/reconciliation/report/[jobId]"
# Get as HTML
curl "http://localhost:3000/api/reconciliation/report/[jobId]?format=html"- Scheduled Trigger — Runs daily at 2 AM UTC (configurable)
- Ledger Range Calculation — Determines which ledgers to reconcile based on
lookbackDays - Queue Job — Adds reconciliation job to Bull queue
- Process Job — Bull worker processes the job with retry logic
- Compare Data — Compares local DB with Stellar RPC
- Detect Discrepancies — Identifies gaps and mismatches
- Record Audit Trail — Logs all findings
- Auto-Repair (Optional) — Reindexes missing events if enabled
- Report — Generates summary report
# Trigger a manual reconciliation for a specific ledger range
curl -X POST http://localhost:3000/api/reconciliation/trigger \
-H "Content-Type: application/json" \
-d '{
"startLedger": 1000000,
"endLedger": 1010000,
"contractIds": ["CABC001"],
"autoFix": true
}'The reconciliation system detects:
- Missing Events — Events in RPC but not in local database
- Extra Events — Events in database not found in RPC (possible re-org)
- Data Mismatches — Event data doesn't match between DB and RPC
- Corruption — Hash mismatches indicating data corruption
Every reconciliation action is logged:
// Example audit log entry
{
jobId: "1000-2000-1234567890",
action: "detected", // "detected" | "fixed" | "flagged" | "verified"
eventId: "event-12345",
ledger: 1500,
details: {
issue: "Event missing from local database",
action: "reindex"
},
createdAt: "2026-06-19T14:32:00Z"
}The system accurately detects when database records are deleted:
# 1. Artificially delete an event
DELETE FROM events WHERE id = 'event-12345';
# 2. Trigger reconciliation
curl -X POST http://localhost:3000/api/reconciliation/trigger \
-d '{"startLedger": 1000, "endLedger": 2000}'
# 3. Check the report
curl http://localhost:3000/api/reconciliation/report/[jobId]
# Response includes:
{
"discrepancies": [
{
"eventId": "event-12345",
"issue": "Event missing from local database",
"action": "reindex"
}
]
}Every action is logged for administrator oversight:
# Get audit logs for a job
curl http://localhost:3000/api/reconciliation/report/[jobId]
# Response includes audit timeline:
{
"timeline": [
{
"timestamp": "2026-06-19T14:30:00Z",
"action": "detected",
"eventId": "event-12345",
"ledger": 1500,
"details": {...}
},
{
"timestamp": "2026-06-19T14:31:00Z",
"action": "fixed",
"eventId": "event-12345",
"ledger": 1500,
"details": {...}
}
]
}Run the comprehensive test suite:
npm test
# Watch mode
npm run test:watchTests cover:
- ✓ Detecting missing events
- ✓ Detecting data integrity mismatches
- ✓ Recording audit trails
- ✓ Database persistence
- ✓ Event verification
-- Check total events
SELECT COUNT(*) as total_events FROM events;
-- Check verified events
SELECT COUNT(*) as verified_events FROM events WHERE rpc_verified = true;
-- Check events with discrepancies
SELECT * FROM events WHERE discrepancies IS NOT NULL;# Archived old events (before a date)
# This is handled via the API in production# Create new migration
npm run db:migrate
# Reset database (DEV ONLY)
npx prisma migrate reset# Check if Redis is running
redis-cli ping
# Should return: PONG
# If not running, start it
redis-server# Verify DATABASE_URL in .env.local
# Check database server is running
# Verify credentials
# Test connection
npx prisma db execute --stdin << 'EOF'
SELECT 1;
EOF# Check queue status
curl http://localhost:3000/api/reconciliation/status
# Verify Bull worker is running
# Check logs for worker errors# Get job status
curl http://localhost:3000/api/reconciliation/status
# Manual trigger new job
curl -X POST http://localhost:3000/api/reconciliation/trigger \
-d '{"startLedger": ..., "endLedger": ...}'- Batch Size — Process events in chunks of 1000 (configurable)
- Concurrency — Queue processes 5 jobs concurrently (configurable)
- Lookback Days — Reconcile 7 days of history by default
- Retry Logic — Automatic exponential backoff for failures
For large event volumes:
- Increase
QUEUE_CONCURRENCY(default: 5) - Decrease
lookbackDaysor schedule more frequent reconciliations - Use database indexing on
(ledger, contractId)
lib/
├── db/
│ ├── client.ts # Prisma client setup
│ └── utils.ts # Database utilities
├── jobs/
│ └── queue.ts # Bull queue configuration
├── reconciliation/
│ ├── engine.ts # Main reconciliation logic
│ ├── comparator.ts # DB vs RPC comparison
│ ├── auditor.ts # Audit trail logging
│ ├── scheduler.ts # Cron scheduler
│ └── reconciliation.test.ts # Comprehensive tests
├── translator/
│ └── persistence.ts # Event translation & persistence
└── stellar/
└── indexer-persistent.ts # Persistent indexer wrapper
app/api/
├── health/route.ts # System health endpoint
└── reconciliation/
├── status/route.ts # Job status
├── trigger/route.ts # Manual trigger
├── config/route.ts # Configuration
├── history/route.ts # Job history
└── report/[jobId]/route.ts # Detailed reports
prisma/
├── schema.prisma # Database schema
└── seed.ts # Database seeding
- Deploy Database — Set up PostgreSQL in your environment
- Configure Redis — Start Redis for job queue
- Run Migrations —
npm run db:migrate - Start Application —
npm run devornpm start - Verify Health —
curl http://localhost:3000/api/health - Monitor Reconciliation — Check reconciliation status regularly
For issues or questions:
- Check logs:
tail -f logs/reconciliation.log - Review database state: Use
prisma studio - Test manually: Use provided curl examples
- Review tests:
lib/reconciliation/reconciliation.test.ts
This reconciliation worker provides:
✅ 100% Data Completeness — Guarantees no events are lost ✅ Automated Detection — Identifies gaps without manual intervention ✅ Self-Healing — Auto-repairs missing events (optional) ✅ Complete Audit Trail — Compliance-ready logging ✅ Easy Monitoring — Clear status endpoints and reports ✅ Production-Ready — Retry logic, error handling, scalability
Your Open-Audit instance now acts as a trusted auditing authority for the Stellar/Soroban ecosystem!