A migration for the resolutions table has been created to support finalized market resolutions for settlement and portfolio closeout.
Location: prisma/migrations/20260428000000_add_resolutions_table/migration.sql
Contains:
- ✓
ResolutionStatusenum with values:ACTIVE,CORRECTED,OVERRIDDEN - ✓
resolutionstable with:id(TEXT, PRIMARY KEY, UUID)market_id(TEXT, FOREIGN KEY → markets.id with CASCADE delete)outcome(BOOLEAN) - YES (true) or NO (false)finalized_at(TIMESTAMP) - When resolution was finalizedprovenance(TEXT) - Source attribution (e.g., CHAINLINK, PYTH, MANUAL)status(ResolutionStatus) - Tracks state transitionscorrection_override_metadata(JSONB) - Audit trail for corrections/overridescreated_at(TIMESTAMP)updated_at(TIMESTAMP)
- ✓ Enforces one ACTIVE resolution per market via partial unique index
- ✓ 6 strategic indexes for query optimization
Location: prisma/schema.prisma
Changes:
- ✓ Added
ResolutionStatusenum (ACTIVE, CORRECTED, OVERRIDDEN) - ✓ Added
Resolutionmodel with:- All required fields and relationships
- Unique constraint on
(marketId, ACTIVE status) - Proper field mappings to database column names
- Comprehensive indexes for performance
- Relationship to
Marketmodel with cascade delete
- ✓ Updated
Marketmodel to includeresolutionsrelationship
Location: RESOLUTION_MIGRATION_TESTING.md
Includes:
- Migration overview and acceptance criteria verification
- Step-by-step testing procedures
- SQL verification queries
- TypeScript/Prisma ORM usage examples
- Rollback plan
- Success criteria checklist
| Criterion | Status | Details |
|---|---|---|
| Resolution table keyed by market ID | ✓ | Primary key is UUID id, foreign key relationship with Markets |
| Includes outcome field | ✓ | Boolean field: true = YES, false = NO |
| Includes finalized_at field | ✓ | TIMESTAMP field for settlement cutoff |
| Includes provenance field | ✓ | TEXT field for source attribution |
| Enforces one active final resolution per market | ✓ | Partial unique index: resolutions_market_id_active_idx where status = 'ACTIVE' |
| Correction/override metadata strategy | ✓ | JSONB field correction_override_metadata with ResolutionStatus enum (ACTIVE, CORRECTED, OVERRIDDEN) |
- Foreign key constraint with cascade delete for data consistency
- Unique partial index prevents multiple active resolutions per market
- NOT NULL constraints on critical fields
correctionOverrideMetadataJSONB field tracks:- When correction occurred
- Previous outcome value
- Reason for correction/override
- Who made the change
- Status transitions (ACTIVE → CORRECTED/OVERRIDDEN)
- Market lookups:
resolutions_market_id_idx - Status filtering:
resolutions_status_idx - Temporal queries:
resolutions_finalized_at_idx - Compound queries:
resolutions_market_id_status_idx - Pagination:
resolutions_created_at_idx(DESC)
finalizedAttimestamp for settlement window enforcementoutcomeboolean for payout calculationsstatusfield distinguishes between active and historical resolutions- Cascade delete ensures referential integrity when markets are archived
cd /workspaces/vatix-backend
pnpm prisma:migrate dev --name "verify resolutions migration"pnpm prisma:deploypnpm prisma:generate # Regenerate Prisma client
pnpm test # Run test suiteSELECT * FROM "_prisma_migrations"
WHERE migration = '20260428000000_add_resolutions_table';\d resolutions-- Insert first resolution (should succeed)
INSERT INTO resolutions (id, market_id, outcome, finalized_at, provenance, status)
VALUES ('res-1', 'market-1', true, NOW(), 'TEST', 'ACTIVE');
-- Try inserting second ACTIVE resolution (should fail)
INSERT INTO resolutions (id, market_id, outcome, finalized_at, provenance, status)
VALUES ('res-2', 'market-1', false, NOW(), 'TEST', 'ACTIVE');
-- Expected: Error: duplicate key violates unique constraint
-- Insert with different status (should succeed)
INSERT INTO resolutions (id, market_id, outcome, finalized_at, provenance, status)
VALUES ('res-2', 'market-1', false, NOW(), 'TEST', 'CORRECTED');import { prisma } from "@/services/prisma";
// Query should work
const activeResolution = await prisma.resolution.findFirst({
where: { status: "ACTIVE" },
});
console.log("✓ Prisma client can access Resolution model");- ACTIVE: Current final resolution for the market
- CORRECTED: Previous ACTIVE resolution that was corrected (new one becomes ACTIVE)
- OVERRIDDEN: Previous ACTIVE resolution that was overridden (new one becomes ACTIVE)
When a resolution needs to be corrected:
- Update existing ACTIVE resolution to CORRECTED/OVERRIDDEN status
- Store previous state in
correctionOverrideMetadata - Create new ACTIVE resolution with updated outcome
- Partial unique index prevents simultaneous active resolutions
- Market reaches
endTime - Resolution consensus established (via resolution candidates)
- Final resolution created with
outcomeandfinalizedAt - Settlement engine uses
finalizedAtfor cutoff - Portfolio closeout completed
- Historical resolutions preserved for audit
- Migration SQL
- Schema Changes - Lines 43-47 (enum) and 168-188 (model)
- Testing Guide
Status: ✅ COMPLETE - Ready for testing and deployment