2.1 KiB
2.1 KiB
Database Migration Strategy: Mandatory Organizer Ownership Invariant
This document details the database schema migration strategy for enforcing mandatory, non-null organizerId on the Giveaway table in production.
1. Context & Invariant
In Randomayzer, every giveaway is owned by an authenticated Organizer (represented by the User model via VK ID OAuth 2.1).
To prevent broken access control and ambiguous authorization states:
Giveaway.organizerIdis strictlyNOT NULL.- Foreign key relation is defined with
onDelete: Restrict, strictly preventing the deletion of an organizer account while owned giveaways exist.
2. Prisma Schema Definition
model User {
id String @id @default(cuid())
vkUserId String @unique
giveaways Giveaway[]
...
}
model Giveaway {
id String @id @default(cuid())
organizerId String
organizer User @relation(fields: [organizerId], references: [id], onDelete: Restrict)
...
@@index([organizerId])
}
3. Migration Plan for Existing Records
A. Development & Staging Environments
Existing anonymous test records created prior to Phase 2.2 can be purged:
DELETE FROM "ParticipantSnapshot" WHERE "giveawayId" IN (SELECT "id" FROM "Giveaway" WHERE "organizerId" IS NULL);
DELETE FROM "Participant" WHERE "giveawayId" IN (SELECT "id" FROM "Giveaway" WHERE "organizerId" IS NULL);
DELETE FROM "Giveaway" WHERE "organizerId" IS NULL;
B. Production Migration Protocol
- Never assign legacy records to arbitrary users: If unassigned giveaways exist in a production database, do not automatically bind them to random organizers.
- Quarantine or Admin Assignment: Migrate legacy orphan giveaways to a designated system quarantine table or assign to an explicitly verified administrative organizer.
- Execute SQL Migration:
-- Step 1: Verify 0 null records remain
SELECT COUNT(*) FROM "Giveaway" WHERE "organizerId" IS NULL;
-- Step 2: Enforce NOT NULL and Restrict constraint
ALTER TABLE "Giveaway" ALTER COLUMN "organizerId" SET NOT NULL;