Switch from db push to versioned Prisma migrations

Replace 2 stale migration files with a single baseline migration
capturing the full 40+ model schema. The database was freshly reset
via clean-slate, making this the ideal time to establish migration
history. Dockerfile now runs prisma migrate deploy before app start.
Updated SETUP.md and ROADMAP.md to reference prisma migrate dev
instead of db push.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Leivur Djurhuus 2026-04-06 14:45:36 -05:00
parent 29657aeefd
commit 4149b2cf40
6 changed files with 458 additions and 17 deletions

View file

@ -51,4 +51,4 @@ EXPOSE 3000
ENV PORT=3000
ENV HOSTNAME="0.0.0.0"
CMD ["node", "server.js"]
CMD ["sh", "-c", "npx prisma migrate deploy && node server.js"]

View file

@ -127,7 +127,7 @@ The review tool lives at its own dedicated page (`/projects/[projectId]/delivera
- `Revision.attachments` JSON stores `{ referenceImage, currentImage }` with metadata
- Comparison viewer with 4 modes: side-by-side, wipe, overlay, toggle
- SVG annotation layer with 7 tools (rect, ellipse, arrow, freehand, text, pin, screenshot paste)
- Annotation model in Prisma schema (requires `db push` to sync)
- Annotation model in Prisma schema (use `prisma migrate dev` to create migration)
- Annotation API: GET/POST `/api/revisions/[id]/annotations`, PATCH/DELETE `/api/revisions/[id]/annotations/[id]`
- Annotations linked to comments (transactional create), undo/redo stack
- Screenshot paste: Cmd+V pastes clipboard image as draggable/resizable callout
@ -1310,7 +1310,7 @@ src/
- **Service layer** → Prisma queries + business rules (testable, reusable)
- **URL-synced filters** via `nuqs` — views are shareable/bookmarkable
- **Server Components** for initial fetch, **TanStack Query** for mutations/cache
- **`npx prisma db push`** for schema changes (no migrations dir — use db push)
- **`npx prisma migrate dev`** for schema changes (versioned migrations in `prisma/migrations/`)
### Local Dev
```bash

View file

@ -134,14 +134,14 @@ NEXTAUTH_URL="http://localhost:3000"
## 5. Initialize the Database
Push the Prisma schema to the database and run the seed script:
Apply migrations and run the seed script:
```bash
npx prisma db push
npx prisma migrate dev
npx prisma db seed
```
`db push` creates all tables from `prisma/schema.prisma`.
`migrate dev` applies pending migrations and creates new ones from schema changes.
`db seed` populates:
- 10 pipeline stage templates with dependency rules
@ -177,7 +177,7 @@ be logged in automatically as the dev admin user.
| Format | `npm run format` | Prettier format all files |
| Format check | `npm run format:check` | Prettier check (no write) |
| Generate client | `npm run db:generate` | Regenerate Prisma client |
| Push schema | `npm run db:push` | Sync schema to database (no migration files) |
| Migrate | `npm run db:migrate` | Apply/create migrations |
| Seed | `npm run db:seed` | Run seed script |
| Studio | `npm run db:studio` | Open Prisma Studio GUI |
@ -234,7 +234,7 @@ The workflow for moving between macOS and Windows:
```bash
git pull
npm install # in case dependencies changed
npx prisma db push # in case schema changed
npx prisma migrate dev # apply any new migrations
npm run dev
```
@ -266,8 +266,8 @@ taskkill /PID <pid> /F
### Schema out of sync after git pull
```bash
npx prisma db push # applies any schema changes
npx prisma generate # regenerates the client types
npx prisma migrate dev # applies pending migrations, creates new ones if schema changed
npx prisma generate # regenerates the client types
```
### nvm: command not found (macOS)

View file

@ -0,0 +1,50 @@
---
date: 2026-04-06
topic: versioned-migration-baseline
---
# Versioned Migration Baseline
## Problem Frame
The project uses `db push` for schema changes, which has no version history and no rollback path. The database was just reset to a clean state via the clean-slate toolkit. Two stale migration files exist in `prisma/migrations/` from early development (March 2026) but the schema has evolved far beyond them (40+ models now). Before real user data enters the database, the migration history must be established so future schema changes are versioned, repeatable, and auditable.
## Requirements
**Baseline Migration**
- R1. Delete the 2 stale migration files and create a single fresh baseline migration capturing the full current schema (40+ models).
- R2. The baseline migration must be marked as "already applied" against the current database (which already has the schema via `db push`) using `prisma migrate resolve`.
**Enforce Migrations Going Forward**
- R3. All future schema changes must use `prisma migrate dev` (development) and `prisma migrate deploy` (production), not `db push`.
- R4. Update the Dockerfile to run `npx prisma migrate deploy` before `node server.js` so production deployments apply pending migrations automatically.
**Developer Workflow**
- R5. Update `SETUP.md` or equivalent docs to reflect the new migration workflow (`prisma migrate dev` instead of `db push`).
## Success Criteria
- `prisma migrate status` shows no pending migrations and no drift against the current database.
- The Dockerfile runs migrations before starting the app.
- A new schema change created with `prisma migrate dev` produces a versioned migration file that can be applied to production with `prisma migrate deploy`.
## Scope Boundaries
- Not in scope: migrating data between schema versions (the database is clean — no data migration needed).
- Not in scope: CI checks to reject `db push` usage (nice-to-have for later).
- Not in scope: changing the Prisma adapter or connection setup.
## Key Decisions
- **Delete and re-baseline vs. squash:** Delete the 2 stale migrations and create a fresh baseline. The old migrations are artifacts of early prototyping and don't represent the current schema. A clean baseline is simpler than trying to reconcile drift.
- **Timing is ideal:** The database was just purged and re-seeded with the clean-slate toolkit. The schema matches `schema.prisma` exactly — no drift to resolve beyond marking the baseline as applied.
## Outstanding Questions
### Deferred to Planning
- [Affects R1][Technical] Determine the exact Prisma CLI commands for baselining (`prisma migrate diff`, `prisma migrate resolve`, or manual SQL baseline).
- [Affects R4][Technical] Determine whether the Dockerfile CMD should chain `prisma migrate deploy && node server.js` or use an entrypoint script.
## Next Steps
-> `/ce:plan` for structured implementation planning

View file

@ -1,4 +0,0 @@
-- AlterTable
ALTER TABLE "deliverable_stages" ADD COLUMN "manualSchedule" BOOLEAN NOT NULL DEFAULT false,
ADD COLUMN "scheduleConflict" BOOLEAN NOT NULL DEFAULT false,
ADD COLUMN "scheduleDelta" INTEGER;

View file

@ -1,5 +1,5 @@
-- Enable pgvector extension (must be before any vector column usage)
CREATE EXTENSION IF NOT EXISTS vector;
-- CreateSchema
CREATE SCHEMA IF NOT EXISTS "public";
-- CreateEnum
CREATE TYPE "Role" AS ENUM ('ADMIN', 'PRODUCER', 'ARTIST');
@ -31,6 +31,28 @@ CREATE TYPE "SkillLevel" AS ENUM ('JUNIOR', 'INTERMEDIATE', 'SENIOR', 'LEAD');
-- CreateEnum
CREATE TYPE "ExecutionStatus" AS ENUM ('SUCCESS', 'PARTIAL_FAILURE', 'FAILURE');
-- CreateEnum
CREATE TYPE "Permission" AS ENUM ('PROJECT_CREATE', 'PROJECT_UPDATE', 'PROJECT_DELETE', 'PROJECT_VIEW', 'DELIVERABLE_CREATE', 'DELIVERABLE_UPDATE', 'DELIVERABLE_DELETE', 'STAGE_UPDATE_STATUS', 'STAGE_ASSIGN', 'STAGE_SCHEDULE', 'REVISION_CREATE', 'REVISION_REVIEW', 'COMMENT_CREATE', 'COMMENT_DELETE_ANY', 'PIPELINE_MANAGE', 'USER_MANAGE', 'ROLE_MANAGE', 'ORG_SETTINGS', 'AUTOMATION_MANAGE', 'FIELD_CUSTOMIZE');
-- CreateEnum
CREATE TYPE "AnnotationType" AS ENUM ('RECTANGLE', 'ELLIPSE', 'ARROW', 'FREEHAND', 'TEXT', 'PIN', 'SCREENSHOT');
-- CreateEnum
CREATE TYPE "FeedbackStatus" AS ENUM ('OPEN', 'IN_PROGRESS', 'RESOLVED', 'VERIFIED', 'REOPENED');
-- CreateEnum
CREATE TYPE "ReviewSessionStatus" AS ENUM ('DRAFT', 'IN_PROGRESS', 'COMPLETED');
-- CreateTable
CREATE TABLE "org_role_permissions" (
"id" TEXT NOT NULL,
"organizationId" TEXT NOT NULL,
"role" "Role" NOT NULL,
"permission" "Permission" NOT NULL,
CONSTRAINT "org_role_permissions_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "organizations" (
"id" TEXT NOT NULL,
@ -117,6 +139,46 @@ CREATE TABLE "pipeline_stage_dependencies" (
CONSTRAINT "pipeline_stage_dependencies_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "pipeline_templates" (
"id" TEXT NOT NULL,
"name" TEXT NOT NULL,
"description" TEXT,
"organizationId" TEXT NOT NULL,
"isArchived" BOOLEAN NOT NULL DEFAULT false,
"isDefault" BOOLEAN NOT NULL DEFAULT false,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "pipeline_templates_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "pipeline_stage_definitions" (
"id" TEXT NOT NULL,
"pipelineId" TEXT NOT NULL,
"name" TEXT NOT NULL,
"slug" TEXT NOT NULL,
"order" INTEGER NOT NULL,
"isCriticalGate" BOOLEAN NOT NULL DEFAULT false,
"isOptional" BOOLEAN NOT NULL DEFAULT false,
"description" TEXT,
"estimatedDays" DOUBLE PRECISION,
"color" TEXT,
"customStatuses" JSONB,
CONSTRAINT "pipeline_stage_definitions_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "pipeline_stage_dependencies_v2" (
"id" TEXT NOT NULL,
"stageId" TEXT NOT NULL,
"prerequisiteId" TEXT NOT NULL,
CONSTRAINT "pipeline_stage_dependencies_v2_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "projects" (
"id" TEXT NOT NULL,
@ -140,7 +202,9 @@ CREATE TABLE "projects" (
"actualCost" DOUBLE PRECISION,
"agency" TEXT,
"embedding" vector(768),
"customFields" JSONB,
"organizationId" TEXT NOT NULL,
"pipelineTemplateId" TEXT,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
@ -162,7 +226,9 @@ CREATE TABLE "deliverables" (
"actualDeliveryDate" TIMESTAMP(3),
"wfInputDate" TIMESTAMP(3),
"embedding" vector(768),
"customFields" JSONB,
"projectId" TEXT NOT NULL,
"organizationId" TEXT,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
@ -179,8 +245,13 @@ CREATE TABLE "deliverable_stages" (
"dueDate" TIMESTAMP(3),
"notes" TEXT,
"subStatus" TEXT,
"manualSchedule" BOOLEAN NOT NULL DEFAULT false,
"scheduleConflict" BOOLEAN NOT NULL DEFAULT false,
"scheduleDelta" INTEGER,
"deliverableId" TEXT NOT NULL,
"templateId" TEXT NOT NULL,
"stageDefinitionId" TEXT,
"organizationId" TEXT,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
@ -312,6 +383,53 @@ CREATE TABLE "chat_messages" (
CONSTRAINT "chat_messages_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "custom_field_definitions" (
"id" TEXT NOT NULL,
"organizationId" TEXT NOT NULL,
"entityType" TEXT NOT NULL,
"fieldName" TEXT NOT NULL,
"fieldType" TEXT NOT NULL,
"fieldOptions" JSONB,
"isRequired" BOOLEAN NOT NULL DEFAULT false,
"order" INTEGER NOT NULL DEFAULT 0,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "custom_field_definitions_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "notification_rules" (
"id" TEXT NOT NULL,
"organizationId" TEXT NOT NULL,
"name" TEXT NOT NULL,
"isEnabled" BOOLEAN NOT NULL DEFAULT true,
"event" TEXT NOT NULL,
"conditions" JSONB,
"channels" JSONB NOT NULL,
"recipientRoles" JSONB NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "notification_rules_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "invitations" (
"id" TEXT NOT NULL,
"email" TEXT NOT NULL,
"role" "Role" NOT NULL DEFAULT 'ARTIST',
"organizationId" TEXT NOT NULL,
"invitedById" TEXT NOT NULL,
"token" TEXT NOT NULL,
"expiresAt" TIMESTAMP(3) NOT NULL,
"acceptedAt" TIMESTAMP(3),
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "invitations_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "search_logs" (
"id" TEXT NOT NULL,
@ -324,6 +442,99 @@ CREATE TABLE "search_logs" (
CONSTRAINT "search_logs_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "annotations" (
"id" TEXT NOT NULL,
"commentId" TEXT NOT NULL,
"revisionId" TEXT NOT NULL,
"type" "AnnotationType" NOT NULL,
"data" JSONB NOT NULL,
"imageX" DOUBLE PRECISION NOT NULL,
"imageY" DOUBLE PRECISION NOT NULL,
"timestampSeconds" DOUBLE PRECISION,
"frameThumbnailUrl" TEXT,
"createdById" TEXT NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "annotations_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "feedback_items" (
"id" TEXT NOT NULL,
"deliverableStageId" TEXT NOT NULL,
"revisionId" TEXT NOT NULL,
"annotationId" TEXT,
"commentId" TEXT,
"summary" TEXT NOT NULL,
"isActionItem" BOOLEAN NOT NULL DEFAULT true,
"status" "FeedbackStatus" NOT NULL DEFAULT 'OPEN',
"sortOrder" INTEGER NOT NULL DEFAULT 0,
"assignedToId" TEXT,
"createdById" TEXT NOT NULL,
"resolvedById" TEXT,
"resolvedAt" TIMESTAMP(3),
"resolutionNote" TEXT,
"verifiedById" TEXT,
"verifiedAt" TIMESTAMP(3),
"carriedFromId" TEXT,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "feedback_items_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "review_sessions" (
"id" TEXT NOT NULL,
"name" TEXT NOT NULL,
"description" TEXT,
"status" "ReviewSessionStatus" NOT NULL DEFAULT 'DRAFT',
"createdById" TEXT NOT NULL,
"organizationId" TEXT NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "review_sessions_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "review_session_items" (
"id" TEXT NOT NULL,
"sessionId" TEXT NOT NULL,
"deliverableStageId" TEXT NOT NULL,
"revisionId" TEXT,
"sortOrder" INTEGER NOT NULL,
"decision" TEXT,
"decisionNote" TEXT,
"decidedById" TEXT,
"decidedAt" TIMESTAMP(3),
CONSTRAINT "review_session_items_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "color_probes" (
"id" TEXT NOT NULL,
"revisionId" TEXT NOT NULL,
"index" INTEGER NOT NULL,
"workingX" DOUBLE PRECISION NOT NULL,
"workingY" DOUBLE PRECISION NOT NULL,
"referenceX" DOUBLE PRECISION NOT NULL,
"referenceY" DOUBLE PRECISION NOT NULL,
"createdById" TEXT NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "color_probes_pkey" PRIMARY KEY ("id")
);
-- CreateIndex
CREATE INDEX "org_role_permissions_organizationId_idx" ON "org_role_permissions"("organizationId");
-- CreateIndex
CREATE UNIQUE INDEX "org_role_permissions_organizationId_role_permission_key" ON "org_role_permissions"("organizationId", "role", "permission");
-- CreateIndex
CREATE UNIQUE INDEX "organizations_domain_key" ON "organizations"("domain");
@ -351,29 +562,56 @@ CREATE UNIQUE INDEX "pipeline_stage_templates_order_key" ON "pipeline_stage_temp
-- CreateIndex
CREATE UNIQUE INDEX "pipeline_stage_dependencies_stageId_prerequisiteId_key" ON "pipeline_stage_dependencies"("stageId", "prerequisiteId");
-- CreateIndex
CREATE INDEX "pipeline_templates_organizationId_idx" ON "pipeline_templates"("organizationId");
-- CreateIndex
CREATE UNIQUE INDEX "pipeline_templates_organizationId_name_key" ON "pipeline_templates"("organizationId", "name");
-- CreateIndex
CREATE UNIQUE INDEX "pipeline_stage_definitions_pipelineId_slug_key" ON "pipeline_stage_definitions"("pipelineId", "slug");
-- CreateIndex
CREATE UNIQUE INDEX "pipeline_stage_definitions_pipelineId_order_key" ON "pipeline_stage_definitions"("pipelineId", "order");
-- CreateIndex
CREATE UNIQUE INDEX "pipeline_stage_dependencies_v2_stageId_prerequisiteId_key" ON "pipeline_stage_dependencies_v2"("stageId", "prerequisiteId");
-- CreateIndex
CREATE UNIQUE INDEX "projects_projectCode_key" ON "projects"("projectCode");
-- CreateIndex
CREATE INDEX "projects_organizationId_idx" ON "projects"("organizationId");
-- CreateIndex
CREATE INDEX "projects_pipelineTemplateId_idx" ON "projects"("pipelineTemplateId");
-- CreateIndex
CREATE INDEX "projects_status_idx" ON "projects"("status");
-- CreateIndex
CREATE INDEX "deliverables_projectId_idx" ON "deliverables"("projectId");
-- CreateIndex
CREATE INDEX "deliverables_organizationId_idx" ON "deliverables"("organizationId");
-- CreateIndex
CREATE INDEX "deliverables_status_idx" ON "deliverables"("status");
-- CreateIndex
CREATE INDEX "deliverable_stages_deliverableId_idx" ON "deliverable_stages"("deliverableId");
-- CreateIndex
CREATE INDEX "deliverable_stages_stageDefinitionId_idx" ON "deliverable_stages"("stageDefinitionId");
-- CreateIndex
CREATE INDEX "deliverable_stages_organizationId_idx" ON "deliverable_stages"("organizationId");
-- CreateIndex
CREATE INDEX "deliverable_stages_status_idx" ON "deliverable_stages"("status");
-- CreateIndex
CREATE UNIQUE INDEX "deliverable_stages_deliverableId_templateId_key" ON "deliverable_stages"("deliverableId", "templateId");
CREATE UNIQUE INDEX "deliverable_stages_deliverableId_stageDefinitionId_key" ON "deliverable_stages"("deliverableId", "stageDefinitionId");
-- CreateIndex
CREATE INDEX "stage_assignments_userId_idx" ON "stage_assignments"("userId");
@ -414,9 +652,72 @@ CREATE INDEX "chat_messages_sessionId_idx" ON "chat_messages"("sessionId");
-- CreateIndex
CREATE INDEX "chat_messages_userId_idx" ON "chat_messages"("userId");
-- CreateIndex
CREATE INDEX "custom_field_definitions_organizationId_idx" ON "custom_field_definitions"("organizationId");
-- CreateIndex
CREATE UNIQUE INDEX "custom_field_definitions_organizationId_entityType_fieldNam_key" ON "custom_field_definitions"("organizationId", "entityType", "fieldName");
-- CreateIndex
CREATE INDEX "notification_rules_organizationId_idx" ON "notification_rules"("organizationId");
-- CreateIndex
CREATE INDEX "notification_rules_event_idx" ON "notification_rules"("event");
-- CreateIndex
CREATE UNIQUE INDEX "invitations_token_key" ON "invitations"("token");
-- CreateIndex
CREATE INDEX "invitations_organizationId_idx" ON "invitations"("organizationId");
-- CreateIndex
CREATE INDEX "invitations_token_idx" ON "invitations"("token");
-- CreateIndex
CREATE UNIQUE INDEX "invitations_email_organizationId_key" ON "invitations"("email", "organizationId");
-- CreateIndex
CREATE INDEX "search_logs_userId_idx" ON "search_logs"("userId");
-- CreateIndex
CREATE INDEX "annotations_commentId_idx" ON "annotations"("commentId");
-- CreateIndex
CREATE INDEX "annotations_revisionId_idx" ON "annotations"("revisionId");
-- CreateIndex
CREATE INDEX "annotations_revisionId_timestampSeconds_idx" ON "annotations"("revisionId", "timestampSeconds");
-- CreateIndex
CREATE INDEX "feedback_items_deliverableStageId_idx" ON "feedback_items"("deliverableStageId");
-- CreateIndex
CREATE INDEX "feedback_items_revisionId_idx" ON "feedback_items"("revisionId");
-- CreateIndex
CREATE INDEX "feedback_items_assignedToId_idx" ON "feedback_items"("assignedToId");
-- CreateIndex
CREATE INDEX "feedback_items_status_idx" ON "feedback_items"("status");
-- CreateIndex
CREATE INDEX "review_sessions_organizationId_idx" ON "review_sessions"("organizationId");
-- CreateIndex
CREATE INDEX "review_sessions_status_idx" ON "review_sessions"("status");
-- CreateIndex
CREATE INDEX "review_session_items_sessionId_idx" ON "review_session_items"("sessionId");
-- CreateIndex
CREATE INDEX "color_probes_revisionId_idx" ON "color_probes"("revisionId");
-- CreateIndex
CREATE UNIQUE INDEX "color_probes_revisionId_index_key" ON "color_probes"("revisionId", "index");
-- AddForeignKey
ALTER TABLE "org_role_permissions" ADD CONSTRAINT "org_role_permissions_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "organizations"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "users" ADD CONSTRAINT "users_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "organizations"("id") ON DELETE SET NULL ON UPDATE CASCADE;
@ -432,18 +733,42 @@ ALTER TABLE "pipeline_stage_dependencies" ADD CONSTRAINT "pipeline_stage_depende
-- AddForeignKey
ALTER TABLE "pipeline_stage_dependencies" ADD CONSTRAINT "pipeline_stage_dependencies_prerequisiteId_fkey" FOREIGN KEY ("prerequisiteId") REFERENCES "pipeline_stage_templates"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "pipeline_templates" ADD CONSTRAINT "pipeline_templates_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "organizations"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "pipeline_stage_definitions" ADD CONSTRAINT "pipeline_stage_definitions_pipelineId_fkey" FOREIGN KEY ("pipelineId") REFERENCES "pipeline_templates"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "pipeline_stage_dependencies_v2" ADD CONSTRAINT "pipeline_stage_dependencies_v2_stageId_fkey" FOREIGN KEY ("stageId") REFERENCES "pipeline_stage_definitions"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "pipeline_stage_dependencies_v2" ADD CONSTRAINT "pipeline_stage_dependencies_v2_prerequisiteId_fkey" FOREIGN KEY ("prerequisiteId") REFERENCES "pipeline_stage_definitions"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "projects" ADD CONSTRAINT "projects_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "organizations"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "projects" ADD CONSTRAINT "projects_pipelineTemplateId_fkey" FOREIGN KEY ("pipelineTemplateId") REFERENCES "pipeline_templates"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "deliverables" ADD CONSTRAINT "deliverables_projectId_fkey" FOREIGN KEY ("projectId") REFERENCES "projects"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "deliverables" ADD CONSTRAINT "deliverables_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "organizations"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "deliverable_stages" ADD CONSTRAINT "deliverable_stages_deliverableId_fkey" FOREIGN KEY ("deliverableId") REFERENCES "deliverables"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "deliverable_stages" ADD CONSTRAINT "deliverable_stages_templateId_fkey" FOREIGN KEY ("templateId") REFERENCES "pipeline_stage_templates"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "deliverable_stages" ADD CONSTRAINT "deliverable_stages_stageDefinitionId_fkey" FOREIGN KEY ("stageDefinitionId") REFERENCES "pipeline_stage_definitions"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "deliverable_stages" ADD CONSTRAINT "deliverable_stages_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "organizations"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "stage_assignments" ADD CONSTRAINT "stage_assignments_deliverableStageId_fkey" FOREIGN KEY ("deliverableStageId") REFERENCES "deliverable_stages"("id") ON DELETE CASCADE ON UPDATE CASCADE;
@ -489,5 +814,75 @@ ALTER TABLE "automation_executions" ADD CONSTRAINT "automation_executions_ruleId
-- AddForeignKey
ALTER TABLE "chat_messages" ADD CONSTRAINT "chat_messages_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "custom_field_definitions" ADD CONSTRAINT "custom_field_definitions_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "organizations"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "notification_rules" ADD CONSTRAINT "notification_rules_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "organizations"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "invitations" ADD CONSTRAINT "invitations_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "organizations"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "invitations" ADD CONSTRAINT "invitations_invitedById_fkey" FOREIGN KEY ("invitedById") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "search_logs" ADD CONSTRAINT "search_logs_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "annotations" ADD CONSTRAINT "annotations_commentId_fkey" FOREIGN KEY ("commentId") REFERENCES "comments"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "annotations" ADD CONSTRAINT "annotations_revisionId_fkey" FOREIGN KEY ("revisionId") REFERENCES "revisions"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "annotations" ADD CONSTRAINT "annotations_createdById_fkey" FOREIGN KEY ("createdById") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "feedback_items" ADD CONSTRAINT "feedback_items_deliverableStageId_fkey" FOREIGN KEY ("deliverableStageId") REFERENCES "deliverable_stages"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "feedback_items" ADD CONSTRAINT "feedback_items_revisionId_fkey" FOREIGN KEY ("revisionId") REFERENCES "revisions"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "feedback_items" ADD CONSTRAINT "feedback_items_annotationId_fkey" FOREIGN KEY ("annotationId") REFERENCES "annotations"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "feedback_items" ADD CONSTRAINT "feedback_items_commentId_fkey" FOREIGN KEY ("commentId") REFERENCES "comments"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "feedback_items" ADD CONSTRAINT "feedback_items_assignedToId_fkey" FOREIGN KEY ("assignedToId") REFERENCES "users"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "feedback_items" ADD CONSTRAINT "feedback_items_createdById_fkey" FOREIGN KEY ("createdById") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "feedback_items" ADD CONSTRAINT "feedback_items_resolvedById_fkey" FOREIGN KEY ("resolvedById") REFERENCES "users"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "feedback_items" ADD CONSTRAINT "feedback_items_verifiedById_fkey" FOREIGN KEY ("verifiedById") REFERENCES "users"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "feedback_items" ADD CONSTRAINT "feedback_items_carriedFromId_fkey" FOREIGN KEY ("carriedFromId") REFERENCES "feedback_items"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "review_sessions" ADD CONSTRAINT "review_sessions_createdById_fkey" FOREIGN KEY ("createdById") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "review_session_items" ADD CONSTRAINT "review_session_items_sessionId_fkey" FOREIGN KEY ("sessionId") REFERENCES "review_sessions"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "review_session_items" ADD CONSTRAINT "review_session_items_deliverableStageId_fkey" FOREIGN KEY ("deliverableStageId") REFERENCES "deliverable_stages"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "review_session_items" ADD CONSTRAINT "review_session_items_revisionId_fkey" FOREIGN KEY ("revisionId") REFERENCES "revisions"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "review_session_items" ADD CONSTRAINT "review_session_items_decidedById_fkey" FOREIGN KEY ("decidedById") REFERENCES "users"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "color_probes" ADD CONSTRAINT "color_probes_revisionId_fkey" FOREIGN KEY ("revisionId") REFERENCES "revisions"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "color_probes" ADD CONSTRAINT "color_probes_createdById_fkey" FOREIGN KEY ("createdById") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE;