@tickernelz/paperclip-pro-db 2026.1011.2 → 2026.1012.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/backup-lib.d.ts +2 -0
- package/dist/backup-lib.d.ts.map +1 -1
- package/dist/backup-lib.js +52 -15
- package/dist/backup-lib.js.map +1 -1
- package/dist/backup-lib.test.js +64 -2
- package/dist/backup-lib.test.js.map +1 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +81 -42
- package/dist/client.js.map +1 -1
- package/dist/client.test.js +33 -0
- package/dist/client.test.js.map +1 -1
- package/dist/connections-v3-schema-core-migration.test.js +3 -0
- package/dist/connections-v3-schema-core-migration.test.js.map +1 -1
- package/dist/heartbeat-run-issue-privacy-migration.test.d.ts +2 -0
- package/dist/heartbeat-run-issue-privacy-migration.test.d.ts.map +1 -0
- package/dist/heartbeat-run-issue-privacy-migration.test.js +265 -0
- package/dist/heartbeat-run-issue-privacy-migration.test.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/migrations/0315_chunky_chamber.sql +3 -0
- package/dist/migrations/0316_lumpy_maria_hill.sql +157 -0
- package/dist/migrations/0317_colossal_otto_octavius.sql +24 -0
- package/dist/migrations/0318_supreme_garia.sql +1 -0
- package/dist/migrations/0319_curvy_shadow_king.sql +27 -0
- package/dist/migrations/0320_chubby_vin_gonzales.sql +7 -0
- package/dist/migrations/0321_familiar_titania.sql +4 -0
- package/dist/migrations/0322_cool_naoko.sql +3 -0
- package/dist/migrations/0323_whole_steel_serpent.sql +20 -0
- package/dist/migrations/0324_loving_the_hood.sql +77 -0
- package/dist/migrations/0325_agent_commentary.sql +33 -0
- package/dist/migrations/0326_mcp_file_transfers.sql +48 -0
- package/dist/migrations/0327_easy_eternity.sql +232 -0
- package/dist/migrations/0328_private_task_access.sql +278 -0
- package/dist/migrations/0329_private_task_draft_assets.sql +28 -0
- package/dist/migrations/0330_rapid_emma_frost.sql +44 -0
- package/dist/migrations/0331_premium_slayback.sql +81 -0
- package/dist/migrations/0332_messy_famine.sql +189 -0
- package/dist/migrations/0333_strong_blacklash.sql +23 -0
- package/dist/migrations/0334_heavy_captain_midlands.sql +15 -0
- package/dist/migrations/0335_daily_onslaught.sql +16 -0
- package/dist/migrations/0336_acoustic_human_fly.sql +1 -0
- package/dist/migrations/0337_reflective_kree.sql +98 -0
- package/dist/migrations/0338_petite_shockwave.sql +4 -0
- package/dist/migrations/0339_long_franklin_storm.sql +153 -0
- package/dist/migrations/0340_aberrant_machine_man.sql +6 -0
- package/dist/migrations/0341_blushing_screwball.sql +17 -0
- package/dist/migrations/0342_sad_proteus.sql +23 -0
- package/dist/migrations/0343_chunky_mentallo.sql +52 -0
- package/dist/migrations/0344_free_wolf_cub.sql +18 -0
- package/dist/migrations/0345_spooky_white_tiger.sql +7 -0
- package/dist/migrations/0346_panoramic_spyke.sql +74 -0
- package/dist/migrations/0347_little_night_nurse.sql +1 -0
- package/dist/migrations/meta/_journal.json +232 -1
- package/dist/private-task-draft-assets-migration.test.d.ts +2 -0
- package/dist/private-task-draft-assets-migration.test.d.ts.map +1 -0
- package/dist/private-task-draft-assets-migration.test.js +35 -0
- package/dist/private-task-draft-assets-migration.test.js.map +1 -0
- package/dist/question-response-history-migration.test.d.ts +2 -0
- package/dist/question-response-history-migration.test.d.ts.map +1 -0
- package/dist/question-response-history-migration.test.js +53 -0
- package/dist/question-response-history-migration.test.js.map +1 -0
- package/dist/schema/accounting.d.ts +1282 -0
- package/dist/schema/accounting.d.ts.map +1 -0
- package/dist/schema/accounting.js +120 -0
- package/dist/schema/accounting.js.map +1 -0
- package/dist/schema/adapter_auth_sessions.d.ts +2 -2
- package/dist/schema/agent_commentary.d.ts +181 -0
- package/dist/schema/agent_commentary.d.ts.map +1 -0
- package/dist/schema/agent_commentary.js +24 -0
- package/dist/schema/agent_commentary.js.map +1 -0
- package/dist/schema/agent_identity_keys.d.ts +131 -0
- package/dist/schema/agent_identity_keys.d.ts.map +1 -0
- package/dist/schema/agent_identity_keys.js +20 -0
- package/dist/schema/agent_identity_keys.js.map +1 -0
- package/dist/schema/agent_runtime_state.d.ts +2 -2
- package/dist/schema/agent_runtime_state.js +2 -2
- package/dist/schema/agent_runtime_state.js.map +1 -1
- package/dist/schema/agent_wakeup_requests.d.ts.map +1 -1
- package/dist/schema/agent_wakeup_requests.js +6 -0
- package/dist/schema/agent_wakeup_requests.js.map +1 -1
- package/dist/schema/agents.d.ts +132 -2
- package/dist/schema/agents.d.ts.map +1 -1
- package/dist/schema/agents.js +10 -2
- package/dist/schema/agents.js.map +1 -1
- package/dist/schema/ai_connection_defaults.d.ts +2 -2
- package/dist/schema/ai_connection_defaults.js +1 -1
- package/dist/schema/ai_connection_defaults.js.map +1 -1
- package/dist/schema/ai_connection_routing.d.ts +8 -8
- package/dist/schema/ai_provider_defaults.d.ts +2 -2
- package/dist/schema/ai_provider_defaults.js +1 -1
- package/dist/schema/ai_provider_defaults.js.map +1 -1
- package/dist/schema/ai_subscriptions.d.ts +619 -0
- package/dist/schema/ai_subscriptions.d.ts.map +1 -0
- package/dist/schema/ai_subscriptions.js +61 -0
- package/dist/schema/ai_subscriptions.js.map +1 -0
- package/dist/schema/budget_incidents.d.ts +2 -2
- package/dist/schema/budget_incidents.js +3 -3
- package/dist/schema/budget_incidents.js.map +1 -1
- package/dist/schema/budget_policies.d.ts +68 -0
- package/dist/schema/budget_policies.d.ts.map +1 -1
- package/dist/schema/budget_policies.js +7 -1
- package/dist/schema/budget_policies.js.map +1 -1
- package/dist/schema/chat_channels.d.ts +21 -4
- package/dist/schema/chat_channels.d.ts.map +1 -1
- package/dist/schema/chat_channels.js +3 -2
- package/dist/schema/chat_channels.js.map +1 -1
- package/dist/schema/chat_github.d.ts +108 -0
- package/dist/schema/chat_github.d.ts.map +1 -1
- package/dist/schema/chat_github.js +7 -0
- package/dist/schema/chat_github.js.map +1 -1
- package/dist/schema/chat_slack_registrations.d.ts +287 -0
- package/dist/schema/chat_slack_registrations.d.ts.map +1 -0
- package/dist/schema/chat_slack_registrations.js +26 -0
- package/dist/schema/chat_slack_registrations.js.map +1 -0
- package/dist/schema/chat_voice_callbacks.d.ts +128 -0
- package/dist/schema/chat_voice_callbacks.d.ts.map +1 -0
- package/dist/schema/chat_voice_callbacks.js +18 -0
- package/dist/schema/chat_voice_callbacks.js.map +1 -0
- package/dist/schema/chat_voice_inbound.d.ts +461 -0
- package/dist/schema/chat_voice_inbound.d.ts.map +1 -0
- package/dist/schema/chat_voice_inbound.js +45 -0
- package/dist/schema/chat_voice_inbound.js.map +1 -0
- package/dist/schema/chat_voice_reports.d.ts +184 -0
- package/dist/schema/chat_voice_reports.d.ts.map +1 -0
- package/dist/schema/chat_voice_reports.js +24 -0
- package/dist/schema/chat_voice_reports.js.map +1 -0
- package/dist/schema/chat_voice_sessions.d.ts +730 -0
- package/dist/schema/chat_voice_sessions.d.ts.map +1 -0
- package/dist/schema/chat_voice_sessions.js +85 -0
- package/dist/schema/chat_voice_sessions.js.map +1 -0
- package/dist/schema/companies.d.ts +19 -2
- package/dist/schema/companies.d.ts.map +1 -1
- package/dist/schema/companies.js +3 -2
- package/dist/schema/companies.js.map +1 -1
- package/dist/schema/cost_events.d.ts +141 -3
- package/dist/schema/cost_events.d.ts.map +1 -1
- package/dist/schema/cost_events.js +20 -3
- package/dist/schema/cost_events.js.map +1 -1
- package/dist/schema/decision_models.d.ts +579 -0
- package/dist/schema/decision_models.d.ts.map +1 -0
- package/dist/schema/decision_models.js +50 -0
- package/dist/schema/decision_models.js.map +1 -0
- package/dist/schema/dot_runner.d.ts +980 -0
- package/dist/schema/dot_runner.d.ts.map +1 -0
- package/dist/schema/dot_runner.js +82 -0
- package/dist/schema/dot_runner.js.map +1 -0
- package/dist/schema/fast_responses.d.ts +662 -0
- package/dist/schema/fast_responses.d.ts.map +1 -0
- package/dist/schema/fast_responses.js +65 -0
- package/dist/schema/fast_responses.js.map +1 -0
- package/dist/schema/finance_events.d.ts +36 -2
- package/dist/schema/finance_events.d.ts.map +1 -1
- package/dist/schema/finance_events.js +5 -2
- package/dist/schema/finance_events.js.map +1 -1
- package/dist/schema/heartbeat_runs.d.ts +138 -0
- package/dist/schema/heartbeat_runs.d.ts.map +1 -1
- package/dist/schema/heartbeat_runs.js +17 -1
- package/dist/schema/heartbeat_runs.js.map +1 -1
- package/dist/schema/index.d.ts +17 -0
- package/dist/schema/index.d.ts.map +1 -1
- package/dist/schema/index.js +17 -0
- package/dist/schema/index.js.map +1 -1
- package/dist/schema/issue_access_grants.d.ts +161 -0
- package/dist/schema/issue_access_grants.d.ts.map +1 -0
- package/dist/schema/issue_access_grants.js +21 -0
- package/dist/schema/issue_access_grants.js.map +1 -0
- package/dist/schema/issue_comments.d.ts +36 -0
- package/dist/schema/issue_comments.d.ts.map +1 -1
- package/dist/schema/issue_comments.js +2 -0
- package/dist/schema/issue_comments.js.map +1 -1
- package/dist/schema/issues.d.ts +51 -0
- package/dist/schema/issues.d.ts.map +1 -1
- package/dist/schema/issues.js +6 -0
- package/dist/schema/issues.js.map +1 -1
- package/dist/schema/plugin_lifecycle_acknowledgments.d.ts +59 -0
- package/dist/schema/plugin_lifecycle_acknowledgments.d.ts.map +1 -0
- package/dist/schema/plugin_lifecycle_acknowledgments.js +12 -0
- package/dist/schema/plugin_lifecycle_acknowledgments.js.map +1 -0
- package/dist/schema/project_access_members.d.ts +111 -0
- package/dist/schema/project_access_members.d.ts.map +1 -0
- package/dist/schema/project_access_members.js +18 -0
- package/dist/schema/project_access_members.js.map +1 -0
- package/dist/schema/projects.d.ts +51 -0
- package/dist/schema/projects.d.ts.map +1 -1
- package/dist/schema/projects.js +9 -1
- package/dist/schema/projects.js.map +1 -1
- package/dist/schema/public_mcp.d.ts +2100 -0
- package/dist/schema/public_mcp.d.ts.map +1 -0
- package/dist/schema/public_mcp.js +191 -0
- package/dist/schema/public_mcp.js.map +1 -0
- package/dist/schema/resource_lifecycle_events.d.ts +2 -2
- package/dist/schema/resource_lifecycle_events.d.ts.map +1 -1
- package/dist/schema/resource_lifecycle_events.js +2 -1
- package/dist/schema/resource_lifecycle_events.js.map +1 -1
- package/dist/schema/status_cards.d.ts +2 -2
- package/dist/schema/status_cards.js +2 -2
- package/dist/schema/status_cards.js.map +1 -1
- package/dist/schema/tool_access.d.ts +18 -0
- package/dist/schema/tool_access.d.ts.map +1 -1
- package/dist/schema/tool_access.js +3 -3
- package/dist/schema/tool_access.js.map +1 -1
- package/dist/schema/user_company_preferences.d.ts +127 -0
- package/dist/schema/user_company_preferences.d.ts.map +1 -0
- package/dist/schema/user_company_preferences.js +16 -0
- package/dist/schema/user_company_preferences.js.map +1 -0
- package/dist/speko-voice-migration.test.d.ts +2 -0
- package/dist/speko-voice-migration.test.d.ts.map +1 -0
- package/dist/speko-voice-migration.test.js +88 -0
- package/dist/speko-voice-migration.test.js.map +1 -0
- package/dist/work-signals.d.ts +20 -0
- package/dist/work-signals.d.ts.map +1 -0
- package/dist/work-signals.js +123 -0
- package/dist/work-signals.js.map +1 -0
- package/dist/work-signals.test.d.ts +2 -0
- package/dist/work-signals.test.d.ts.map +1 -0
- package/dist/work-signals.test.js +177 -0
- package/dist/work-signals.test.js.map +1 -0
- package/package.json +4 -4
- package/dist/seed.d.ts +0 -2
- package/dist/seed.d.ts.map +0 -1
- package/dist/seed.js +0 -91
- package/dist/seed.js.map +0 -1
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
-- Runs through the Paperclip migration executor outside a file-wide transaction.
|
|
2
|
+
-- Each idempotent keyset batch commits before advancing; history is recorded last.
|
|
3
|
+
CREATE TABLE IF NOT EXISTS "issue_access_grants" (
|
|
4
|
+
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
|
5
|
+
"issue_id" uuid NOT NULL,
|
|
6
|
+
"subject_type" text NOT NULL,
|
|
7
|
+
"subject_id" text NOT NULL,
|
|
8
|
+
"source" text NOT NULL,
|
|
9
|
+
"granted_by_user_id" text,
|
|
10
|
+
"granted_by_agent_id" uuid,
|
|
11
|
+
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
|
|
12
|
+
"revoked_at" timestamp with time zone,
|
|
13
|
+
CONSTRAINT "issue_access_grants_subject_type_check" CHECK ("issue_access_grants"."subject_type" in ('user', 'agent')),
|
|
14
|
+
CONSTRAINT "issue_access_grants_source_check" CHECK ("issue_access_grants"."source" in ('explicit', 'assignment', 'project'))
|
|
15
|
+
);
|
|
16
|
+
--> statement-breakpoint
|
|
17
|
+
CREATE TABLE IF NOT EXISTS "project_access_members" (
|
|
18
|
+
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
|
19
|
+
"company_id" uuid NOT NULL,
|
|
20
|
+
"project_id" uuid NOT NULL,
|
|
21
|
+
"subject_type" text NOT NULL,
|
|
22
|
+
"subject_id" text NOT NULL,
|
|
23
|
+
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
|
|
24
|
+
CONSTRAINT "project_access_members_subject_type_check" CHECK ("project_access_members"."subject_type" in ('user', 'agent'))
|
|
25
|
+
);
|
|
26
|
+
--> statement-breakpoint
|
|
27
|
+
ALTER TABLE "workspace_operations" DROP CONSTRAINT IF EXISTS "workspace_operations_heartbeat_run_id_heartbeat_runs_id_fk";
|
|
28
|
+
--> statement-breakpoint
|
|
29
|
+
ALTER TABLE "workspace_operations" DROP CONSTRAINT IF EXISTS "workspace_operations_issue_id_issues_id_fk";
|
|
30
|
+
--> statement-breakpoint
|
|
31
|
+
ALTER TABLE "heartbeat_runs" ADD COLUMN IF NOT EXISTS "scope_kind" text DEFAULT 'company' NOT NULL;--> statement-breakpoint
|
|
32
|
+
ALTER TABLE "heartbeat_runs" ADD COLUMN IF NOT EXISTS "issue_id" uuid;--> statement-breakpoint
|
|
33
|
+
ALTER TABLE "issues" ADD COLUMN IF NOT EXISTS "visibility" text DEFAULT 'open' NOT NULL;--> statement-breakpoint
|
|
34
|
+
ALTER TABLE "issues" ADD COLUMN IF NOT EXISTS "privacy_root_issue_id" uuid;--> statement-breakpoint
|
|
35
|
+
ALTER TABLE "issues" ADD COLUMN IF NOT EXISTS "privacy_parent_issue_id" uuid;--> statement-breakpoint
|
|
36
|
+
ALTER TABLE "projects" ADD COLUMN IF NOT EXISTS "visibility" text DEFAULT 'open' NOT NULL;--> statement-breakpoint
|
|
37
|
+
ALTER TABLE "projects" ADD COLUMN IF NOT EXISTS "personal_owner_user_id" text;--> statement-breakpoint
|
|
38
|
+
DO $$ BEGIN
|
|
39
|
+
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'issue_access_grants_issue_id_issues_id_fk' AND conrelid = 'public.issue_access_grants'::regclass) THEN
|
|
40
|
+
ALTER TABLE "issue_access_grants" ADD CONSTRAINT "issue_access_grants_issue_id_issues_id_fk" FOREIGN KEY ("issue_id") REFERENCES "public"."issues"("id") ON DELETE cascade ON UPDATE no action;
|
|
41
|
+
END IF;
|
|
42
|
+
END $$;--> statement-breakpoint
|
|
43
|
+
DO $$ BEGIN
|
|
44
|
+
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'issue_access_grants_granted_by_agent_id_agents_id_fk' AND conrelid = 'public.issue_access_grants'::regclass) THEN
|
|
45
|
+
ALTER TABLE "issue_access_grants" ADD CONSTRAINT "issue_access_grants_granted_by_agent_id_agents_id_fk" FOREIGN KEY ("granted_by_agent_id") REFERENCES "public"."agents"("id") ON DELETE set null ON UPDATE no action;
|
|
46
|
+
END IF;
|
|
47
|
+
END $$;--> statement-breakpoint
|
|
48
|
+
DO $$ BEGIN
|
|
49
|
+
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'project_access_members_company_id_companies_id_fk' AND conrelid = 'public.project_access_members'::regclass) THEN
|
|
50
|
+
ALTER TABLE "project_access_members" ADD CONSTRAINT "project_access_members_company_id_companies_id_fk" FOREIGN KEY ("company_id") REFERENCES "public"."companies"("id") ON DELETE cascade ON UPDATE no action;
|
|
51
|
+
END IF;
|
|
52
|
+
END $$;--> statement-breakpoint
|
|
53
|
+
DO $$ BEGIN
|
|
54
|
+
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'project_access_members_project_id_projects_id_fk' AND conrelid = 'public.project_access_members'::regclass) THEN
|
|
55
|
+
ALTER TABLE "project_access_members" ADD CONSTRAINT "project_access_members_project_id_projects_id_fk" FOREIGN KEY ("project_id") REFERENCES "public"."projects"("id") ON DELETE cascade ON UPDATE no action;
|
|
56
|
+
END IF;
|
|
57
|
+
END $$;--> statement-breakpoint
|
|
58
|
+
CREATE INDEX IF NOT EXISTS "issue_access_grants_subject_active_issue_idx" ON "issue_access_grants" USING btree ("subject_type","subject_id","revoked_at","issue_id");--> statement-breakpoint
|
|
59
|
+
CREATE INDEX IF NOT EXISTS "issue_access_grants_issue_idx" ON "issue_access_grants" USING btree ("issue_id","created_at");--> statement-breakpoint
|
|
60
|
+
CREATE UNIQUE INDEX IF NOT EXISTS "project_access_members_project_subject_uq" ON "project_access_members" USING btree ("project_id","subject_type","subject_id");--> statement-breakpoint
|
|
61
|
+
CREATE INDEX IF NOT EXISTS "project_access_members_subject_lookup_idx" ON "project_access_members" USING btree ("company_id","subject_type","subject_id","project_id");--> statement-breakpoint
|
|
62
|
+
DO $$ BEGIN
|
|
63
|
+
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'heartbeat_runs_issue_id_issues_id_fk' AND conrelid = 'public.heartbeat_runs'::regclass) THEN
|
|
64
|
+
ALTER TABLE "heartbeat_runs" ADD CONSTRAINT "heartbeat_runs_issue_id_issues_id_fk" FOREIGN KEY ("issue_id") REFERENCES "public"."issues"("id") ON DELETE set null ON UPDATE no action;
|
|
65
|
+
END IF;
|
|
66
|
+
END $$;--> statement-breakpoint
|
|
67
|
+
DO $$ BEGIN
|
|
68
|
+
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'issues_privacy_root_issue_id_issues_id_fk' AND conrelid = 'public.issues'::regclass) THEN
|
|
69
|
+
ALTER TABLE "issues" ADD CONSTRAINT "issues_privacy_root_issue_id_issues_id_fk" FOREIGN KEY ("privacy_root_issue_id") REFERENCES "public"."issues"("id") ON DELETE no action ON UPDATE no action;
|
|
70
|
+
END IF;
|
|
71
|
+
END $$;--> statement-breakpoint
|
|
72
|
+
DO $$ BEGIN
|
|
73
|
+
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'issues_privacy_parent_issue_id_issues_id_fk' AND conrelid = 'public.issues'::regclass) THEN
|
|
74
|
+
ALTER TABLE "issues" ADD CONSTRAINT "issues_privacy_parent_issue_id_issues_id_fk" FOREIGN KEY ("privacy_parent_issue_id") REFERENCES "public"."issues"("id") ON DELETE set null ON UPDATE no action;
|
|
75
|
+
END IF;
|
|
76
|
+
END $$;--> statement-breakpoint
|
|
77
|
+
DO $$ BEGIN
|
|
78
|
+
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'workspace_operations_heartbeat_run_id_heartbeat_runs_id_fk' AND conrelid = 'public.workspace_operations'::regclass) THEN
|
|
79
|
+
ALTER TABLE "workspace_operations" ADD CONSTRAINT "workspace_operations_heartbeat_run_id_heartbeat_runs_id_fk" FOREIGN KEY ("heartbeat_run_id") REFERENCES "public"."heartbeat_runs"("id") ON DELETE set null ON UPDATE no action;
|
|
80
|
+
END IF;
|
|
81
|
+
END $$;--> statement-breakpoint
|
|
82
|
+
DO $$ BEGIN
|
|
83
|
+
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'workspace_operations_issue_id_issues_id_fk' AND conrelid = 'public.workspace_operations'::regclass) THEN
|
|
84
|
+
ALTER TABLE "workspace_operations" ADD CONSTRAINT "workspace_operations_issue_id_issues_id_fk" FOREIGN KEY ("issue_id") REFERENCES "public"."issues"("id") ON DELETE set null ON UPDATE no action;
|
|
85
|
+
END IF;
|
|
86
|
+
END $$;--> statement-breakpoint
|
|
87
|
+
CREATE INDEX CONCURRENTLY IF NOT EXISTS "heartbeat_runs_company_issue_created_idx" ON "heartbeat_runs" USING btree ("company_id","issue_id","created_at");--> statement-breakpoint
|
|
88
|
+
CREATE INDEX CONCURRENTLY IF NOT EXISTS "issues_company_privacy_parent_idx" ON "issues" USING btree ("company_id","privacy_parent_issue_id");--> statement-breakpoint
|
|
89
|
+
CREATE INDEX CONCURRENTLY IF NOT EXISTS "issues_company_privacy_root_idx" ON "issues" USING btree ("company_id","privacy_root_issue_id");--> statement-breakpoint
|
|
90
|
+
CREATE UNIQUE INDEX CONCURRENTLY IF NOT EXISTS "projects_company_personal_owner_uq" ON "projects" USING btree ("company_id","personal_owner_user_id") WHERE "projects"."personal_owner_user_id" is not null;--> statement-breakpoint
|
|
91
|
+
DO $$ BEGIN
|
|
92
|
+
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'heartbeat_runs_scope_binding_check' AND conrelid = 'public.heartbeat_runs'::regclass) THEN
|
|
93
|
+
ALTER TABLE "heartbeat_runs" ADD CONSTRAINT "heartbeat_runs_scope_binding_check" CHECK (("heartbeat_runs"."scope_kind" = 'company' AND "heartbeat_runs"."issue_id" IS NULL)
|
|
94
|
+
OR "heartbeat_runs"."scope_kind" = 'issue');
|
|
95
|
+
END IF;
|
|
96
|
+
END $$;--> statement-breakpoint
|
|
97
|
+
DO $$ BEGIN
|
|
98
|
+
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'issues_visibility_check' AND conrelid = 'public.issues'::regclass) THEN
|
|
99
|
+
ALTER TABLE "issues" ADD CONSTRAINT "issues_visibility_check" CHECK ("issues"."visibility" in ('open', 'private'));
|
|
100
|
+
END IF;
|
|
101
|
+
END $$;--> statement-breakpoint
|
|
102
|
+
DO $$ BEGIN
|
|
103
|
+
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'projects_visibility_check' AND conrelid = 'public.projects'::regclass) THEN
|
|
104
|
+
ALTER TABLE "projects" ADD CONSTRAINT "projects_visibility_check" CHECK ("projects"."visibility" in ('open', 'private'));
|
|
105
|
+
END IF;
|
|
106
|
+
END $$;
|
|
107
|
+
--> statement-breakpoint
|
|
108
|
+
CREATE OR REPLACE FUNCTION set_heartbeat_run_scope_kind() RETURNS trigger LANGUAGE plpgsql AS $$
|
|
109
|
+
DECLARE candidate uuid;
|
|
110
|
+
BEGIN
|
|
111
|
+
-- A private run never becomes a company run through context edits or deletion.
|
|
112
|
+
IF TG_OP = 'UPDATE' AND OLD.scope_kind = 'issue' THEN
|
|
113
|
+
IF OLD.issue_id IS NOT NULL AND NEW.issue_id IS NOT NULL AND OLD.issue_id <> NEW.issue_id THEN
|
|
114
|
+
RAISE EXCEPTION 'run task binding is immutable';
|
|
115
|
+
END IF;
|
|
116
|
+
IF OLD.issue_id IS NOT NULL AND NEW.native_issue_id IS NOT NULL AND OLD.issue_id <> NEW.native_issue_id THEN
|
|
117
|
+
RAISE EXCEPTION 'native run task binding disagrees with privacy binding';
|
|
118
|
+
END IF;
|
|
119
|
+
NEW.scope_kind := 'issue';
|
|
120
|
+
RETURN NEW;
|
|
121
|
+
END IF;
|
|
122
|
+
candidate := coalesce(NEW.native_issue_id, NEW.issue_id);
|
|
123
|
+
IF candidate IS NULL AND coalesce(NEW.context_snapshot->>'issueId', NEW.context_snapshot->>'taskId') ~* '^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$' THEN
|
|
124
|
+
candidate := coalesce(NEW.context_snapshot->>'issueId', NEW.context_snapshot->>'taskId')::uuid;
|
|
125
|
+
END IF;
|
|
126
|
+
IF candidate IS NOT NULL OR NEW.context_snapshot ? 'issueId' OR NEW.context_snapshot ? 'taskId' OR NEW.scope_kind = 'issue' THEN
|
|
127
|
+
NEW.scope_kind := 'issue';
|
|
128
|
+
SELECT id INTO NEW.issue_id FROM issues WHERE id = candidate AND company_id = NEW.company_id;
|
|
129
|
+
ELSE
|
|
130
|
+
NEW.scope_kind := 'company';
|
|
131
|
+
END IF;
|
|
132
|
+
RETURN NEW;
|
|
133
|
+
END $$;
|
|
134
|
+
--> statement-breakpoint
|
|
135
|
+
DO $$ BEGIN
|
|
136
|
+
DROP TRIGGER IF EXISTS heartbeat_runs_set_scope_kind ON heartbeat_runs;
|
|
137
|
+
CREATE TRIGGER heartbeat_runs_set_scope_kind BEFORE INSERT OR UPDATE OF issue_id, native_issue_id, context_snapshot, scope_kind
|
|
138
|
+
ON heartbeat_runs FOR EACH ROW EXECUTE FUNCTION set_heartbeat_run_scope_kind();
|
|
139
|
+
END $$;
|
|
140
|
+
--> statement-breakpoint
|
|
141
|
+
-- Indexed primary-key keyset batches visit each historical run once. Missing
|
|
142
|
+
-- source tasks become issue-scoped tombstones, never company-visible run content.
|
|
143
|
+
DO $$ DECLARE cursor_id uuid := '00000000-0000-0000-0000-000000000000'; next_id uuid;
|
|
144
|
+
BEGIN LOOP
|
|
145
|
+
WITH batch AS MATERIALIZED (SELECT id FROM heartbeat_runs WHERE id > cursor_id ORDER BY id LIMIT 1000),
|
|
146
|
+
changed AS (UPDATE heartbeat_runs r SET scope_kind = r.scope_kind FROM batch b WHERE r.id = b.id RETURNING r.id)
|
|
147
|
+
SELECT id INTO next_id FROM changed ORDER BY id DESC LIMIT 1;
|
|
148
|
+
EXIT WHEN next_id IS NULL;
|
|
149
|
+
cursor_id := next_id;
|
|
150
|
+
COMMIT;
|
|
151
|
+
END LOOP; END $$;
|
|
152
|
+
--> statement-breakpoint
|
|
153
|
+
-- Existing structural children acquire downward inheritance without widening
|
|
154
|
+
-- any task's visibility. New provenance edges are written at task creation.
|
|
155
|
+
DO $$ DECLARE cursor_id uuid := '00000000-0000-0000-0000-000000000000'; next_id uuid;
|
|
156
|
+
BEGIN LOOP
|
|
157
|
+
WITH batch AS MATERIALIZED (SELECT id FROM issues WHERE id > cursor_id ORDER BY id LIMIT 1000),
|
|
158
|
+
changed AS (UPDATE issues i SET privacy_parent_issue_id = coalesce(i.privacy_parent_issue_id, i.parent_id)
|
|
159
|
+
FROM batch b WHERE i.id = b.id RETURNING i.id)
|
|
160
|
+
SELECT id INTO next_id FROM changed ORDER BY id DESC LIMIT 1;
|
|
161
|
+
EXIT WHEN next_id IS NULL;
|
|
162
|
+
cursor_id := next_id;
|
|
163
|
+
COMMIT;
|
|
164
|
+
END LOOP; END $$;
|
|
165
|
+
--> statement-breakpoint
|
|
166
|
+
-- Keep workspace provenance after reassignment/deletion. A previous task may
|
|
167
|
+
-- have left files behind; losing the live FK must not publish those files.
|
|
168
|
+
CREATE OR REPLACE FUNCTION retain_workspace_privacy_sources() RETURNS trigger LANGUAGE plpgsql AS $$
|
|
169
|
+
DECLARE sources jsonb := '{}'::jsonb; linked jsonb;
|
|
170
|
+
BEGIN
|
|
171
|
+
IF TG_OP = 'UPDATE' AND jsonb_typeof(OLD.metadata->'_issuePrivacySources') = 'object' THEN
|
|
172
|
+
sources := OLD.metadata->'_issuePrivacySources';
|
|
173
|
+
END IF;
|
|
174
|
+
IF NEW.source_issue_id IS NOT NULL THEN
|
|
175
|
+
sources := sources || jsonb_build_object(NEW.source_issue_id::text, true);
|
|
176
|
+
END IF;
|
|
177
|
+
SELECT jsonb_object_agg(id::text, true) INTO linked FROM issues
|
|
178
|
+
WHERE execution_workspace_id = NEW.id AND company_id = NEW.company_id;
|
|
179
|
+
sources := sources || coalesce(linked, '{}'::jsonb);
|
|
180
|
+
NEW.metadata := coalesce(NEW.metadata, '{}'::jsonb) || jsonb_build_object('_issuePrivacySources', sources);
|
|
181
|
+
RETURN NEW;
|
|
182
|
+
END $$;
|
|
183
|
+
--> statement-breakpoint
|
|
184
|
+
DO $$ BEGIN
|
|
185
|
+
DROP TRIGGER IF EXISTS execution_workspaces_privacy_sources ON execution_workspaces;
|
|
186
|
+
CREATE TRIGGER execution_workspaces_privacy_sources BEFORE INSERT OR UPDATE OF source_issue_id, metadata
|
|
187
|
+
ON execution_workspaces FOR EACH ROW EXECUTE FUNCTION retain_workspace_privacy_sources();
|
|
188
|
+
END $$;
|
|
189
|
+
--> statement-breakpoint
|
|
190
|
+
CREATE OR REPLACE FUNCTION record_issue_workspace_privacy_source() RETURNS trigger LANGUAGE plpgsql AS $$
|
|
191
|
+
BEGIN
|
|
192
|
+
IF NEW.execution_workspace_id IS NOT NULL THEN
|
|
193
|
+
UPDATE execution_workspaces SET metadata = metadata
|
|
194
|
+
WHERE id = NEW.execution_workspace_id AND company_id = NEW.company_id;
|
|
195
|
+
END IF;
|
|
196
|
+
RETURN NEW;
|
|
197
|
+
END $$;
|
|
198
|
+
--> statement-breakpoint
|
|
199
|
+
DO $$ BEGIN
|
|
200
|
+
DROP TRIGGER IF EXISTS issues_record_workspace_privacy_source ON issues;
|
|
201
|
+
CREATE TRIGGER issues_record_workspace_privacy_source AFTER INSERT OR UPDATE OF execution_workspace_id
|
|
202
|
+
ON issues FOR EACH ROW EXECUTE FUNCTION record_issue_workspace_privacy_source();
|
|
203
|
+
END $$;
|
|
204
|
+
--> statement-breakpoint
|
|
205
|
+
DO $$ DECLARE cursor_id uuid := '00000000-0000-0000-0000-000000000000'; next_id uuid;
|
|
206
|
+
BEGIN LOOP
|
|
207
|
+
WITH batch AS MATERIALIZED (SELECT id FROM execution_workspaces WHERE id > cursor_id ORDER BY id LIMIT 1000),
|
|
208
|
+
changed AS (UPDATE execution_workspaces w SET metadata = metadata FROM batch b WHERE w.id = b.id RETURNING w.id)
|
|
209
|
+
SELECT id INTO next_id FROM changed ORDER BY id DESC LIMIT 1;
|
|
210
|
+
EXIT WHEN next_id IS NULL;
|
|
211
|
+
cursor_id := next_id;
|
|
212
|
+
COMMIT;
|
|
213
|
+
END LOOP; END $$;
|
|
214
|
+
|
|
215
|
+
--> statement-breakpoint
|
|
216
|
+
-- Preserve operation history while retaining every original task/run boundary.
|
|
217
|
+
CREATE OR REPLACE FUNCTION paperclip_keep_operation_privacy_sources() RETURNS trigger AS $$
|
|
218
|
+
DECLARE issue_sources jsonb := '{}'::jsonb; run_sources jsonb := '{}'::jsonb;
|
|
219
|
+
BEGIN
|
|
220
|
+
IF TG_OP = 'UPDATE' THEN
|
|
221
|
+
issue_sources := COALESCE(OLD.metadata->'_issuePrivacySources', '{}'::jsonb);
|
|
222
|
+
run_sources := COALESCE(OLD.metadata->'_runPrivacySources', '{}'::jsonb);
|
|
223
|
+
IF OLD.issue_id IS NOT NULL THEN issue_sources := issue_sources || jsonb_build_object(OLD.issue_id::text, true); END IF;
|
|
224
|
+
IF OLD.heartbeat_run_id IS NOT NULL THEN run_sources := run_sources || jsonb_build_object(OLD.heartbeat_run_id::text, true); END IF;
|
|
225
|
+
END IF;
|
|
226
|
+
IF NEW.issue_id IS NOT NULL THEN issue_sources := issue_sources || jsonb_build_object(NEW.issue_id::text, true); END IF;
|
|
227
|
+
IF NEW.heartbeat_run_id IS NOT NULL THEN run_sources := run_sources || jsonb_build_object(NEW.heartbeat_run_id::text, true); END IF;
|
|
228
|
+
NEW.metadata := COALESCE(NEW.metadata, '{}'::jsonb) || jsonb_build_object('_issuePrivacySources', issue_sources, '_runPrivacySources', run_sources);
|
|
229
|
+
RETURN NEW;
|
|
230
|
+
END;
|
|
231
|
+
$$ LANGUAGE plpgsql;
|
|
232
|
+
--> statement-breakpoint
|
|
233
|
+
DO $$ BEGIN
|
|
234
|
+
DROP TRIGGER IF EXISTS workspace_operations_keep_privacy_sources ON workspace_operations;
|
|
235
|
+
CREATE TRIGGER workspace_operations_keep_privacy_sources BEFORE INSERT OR UPDATE ON workspace_operations
|
|
236
|
+
FOR EACH ROW EXECUTE FUNCTION paperclip_keep_operation_privacy_sources();
|
|
237
|
+
END $$;
|
|
238
|
+
--> statement-breakpoint
|
|
239
|
+
DO $$
|
|
240
|
+
DECLARE cursor_id uuid := '00000000-0000-0000-0000-000000000000'; batch_ids uuid[];
|
|
241
|
+
BEGIN
|
|
242
|
+
LOOP
|
|
243
|
+
SELECT array_agg(id ORDER BY id) INTO batch_ids FROM (
|
|
244
|
+
SELECT id FROM workspace_operations WHERE id > cursor_id ORDER BY id LIMIT 1000
|
|
245
|
+
) batch;
|
|
246
|
+
EXIT WHEN batch_ids IS NULL;
|
|
247
|
+
UPDATE workspace_operations SET metadata = metadata WHERE id = ANY(batch_ids);
|
|
248
|
+
cursor_id := batch_ids[array_length(batch_ids, 1)];
|
|
249
|
+
COMMIT;
|
|
250
|
+
END LOOP;
|
|
251
|
+
END $$;
|
|
252
|
+
|
|
253
|
+
--> statement-breakpoint
|
|
254
|
+
ALTER TABLE projects ADD COLUMN IF NOT EXISTS privacy_owner_user_id text;
|
|
255
|
+
--> statement-breakpoint
|
|
256
|
+
-- Recover management authority from creation evidence, never from read grants.
|
|
257
|
+
DO $$
|
|
258
|
+
DECLARE cursor_id uuid := '00000000-0000-0000-0000-000000000000'; batch_ids uuid[];
|
|
259
|
+
BEGIN
|
|
260
|
+
LOOP
|
|
261
|
+
SELECT array_agg(id ORDER BY id) INTO batch_ids FROM (
|
|
262
|
+
SELECT id FROM projects WHERE id > cursor_id ORDER BY id LIMIT 1000
|
|
263
|
+
) batch;
|
|
264
|
+
EXIT WHEN batch_ids IS NULL;
|
|
265
|
+
UPDATE projects p SET privacy_owner_user_id = COALESCE(p.personal_owner_user_id, (
|
|
266
|
+
SELECT CASE WHEN a.actor_type = 'user' THEN a.actor_id ELSE coalesce(a.responsible_user_id, r.responsible_user_id) END
|
|
267
|
+
FROM activity_log a LEFT JOIN heartbeat_runs r ON r.id = a.run_id AND r.company_id = a.company_id
|
|
268
|
+
WHERE a.company_id = p.company_id AND a.entity_type = 'project' AND a.entity_id = p.id::text AND a.action = 'project.created'
|
|
269
|
+
ORDER BY a.created_at, a.id LIMIT 1
|
|
270
|
+
)) WHERE p.id = ANY(batch_ids) AND p.privacy_owner_user_id IS NULL;
|
|
271
|
+
INSERT INTO project_access_members (company_id, project_id, subject_type, subject_id)
|
|
272
|
+
SELECT company_id, id, 'user', privacy_owner_user_id FROM projects
|
|
273
|
+
WHERE id = ANY(batch_ids) AND visibility = 'private' AND privacy_owner_user_id IS NOT NULL
|
|
274
|
+
ON CONFLICT (project_id, subject_type, subject_id) DO NOTHING;
|
|
275
|
+
cursor_id := batch_ids[array_length(batch_ids, 1)];
|
|
276
|
+
COMMIT;
|
|
277
|
+
END LOOP;
|
|
278
|
+
END $$;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
-- Runs through the Paperclip migration executor outside a file-wide transaction.
|
|
2
|
+
-- Each idempotent keyset batch commits before advancing; history is recorded last.
|
|
3
|
+
-- Bind historical inline draft images to their first owned task. Unbound drafts
|
|
4
|
+
-- remain uploader-only. Attachment deletion never makes the draft company-open.
|
|
5
|
+
DO $$
|
|
6
|
+
DECLARE cursor_id uuid := '00000000-0000-0000-0000-000000000000'; next_id uuid;
|
|
7
|
+
BEGIN
|
|
8
|
+
LOOP
|
|
9
|
+
SELECT max(id::text)::uuid INTO next_id FROM (
|
|
10
|
+
SELECT id FROM assets WHERE id > cursor_id AND object_key LIKE company_id::text || '/assets/issues/drafts/%'
|
|
11
|
+
ORDER BY id LIMIT 1000
|
|
12
|
+
) batch;
|
|
13
|
+
EXIT WHEN next_id IS NULL;
|
|
14
|
+
INSERT INTO issue_attachments (company_id, issue_id, asset_id)
|
|
15
|
+
SELECT a.company_id, first_issue.id, a.id FROM assets a
|
|
16
|
+
CROSS JOIN LATERAL (
|
|
17
|
+
SELECT i.id FROM issues i WHERE i.company_id = a.company_id
|
|
18
|
+
AND (i.created_by_user_id = a.created_by_user_id OR i.responsible_user_id = a.created_by_user_id
|
|
19
|
+
OR i.created_by_agent_id = a.created_by_agent_id)
|
|
20
|
+
AND strpos(coalesce(i.description, ''), '/api/assets/' || a.id::text || '/content') > 0
|
|
21
|
+
ORDER BY i.created_at, i.id LIMIT 1
|
|
22
|
+
) first_issue
|
|
23
|
+
WHERE a.id > cursor_id AND a.id <= next_id AND a.object_key LIKE a.company_id::text || '/assets/issues/drafts/%'
|
|
24
|
+
ON CONFLICT DO NOTHING;
|
|
25
|
+
cursor_id := next_id;
|
|
26
|
+
COMMIT;
|
|
27
|
+
END LOOP;
|
|
28
|
+
END $$;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
CREATE TABLE IF NOT EXISTS "user_company_preferences" (
|
|
2
|
+
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
|
3
|
+
"company_id" uuid NOT NULL,
|
|
4
|
+
"user_id" text NOT NULL,
|
|
5
|
+
"primary_agent_id" uuid,
|
|
6
|
+
"primary_agent_initialized" boolean DEFAULT false NOT NULL,
|
|
7
|
+
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
|
|
8
|
+
"updated_at" timestamp with time zone DEFAULT now() NOT NULL
|
|
9
|
+
);
|
|
10
|
+
--> statement-breakpoint
|
|
11
|
+
DO $$ BEGIN
|
|
12
|
+
ALTER TABLE "user_company_preferences" ADD CONSTRAINT "user_company_preferences_company_id_companies_id_fk" FOREIGN KEY ("company_id") REFERENCES "public"."companies"("id") ON DELETE cascade ON UPDATE no action;
|
|
13
|
+
EXCEPTION WHEN duplicate_object THEN NULL;
|
|
14
|
+
END $$;
|
|
15
|
+
--> statement-breakpoint
|
|
16
|
+
DO $$ BEGIN
|
|
17
|
+
ALTER TABLE "user_company_preferences" ADD CONSTRAINT "user_company_preferences_primary_agent_id_agents_id_fk" FOREIGN KEY ("primary_agent_id") REFERENCES "public"."agents"("id") ON DELETE set null ON UPDATE no action;
|
|
18
|
+
EXCEPTION WHEN duplicate_object THEN NULL;
|
|
19
|
+
END $$;
|
|
20
|
+
--> statement-breakpoint
|
|
21
|
+
CREATE UNIQUE INDEX IF NOT EXISTS "user_company_preferences_company_user_uq" ON "user_company_preferences" USING btree ("company_id","user_id");--> statement-breakpoint
|
|
22
|
+
CREATE INDEX IF NOT EXISTS "user_company_preferences_primary_agent_idx" ON "user_company_preferences" USING btree ("primary_agent_id");--> statement-breakpoint
|
|
23
|
+
-- Attribute only explicit human creation events. Select the original event
|
|
24
|
+
-- before joining the agent: deletion/termination must not promote a later hire.
|
|
25
|
+
WITH first_creations AS (
|
|
26
|
+
SELECT DISTINCT ON (company_id, actor_id)
|
|
27
|
+
company_id, actor_id AS user_id, entity_id AS agent_id
|
|
28
|
+
FROM activity_log
|
|
29
|
+
WHERE actor_type = 'user'
|
|
30
|
+
AND actor_id NOT IN ('', 'board', 'system', 'unknown', 'unknown-user')
|
|
31
|
+
AND entity_type = 'agent'
|
|
32
|
+
AND action IN ('agent.created', 'agent.hire_created')
|
|
33
|
+
ORDER BY company_id, actor_id, created_at, id
|
|
34
|
+
)
|
|
35
|
+
INSERT INTO user_company_preferences (company_id, user_id, primary_agent_id, primary_agent_initialized)
|
|
36
|
+
SELECT c.company_id, c.user_id,
|
|
37
|
+
CASE WHEN a.status != 'terminated' AND m.state IS DISTINCT FROM 'left'
|
|
38
|
+
THEN a.id ELSE NULL END,
|
|
39
|
+
true
|
|
40
|
+
FROM first_creations c
|
|
41
|
+
LEFT JOIN agents a ON a.id::text = c.agent_id AND a.company_id = c.company_id
|
|
42
|
+
LEFT JOIN agent_memberships m ON m.company_id = c.company_id AND m.user_id = c.user_id AND m.agent_id = a.id
|
|
43
|
+
WHERE a.metadata->'paperclipBuiltInAgent' IS NULL
|
|
44
|
+
ON CONFLICT (company_id, user_id) DO NOTHING;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
-- Idempotent for installations that applied the pre-merge decision migration.
|
|
2
|
+
CREATE TABLE IF NOT EXISTS "company_decision_models" (
|
|
3
|
+
"company_id" uuid PRIMARY KEY NOT NULL,
|
|
4
|
+
"connection_id" uuid,
|
|
5
|
+
"grant_id" uuid,
|
|
6
|
+
"enabled" boolean DEFAULT false NOT NULL,
|
|
7
|
+
"allow_background" boolean DEFAULT true NOT NULL,
|
|
8
|
+
"provider" text,
|
|
9
|
+
"model" text,
|
|
10
|
+
"updated_at" timestamp with time zone DEFAULT now() NOT NULL,
|
|
11
|
+
CONSTRAINT "company_decisions_configured" CHECK (("company_decision_models"."connection_id" is null) = ("company_decision_models"."grant_id" is null) and (not "company_decision_models"."enabled" or ("company_decision_models"."connection_id" is not null and "company_decision_models"."provider" is not null and "company_decision_models"."model" is not null)))
|
|
12
|
+
);
|
|
13
|
+
--> statement-breakpoint
|
|
14
|
+
CREATE TABLE IF NOT EXISTS "decision_invocations" (
|
|
15
|
+
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
|
16
|
+
"company_id" uuid NOT NULL,
|
|
17
|
+
"feature" text NOT NULL,
|
|
18
|
+
"actor_type" text NOT NULL,
|
|
19
|
+
"actor_id" text NOT NULL,
|
|
20
|
+
"responsible_user_id" text,
|
|
21
|
+
"agent_id" uuid,
|
|
22
|
+
"issue_id" uuid,
|
|
23
|
+
"project_id" uuid,
|
|
24
|
+
"run_id" uuid,
|
|
25
|
+
"identity_context_id" uuid,
|
|
26
|
+
"connection_id" uuid NOT NULL,
|
|
27
|
+
"grant_id" uuid NOT NULL,
|
|
28
|
+
"provider" text NOT NULL,
|
|
29
|
+
"model" text NOT NULL,
|
|
30
|
+
"question_types" jsonb NOT NULL,
|
|
31
|
+
"status" text DEFAULT 'running' NOT NULL,
|
|
32
|
+
"error_code" text,
|
|
33
|
+
"provider_request_id" text,
|
|
34
|
+
"cost_event_id" uuid,
|
|
35
|
+
"started_at" timestamp with time zone DEFAULT now() NOT NULL,
|
|
36
|
+
"finished_at" timestamp with time zone,
|
|
37
|
+
"duration_ms" integer,
|
|
38
|
+
"input_tokens" integer,
|
|
39
|
+
"output_tokens" integer,
|
|
40
|
+
CONSTRAINT "decision_invocations_status_check" CHECK ("decision_invocations"."status" in ('running', 'succeeded', 'failed', 'unknown'))
|
|
41
|
+
);
|
|
42
|
+
--> statement-breakpoint
|
|
43
|
+
ALTER TABLE "budget_reservations" ALTER COLUMN "run_id" DROP NOT NULL;--> statement-breakpoint
|
|
44
|
+
ALTER TABLE "budget_reservations" ALTER COLUMN "agent_id" DROP NOT NULL;--> statement-breakpoint
|
|
45
|
+
ALTER TABLE "cost_events" ALTER COLUMN "agent_id" DROP NOT NULL;--> statement-breakpoint
|
|
46
|
+
ALTER TABLE "budget_reservations" ADD COLUMN IF NOT EXISTS "decision_invocation_id" uuid;--> statement-breakpoint
|
|
47
|
+
ALTER TABLE "cost_events" ADD COLUMN IF NOT EXISTS "usage_kind" text DEFAULT 'agent' NOT NULL;--> statement-breakpoint
|
|
48
|
+
ALTER TABLE "cost_events" ADD COLUMN IF NOT EXISTS "responsible_user_id" text;--> statement-breakpoint
|
|
49
|
+
DO $$ BEGIN
|
|
50
|
+
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'company_decision_models_company_id_companies_id_fk' AND conrelid = 'company_decision_models'::regclass) THEN
|
|
51
|
+
ALTER TABLE "company_decision_models" ADD CONSTRAINT "company_decision_models_company_id_companies_id_fk" FOREIGN KEY ("company_id") REFERENCES "public"."companies"("id") ON DELETE cascade ON UPDATE no action;
|
|
52
|
+
END IF;
|
|
53
|
+
END $$;--> statement-breakpoint
|
|
54
|
+
DO $$ BEGIN
|
|
55
|
+
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'decision_invocations_company_id_companies_id_fk' AND conrelid = 'decision_invocations'::regclass) THEN
|
|
56
|
+
ALTER TABLE "decision_invocations" ADD CONSTRAINT "decision_invocations_company_id_companies_id_fk" FOREIGN KEY ("company_id") REFERENCES "public"."companies"("id") ON DELETE cascade ON UPDATE no action;
|
|
57
|
+
END IF;
|
|
58
|
+
END $$;--> statement-breakpoint
|
|
59
|
+
DO $$ BEGIN
|
|
60
|
+
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'decision_invocations_cost_event_id_cost_events_id_fk' AND conrelid = 'decision_invocations'::regclass) THEN
|
|
61
|
+
ALTER TABLE "decision_invocations" ADD CONSTRAINT "decision_invocations_cost_event_id_cost_events_id_fk" FOREIGN KEY ("cost_event_id") REFERENCES "public"."cost_events"("id") ON DELETE no action ON UPDATE no action;
|
|
62
|
+
END IF;
|
|
63
|
+
END $$;--> statement-breakpoint
|
|
64
|
+
CREATE INDEX IF NOT EXISTS "decision_invocations_company_started_idx" ON "decision_invocations" USING btree ("company_id","started_at","id");--> statement-breakpoint
|
|
65
|
+
CREATE INDEX IF NOT EXISTS "decision_invocations_pending_idx" ON "decision_invocations" USING btree ("started_at") WHERE "decision_invocations"."status" = 'running';--> statement-breakpoint
|
|
66
|
+
CREATE INDEX IF NOT EXISTS "decision_invocations_cost_idx" ON "decision_invocations" USING btree ("cost_event_id");--> statement-breakpoint
|
|
67
|
+
CREATE UNIQUE INDEX IF NOT EXISTS "budget_reservations_decision_idx" ON "budget_reservations" USING btree ("company_id","decision_invocation_id");--> statement-breakpoint
|
|
68
|
+
DO $$ BEGIN
|
|
69
|
+
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'budget_reservations_source_check' AND conrelid = 'budget_reservations'::regclass) THEN
|
|
70
|
+
ALTER TABLE "budget_reservations" ADD CONSTRAINT "budget_reservations_source_check" CHECK (("budget_reservations"."run_id" is not null)::int + ("budget_reservations"."decision_invocation_id" is not null)::int = 1);
|
|
71
|
+
END IF;
|
|
72
|
+
END $$;--> statement-breakpoint
|
|
73
|
+
DO $$ BEGIN
|
|
74
|
+
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'cost_events_usage_kind_check' AND conrelid = 'cost_events'::regclass) THEN
|
|
75
|
+
ALTER TABLE "cost_events" ADD CONSTRAINT "cost_events_usage_kind_check" CHECK ("cost_events"."usage_kind" = 'decision' or ("cost_events"."usage_kind" = 'agent' and "cost_events"."agent_id" is not null));
|
|
76
|
+
END IF;
|
|
77
|
+
END $$;
|
|
78
|
+
--> statement-breakpoint
|
|
79
|
+
ALTER TABLE "company_decision_models" DROP CONSTRAINT IF EXISTS "company_decision_models_connection_id_tool_connections_id_fk";
|
|
80
|
+
--> statement-breakpoint
|
|
81
|
+
ALTER TABLE "company_decision_models" DROP CONSTRAINT IF EXISTS "company_decision_models_grant_id_connection_grants_id_fk";
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
-- Dot-only additions after the merged public MCP gateway. Safe to reapply to a prototype schema.
|
|
2
|
+
CREATE TABLE IF NOT EXISTS "dot_agent_bindings" (
|
|
3
|
+
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
|
4
|
+
"company_id" uuid NOT NULL,
|
|
5
|
+
"agent_id" uuid NOT NULL,
|
|
6
|
+
"operator_id" text NOT NULL,
|
|
7
|
+
"grant_id" uuid,
|
|
8
|
+
"generation" integer DEFAULT 1 NOT NULL,
|
|
9
|
+
"status" text DEFAULT 'pairing' NOT NULL,
|
|
10
|
+
"pairing_code_hash" text,
|
|
11
|
+
"pairing_expires_at" timestamp with time zone,
|
|
12
|
+
"dot_url" text,
|
|
13
|
+
"challenge_hash" text,
|
|
14
|
+
"challenge_expires_at" timestamp with time zone,
|
|
15
|
+
"ready_at" timestamp with time zone,
|
|
16
|
+
"revoked_at" timestamp with time zone,
|
|
17
|
+
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
|
|
18
|
+
"updated_at" timestamp with time zone DEFAULT now() NOT NULL
|
|
19
|
+
);
|
|
20
|
+
--> statement-breakpoint
|
|
21
|
+
CREATE TABLE IF NOT EXISTS "dot_mailbox_items" (
|
|
22
|
+
"id" bigserial PRIMARY KEY NOT NULL,
|
|
23
|
+
"company_id" uuid NOT NULL,
|
|
24
|
+
"binding_id" uuid NOT NULL,
|
|
25
|
+
"binding_generation" integer NOT NULL,
|
|
26
|
+
"assignment_id" uuid,
|
|
27
|
+
"kind" text NOT NULL,
|
|
28
|
+
"source_event_id" text NOT NULL,
|
|
29
|
+
"references" jsonb NOT NULL,
|
|
30
|
+
"created_at" timestamp with time zone DEFAULT now() NOT NULL
|
|
31
|
+
);
|
|
32
|
+
--> statement-breakpoint
|
|
33
|
+
CREATE TABLE IF NOT EXISTS "dot_runner_assignments" (
|
|
34
|
+
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
|
35
|
+
"company_id" uuid NOT NULL,
|
|
36
|
+
"binding_id" uuid NOT NULL,
|
|
37
|
+
"binding_generation" integer NOT NULL,
|
|
38
|
+
"run_id" uuid NOT NULL,
|
|
39
|
+
"agent_id" uuid NOT NULL,
|
|
40
|
+
"normalized_session_id" text NOT NULL,
|
|
41
|
+
"turn_id" text NOT NULL,
|
|
42
|
+
"revision" integer DEFAULT 1 NOT NULL,
|
|
43
|
+
"controller_generation" integer NOT NULL,
|
|
44
|
+
"catalog_digest" text NOT NULL,
|
|
45
|
+
"status" text NOT NULL,
|
|
46
|
+
"projection" jsonb NOT NULL,
|
|
47
|
+
"accept_by" timestamp with time zone NOT NULL,
|
|
48
|
+
"expires_at" timestamp with time zone NOT NULL,
|
|
49
|
+
"accepted_at" timestamp with time zone,
|
|
50
|
+
"settled_at" timestamp with time zone,
|
|
51
|
+
"last_activity_at" timestamp with time zone DEFAULT now() NOT NULL,
|
|
52
|
+
"created_at" timestamp with time zone DEFAULT now() NOT NULL
|
|
53
|
+
);
|
|
54
|
+
--> statement-breakpoint
|
|
55
|
+
CREATE TABLE IF NOT EXISTS "dot_runner_operations" (
|
|
56
|
+
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
|
57
|
+
"company_id" uuid NOT NULL,
|
|
58
|
+
"assignment_id" uuid NOT NULL,
|
|
59
|
+
"request_id" uuid NOT NULL,
|
|
60
|
+
"digest" text NOT NULL,
|
|
61
|
+
"command" jsonb NOT NULL,
|
|
62
|
+
"status" text DEFAULT 'reserved' NOT NULL,
|
|
63
|
+
"outcome" jsonb,
|
|
64
|
+
"source_event_id" text,
|
|
65
|
+
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
|
|
66
|
+
"updated_at" timestamp with time zone DEFAULT now() NOT NULL
|
|
67
|
+
);
|
|
68
|
+
--> statement-breakpoint
|
|
69
|
+
ALTER TABLE "mcp_event_deliveries" ALTER COLUMN "activity_id" DROP NOT NULL;
|
|
70
|
+
--> statement-breakpoint
|
|
71
|
+
ALTER TABLE "mcp_event_subscriptions" ALTER COLUMN "task_id" DROP NOT NULL;
|
|
72
|
+
--> statement-breakpoint
|
|
73
|
+
ALTER TABLE "mcp_event_deliveries" ADD COLUMN IF NOT EXISTS "mailbox_item_id" integer;
|
|
74
|
+
--> statement-breakpoint
|
|
75
|
+
ALTER TABLE "mcp_event_subscriptions" ADD COLUMN IF NOT EXISTS "binding_id" uuid;
|
|
76
|
+
--> statement-breakpoint
|
|
77
|
+
ALTER TABLE "mcp_oauth_grants" ADD COLUMN IF NOT EXISTS "purpose" text DEFAULT 'personal' NOT NULL;
|
|
78
|
+
--> statement-breakpoint
|
|
79
|
+
ALTER TABLE "mcp_oauth_grants" ADD COLUMN IF NOT EXISTS "agent_id" uuid;
|
|
80
|
+
--> statement-breakpoint
|
|
81
|
+
DO $$ BEGIN
|
|
82
|
+
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'dot_agent_bindings_company_id_companies_id_fk' AND conrelid = 'public.dot_agent_bindings'::regclass) THEN
|
|
83
|
+
ALTER TABLE "dot_agent_bindings" ADD CONSTRAINT "dot_agent_bindings_company_id_companies_id_fk" FOREIGN KEY ("company_id") REFERENCES "public"."companies"("id") ON DELETE cascade ON UPDATE no action;
|
|
84
|
+
END IF;
|
|
85
|
+
END $$;
|
|
86
|
+
--> statement-breakpoint
|
|
87
|
+
DO $$ BEGIN
|
|
88
|
+
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'dot_agent_bindings_agent_id_agents_id_fk' AND conrelid = 'public.dot_agent_bindings'::regclass) THEN
|
|
89
|
+
ALTER TABLE "dot_agent_bindings" ADD CONSTRAINT "dot_agent_bindings_agent_id_agents_id_fk" FOREIGN KEY ("agent_id") REFERENCES "public"."agents"("id") ON DELETE cascade ON UPDATE no action;
|
|
90
|
+
END IF;
|
|
91
|
+
END $$;
|
|
92
|
+
--> statement-breakpoint
|
|
93
|
+
DO $$ BEGIN
|
|
94
|
+
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'dot_agent_bindings_grant_id_mcp_oauth_grants_id_fk' AND conrelid = 'public.dot_agent_bindings'::regclass) THEN
|
|
95
|
+
ALTER TABLE "dot_agent_bindings" ADD CONSTRAINT "dot_agent_bindings_grant_id_mcp_oauth_grants_id_fk" FOREIGN KEY ("grant_id") REFERENCES "public"."mcp_oauth_grants"("id") ON DELETE set null ON UPDATE no action;
|
|
96
|
+
END IF;
|
|
97
|
+
END $$;
|
|
98
|
+
--> statement-breakpoint
|
|
99
|
+
DO $$ BEGIN
|
|
100
|
+
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'dot_mailbox_items_company_id_companies_id_fk' AND conrelid = 'public.dot_mailbox_items'::regclass) THEN
|
|
101
|
+
ALTER TABLE "dot_mailbox_items" ADD CONSTRAINT "dot_mailbox_items_company_id_companies_id_fk" FOREIGN KEY ("company_id") REFERENCES "public"."companies"("id") ON DELETE cascade ON UPDATE no action;
|
|
102
|
+
END IF;
|
|
103
|
+
END $$;
|
|
104
|
+
--> statement-breakpoint
|
|
105
|
+
DO $$ BEGIN
|
|
106
|
+
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'dot_mailbox_items_binding_id_dot_agent_bindings_id_fk' AND conrelid = 'public.dot_mailbox_items'::regclass) THEN
|
|
107
|
+
ALTER TABLE "dot_mailbox_items" ADD CONSTRAINT "dot_mailbox_items_binding_id_dot_agent_bindings_id_fk" FOREIGN KEY ("binding_id") REFERENCES "public"."dot_agent_bindings"("id") ON DELETE cascade ON UPDATE no action;
|
|
108
|
+
END IF;
|
|
109
|
+
END $$;
|
|
110
|
+
--> statement-breakpoint
|
|
111
|
+
DO $$ BEGIN
|
|
112
|
+
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'dot_mailbox_items_assignment_id_dot_runner_assignments_id_fk' AND conrelid = 'public.dot_mailbox_items'::regclass) THEN
|
|
113
|
+
ALTER TABLE "dot_mailbox_items" ADD CONSTRAINT "dot_mailbox_items_assignment_id_dot_runner_assignments_id_fk" FOREIGN KEY ("assignment_id") REFERENCES "public"."dot_runner_assignments"("id") ON DELETE cascade ON UPDATE no action;
|
|
114
|
+
END IF;
|
|
115
|
+
END $$;
|
|
116
|
+
--> statement-breakpoint
|
|
117
|
+
DO $$ BEGIN
|
|
118
|
+
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'dot_runner_assignments_company_id_companies_id_fk' AND conrelid = 'public.dot_runner_assignments'::regclass) THEN
|
|
119
|
+
ALTER TABLE "dot_runner_assignments" ADD CONSTRAINT "dot_runner_assignments_company_id_companies_id_fk" FOREIGN KEY ("company_id") REFERENCES "public"."companies"("id") ON DELETE cascade ON UPDATE no action;
|
|
120
|
+
END IF;
|
|
121
|
+
END $$;
|
|
122
|
+
--> statement-breakpoint
|
|
123
|
+
DO $$ BEGIN
|
|
124
|
+
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'dot_runner_assignments_binding_id_dot_agent_bindings_id_fk' AND conrelid = 'public.dot_runner_assignments'::regclass) THEN
|
|
125
|
+
ALTER TABLE "dot_runner_assignments" ADD CONSTRAINT "dot_runner_assignments_binding_id_dot_agent_bindings_id_fk" FOREIGN KEY ("binding_id") REFERENCES "public"."dot_agent_bindings"("id") ON DELETE cascade ON UPDATE no action;
|
|
126
|
+
END IF;
|
|
127
|
+
END $$;
|
|
128
|
+
--> statement-breakpoint
|
|
129
|
+
DO $$ BEGIN
|
|
130
|
+
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'dot_runner_assignments_run_id_heartbeat_runs_id_fk' AND conrelid = 'public.dot_runner_assignments'::regclass) THEN
|
|
131
|
+
ALTER TABLE "dot_runner_assignments" ADD CONSTRAINT "dot_runner_assignments_run_id_heartbeat_runs_id_fk" FOREIGN KEY ("run_id") REFERENCES "public"."heartbeat_runs"("id") ON DELETE cascade ON UPDATE no action;
|
|
132
|
+
END IF;
|
|
133
|
+
END $$;
|
|
134
|
+
--> statement-breakpoint
|
|
135
|
+
DO $$ BEGIN
|
|
136
|
+
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'dot_runner_assignments_agent_id_agents_id_fk' AND conrelid = 'public.dot_runner_assignments'::regclass) THEN
|
|
137
|
+
ALTER TABLE "dot_runner_assignments" ADD CONSTRAINT "dot_runner_assignments_agent_id_agents_id_fk" FOREIGN KEY ("agent_id") REFERENCES "public"."agents"("id") ON DELETE cascade ON UPDATE no action;
|
|
138
|
+
END IF;
|
|
139
|
+
END $$;
|
|
140
|
+
--> statement-breakpoint
|
|
141
|
+
DO $$ BEGIN
|
|
142
|
+
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'dot_runner_operations_company_id_companies_id_fk' AND conrelid = 'public.dot_runner_operations'::regclass) THEN
|
|
143
|
+
ALTER TABLE "dot_runner_operations" ADD CONSTRAINT "dot_runner_operations_company_id_companies_id_fk" FOREIGN KEY ("company_id") REFERENCES "public"."companies"("id") ON DELETE cascade ON UPDATE no action;
|
|
144
|
+
END IF;
|
|
145
|
+
END $$;
|
|
146
|
+
--> statement-breakpoint
|
|
147
|
+
DO $$ BEGIN
|
|
148
|
+
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'dot_runner_operations_assignment_id_dot_runner_assignments_id_fk' AND conrelid = 'public.dot_runner_operations'::regclass) THEN
|
|
149
|
+
ALTER TABLE "dot_runner_operations" ADD CONSTRAINT "dot_runner_operations_assignment_id_dot_runner_assignments_id_fk" FOREIGN KEY ("assignment_id") REFERENCES "public"."dot_runner_assignments"("id") ON DELETE cascade ON UPDATE no action;
|
|
150
|
+
END IF;
|
|
151
|
+
END $$;
|
|
152
|
+
--> statement-breakpoint
|
|
153
|
+
CREATE UNIQUE INDEX IF NOT EXISTS "dot_bindings_active_agent_uq" ON "dot_agent_bindings" USING btree ("company_id","agent_id") WHERE "dot_agent_bindings"."revoked_at" IS NULL;
|
|
154
|
+
--> statement-breakpoint
|
|
155
|
+
CREATE UNIQUE INDEX IF NOT EXISTS "dot_bindings_active_grant_uq" ON "dot_agent_bindings" USING btree ("grant_id") WHERE "dot_agent_bindings"."revoked_at" IS NULL AND "dot_agent_bindings"."grant_id" IS NOT NULL;
|
|
156
|
+
--> statement-breakpoint
|
|
157
|
+
CREATE UNIQUE INDEX IF NOT EXISTS "dot_bindings_pairing_code_uq" ON "dot_agent_bindings" USING btree ("pairing_code_hash");
|
|
158
|
+
--> statement-breakpoint
|
|
159
|
+
CREATE UNIQUE INDEX IF NOT EXISTS "dot_mailbox_event_uq" ON "dot_mailbox_items" USING btree ("binding_id","binding_generation","source_event_id");
|
|
160
|
+
--> statement-breakpoint
|
|
161
|
+
CREATE INDEX IF NOT EXISTS "dot_mailbox_binding_cursor_idx" ON "dot_mailbox_items" USING btree ("binding_id","binding_generation","id");
|
|
162
|
+
--> statement-breakpoint
|
|
163
|
+
CREATE UNIQUE INDEX IF NOT EXISTS "dot_assignments_turn_uq" ON "dot_runner_assignments" USING btree ("run_id","turn_id");
|
|
164
|
+
--> statement-breakpoint
|
|
165
|
+
CREATE UNIQUE INDEX IF NOT EXISTS "dot_assignments_active_binding_uq" ON "dot_runner_assignments" USING btree ("binding_id") WHERE "dot_runner_assignments"."status" IN ('offered', 'accepted');
|
|
166
|
+
--> statement-breakpoint
|
|
167
|
+
CREATE INDEX IF NOT EXISTS "dot_assignments_company_idx" ON "dot_runner_assignments" USING btree ("company_id");
|
|
168
|
+
--> statement-breakpoint
|
|
169
|
+
CREATE UNIQUE INDEX IF NOT EXISTS "dot_operations_request_uq" ON "dot_runner_operations" USING btree ("assignment_id","request_id");
|
|
170
|
+
--> statement-breakpoint
|
|
171
|
+
DO $$ BEGIN
|
|
172
|
+
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'mcp_oauth_grants_agent_id_agents_id_fk' AND conrelid = 'public.mcp_oauth_grants'::regclass) THEN
|
|
173
|
+
ALTER TABLE "mcp_oauth_grants" ADD CONSTRAINT "mcp_oauth_grants_agent_id_agents_id_fk" FOREIGN KEY ("agent_id") REFERENCES "public"."agents"("id") ON DELETE cascade ON UPDATE no action;
|
|
174
|
+
END IF;
|
|
175
|
+
END $$;
|
|
176
|
+
--> statement-breakpoint
|
|
177
|
+
CREATE UNIQUE INDEX IF NOT EXISTS "mcp_event_deliveries_mailbox_uq" ON "mcp_event_deliveries" USING btree ("subscription_id","mailbox_item_id");
|
|
178
|
+
--> statement-breakpoint
|
|
179
|
+
DO $$ BEGIN
|
|
180
|
+
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'mcp_delivery_source_check' AND conrelid = 'public.mcp_event_deliveries'::regclass) THEN
|
|
181
|
+
ALTER TABLE "mcp_event_deliveries" ADD CONSTRAINT "mcp_delivery_source_check" CHECK (("mcp_event_deliveries"."activity_id" IS NOT NULL AND "mcp_event_deliveries"."mailbox_item_id" IS NULL) OR ("mcp_event_deliveries"."activity_id" IS NULL AND "mcp_event_deliveries"."mailbox_item_id" IS NOT NULL));
|
|
182
|
+
END IF;
|
|
183
|
+
END $$;
|
|
184
|
+
--> statement-breakpoint
|
|
185
|
+
DO $$ BEGIN
|
|
186
|
+
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'mcp_subscription_resource_check' AND conrelid = 'public.mcp_event_subscriptions'::regclass) THEN
|
|
187
|
+
ALTER TABLE "mcp_event_subscriptions" ADD CONSTRAINT "mcp_subscription_resource_check" CHECK (("mcp_event_subscriptions"."task_id" IS NOT NULL AND "mcp_event_subscriptions"."binding_id" IS NULL) OR ("mcp_event_subscriptions"."task_id" IS NULL AND "mcp_event_subscriptions"."binding_id" IS NOT NULL));
|
|
188
|
+
END IF;
|
|
189
|
+
END $$;
|