Competition/Round architecture: full platform rewrite (Phases 1-9)
All checks were successful
Build and Push Docker Image / build (push) Successful in 7m45s
All checks were successful
Build and Push Docker Image / build (push) Successful in 7m45s
Replace Pipeline/Stage system with Competition/Round architecture. New schema: Competition, Round (7 types), JuryGroup, AssignmentPolicy, ProjectRoundState, DeliberationSession, ResultLock, SubmissionWindow. New services: round-engine, round-assignment, deliberation, result-lock, submission-manager, competition-context, ai-prompt-guard. Full admin/jury/applicant/mentor UI rewrite. AI prompt hardening with structured prompts, retry logic, and injection detection. All legacy pipeline/stage code removed. 4 new migrations + seed aligned. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,99 +1,99 @@
|
||||
-- Migration: Add live voting enhancements (criteria voting, audience voting, AudienceVoter)
|
||||
-- Brings LiveVotingSession, LiveVote, and new AudienceVoter model in sync with schema.prisma
|
||||
-- Uses IF NOT EXISTS / DO $$ guards for idempotent execution
|
||||
|
||||
-- =============================================================================
|
||||
-- 1. LiveVotingSession: Add criteria-based & audience voting columns
|
||||
-- =============================================================================
|
||||
|
||||
ALTER TABLE "LiveVotingSession" ADD COLUMN IF NOT EXISTS "votingMode" TEXT NOT NULL DEFAULT 'simple';
|
||||
ALTER TABLE "LiveVotingSession" ADD COLUMN IF NOT EXISTS "criteriaJson" JSONB;
|
||||
ALTER TABLE "LiveVotingSession" ADD COLUMN IF NOT EXISTS "audienceVotingMode" TEXT NOT NULL DEFAULT 'disabled';
|
||||
ALTER TABLE "LiveVotingSession" ADD COLUMN IF NOT EXISTS "audienceMaxFavorites" INTEGER NOT NULL DEFAULT 3;
|
||||
ALTER TABLE "LiveVotingSession" ADD COLUMN IF NOT EXISTS "audienceRequireId" BOOLEAN NOT NULL DEFAULT false;
|
||||
ALTER TABLE "LiveVotingSession" ADD COLUMN IF NOT EXISTS "audienceVotingDuration" INTEGER;
|
||||
|
||||
-- =============================================================================
|
||||
-- 2. LiveVote: Add criteria scores, audience voter link, make userId nullable
|
||||
-- =============================================================================
|
||||
|
||||
ALTER TABLE "LiveVote" ADD COLUMN IF NOT EXISTS "criterionScoresJson" JSONB;
|
||||
ALTER TABLE "LiveVote" ADD COLUMN IF NOT EXISTS "audienceVoterId" TEXT;
|
||||
|
||||
-- Make userId nullable (was NOT NULL in init migration)
|
||||
ALTER TABLE "LiveVote" ALTER COLUMN "userId" DROP NOT NULL;
|
||||
|
||||
-- =============================================================================
|
||||
-- 3. AudienceVoter: New table for audience participation
|
||||
-- =============================================================================
|
||||
|
||||
CREATE TABLE IF NOT EXISTS "AudienceVoter" (
|
||||
"id" TEXT NOT NULL,
|
||||
"sessionId" TEXT NOT NULL,
|
||||
"token" TEXT NOT NULL,
|
||||
"identifier" TEXT,
|
||||
"identifierType" TEXT,
|
||||
"ipAddress" TEXT,
|
||||
"userAgent" TEXT,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "AudienceVoter_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- Unique constraint on token
|
||||
DO $$ BEGIN
|
||||
ALTER TABLE "AudienceVoter" ADD CONSTRAINT "AudienceVoter_token_key" UNIQUE ("token");
|
||||
EXCEPTION WHEN duplicate_object THEN NULL; END $$;
|
||||
|
||||
-- Indexes
|
||||
CREATE INDEX IF NOT EXISTS "AudienceVoter_sessionId_idx" ON "AudienceVoter"("sessionId");
|
||||
CREATE INDEX IF NOT EXISTS "AudienceVoter_token_idx" ON "AudienceVoter"("token");
|
||||
|
||||
-- Foreign key: AudienceVoter.sessionId -> LiveVotingSession.id
|
||||
DO $$ BEGIN
|
||||
ALTER TABLE "AudienceVoter" ADD CONSTRAINT "AudienceVoter_sessionId_fkey"
|
||||
FOREIGN KEY ("sessionId") REFERENCES "LiveVotingSession"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
EXCEPTION WHEN duplicate_object THEN NULL; END $$;
|
||||
|
||||
-- =============================================================================
|
||||
-- 4. LiveVote: Foreign key and indexes for audienceVoterId
|
||||
-- =============================================================================
|
||||
|
||||
CREATE INDEX IF NOT EXISTS "LiveVote_audienceVoterId_idx" ON "LiveVote"("audienceVoterId");
|
||||
|
||||
-- Foreign key: LiveVote.audienceVoterId -> AudienceVoter.id
|
||||
DO $$ BEGIN
|
||||
ALTER TABLE "LiveVote" ADD CONSTRAINT "LiveVote_audienceVoterId_fkey"
|
||||
FOREIGN KEY ("audienceVoterId") REFERENCES "AudienceVoter"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
EXCEPTION WHEN duplicate_object THEN NULL; END $$;
|
||||
|
||||
-- Unique constraint: sessionId + projectId + audienceVoterId
|
||||
DO $$ BEGIN
|
||||
ALTER TABLE "LiveVote" ADD CONSTRAINT "LiveVote_sessionId_projectId_audienceVoterId_key"
|
||||
UNIQUE ("sessionId", "projectId", "audienceVoterId");
|
||||
EXCEPTION WHEN duplicate_object THEN NULL; END $$;
|
||||
|
||||
-- =============================================================================
|
||||
-- SUMMARY:
|
||||
--
|
||||
-- LiveVotingSession new columns:
|
||||
-- - votingMode (TEXT, default 'simple')
|
||||
-- - criteriaJson (JSONB, nullable)
|
||||
-- - audienceVotingMode (TEXT, default 'disabled')
|
||||
-- - audienceMaxFavorites (INTEGER, default 3)
|
||||
-- - audienceRequireId (BOOLEAN, default false)
|
||||
-- - audienceVotingDuration (INTEGER, nullable)
|
||||
--
|
||||
-- LiveVote changes:
|
||||
-- - criterionScoresJson (JSONB, nullable) - new column
|
||||
-- - audienceVoterId (TEXT, nullable) - new column
|
||||
-- - userId changed from NOT NULL to nullable
|
||||
-- - New unique: (sessionId, projectId, audienceVoterId)
|
||||
-- - New index: audienceVoterId
|
||||
-- - New FK: audienceVoterId -> AudienceVoter(id)
|
||||
--
|
||||
-- New table: AudienceVoter
|
||||
-- - id, sessionId, token (unique), identifier, identifierType,
|
||||
-- ipAddress, userAgent, createdAt
|
||||
-- - FK: sessionId -> LiveVotingSession(id) CASCADE
|
||||
-- =============================================================================
|
||||
-- Migration: Add live voting enhancements (criteria voting, audience voting, AudienceVoter)
|
||||
-- Brings LiveVotingSession, LiveVote, and new AudienceVoter model in sync with schema.prisma
|
||||
-- Uses IF NOT EXISTS / DO $$ guards for idempotent execution
|
||||
|
||||
-- =============================================================================
|
||||
-- 1. LiveVotingSession: Add criteria-based & audience voting columns
|
||||
-- =============================================================================
|
||||
|
||||
ALTER TABLE "LiveVotingSession" ADD COLUMN IF NOT EXISTS "votingMode" TEXT NOT NULL DEFAULT 'simple';
|
||||
ALTER TABLE "LiveVotingSession" ADD COLUMN IF NOT EXISTS "criteriaJson" JSONB;
|
||||
ALTER TABLE "LiveVotingSession" ADD COLUMN IF NOT EXISTS "audienceVotingMode" TEXT NOT NULL DEFAULT 'disabled';
|
||||
ALTER TABLE "LiveVotingSession" ADD COLUMN IF NOT EXISTS "audienceMaxFavorites" INTEGER NOT NULL DEFAULT 3;
|
||||
ALTER TABLE "LiveVotingSession" ADD COLUMN IF NOT EXISTS "audienceRequireId" BOOLEAN NOT NULL DEFAULT false;
|
||||
ALTER TABLE "LiveVotingSession" ADD COLUMN IF NOT EXISTS "audienceVotingDuration" INTEGER;
|
||||
|
||||
-- =============================================================================
|
||||
-- 2. LiveVote: Add criteria scores, audience voter link, make userId nullable
|
||||
-- =============================================================================
|
||||
|
||||
ALTER TABLE "LiveVote" ADD COLUMN IF NOT EXISTS "criterionScoresJson" JSONB;
|
||||
ALTER TABLE "LiveVote" ADD COLUMN IF NOT EXISTS "audienceVoterId" TEXT;
|
||||
|
||||
-- Make userId nullable (was NOT NULL in init migration)
|
||||
ALTER TABLE "LiveVote" ALTER COLUMN "userId" DROP NOT NULL;
|
||||
|
||||
-- =============================================================================
|
||||
-- 3. AudienceVoter: New table for audience participation
|
||||
-- =============================================================================
|
||||
|
||||
CREATE TABLE IF NOT EXISTS "AudienceVoter" (
|
||||
"id" TEXT NOT NULL,
|
||||
"sessionId" TEXT NOT NULL,
|
||||
"token" TEXT NOT NULL,
|
||||
"identifier" TEXT,
|
||||
"identifierType" TEXT,
|
||||
"ipAddress" TEXT,
|
||||
"userAgent" TEXT,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "AudienceVoter_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- Unique constraint on token
|
||||
DO $$ BEGIN
|
||||
ALTER TABLE "AudienceVoter" ADD CONSTRAINT "AudienceVoter_token_key" UNIQUE ("token");
|
||||
EXCEPTION WHEN duplicate_object THEN NULL; END $$;
|
||||
|
||||
-- Indexes
|
||||
CREATE INDEX IF NOT EXISTS "AudienceVoter_sessionId_idx" ON "AudienceVoter"("sessionId");
|
||||
CREATE INDEX IF NOT EXISTS "AudienceVoter_token_idx" ON "AudienceVoter"("token");
|
||||
|
||||
-- Foreign key: AudienceVoter.sessionId -> LiveVotingSession.id
|
||||
DO $$ BEGIN
|
||||
ALTER TABLE "AudienceVoter" ADD CONSTRAINT "AudienceVoter_sessionId_fkey"
|
||||
FOREIGN KEY ("sessionId") REFERENCES "LiveVotingSession"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
EXCEPTION WHEN duplicate_object THEN NULL; END $$;
|
||||
|
||||
-- =============================================================================
|
||||
-- 4. LiveVote: Foreign key and indexes for audienceVoterId
|
||||
-- =============================================================================
|
||||
|
||||
CREATE INDEX IF NOT EXISTS "LiveVote_audienceVoterId_idx" ON "LiveVote"("audienceVoterId");
|
||||
|
||||
-- Foreign key: LiveVote.audienceVoterId -> AudienceVoter.id
|
||||
DO $$ BEGIN
|
||||
ALTER TABLE "LiveVote" ADD CONSTRAINT "LiveVote_audienceVoterId_fkey"
|
||||
FOREIGN KEY ("audienceVoterId") REFERENCES "AudienceVoter"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
EXCEPTION WHEN duplicate_object THEN NULL; END $$;
|
||||
|
||||
-- Unique constraint: sessionId + projectId + audienceVoterId
|
||||
DO $$ BEGIN
|
||||
ALTER TABLE "LiveVote" ADD CONSTRAINT "LiveVote_sessionId_projectId_audienceVoterId_key"
|
||||
UNIQUE ("sessionId", "projectId", "audienceVoterId");
|
||||
EXCEPTION WHEN duplicate_object THEN NULL; END $$;
|
||||
|
||||
-- =============================================================================
|
||||
-- SUMMARY:
|
||||
--
|
||||
-- LiveVotingSession new columns:
|
||||
-- - votingMode (TEXT, default 'simple')
|
||||
-- - criteriaJson (JSONB, nullable)
|
||||
-- - audienceVotingMode (TEXT, default 'disabled')
|
||||
-- - audienceMaxFavorites (INTEGER, default 3)
|
||||
-- - audienceRequireId (BOOLEAN, default false)
|
||||
-- - audienceVotingDuration (INTEGER, nullable)
|
||||
--
|
||||
-- LiveVote changes:
|
||||
-- - criterionScoresJson (JSONB, nullable) - new column
|
||||
-- - audienceVoterId (TEXT, nullable) - new column
|
||||
-- - userId changed from NOT NULL to nullable
|
||||
-- - New unique: (sessionId, projectId, audienceVoterId)
|
||||
-- - New index: audienceVoterId
|
||||
-- - New FK: audienceVoterId -> AudienceVoter(id)
|
||||
--
|
||||
-- New table: AudienceVoter
|
||||
-- - id, sessionId, token (unique), identifier, identifierType,
|
||||
-- ipAddress, userAgent, createdAt
|
||||
-- - FK: sessionId -> LiveVotingSession(id) CASCADE
|
||||
-- =============================================================================
|
||||
|
||||
Reference in New Issue
Block a user