fix(db): constrain annotation ownership

This commit is contained in:
Dotta committed 2026-06-17 15:33:50 +00:00
1 parent 1dae0d0a2d
commit 1cf7ba496c
4 files changed
+34 -2

No files matched your search

@@ -62,6 +62,22 @@ DO $$ BEGIN
END IF;
END $$;
--> statement-breakpoint
DO $$ BEGIN
IF NOT EXISTS (
SELECT 1 FROM "pg_constraint" WHERE "conname" = 'document_annotation_threads_exactly_one_owner_chk'
) THEN
ALTER TABLE "document_annotation_threads" ADD CONSTRAINT "document_annotation_threads_exactly_one_owner_chk" CHECK (num_nonnulls("issue_id", "routine_id") = 1);
END IF;
END $$;
--> statement-breakpoint
DO $$ BEGIN
IF NOT EXISTS (
SELECT 1 FROM "pg_constraint" WHERE "conname" = 'document_annotation_comments_exactly_one_owner_chk'
) THEN
ALTER TABLE "document_annotation_comments" ADD CONSTRAINT "document_annotation_comments_exactly_one_owner_chk" CHECK (num_nonnulls("issue_id", "routine_id") = 1);
END IF;
END $$;
--> statement-breakpoint
CREATE INDEX IF NOT EXISTS "document_annotation_threads_company_routine_status_idx" ON "document_annotation_threads" USING btree ("company_id","routine_id","status");
--> statement-breakpoint
CREATE INDEX IF NOT EXISTS "document_annotation_comments_company_routine_created_at_idx" ON "document_annotation_comments" USING btree ("company_id","routine_id","created_at");
@@ -1,5 +1,6 @@
import type { IssueCommentAuthorType } from "@paperclipai/shared";
import { index, pgTable, text, timestamp, uuid } from "drizzle-orm/pg-core";
import { sql } from "drizzle-orm";
import { check, index, pgTable, text, timestamp, uuid } from "drizzle-orm/pg-core";
import { agents } from "./agents.js";
import { companies } from "./companies.js";
import { documentAnnotationThreads } from "./document_annotation_threads.js";
@@ -50,5 +51,9 @@ export const documentAnnotationComments = pgTable(
),
issueCommentIdx: index("document_annotation_comments_issue_comment_idx").on(table.issueCommentId),
bodySearchIdx: index("document_annotation_comments_body_search_idx").using("gin", table.body.op("gin_trgm_ops")),
exactlyOneOwnerChk: check(
"document_annotation_comments_exactly_one_owner_chk",
sql`num_nonnulls(${table.issueId}, ${table.routineId}) = 1`,
),
}),
);
@@ -4,7 +4,8 @@ import type {
DocumentAnnotationAnchorState,
DocumentAnnotationThreadStatus,
} from "@paperclipai/shared";
import { index, integer, jsonb, pgTable, text, timestamp, uuid } from "drizzle-orm/pg-core";
import { sql } from "drizzle-orm";
import { check, index, integer, jsonb, pgTable, text, timestamp, uuid } from "drizzle-orm/pg-core";
import { agents } from "./agents.js";
import { companies } from "./companies.js";
import { documentRevisions } from "./document_revisions.js";
@@ -73,5 +74,9 @@ export const documentAnnotationThreads = pgTable(
table.companyId,
table.anchorState,
),
exactlyOneOwnerChk: check(
"document_annotation_threads_exactly_one_owner_chk",
sql`num_nonnulls(${table.issueId}, ${table.routineId}) = 1`,
),
}),
);
@@ -9,6 +9,8 @@ import {
companySecrets,
companySecretVersions,
createDb,
documentRevisions,
documents,
executionWorkspaces,
heartbeatRuns,
instanceSettings,
@@ -17,6 +19,7 @@ import {
issues,
projectWorkspaces,
projects,
routineDocuments,
routineRuns,
routines,
routineTriggers,
@@ -65,6 +68,9 @@ describeEmbeddedPostgres("routine service live-execution coalescing", () => {
await db.delete(routineRuns);
await db.delete(routineTriggers);
await db.delete(routines);
await db.delete(routineDocuments);
await db.delete(documentRevisions);
await db.delete(documents);
await db.delete(companySecretVersions);
await db.delete(companySecrets);
await db.delete(heartbeatRuns);