@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.
Files changed (224) hide show
  1. package/dist/backup-lib.d.ts +2 -0
  2. package/dist/backup-lib.d.ts.map +1 -1
  3. package/dist/backup-lib.js +52 -15
  4. package/dist/backup-lib.js.map +1 -1
  5. package/dist/backup-lib.test.js +64 -2
  6. package/dist/backup-lib.test.js.map +1 -1
  7. package/dist/client.d.ts.map +1 -1
  8. package/dist/client.js +81 -42
  9. package/dist/client.js.map +1 -1
  10. package/dist/client.test.js +33 -0
  11. package/dist/client.test.js.map +1 -1
  12. package/dist/connections-v3-schema-core-migration.test.js +3 -0
  13. package/dist/connections-v3-schema-core-migration.test.js.map +1 -1
  14. package/dist/heartbeat-run-issue-privacy-migration.test.d.ts +2 -0
  15. package/dist/heartbeat-run-issue-privacy-migration.test.d.ts.map +1 -0
  16. package/dist/heartbeat-run-issue-privacy-migration.test.js +265 -0
  17. package/dist/heartbeat-run-issue-privacy-migration.test.js.map +1 -0
  18. package/dist/index.d.ts +1 -0
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +1 -0
  21. package/dist/index.js.map +1 -1
  22. package/dist/migrations/0315_chunky_chamber.sql +3 -0
  23. package/dist/migrations/0316_lumpy_maria_hill.sql +157 -0
  24. package/dist/migrations/0317_colossal_otto_octavius.sql +24 -0
  25. package/dist/migrations/0318_supreme_garia.sql +1 -0
  26. package/dist/migrations/0319_curvy_shadow_king.sql +27 -0
  27. package/dist/migrations/0320_chubby_vin_gonzales.sql +7 -0
  28. package/dist/migrations/0321_familiar_titania.sql +4 -0
  29. package/dist/migrations/0322_cool_naoko.sql +3 -0
  30. package/dist/migrations/0323_whole_steel_serpent.sql +20 -0
  31. package/dist/migrations/0324_loving_the_hood.sql +77 -0
  32. package/dist/migrations/0325_agent_commentary.sql +33 -0
  33. package/dist/migrations/0326_mcp_file_transfers.sql +48 -0
  34. package/dist/migrations/0327_easy_eternity.sql +232 -0
  35. package/dist/migrations/0328_private_task_access.sql +278 -0
  36. package/dist/migrations/0329_private_task_draft_assets.sql +28 -0
  37. package/dist/migrations/0330_rapid_emma_frost.sql +44 -0
  38. package/dist/migrations/0331_premium_slayback.sql +81 -0
  39. package/dist/migrations/0332_messy_famine.sql +189 -0
  40. package/dist/migrations/0333_strong_blacklash.sql +23 -0
  41. package/dist/migrations/0334_heavy_captain_midlands.sql +15 -0
  42. package/dist/migrations/0335_daily_onslaught.sql +16 -0
  43. package/dist/migrations/0336_acoustic_human_fly.sql +1 -0
  44. package/dist/migrations/0337_reflective_kree.sql +98 -0
  45. package/dist/migrations/0338_petite_shockwave.sql +4 -0
  46. package/dist/migrations/0339_long_franklin_storm.sql +153 -0
  47. package/dist/migrations/0340_aberrant_machine_man.sql +6 -0
  48. package/dist/migrations/0341_blushing_screwball.sql +17 -0
  49. package/dist/migrations/0342_sad_proteus.sql +23 -0
  50. package/dist/migrations/0343_chunky_mentallo.sql +52 -0
  51. package/dist/migrations/0344_free_wolf_cub.sql +18 -0
  52. package/dist/migrations/0345_spooky_white_tiger.sql +7 -0
  53. package/dist/migrations/0346_panoramic_spyke.sql +74 -0
  54. package/dist/migrations/0347_little_night_nurse.sql +1 -0
  55. package/dist/migrations/meta/_journal.json +232 -1
  56. package/dist/private-task-draft-assets-migration.test.d.ts +2 -0
  57. package/dist/private-task-draft-assets-migration.test.d.ts.map +1 -0
  58. package/dist/private-task-draft-assets-migration.test.js +35 -0
  59. package/dist/private-task-draft-assets-migration.test.js.map +1 -0
  60. package/dist/question-response-history-migration.test.d.ts +2 -0
  61. package/dist/question-response-history-migration.test.d.ts.map +1 -0
  62. package/dist/question-response-history-migration.test.js +53 -0
  63. package/dist/question-response-history-migration.test.js.map +1 -0
  64. package/dist/schema/accounting.d.ts +1282 -0
  65. package/dist/schema/accounting.d.ts.map +1 -0
  66. package/dist/schema/accounting.js +120 -0
  67. package/dist/schema/accounting.js.map +1 -0
  68. package/dist/schema/adapter_auth_sessions.d.ts +2 -2
  69. package/dist/schema/agent_commentary.d.ts +181 -0
  70. package/dist/schema/agent_commentary.d.ts.map +1 -0
  71. package/dist/schema/agent_commentary.js +24 -0
  72. package/dist/schema/agent_commentary.js.map +1 -0
  73. package/dist/schema/agent_identity_keys.d.ts +131 -0
  74. package/dist/schema/agent_identity_keys.d.ts.map +1 -0
  75. package/dist/schema/agent_identity_keys.js +20 -0
  76. package/dist/schema/agent_identity_keys.js.map +1 -0
  77. package/dist/schema/agent_runtime_state.d.ts +2 -2
  78. package/dist/schema/agent_runtime_state.js +2 -2
  79. package/dist/schema/agent_runtime_state.js.map +1 -1
  80. package/dist/schema/agent_wakeup_requests.d.ts.map +1 -1
  81. package/dist/schema/agent_wakeup_requests.js +6 -0
  82. package/dist/schema/agent_wakeup_requests.js.map +1 -1
  83. package/dist/schema/agents.d.ts +132 -2
  84. package/dist/schema/agents.d.ts.map +1 -1
  85. package/dist/schema/agents.js +10 -2
  86. package/dist/schema/agents.js.map +1 -1
  87. package/dist/schema/ai_connection_defaults.d.ts +2 -2
  88. package/dist/schema/ai_connection_defaults.js +1 -1
  89. package/dist/schema/ai_connection_defaults.js.map +1 -1
  90. package/dist/schema/ai_connection_routing.d.ts +8 -8
  91. package/dist/schema/ai_provider_defaults.d.ts +2 -2
  92. package/dist/schema/ai_provider_defaults.js +1 -1
  93. package/dist/schema/ai_provider_defaults.js.map +1 -1
  94. package/dist/schema/ai_subscriptions.d.ts +619 -0
  95. package/dist/schema/ai_subscriptions.d.ts.map +1 -0
  96. package/dist/schema/ai_subscriptions.js +61 -0
  97. package/dist/schema/ai_subscriptions.js.map +1 -0
  98. package/dist/schema/budget_incidents.d.ts +2 -2
  99. package/dist/schema/budget_incidents.js +3 -3
  100. package/dist/schema/budget_incidents.js.map +1 -1
  101. package/dist/schema/budget_policies.d.ts +68 -0
  102. package/dist/schema/budget_policies.d.ts.map +1 -1
  103. package/dist/schema/budget_policies.js +7 -1
  104. package/dist/schema/budget_policies.js.map +1 -1
  105. package/dist/schema/chat_channels.d.ts +21 -4
  106. package/dist/schema/chat_channels.d.ts.map +1 -1
  107. package/dist/schema/chat_channels.js +3 -2
  108. package/dist/schema/chat_channels.js.map +1 -1
  109. package/dist/schema/chat_github.d.ts +108 -0
  110. package/dist/schema/chat_github.d.ts.map +1 -1
  111. package/dist/schema/chat_github.js +7 -0
  112. package/dist/schema/chat_github.js.map +1 -1
  113. package/dist/schema/chat_slack_registrations.d.ts +287 -0
  114. package/dist/schema/chat_slack_registrations.d.ts.map +1 -0
  115. package/dist/schema/chat_slack_registrations.js +26 -0
  116. package/dist/schema/chat_slack_registrations.js.map +1 -0
  117. package/dist/schema/chat_voice_callbacks.d.ts +128 -0
  118. package/dist/schema/chat_voice_callbacks.d.ts.map +1 -0
  119. package/dist/schema/chat_voice_callbacks.js +18 -0
  120. package/dist/schema/chat_voice_callbacks.js.map +1 -0
  121. package/dist/schema/chat_voice_inbound.d.ts +461 -0
  122. package/dist/schema/chat_voice_inbound.d.ts.map +1 -0
  123. package/dist/schema/chat_voice_inbound.js +45 -0
  124. package/dist/schema/chat_voice_inbound.js.map +1 -0
  125. package/dist/schema/chat_voice_reports.d.ts +184 -0
  126. package/dist/schema/chat_voice_reports.d.ts.map +1 -0
  127. package/dist/schema/chat_voice_reports.js +24 -0
  128. package/dist/schema/chat_voice_reports.js.map +1 -0
  129. package/dist/schema/chat_voice_sessions.d.ts +730 -0
  130. package/dist/schema/chat_voice_sessions.d.ts.map +1 -0
  131. package/dist/schema/chat_voice_sessions.js +85 -0
  132. package/dist/schema/chat_voice_sessions.js.map +1 -0
  133. package/dist/schema/companies.d.ts +19 -2
  134. package/dist/schema/companies.d.ts.map +1 -1
  135. package/dist/schema/companies.js +3 -2
  136. package/dist/schema/companies.js.map +1 -1
  137. package/dist/schema/cost_events.d.ts +141 -3
  138. package/dist/schema/cost_events.d.ts.map +1 -1
  139. package/dist/schema/cost_events.js +20 -3
  140. package/dist/schema/cost_events.js.map +1 -1
  141. package/dist/schema/decision_models.d.ts +579 -0
  142. package/dist/schema/decision_models.d.ts.map +1 -0
  143. package/dist/schema/decision_models.js +50 -0
  144. package/dist/schema/decision_models.js.map +1 -0
  145. package/dist/schema/dot_runner.d.ts +980 -0
  146. package/dist/schema/dot_runner.d.ts.map +1 -0
  147. package/dist/schema/dot_runner.js +82 -0
  148. package/dist/schema/dot_runner.js.map +1 -0
  149. package/dist/schema/fast_responses.d.ts +662 -0
  150. package/dist/schema/fast_responses.d.ts.map +1 -0
  151. package/dist/schema/fast_responses.js +65 -0
  152. package/dist/schema/fast_responses.js.map +1 -0
  153. package/dist/schema/finance_events.d.ts +36 -2
  154. package/dist/schema/finance_events.d.ts.map +1 -1
  155. package/dist/schema/finance_events.js +5 -2
  156. package/dist/schema/finance_events.js.map +1 -1
  157. package/dist/schema/heartbeat_runs.d.ts +138 -0
  158. package/dist/schema/heartbeat_runs.d.ts.map +1 -1
  159. package/dist/schema/heartbeat_runs.js +17 -1
  160. package/dist/schema/heartbeat_runs.js.map +1 -1
  161. package/dist/schema/index.d.ts +17 -0
  162. package/dist/schema/index.d.ts.map +1 -1
  163. package/dist/schema/index.js +17 -0
  164. package/dist/schema/index.js.map +1 -1
  165. package/dist/schema/issue_access_grants.d.ts +161 -0
  166. package/dist/schema/issue_access_grants.d.ts.map +1 -0
  167. package/dist/schema/issue_access_grants.js +21 -0
  168. package/dist/schema/issue_access_grants.js.map +1 -0
  169. package/dist/schema/issue_comments.d.ts +36 -0
  170. package/dist/schema/issue_comments.d.ts.map +1 -1
  171. package/dist/schema/issue_comments.js +2 -0
  172. package/dist/schema/issue_comments.js.map +1 -1
  173. package/dist/schema/issues.d.ts +51 -0
  174. package/dist/schema/issues.d.ts.map +1 -1
  175. package/dist/schema/issues.js +6 -0
  176. package/dist/schema/issues.js.map +1 -1
  177. package/dist/schema/plugin_lifecycle_acknowledgments.d.ts +59 -0
  178. package/dist/schema/plugin_lifecycle_acknowledgments.d.ts.map +1 -0
  179. package/dist/schema/plugin_lifecycle_acknowledgments.js +12 -0
  180. package/dist/schema/plugin_lifecycle_acknowledgments.js.map +1 -0
  181. package/dist/schema/project_access_members.d.ts +111 -0
  182. package/dist/schema/project_access_members.d.ts.map +1 -0
  183. package/dist/schema/project_access_members.js +18 -0
  184. package/dist/schema/project_access_members.js.map +1 -0
  185. package/dist/schema/projects.d.ts +51 -0
  186. package/dist/schema/projects.d.ts.map +1 -1
  187. package/dist/schema/projects.js +9 -1
  188. package/dist/schema/projects.js.map +1 -1
  189. package/dist/schema/public_mcp.d.ts +2100 -0
  190. package/dist/schema/public_mcp.d.ts.map +1 -0
  191. package/dist/schema/public_mcp.js +191 -0
  192. package/dist/schema/public_mcp.js.map +1 -0
  193. package/dist/schema/resource_lifecycle_events.d.ts +2 -2
  194. package/dist/schema/resource_lifecycle_events.d.ts.map +1 -1
  195. package/dist/schema/resource_lifecycle_events.js +2 -1
  196. package/dist/schema/resource_lifecycle_events.js.map +1 -1
  197. package/dist/schema/status_cards.d.ts +2 -2
  198. package/dist/schema/status_cards.js +2 -2
  199. package/dist/schema/status_cards.js.map +1 -1
  200. package/dist/schema/tool_access.d.ts +18 -0
  201. package/dist/schema/tool_access.d.ts.map +1 -1
  202. package/dist/schema/tool_access.js +3 -3
  203. package/dist/schema/tool_access.js.map +1 -1
  204. package/dist/schema/user_company_preferences.d.ts +127 -0
  205. package/dist/schema/user_company_preferences.d.ts.map +1 -0
  206. package/dist/schema/user_company_preferences.js +16 -0
  207. package/dist/schema/user_company_preferences.js.map +1 -0
  208. package/dist/speko-voice-migration.test.d.ts +2 -0
  209. package/dist/speko-voice-migration.test.d.ts.map +1 -0
  210. package/dist/speko-voice-migration.test.js +88 -0
  211. package/dist/speko-voice-migration.test.js.map +1 -0
  212. package/dist/work-signals.d.ts +20 -0
  213. package/dist/work-signals.d.ts.map +1 -0
  214. package/dist/work-signals.js +123 -0
  215. package/dist/work-signals.js.map +1 -0
  216. package/dist/work-signals.test.d.ts +2 -0
  217. package/dist/work-signals.test.d.ts.map +1 -0
  218. package/dist/work-signals.test.js +177 -0
  219. package/dist/work-signals.test.js.map +1 -0
  220. package/package.json +4 -4
  221. package/dist/seed.d.ts +0 -2
  222. package/dist/seed.d.ts.map +0 -1
  223. package/dist/seed.js +0 -91
  224. package/dist/seed.js.map +0 -1
@@ -0,0 +1,23 @@
1
+ CREATE TABLE IF NOT EXISTS "chat_slack_registrations" (
2
+ "endpoint_id" uuid PRIMARY KEY NOT NULL,
3
+ "company_id" uuid NOT NULL,
4
+ "request_id" uuid NOT NULL,
5
+ "status" text NOT NULL,
6
+ "manifest" jsonb NOT NULL,
7
+ "manifest_hash" text NOT NULL,
8
+ "callback_uri" text NOT NULL,
9
+ "app_id" text,
10
+ "client_id" text,
11
+ "secret_ids" jsonb DEFAULT '{}'::jsonb NOT NULL,
12
+ "workspace_id" text,
13
+ "bot_user_id" text,
14
+ "error_code" text,
15
+ "created_by_user_id" text NOT NULL,
16
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
17
+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL,
18
+ CONSTRAINT "chat_slack_registration_status_check" CHECK ("chat_slack_registrations"."status" in ('creating', 'uncertain', 'failed', 'install', 'credentials_saved', 'configured', 'removed'))
19
+ );
20
+ --> statement-breakpoint
21
+ DO $$ BEGIN
22
+ ALTER TABLE "chat_slack_registrations" ADD CONSTRAINT "chat_slack_registrations_company_id_endpoint_id_chat_endpoints_company_id_id_fk" FOREIGN KEY ("company_id","endpoint_id") REFERENCES "public"."chat_endpoints"("company_id","id") ON DELETE cascade ON UPDATE no action;
23
+ EXCEPTION WHEN duplicate_object THEN NULL; END $$;
@@ -0,0 +1,15 @@
1
+ ALTER TABLE "mcp_oauth_tokens" ALTER COLUMN "expires_at" DROP NOT NULL;
2
+ --> statement-breakpoint
3
+ -- Active Dot connections keep working without another consent flow. Expired
4
+ -- or consumed credentials stay invalid, revoked grants stay revoked, and
5
+ -- personal assistant connections retain their expiry.
6
+ UPDATE "mcp_oauth_tokens" AS tokens
7
+ SET "expires_at" = NULL
8
+ FROM "mcp_oauth_grants" AS grants
9
+ WHERE tokens."grant_id" = grants."id"
10
+ AND tokens."kind" = 'refresh'
11
+ AND tokens."used_at" IS NULL
12
+ AND tokens."expires_at" > now()
13
+ AND grants."purpose" = 'agent'
14
+ AND grants."resource" LIKE '%/mcp/runner'
15
+ AND grants."revoked_at" IS NULL;
@@ -0,0 +1,16 @@
1
+ ALTER TABLE "agents" ADD COLUMN IF NOT EXISTS "lifecycle_state" text DEFAULT 'ready' NOT NULL;--> statement-breakpoint
2
+ ALTER TABLE "agents" ADD COLUMN IF NOT EXISTS "lifecycle_required_plugin_ids" jsonb;--> statement-breakpoint
3
+ ALTER TABLE "agents" ADD COLUMN IF NOT EXISTS "lifecycle_holds" jsonb DEFAULT '[]'::jsonb NOT NULL;--> statement-breakpoint
4
+ ALTER TABLE "agents" ADD COLUMN IF NOT EXISTS "lifecycle_version" integer DEFAULT 0 NOT NULL;--> statement-breakpoint
5
+ ALTER TABLE "agents" ADD COLUMN IF NOT EXISTS "lifecycle_error" text;--> statement-breakpoint
6
+ ALTER TABLE "agents" ADD COLUMN IF NOT EXISTS "lifecycle_operation" jsonb;--> statement-breakpoint
7
+ CREATE INDEX IF NOT EXISTS "agents_lifecycle_work_idx" ON "agents" USING btree ("lifecycle_state","updated_at","id");
8
+ --> statement-breakpoint
9
+ UPDATE "agents" SET
10
+ "lifecycle_state" = CASE "status"
11
+ WHEN 'pending_approval' THEN 'pending_approval'
12
+ WHEN 'paused' THEN 'paused'
13
+ WHEN 'terminated' THEN 'terminated'
14
+ ELSE 'ready' END,
15
+ "lifecycle_holds" = CASE WHEN "status" = 'paused'
16
+ THEN jsonb_build_array(coalesce("pause_reason", 'manual')) ELSE '[]'::jsonb END;
@@ -0,0 +1 @@
1
+ ALTER TABLE "chat_endpoints" ADD COLUMN IF NOT EXISTS "require_at_mention" boolean DEFAULT false NOT NULL;
@@ -0,0 +1,98 @@
1
+ CREATE TABLE IF NOT EXISTS "ai_subscription_connections" (
2
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
3
+ "company_id" uuid NOT NULL,
4
+ "connection_id" uuid NOT NULL,
5
+ "grant_id" uuid NOT NULL,
6
+ "credential_key" text NOT NULL,
7
+ "subscription_id" uuid NOT NULL
8
+ );
9
+ --> statement-breakpoint
10
+ CREATE TABLE IF NOT EXISTS "ai_subscription_prices" (
11
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
12
+ "company_id" uuid NOT NULL,
13
+ "subscription_id" uuid NOT NULL,
14
+ "revision" integer NOT NULL,
15
+ "plan" text NOT NULL,
16
+ "amount_cents" numeric(24, 7),
17
+ "currency" text DEFAULT 'USD' NOT NULL,
18
+ "cadence" text DEFAULT 'month' NOT NULL,
19
+ "status" text DEFAULT 'active' NOT NULL,
20
+ "source" text NOT NULL,
21
+ "source_url" text,
22
+ "effective_at" timestamp with time zone DEFAULT now() NOT NULL,
23
+ CONSTRAINT "ai_subscription_prices_valid" CHECK (("ai_subscription_prices"."amount_cents" is null or "ai_subscription_prices"."amount_cents" >= 0) and "ai_subscription_prices"."cadence" in ('month','year') and "ai_subscription_prices"."status" in ('active','ended','excluded') and "ai_subscription_prices"."source" in ('catalog','user','unknown'))
24
+ );
25
+ --> statement-breakpoint
26
+ CREATE TABLE IF NOT EXISTS "ai_subscriptions" (
27
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
28
+ "company_id" uuid NOT NULL,
29
+ "provider" text NOT NULL,
30
+ "account_key" text NOT NULL,
31
+ "identity_verified" boolean DEFAULT false NOT NULL,
32
+ "name" text NOT NULL,
33
+ "owner_user_ids" text[] DEFAULT '{}'::text[] NOT NULL,
34
+ "shared" boolean DEFAULT false NOT NULL,
35
+ "detected_plan" text,
36
+ "observed_at" timestamp with time zone,
37
+ "last_checked_at" timestamp with time zone,
38
+ "refresh_status" text,
39
+ "merged_into_id" uuid,
40
+ "revision" integer DEFAULT 0 NOT NULL,
41
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
42
+ CONSTRAINT "ai_subscriptions_no_self_merge" CHECK ("ai_subscriptions"."merged_into_id" is null or "ai_subscriptions"."merged_into_id" <> "ai_subscriptions"."id")
43
+ );
44
+ --> statement-breakpoint
45
+ ALTER TABLE "cost_events" ADD COLUMN IF NOT EXISTS "subscription_id" uuid;--> statement-breakpoint
46
+ DO $$ BEGIN
47
+ IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'ai_subscription_connections_company_id_companies_id_fk' AND conrelid = 'ai_subscription_connections'::regclass) THEN
48
+ ALTER TABLE "ai_subscription_connections" ADD CONSTRAINT "ai_subscription_connections_company_id_companies_id_fk" FOREIGN KEY ("company_id") REFERENCES "public"."companies"("id") ON DELETE cascade ON UPDATE no action;
49
+ END IF;
50
+ END $$;--> statement-breakpoint
51
+ DO $$ BEGIN
52
+ IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'ai_subscription_connections_connection_id_tool_connections_id_fk' AND conrelid = 'ai_subscription_connections'::regclass) THEN
53
+ ALTER TABLE "ai_subscription_connections" ADD CONSTRAINT "ai_subscription_connections_connection_id_tool_connections_id_fk" FOREIGN KEY ("connection_id") REFERENCES "public"."tool_connections"("id") ON DELETE cascade ON UPDATE no action;
54
+ END IF;
55
+ END $$;--> statement-breakpoint
56
+ DO $$ BEGIN
57
+ IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'ai_subscription_connections_grant_id_connection_grants_id_fk' AND conrelid = 'ai_subscription_connections'::regclass) THEN
58
+ ALTER TABLE "ai_subscription_connections" ADD CONSTRAINT "ai_subscription_connections_grant_id_connection_grants_id_fk" FOREIGN KEY ("grant_id") REFERENCES "public"."connection_grants"("id") ON DELETE cascade ON UPDATE no action;
59
+ END IF;
60
+ END $$;--> statement-breakpoint
61
+ DO $$ BEGIN
62
+ IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'ai_subscription_connections_subscription_id_ai_subscriptions_id_fk' AND conrelid = 'ai_subscription_connections'::regclass) THEN
63
+ ALTER TABLE "ai_subscription_connections" ADD CONSTRAINT "ai_subscription_connections_subscription_id_ai_subscriptions_id_fk" FOREIGN KEY ("subscription_id") REFERENCES "public"."ai_subscriptions"("id") ON DELETE cascade ON UPDATE no action;
64
+ END IF;
65
+ END $$;--> statement-breakpoint
66
+ DO $$ BEGIN
67
+ IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'ai_subscription_prices_company_id_companies_id_fk' AND conrelid = 'ai_subscription_prices'::regclass) THEN
68
+ ALTER TABLE "ai_subscription_prices" ADD CONSTRAINT "ai_subscription_prices_company_id_companies_id_fk" FOREIGN KEY ("company_id") REFERENCES "public"."companies"("id") ON DELETE cascade ON UPDATE no action;
69
+ END IF;
70
+ END $$;--> statement-breakpoint
71
+ DO $$ BEGIN
72
+ IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'ai_subscription_prices_subscription_id_ai_subscriptions_id_fk' AND conrelid = 'ai_subscription_prices'::regclass) THEN
73
+ ALTER TABLE "ai_subscription_prices" ADD CONSTRAINT "ai_subscription_prices_subscription_id_ai_subscriptions_id_fk" FOREIGN KEY ("subscription_id") REFERENCES "public"."ai_subscriptions"("id") ON DELETE cascade ON UPDATE no action;
74
+ END IF;
75
+ END $$;--> statement-breakpoint
76
+ DO $$ BEGIN
77
+ IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'ai_subscriptions_company_id_companies_id_fk' AND conrelid = 'ai_subscriptions'::regclass) THEN
78
+ ALTER TABLE "ai_subscriptions" ADD CONSTRAINT "ai_subscriptions_company_id_companies_id_fk" FOREIGN KEY ("company_id") REFERENCES "public"."companies"("id") ON DELETE cascade ON UPDATE no action;
79
+ END IF;
80
+ END $$;--> statement-breakpoint
81
+ DO $$ BEGIN
82
+ IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'ai_subscriptions_merged_into_id_ai_subscriptions_id_fk' AND conrelid = 'ai_subscriptions'::regclass) THEN
83
+ ALTER TABLE "ai_subscriptions" ADD CONSTRAINT "ai_subscriptions_merged_into_id_ai_subscriptions_id_fk" FOREIGN KEY ("merged_into_id") REFERENCES "public"."ai_subscriptions"("id") ON DELETE no action ON UPDATE no action;
84
+ END IF;
85
+ END $$;--> statement-breakpoint
86
+ CREATE UNIQUE INDEX IF NOT EXISTS "ai_subscription_connections_grant_idx" ON "ai_subscription_connections" USING btree ("company_id","grant_id");--> statement-breakpoint
87
+ CREATE INDEX IF NOT EXISTS "ai_subscription_connections_credential_idx" ON "ai_subscription_connections" USING btree ("company_id","credential_key");--> statement-breakpoint
88
+ CREATE INDEX IF NOT EXISTS "ai_subscription_connections_account_idx" ON "ai_subscription_connections" USING btree ("company_id","subscription_id");--> statement-breakpoint
89
+ CREATE UNIQUE INDEX IF NOT EXISTS "ai_subscription_prices_revision_idx" ON "ai_subscription_prices" USING btree ("subscription_id","revision");--> statement-breakpoint
90
+ CREATE INDEX IF NOT EXISTS "ai_subscription_prices_company_idx" ON "ai_subscription_prices" USING btree ("company_id");--> statement-breakpoint
91
+ CREATE UNIQUE INDEX IF NOT EXISTS "ai_subscriptions_identity_idx" ON "ai_subscriptions" USING btree ("company_id","provider","account_key");--> statement-breakpoint
92
+ CREATE INDEX IF NOT EXISTS "ai_subscriptions_company_idx" ON "ai_subscriptions" USING btree ("company_id");--> statement-breakpoint
93
+ DO $$ BEGIN
94
+ IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'cost_events_subscription_id_ai_subscriptions_id_fk' AND conrelid = 'cost_events'::regclass) THEN
95
+ ALTER TABLE "cost_events" ADD CONSTRAINT "cost_events_subscription_id_ai_subscriptions_id_fk" FOREIGN KEY ("subscription_id") REFERENCES "public"."ai_subscriptions"("id") ON DELETE no action ON UPDATE no action;
96
+ END IF;
97
+ END $$;--> statement-breakpoint
98
+ CREATE INDEX IF NOT EXISTS "cost_events_company_subscription_occurred_idx" ON "cost_events" USING btree ("company_id","subscription_id","occurred_at");
@@ -0,0 +1,4 @@
1
+ ALTER TABLE "chat_github_registrations" ADD COLUMN IF NOT EXISTS "owner_type" text DEFAULT 'personal' NOT NULL;--> statement-breakpoint
2
+ ALTER TABLE "chat_github_registrations" ADD COLUMN IF NOT EXISTS "owner_login" text;--> statement-breakpoint
3
+ ALTER TABLE "chat_github_registrations" ADD COLUMN IF NOT EXISTS "app_name" text;--> statement-breakpoint
4
+ ALTER TABLE "chat_github_registrations" ADD COLUMN IF NOT EXISTS "handoff" jsonb;
@@ -0,0 +1,153 @@
1
+ CREATE TABLE IF NOT EXISTS "chat_voice_replies" (
2
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
3
+ "company_id" uuid NOT NULL,
4
+ "session_id" uuid NOT NULL,
5
+ "publication_id" uuid NOT NULL,
6
+ "cursor" integer NOT NULL,
7
+ "delivered_at" timestamp with time zone,
8
+ "spoken_at" timestamp with time zone,
9
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
10
+ CONSTRAINT "chat_voice_replies_cursor_check" CHECK ("chat_voice_replies"."cursor" > 0),
11
+ CONSTRAINT "chat_voice_replies_spoken_check" CHECK ("chat_voice_replies"."spoken_at" is null or "chat_voice_replies"."delivered_at" is not null)
12
+ );
13
+ --> statement-breakpoint
14
+ CREATE TABLE IF NOT EXISTS "chat_voice_sessions" (
15
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
16
+ "company_id" uuid NOT NULL,
17
+ "endpoint_id" uuid NOT NULL,
18
+ "conversation_id" uuid NOT NULL,
19
+ "issue_id" uuid NOT NULL,
20
+ "assigned_agent_id" uuid NOT NULL,
21
+ "caller_id" text NOT NULL,
22
+ "caller_authority" text NOT NULL,
23
+ "approved_by_user_id" text,
24
+ "mode" text NOT NULL,
25
+ "state" text DEFAULT 'reserved' NOT NULL,
26
+ "generation" integer NOT NULL,
27
+ "credential_fingerprint" text NOT NULL,
28
+ "provider_session_id" text,
29
+ "tool_token_hash" text NOT NULL,
30
+ "idempotency_key" text NOT NULL,
31
+ "request_fingerprint" text NOT NULL,
32
+ "reply_cursor" integer DEFAULT 0 NOT NULL,
33
+ "error_code" text,
34
+ "expires_at" timestamp with time zone NOT NULL,
35
+ "ended_at" timestamp with time zone,
36
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
37
+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL,
38
+ CONSTRAINT "chat_voice_sessions_company_id_uq" UNIQUE("company_id","id"),
39
+ CONSTRAINT "chat_voice_sessions_state_check" CHECK ("chat_voice_sessions"."state" in ('reserved', 'creating', 'creation_unknown', 'connecting', 'active', 'awaiting_approval', 'ending', 'ended', 'failed', 'expired')),
40
+ CONSTRAINT "chat_voice_sessions_mode_check" CHECK ("chat_voice_sessions"."mode" in ('browser', 'inbound_phone', 'outbound_phone')),
41
+ CONSTRAINT "chat_voice_sessions_authority_check" CHECK ("chat_voice_sessions"."caller_authority" in ('member', 'instance_admin', 'local_board', 'guest_intake', 'pending_approval')),
42
+ CONSTRAINT "chat_voice_sessions_counters_check" CHECK ("chat_voice_sessions"."generation" >= 1 and "chat_voice_sessions"."reply_cursor" >= 0),
43
+ CONSTRAINT "chat_voice_sessions_token_check" CHECK ("chat_voice_sessions"."tool_token_hash" ~ '^[a-f0-9]{64}$'),
44
+ CONSTRAINT "chat_voice_sessions_expiry_check" CHECK ("chat_voice_sessions"."expires_at" > "chat_voice_sessions"."created_at")
45
+ );
46
+ --> statement-breakpoint
47
+ CREATE TABLE IF NOT EXISTS "chat_voice_tool_calls" (
48
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
49
+ "company_id" uuid NOT NULL,
50
+ "session_id" uuid NOT NULL,
51
+ "provider_tool_call_id" text NOT NULL,
52
+ "webhook_id" text NOT NULL,
53
+ "fingerprint" text NOT NULL,
54
+ "tool" text NOT NULL,
55
+ "delivery_id" uuid,
56
+ "response" jsonb NOT NULL,
57
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
58
+ CONSTRAINT "chat_voice_tool_calls_tool_check" CHECK ("chat_voice_tool_calls"."tool" in ('submit_request', 'get_updates'))
59
+ );
60
+ --> statement-breakpoint
61
+ ALTER TABLE "chat_endpoints" DROP CONSTRAINT IF EXISTS "chat_endpoints_provider_check";--> statement-breakpoint
62
+ ALTER TABLE "chat_external_principals" DROP CONSTRAINT IF EXISTS "chat_external_principals_provider_check";--> statement-breakpoint
63
+ ALTER TABLE "tool_connections" DROP CONSTRAINT IF EXISTS "tool_connections_transport_check";--> statement-breakpoint
64
+ ALTER TABLE "tool_connections" DROP CONSTRAINT IF EXISTS "tool_connections_channel_transport_check";--> statement-breakpoint
65
+ DO $$ BEGIN
66
+ IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'chat_voice_replies_company_id_companies_id_fk' AND conrelid = 'chat_voice_replies'::regclass) THEN
67
+ ALTER TABLE "chat_voice_replies" ADD CONSTRAINT "chat_voice_replies_company_id_companies_id_fk" FOREIGN KEY ("company_id") REFERENCES "public"."companies"("id") ON DELETE cascade ON UPDATE no action;
68
+ END IF;
69
+ END $$;--> statement-breakpoint
70
+ DO $$ BEGIN
71
+ IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'chat_voice_replies_session_fk' AND conrelid = 'chat_voice_replies'::regclass) THEN
72
+ ALTER TABLE "chat_voice_replies" ADD CONSTRAINT "chat_voice_replies_session_fk" FOREIGN KEY ("company_id","session_id") REFERENCES "public"."chat_voice_sessions"("company_id","id") ON DELETE no action ON UPDATE no action;
73
+ END IF;
74
+ END $$;--> statement-breakpoint
75
+ DO $$ BEGIN
76
+ IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'chat_voice_replies_publication_fk' AND conrelid = 'chat_voice_replies'::regclass) THEN
77
+ ALTER TABLE "chat_voice_replies" ADD CONSTRAINT "chat_voice_replies_publication_fk" FOREIGN KEY ("company_id","publication_id") REFERENCES "public"."chat_publications"("company_id","id") ON DELETE no action ON UPDATE no action;
78
+ END IF;
79
+ END $$;--> statement-breakpoint
80
+ DO $$ BEGIN
81
+ IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'chat_voice_sessions_company_id_companies_id_fk' AND conrelid = 'chat_voice_sessions'::regclass) THEN
82
+ ALTER TABLE "chat_voice_sessions" ADD CONSTRAINT "chat_voice_sessions_company_id_companies_id_fk" FOREIGN KEY ("company_id") REFERENCES "public"."companies"("id") ON DELETE cascade ON UPDATE no action;
83
+ END IF;
84
+ END $$;--> statement-breakpoint
85
+ DO $$ BEGIN
86
+ IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'chat_voice_sessions_endpoint_fk' AND conrelid = 'chat_voice_sessions'::regclass) THEN
87
+ ALTER TABLE "chat_voice_sessions" ADD CONSTRAINT "chat_voice_sessions_endpoint_fk" FOREIGN KEY ("company_id","endpoint_id") REFERENCES "public"."chat_endpoints"("company_id","id") ON DELETE no action ON UPDATE no action;
88
+ END IF;
89
+ END $$;--> statement-breakpoint
90
+ DO $$ BEGIN
91
+ IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'chat_voice_sessions_conversation_fk' AND conrelid = 'chat_voice_sessions'::regclass) THEN
92
+ ALTER TABLE "chat_voice_sessions" ADD CONSTRAINT "chat_voice_sessions_conversation_fk" FOREIGN KEY ("company_id","conversation_id") REFERENCES "public"."chat_conversations"("company_id","id") ON DELETE no action ON UPDATE no action;
93
+ END IF;
94
+ END $$;--> statement-breakpoint
95
+ DO $$ BEGIN
96
+ IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'chat_voice_sessions_issue_fk' AND conrelid = 'chat_voice_sessions'::regclass) THEN
97
+ ALTER TABLE "chat_voice_sessions" ADD CONSTRAINT "chat_voice_sessions_issue_fk" FOREIGN KEY ("company_id","issue_id") REFERENCES "public"."issues"("company_id","id") ON DELETE no action ON UPDATE no action;
98
+ END IF;
99
+ END $$;--> statement-breakpoint
100
+ DO $$ BEGIN
101
+ IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'chat_voice_sessions_agent_fk' AND conrelid = 'chat_voice_sessions'::regclass) THEN
102
+ ALTER TABLE "chat_voice_sessions" ADD CONSTRAINT "chat_voice_sessions_agent_fk" FOREIGN KEY ("company_id","assigned_agent_id") REFERENCES "public"."agents"("company_id","id") ON DELETE no action ON UPDATE no action;
103
+ END IF;
104
+ END $$;--> statement-breakpoint
105
+ DO $$ BEGIN
106
+ IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'chat_voice_tool_calls_company_id_companies_id_fk' AND conrelid = 'chat_voice_tool_calls'::regclass) THEN
107
+ ALTER TABLE "chat_voice_tool_calls" ADD CONSTRAINT "chat_voice_tool_calls_company_id_companies_id_fk" FOREIGN KEY ("company_id") REFERENCES "public"."companies"("id") ON DELETE cascade ON UPDATE no action;
108
+ END IF;
109
+ END $$;--> statement-breakpoint
110
+ DO $$ BEGIN
111
+ IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'chat_voice_tool_calls_session_fk' AND conrelid = 'chat_voice_tool_calls'::regclass) THEN
112
+ ALTER TABLE "chat_voice_tool_calls" ADD CONSTRAINT "chat_voice_tool_calls_session_fk" FOREIGN KEY ("company_id","session_id") REFERENCES "public"."chat_voice_sessions"("company_id","id") ON DELETE no action ON UPDATE no action;
113
+ END IF;
114
+ END $$;--> statement-breakpoint
115
+ DO $$ BEGIN
116
+ IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'chat_voice_tool_calls_delivery_fk' AND conrelid = 'chat_voice_tool_calls'::regclass) THEN
117
+ ALTER TABLE "chat_voice_tool_calls" ADD CONSTRAINT "chat_voice_tool_calls_delivery_fk" FOREIGN KEY ("company_id","delivery_id") REFERENCES "public"."chat_deliveries"("company_id","id") ON DELETE no action ON UPDATE no action;
118
+ END IF;
119
+ END $$;--> statement-breakpoint
120
+ CREATE UNIQUE INDEX IF NOT EXISTS "chat_voice_replies_publication_uq" ON "chat_voice_replies" USING btree ("session_id","publication_id");--> statement-breakpoint
121
+ CREATE UNIQUE INDEX IF NOT EXISTS "chat_voice_replies_cursor_uq" ON "chat_voice_replies" USING btree ("session_id","cursor");--> statement-breakpoint
122
+ CREATE UNIQUE INDEX IF NOT EXISTS "chat_voice_sessions_provider_uq" ON "chat_voice_sessions" USING btree ("provider_session_id");--> statement-breakpoint
123
+ CREATE UNIQUE INDEX IF NOT EXISTS "chat_voice_sessions_request_uq" ON "chat_voice_sessions" USING btree ("company_id","caller_id","idempotency_key");--> statement-breakpoint
124
+ CREATE UNIQUE INDEX IF NOT EXISTS "chat_voice_sessions_live_caller_task_uq" ON "chat_voice_sessions" USING btree ("company_id","caller_id","issue_id") WHERE "chat_voice_sessions"."state" not in ('ended', 'failed', 'expired');--> statement-breakpoint
125
+ CREATE INDEX IF NOT EXISTS "chat_voice_sessions_expiry_idx" ON "chat_voice_sessions" USING btree ("state","expires_at");--> statement-breakpoint
126
+ CREATE UNIQUE INDEX IF NOT EXISTS "chat_voice_tool_calls_tool_uq" ON "chat_voice_tool_calls" USING btree ("session_id","provider_tool_call_id");--> statement-breakpoint
127
+ CREATE UNIQUE INDEX IF NOT EXISTS "chat_voice_tool_calls_webhook_uq" ON "chat_voice_tool_calls" USING btree ("company_id","webhook_id");--> statement-breakpoint
128
+ DO $$ BEGIN
129
+ IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'chat_endpoints_provider_check' AND conrelid = 'chat_endpoints'::regclass) THEN
130
+ ALTER TABLE "chat_endpoints" ADD CONSTRAINT "chat_endpoints_provider_check" CHECK ("chat_endpoints"."provider" in ('slack', 'github', 'discord', 'microsoft-teams', 'telegram', 'speko', 'agentmail', 'imessage-photon', 'openwa'));
131
+ END IF;
132
+ END $$;--> statement-breakpoint
133
+ DO $$ BEGIN
134
+ IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'chat_external_principals_provider_check' AND conrelid = 'chat_external_principals'::regclass) THEN
135
+ ALTER TABLE "chat_external_principals" ADD CONSTRAINT "chat_external_principals_provider_check" CHECK ("chat_external_principals"."provider" in ('slack', 'github', 'discord', 'microsoft-teams', 'telegram', 'speko', 'agentmail', 'imessage-photon', 'openwa'));
136
+ END IF;
137
+ END $$;--> statement-breakpoint
138
+ DO $$ BEGIN
139
+ IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'tool_connections_transport_check' AND conrelid = 'tool_connections'::regclass) THEN
140
+ ALTER TABLE "tool_connections" ADD CONSTRAINT "tool_connections_transport_check" CHECK ("tool_connections"."transport" in ('mcp_remote', 'rest_api', 'local_stdio', 'chat_sdk', 'voice', 'runtime_auth'));
141
+ END IF;
142
+ END $$;--> statement-breakpoint
143
+ DO $$ BEGIN
144
+ IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'tool_connections_channel_transport_check' AND conrelid = 'tool_connections'::regclass) THEN
145
+ ALTER TABLE "tool_connections" ADD CONSTRAINT "tool_connections_channel_transport_check" CHECK ((
146
+ ("tool_connections"."connection_purpose" = 'tool' and "tool_connections"."transport" not in ('chat_sdk', 'voice', 'runtime_auth'))
147
+ or
148
+ ("tool_connections"."connection_purpose" = 'channel' and ("tool_connections"."transport" in ('chat_sdk', 'voice') or ("tool_connections"."transport" = 'rest_api' and "tool_connections"."config"->>'provider' = 'agentmail')))
149
+ or
150
+ ("tool_connections"."connection_purpose" = 'ai' and "tool_connections"."transport" = 'runtime_auth')
151
+ ));
152
+ END IF;
153
+ END $$;
@@ -0,0 +1,6 @@
1
+ ALTER TABLE "chat_voice_tool_calls" DROP CONSTRAINT IF EXISTS "chat_voice_tool_calls_tool_check";--> statement-breakpoint
2
+ DO $$ BEGIN
3
+ IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'chat_voice_tool_calls_tool_check' AND conrelid = 'chat_voice_tool_calls'::regclass) THEN
4
+ ALTER TABLE "chat_voice_tool_calls" ADD CONSTRAINT "chat_voice_tool_calls_tool_check" CHECK ("chat_voice_tool_calls"."tool" in ('submit_request', 'get_updates', 'answer_question'));
5
+ END IF;
6
+ END $$;
@@ -0,0 +1,17 @@
1
+ CREATE TABLE IF NOT EXISTS "chat_voice_callbacks" (
2
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
3
+ "company_id" uuid NOT NULL,
4
+ "endpoint_id" uuid NOT NULL,
5
+ "user_id" text NOT NULL,
6
+ "phone_number" text NOT NULL,
7
+ "enabled" boolean DEFAULT false NOT NULL,
8
+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL,
9
+ CONSTRAINT "chat_voice_callbacks_phone_check" CHECK ("chat_voice_callbacks"."phone_number" ~ '^\+[1-9][0-9]{6,14}$')
10
+ );
11
+ --> statement-breakpoint
12
+ DO $$ BEGIN
13
+ IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'chat_voice_callbacks_endpoint_fk' AND conrelid = 'chat_voice_callbacks'::regclass) THEN
14
+ ALTER TABLE "chat_voice_callbacks" ADD CONSTRAINT "chat_voice_callbacks_endpoint_fk" FOREIGN KEY ("company_id","endpoint_id") REFERENCES "public"."chat_endpoints"("company_id","id") ON DELETE cascade ON UPDATE no action;
15
+ END IF;
16
+ END $$;--> statement-breakpoint
17
+ CREATE UNIQUE INDEX IF NOT EXISTS "chat_voice_callbacks_owner_uq" ON "chat_voice_callbacks" USING btree ("company_id","endpoint_id","user_id");
@@ -0,0 +1,23 @@
1
+ CREATE TABLE IF NOT EXISTS "chat_voice_reports" (
2
+ "session_id" uuid PRIMARY KEY NOT NULL,
3
+ "company_id" uuid NOT NULL,
4
+ "status" text DEFAULT 'pending' NOT NULL,
5
+ "transcript" jsonb DEFAULT '[]'::jsonb NOT NULL,
6
+ "cost_micro_usd" text,
7
+ "duration_seconds" integer,
8
+ "provider_updated_at" timestamp with time zone,
9
+ "next_check_at" timestamp with time zone DEFAULT now() NOT NULL,
10
+ "attempts" integer DEFAULT 0 NOT NULL,
11
+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL,
12
+ CONSTRAINT "chat_voice_reports_status_check" CHECK ("chat_voice_reports"."status" in ('pending', 'available', 'unavailable')),
13
+ CONSTRAINT "chat_voice_reports_cost_check" CHECK ("chat_voice_reports"."cost_micro_usd" is null or "chat_voice_reports"."cost_micro_usd" ~ '^[0-9]{1,30}$'),
14
+ CONSTRAINT "chat_voice_reports_duration_check" CHECK ("chat_voice_reports"."duration_seconds" is null or "chat_voice_reports"."duration_seconds" >= 0),
15
+ CONSTRAINT "chat_voice_reports_attempts_check" CHECK ("chat_voice_reports"."attempts" >= 0)
16
+ );
17
+ --> statement-breakpoint
18
+ DO $$ BEGIN
19
+ IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'chat_voice_reports_session_fk' AND conrelid = 'chat_voice_reports'::regclass) THEN
20
+ ALTER TABLE "chat_voice_reports" ADD CONSTRAINT "chat_voice_reports_session_fk" FOREIGN KEY ("company_id","session_id") REFERENCES "public"."chat_voice_sessions"("company_id","id") ON DELETE cascade ON UPDATE no action;
21
+ END IF;
22
+ END $$;--> statement-breakpoint
23
+ CREATE INDEX IF NOT EXISTS "chat_voice_reports_pending_idx" ON "chat_voice_reports" USING btree ("status","next_check_at");
@@ -0,0 +1,52 @@
1
+ CREATE TABLE IF NOT EXISTS "chat_voice_inbound_calls" (
2
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
3
+ "company_id" uuid NOT NULL,
4
+ "endpoint_id" uuid NOT NULL,
5
+ "provider_session_id" text NOT NULL,
6
+ "state" text DEFAULT 'awaiting_approval' NOT NULL,
7
+ "approval_code" text NOT NULL,
8
+ "generation" integer NOT NULL,
9
+ "credential_fingerprint" text NOT NULL,
10
+ "tool_token_hash" text NOT NULL,
11
+ "request_fingerprint" text NOT NULL,
12
+ "approved_by_user_id" text,
13
+ "caller_authority" text,
14
+ "requested_issue_id" uuid,
15
+ "session_id" uuid,
16
+ "expires_at" timestamp with time zone NOT NULL,
17
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
18
+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL,
19
+ CONSTRAINT "chat_voice_inbound_provider_uq" UNIQUE("provider_session_id"),
20
+ CONSTRAINT "chat_voice_inbound_state_check" CHECK ("chat_voice_inbound_calls"."state" in ('awaiting_approval', 'approving', 'approved', 'denied', 'expired', 'ended')),
21
+ CONSTRAINT "chat_voice_inbound_token_check" CHECK ("chat_voice_inbound_calls"."tool_token_hash" ~ '^[a-f0-9]{64}$'),
22
+ CONSTRAINT "chat_voice_inbound_code_check" CHECK ("chat_voice_inbound_calls"."approval_code" ~ '^[0-9]{6}$'),
23
+ CONSTRAINT "chat_voice_inbound_generation_check" CHECK ("chat_voice_inbound_calls"."generation" > 0)
24
+ );
25
+ --> statement-breakpoint
26
+ CREATE TABLE IF NOT EXISTS "chat_voice_phone_lines" (
27
+ "endpoint_id" uuid PRIMARY KEY NOT NULL,
28
+ "company_id" uuid NOT NULL,
29
+ "provider_number_id" text NOT NULL,
30
+ "phone_number" text NOT NULL,
31
+ "enabled" boolean DEFAULT false NOT NULL,
32
+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL,
33
+ CONSTRAINT "chat_voice_phone_lines_number_uq" UNIQUE("provider_number_id"),
34
+ CONSTRAINT "chat_voice_phone_lines_number_check" CHECK ("chat_voice_phone_lines"."phone_number" ~ '^\+[1-9][0-9]{6,14}$')
35
+ );
36
+ --> statement-breakpoint
37
+ DO $$ BEGIN
38
+ IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'chat_voice_inbound_endpoint_fk' AND conrelid = 'chat_voice_inbound_calls'::regclass) THEN
39
+ ALTER TABLE "chat_voice_inbound_calls" ADD CONSTRAINT "chat_voice_inbound_endpoint_fk" FOREIGN KEY ("company_id","endpoint_id") REFERENCES "public"."chat_endpoints"("company_id","id") ON DELETE cascade ON UPDATE no action;
40
+ END IF;
41
+ END $$;--> statement-breakpoint
42
+ DO $$ BEGIN
43
+ IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'chat_voice_inbound_session_fk' AND conrelid = 'chat_voice_inbound_calls'::regclass) THEN
44
+ ALTER TABLE "chat_voice_inbound_calls" ADD CONSTRAINT "chat_voice_inbound_session_fk" FOREIGN KEY ("company_id","session_id") REFERENCES "public"."chat_voice_sessions"("company_id","id") ON DELETE no action ON UPDATE no action;
45
+ END IF;
46
+ END $$;--> statement-breakpoint
47
+ DO $$ BEGIN
48
+ IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'chat_voice_phone_lines_endpoint_fk' AND conrelid = 'chat_voice_phone_lines'::regclass) THEN
49
+ ALTER TABLE "chat_voice_phone_lines" ADD CONSTRAINT "chat_voice_phone_lines_endpoint_fk" FOREIGN KEY ("company_id","endpoint_id") REFERENCES "public"."chat_endpoints"("company_id","id") ON DELETE cascade ON UPDATE no action;
50
+ END IF;
51
+ END $$;--> statement-breakpoint
52
+ CREATE INDEX IF NOT EXISTS "chat_voice_inbound_expiry_idx" ON "chat_voice_inbound_calls" USING btree ("state","expires_at");
@@ -0,0 +1,18 @@
1
+ ALTER TABLE "chat_voice_inbound_calls" DROP CONSTRAINT IF EXISTS "chat_voice_inbound_state_check";--> statement-breakpoint
2
+ ALTER TABLE "chat_voice_inbound_calls" ADD COLUMN IF NOT EXISTS "intake_issue_id" uuid;--> statement-breakpoint
3
+ ALTER TABLE "chat_voice_phone_lines" ADD COLUMN IF NOT EXISTS "guest_intake" boolean DEFAULT false NOT NULL;--> statement-breakpoint
4
+ DO $$ BEGIN
5
+ IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'chat_voice_inbound_intake_fk' AND conrelid = 'chat_voice_inbound_calls'::regclass) THEN
6
+ ALTER TABLE "chat_voice_inbound_calls" ADD CONSTRAINT "chat_voice_inbound_intake_fk" FOREIGN KEY ("company_id","intake_issue_id") REFERENCES "public"."issues"("company_id","id") ON DELETE no action ON UPDATE no action;
7
+ END IF;
8
+ END $$;--> statement-breakpoint
9
+ DO $$ BEGIN
10
+ IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'chat_voice_inbound_requested_issue_fk' AND conrelid = 'chat_voice_inbound_calls'::regclass) THEN
11
+ ALTER TABLE "chat_voice_inbound_calls" ADD CONSTRAINT "chat_voice_inbound_requested_issue_fk" FOREIGN KEY ("company_id","requested_issue_id") REFERENCES "public"."issues"("company_id","id") ON DELETE no action ON UPDATE no action;
12
+ END IF;
13
+ END $$;--> statement-breakpoint
14
+ DO $$ BEGIN
15
+ IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'chat_voice_inbound_state_check' AND conrelid = 'chat_voice_inbound_calls'::regclass) THEN
16
+ ALTER TABLE "chat_voice_inbound_calls" ADD CONSTRAINT "chat_voice_inbound_state_check" CHECK ("chat_voice_inbound_calls"."state" in ('guest_intake', 'awaiting_approval', 'approving', 'approved', 'denied', 'expired', 'ended'));
17
+ END IF;
18
+ END $$;
@@ -0,0 +1,7 @@
1
+ ALTER TABLE "chat_voice_phone_lines" ADD COLUMN IF NOT EXISTS "low_trust_environment_id" uuid;
2
+ --> statement-breakpoint
3
+ DO $$ BEGIN
4
+ IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'chat_voice_phone_lines_low_trust_environment_id_environments_id_fk' AND conrelid = 'chat_voice_phone_lines'::regclass) THEN
5
+ ALTER TABLE "chat_voice_phone_lines" ADD CONSTRAINT "chat_voice_phone_lines_low_trust_environment_id_environments_id_fk" FOREIGN KEY ("low_trust_environment_id") REFERENCES "public"."environments"("id") ON DELETE no action ON UPDATE no action;
6
+ END IF;
7
+ END $$;
@@ -0,0 +1,74 @@
1
+ CREATE TABLE IF NOT EXISTS "company_fast_responses" (
2
+ "company_id" uuid PRIMARY KEY NOT NULL,
3
+ "connection_id" uuid,
4
+ "grant_id" uuid,
5
+ "model" text,
6
+ "provider" text,
7
+ "enabled" boolean DEFAULT false NOT NULL,
8
+ "allow_sponsored" boolean DEFAULT true NOT NULL,
9
+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL,
10
+ CONSTRAINT "company_fast_responses_configured" CHECK (("company_fast_responses"."connection_id" is null) = ("company_fast_responses"."grant_id" is null) and (not "company_fast_responses"."enabled" or ("company_fast_responses"."connection_id" is not null and "company_fast_responses"."model" is not null)))
11
+ );
12
+ --> statement-breakpoint
13
+ CREATE TABLE IF NOT EXISTS "fast_response_requests" (
14
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
15
+ "company_id" uuid NOT NULL,
16
+ "source_key" text NOT NULL,
17
+ "source_comment_id" uuid,
18
+ "issue_id" uuid,
19
+ "project_id" uuid,
20
+ "agent_id" uuid,
21
+ "responsible_user_id" text,
22
+ "sponsored" boolean DEFAULT false NOT NULL,
23
+ "endpoint_id" uuid,
24
+ "conversation_id" uuid,
25
+ "delivery_id" uuid,
26
+ "session_generation" integer,
27
+ "status" text DEFAULT 'pending' NOT NULL,
28
+ "publication_status" text DEFAULT 'pending' NOT NULL,
29
+ "connection_id" uuid,
30
+ "grant_id" uuid,
31
+ "provider" text,
32
+ "model" text,
33
+ "provider_request_id" text,
34
+ "cost_event_id" uuid,
35
+ "error_code" text,
36
+ "comment_id" uuid,
37
+ "accepted_at" timestamp with time zone DEFAULT now() NOT NULL,
38
+ "expires_at" timestamp with time zone NOT NULL,
39
+ "started_at" timestamp with time zone,
40
+ "finished_at" timestamp with time zone,
41
+ "duration_ms" integer,
42
+ "input_tokens" integer,
43
+ "output_tokens" integer,
44
+ CONSTRAINT "fast_response_requests_status_check" CHECK ("fast_response_requests"."status" in ('pending', 'running', 'succeeded', 'failed', 'unknown', 'skipped'))
45
+ );
46
+ --> statement-breakpoint
47
+ ALTER TABLE "budget_reservations" DROP CONSTRAINT IF EXISTS "budget_reservations_source_check";--> statement-breakpoint
48
+ ALTER TABLE "cost_events" DROP CONSTRAINT IF EXISTS "cost_events_usage_kind_check";--> statement-breakpoint
49
+ ALTER TABLE "budget_reservations" ADD COLUMN IF NOT EXISTS "fast_response_request_id" uuid;--> statement-breakpoint
50
+ ALTER TABLE "issue_comments" ADD COLUMN IF NOT EXISTS "origin" text DEFAULT 'comment' NOT NULL;--> statement-breakpoint
51
+ ALTER TABLE "issue_comments" ADD COLUMN IF NOT EXISTS "fast_response_request_id" uuid;--> statement-breakpoint
52
+ DO $$ BEGIN
53
+ ALTER TABLE "company_fast_responses" ADD CONSTRAINT "company_fast_responses_company_id_companies_id_fk" FOREIGN KEY ("company_id") REFERENCES "public"."companies"("id") ON DELETE cascade ON UPDATE no action;
54
+ EXCEPTION WHEN duplicate_object THEN NULL; END $$;
55
+ --> statement-breakpoint
56
+ DO $$ BEGIN
57
+ ALTER TABLE "fast_response_requests" ADD CONSTRAINT "fast_response_requests_company_id_companies_id_fk" FOREIGN KEY ("company_id") REFERENCES "public"."companies"("id") ON DELETE cascade ON UPDATE no action;
58
+ EXCEPTION WHEN duplicate_object THEN NULL; END $$;
59
+ --> statement-breakpoint
60
+ DO $$ BEGIN
61
+ ALTER TABLE "fast_response_requests" ADD CONSTRAINT "fast_response_requests_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
+ EXCEPTION WHEN duplicate_object THEN NULL; END $$;
63
+ --> statement-breakpoint
64
+ CREATE UNIQUE INDEX IF NOT EXISTS "fast_response_requests_source_idx" ON "fast_response_requests" USING btree ("company_id","source_key");--> statement-breakpoint
65
+ CREATE INDEX IF NOT EXISTS "fast_response_requests_history_idx" ON "fast_response_requests" USING btree ("company_id","accepted_at");--> statement-breakpoint
66
+ CREATE INDEX IF NOT EXISTS "fast_response_requests_work_idx" ON "fast_response_requests" USING btree ("expires_at") WHERE "fast_response_requests"."status" in ('pending', 'running');--> statement-breakpoint
67
+ CREATE UNIQUE INDEX IF NOT EXISTS "budget_reservations_fast_response_idx" ON "budget_reservations" USING btree ("company_id","fast_response_request_id");--> statement-breakpoint
68
+ DO $$ BEGIN
69
+ 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 + ("budget_reservations"."fast_response_request_id" is not null)::int = 1);
70
+ EXCEPTION WHEN duplicate_object THEN NULL; END $$;
71
+ --> statement-breakpoint
72
+ DO $$ BEGIN
73
+ ALTER TABLE "cost_events" ADD CONSTRAINT "cost_events_usage_kind_check" CHECK ("cost_events"."usage_kind" in ('decision', 'fast_response') or ("cost_events"."usage_kind" = 'agent' and "cost_events"."agent_id" is not null));
74
+ EXCEPTION WHEN duplicate_object THEN NULL; END $$;
@@ -0,0 +1 @@
1
+ CREATE INDEX CONCURRENTLY IF NOT EXISTS "agent_wakeup_requests_question_response_history_idx" ON "agent_wakeup_requests" USING btree ("company_id","idempotency_key") WHERE "agent_wakeup_requests"."idempotency_key" LIKE 'question-response:%';