thinkwork-cli 0.13.1 → 1.0.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 (262) hide show
  1. package/README.md +3 -14
  2. package/dist/{api-client-4DZ266J5.js → api-client-4P4JZOBX.js} +3 -1
  3. package/dist/bowser-6Z6JFAIR.js +2822 -0
  4. package/dist/{chunk-Y2WHJECR.js → chunk-4OMDWYZQ.js} +5 -44
  5. package/dist/chunk-AD2NIWB5.js +6516 -0
  6. package/dist/chunk-DV3MRBR5.js +43 -0
  7. package/dist/chunk-EI5ZX7CN.js +522 -0
  8. package/dist/chunk-EUJ7X6YD.js +126 -0
  9. package/dist/chunk-GG5WKBOX.js +436 -0
  10. package/dist/chunk-I64EZSU5.js +358 -0
  11. package/dist/chunk-KMIJ5KGT.js +128 -0
  12. package/dist/chunk-MWQ7RO76.js +137 -0
  13. package/dist/chunk-OCPHU34C.js +996 -0
  14. package/dist/chunk-OLUQ4U2Z.js +1728 -0
  15. package/dist/chunk-XYM7PE2A.js +2264 -0
  16. package/dist/chunk-YQCYD6NE.js +3299 -0
  17. package/dist/cli.js +49156 -31257
  18. package/dist/commands/enterprise/templates/deploy-repo/scripts/apply-release.mjs +0 -1
  19. package/dist/commands/enterprise/templates/deploy-repo/scripts/smoke.mjs +0 -1
  20. package/dist/commands/enterprise/templates/deploy-repo/terraform/main.tf +0 -14
  21. package/dist/dist-es-2OTNTL4N.js +315 -0
  22. package/dist/dist-es-2XVAH4BQ.js +14726 -0
  23. package/dist/dist-es-3DPDUJAH.js +2000 -0
  24. package/dist/dist-es-BNZTBBVC.js +176 -0
  25. package/dist/dist-es-CD2RBDAC.js +88 -0
  26. package/dist/dist-es-I4FW57PS.js +88 -0
  27. package/dist/dist-es-KL7Y5NB2.js +377 -0
  28. package/dist/dist-es-KVFWJNDY.js +318 -0
  29. package/dist/dist-es-PS73DWNL.js +70 -0
  30. package/dist/dist-es-S3NZQFGT.js +170 -0
  31. package/dist/dist-es-SGCA4P32.js +48 -0
  32. package/dist/dist-es-WBM6J4RA.js +70 -0
  33. package/dist/dist-es-ZGVADYIF.js +485 -0
  34. package/dist/dist-es-ZKC2QKD2.js +377 -0
  35. package/dist/drizzle/0076_scheduled_jobs_marco_backfill.sql +2 -1
  36. package/dist/drizzle/0079_seed_tenant_customize_catalog.sql +1 -0
  37. package/dist/drizzle/0090_brain_schema_extraction.sql +10 -0
  38. package/dist/drizzle/0132_drop_computer_tables.sql +3 -0
  39. package/dist/drizzle/0160_compliance_event_types_plugins.sql +2 -0
  40. package/dist/drizzle/0214_think137_drop_judge_evidence_roi.sql +1 -0
  41. package/dist/drizzle/0216_drop_agent_loop_versions_goal_worker_policy.sql +1 -0
  42. package/dist/drizzle/0227_analyst_reader_role.sql +17 -20
  43. package/dist/drizzle/0230_analyst_rls.sql +28 -36
  44. package/dist/drizzle/0250_kg_schema_extraction.sql +27 -0
  45. package/dist/drizzle/0251_brain_stragglers.sql +21 -0
  46. package/dist/drizzle/0253_drop_brain_substrate.sql +2 -0
  47. package/dist/drizzle/0257_agents_runtime_allow_harness.sql +24 -0
  48. package/dist/drizzle/0261_native_auth_control_plane.sql +332 -0
  49. package/dist/drizzle/0262_auth_subscription_tickets.sql +59 -0
  50. package/dist/drizzle/0263_agentcore_runtime_identifier.sql +69 -0
  51. package/dist/drizzle/0263_drop_workos_auth_runtime.sql +236 -0
  52. package/dist/drizzle/0264_auth_enrollment_attempt_limits.sql +15 -0
  53. package/dist/drizzle/0265_eval_runs_requester_identity.sql +28 -0
  54. package/dist/drizzle/0265_require_fully_valid_auth_publication.sql +27 -0
  55. package/dist/drizzle/0266_auth_identity_recovery_grants.sql +9 -0
  56. package/dist/drizzle/0266_eval_profiles_runtime_type.sql +12 -0
  57. package/dist/drizzle/0267_ontology_candidate_rejections.sql +53 -0
  58. package/dist/drizzle/0268_identity_crosswalk_routing.sql +182 -0
  59. package/dist/drizzle/0269_ontology_system_map.sql +31 -0
  60. package/dist/drizzle/0270_tool_execution_ledger.sql +115 -0
  61. package/dist/drizzle/0271_ontology_twin_declarations.sql +47 -0
  62. package/dist/drizzle/0272_identity_graph_projection_cursor.sql +23 -0
  63. package/dist/drizzle/0273_twin_materialization_suggestions.sql +29 -0
  64. package/dist/drizzle/0274_tenant_mcp_twin_keys.sql +59 -0
  65. package/dist/drizzle/0275_identity_bulk_rebuild_fence.sql +30 -0
  66. package/dist/drizzle/0276_tool_execution_ledger_allow_cascade_delete.sql +18 -0
  67. package/dist/drizzle/0277_knowledge_base_sources.sql +107 -0
  68. package/dist/drizzle/0278_kb_page_transcription.sql +55 -0
  69. package/dist/drizzle/0279_mcp_servers_off_plugin_provenance.sql +93 -0
  70. package/dist/drizzle/0280_work_item_external_refs_drop_plane_provider.sql +46 -0
  71. package/dist/drizzle/0281_tenant_mcp_twin_keys_expiry_suffix.sql +9 -0
  72. package/dist/drizzle/0282_tenant_mcp_twin_keys_grants.sql +24 -0
  73. package/dist/drizzle/0283_agents_agentcore_runtime_dispatch.sql +13 -0
  74. package/dist/drizzle/0284_user_brain_claims.sql +69 -0
  75. package/dist/drizzle/0285_tenant_mcp_twin_keys_trusted_subsystem.sql +30 -0
  76. package/dist/drizzle/0286_brain_analytics_key.sql +26 -0
  77. package/dist/drizzle/0287_brain_subject.sql +25 -0
  78. package/dist/drizzle/0288_multi_lane_identities.sql +25 -0
  79. package/dist/event-streams-7JNLJEEL.js +894 -0
  80. package/dist/event-streams-KDF5RWR6.js +1515 -0
  81. package/dist/loadSso-ETCXTR4I.js +576 -0
  82. package/dist/loadSso-UBD7KUHE.js +583 -0
  83. package/dist/plugins/README.md +2 -2
  84. package/dist/plugins/catalog/package.json +1 -5
  85. package/dist/plugins/catalog/src/__tests__/build-catalog.test.ts +6 -4
  86. package/dist/plugins/catalog/src/__tests__/catalog.test.ts +21 -21
  87. package/dist/plugins/catalog/src/__tests__/contracts.test.ts +102 -94
  88. package/dist/plugins/catalog/src/__tests__/plugin-package.test.ts +7 -8
  89. package/dist/plugins/catalog/src/__tests__/plugin-registry.test.ts +0 -20
  90. package/dist/plugins/catalog/src/contracts.ts +17 -179
  91. package/dist/plugins/catalog/src/registry/generated-first-party.ts +0 -24
  92. package/dist/plugins/n8n/test/integrated-app-contract.test.ts +1 -1
  93. package/dist/plugins/twenty/package.json +2 -1
  94. package/dist/plugins/twenty/scripts/LAMBDA_DEPLOY.md +114 -0
  95. package/dist/plugins/twenty/scripts/build-lambda.sh +29 -0
  96. package/dist/plugins/twenty/scripts/configure-product-views.ts +195 -0
  97. package/dist/plugins/twenty/scripts/lambda-handler.ts +49 -0
  98. package/dist/plugins/twenty/scripts/lib/__tests__/load-attachments.test.ts +38 -0
  99. package/dist/plugins/twenty/scripts/lib/__tests__/load-records.test.ts +145 -2
  100. package/dist/plugins/twenty/scripts/lib/__tests__/mappers.test.ts +397 -151
  101. package/dist/plugins/twenty/scripts/lib/__tests__/members-ensure.test.ts +28 -129
  102. package/dist/plugins/twenty/scripts/lib/__tests__/provision-members-db.test.ts +10 -0
  103. package/dist/plugins/twenty/scripts/lib/__tests__/schema-ensure.test.ts +13 -8
  104. package/dist/plugins/twenty/scripts/lib/lastmile-reader.ts +222 -2
  105. package/dist/plugins/twenty/scripts/lib/load-attachments.ts +29 -0
  106. package/dist/plugins/twenty/scripts/lib/load-records.ts +160 -43
  107. package/dist/plugins/twenty/scripts/lib/mappers.ts +368 -152
  108. package/dist/plugins/twenty/scripts/lib/members-ensure.ts +43 -268
  109. package/dist/plugins/twenty/scripts/lib/provision-members-db.ts +57 -0
  110. package/dist/plugins/twenty/scripts/lib/schema-ensure.ts +136 -31
  111. package/dist/plugins/twenty/scripts/migrate-lastmile.ts +254 -152
  112. package/dist/plugins/twenty/scripts/provision-twenty-members.ts +44 -1
  113. package/dist/plugins/twenty/scripts/purge-lastmile-import.ts +178 -0
  114. package/dist/plugins/twenty/scripts/restructure-products.ts +312 -0
  115. package/dist/plugins/twenty/scripts/retag-stage-values.ts +362 -0
  116. package/dist/plugins/twenty/test/manifest.test.ts +2 -4
  117. package/dist/scripts/post-deploy.sh +79 -1
  118. package/dist/signin-5QZNRSOO.js +821 -0
  119. package/dist/sso-oidc-XK673P54.js +837 -0
  120. package/dist/sts-OXI2UALF.js +1113 -0
  121. package/dist/sts-SQW4NBK3.js +1117 -0
  122. package/dist/terraform/examples/greenfield/main.tf +391 -176
  123. package/dist/terraform/examples/greenfield/terraform.tfvars.example +26 -8
  124. package/dist/terraform/modules/app/agentcore-admin/main.tf +47 -0
  125. package/dist/terraform/modules/app/agentcore-code-interpreter/README.md +39 -47
  126. package/dist/terraform/modules/app/agentcore-code-interpreter/main.tf +13 -66
  127. package/dist/terraform/modules/app/agentcore-identity/main.tf +253 -0
  128. package/dist/terraform/modules/app/agentcore-identity/outputs.tf +51 -0
  129. package/dist/terraform/modules/app/agentcore-identity/scripts/bootstrap_twenty_oauth_client.sh +239 -0
  130. package/dist/terraform/modules/app/agentcore-identity/scripts/delete_identity.sh +22 -0
  131. package/dist/terraform/modules/app/agentcore-identity/scripts/delete_twenty_identity.sh +16 -0
  132. package/dist/terraform/modules/app/agentcore-identity/scripts/delete_workload_identity.sh +19 -0
  133. package/dist/terraform/modules/app/agentcore-identity/scripts/ensure_workload_identity.sh +29 -0
  134. package/dist/terraform/modules/app/agentcore-identity/scripts/read_identity.sh +55 -0
  135. package/dist/terraform/modules/app/agentcore-identity/scripts/reconcile_identity.sh +73 -0
  136. package/dist/terraform/modules/app/agentcore-identity/scripts/reconcile_twenty_identity.sh +45 -0
  137. package/dist/terraform/modules/app/agentcore-identity/scripts/reconcile_twenty_provider.mjs +123 -0
  138. package/dist/terraform/modules/app/agentcore-identity/tests/tainted-marker/after.tf +15 -0
  139. package/dist/terraform/modules/app/agentcore-identity/tests/tainted-marker/before.tf +7 -0
  140. package/dist/terraform/modules/app/agentcore-identity/tests/tainted-marker/identity-after.tf +8 -0
  141. package/dist/terraform/modules/app/agentcore-identity/tests/tainted-marker/identity-before.tf +9 -0
  142. package/dist/terraform/modules/app/agentcore-identity/tests/tainted-marker/thinkwork-after.tf +3 -0
  143. package/dist/terraform/modules/app/agentcore-identity/tests/tainted-marker/thinkwork-before.tf +3 -0
  144. package/dist/terraform/modules/app/agentcore-identity/variables.tf +60 -0
  145. package/dist/terraform/modules/app/agentcore-memory/README.md +46 -9
  146. package/dist/terraform/modules/app/agentcore-memory/main.tf +27 -10
  147. package/dist/terraform/modules/app/agentcore-memory/scripts/create_or_find_memory.sh +156 -24
  148. package/dist/terraform/modules/app/agentcore-pi/README.md +1 -3
  149. package/dist/terraform/modules/app/agentcore-pi/main.tf +42 -52
  150. package/dist/terraform/modules/app/agentcore-pi/outputs.tf +3 -3
  151. package/dist/terraform/modules/app/agentcore-pi/scripts/reconcile_pi_runtime.mjs +175 -0
  152. package/dist/terraform/modules/app/agentcore-pi/variables.tf +35 -28
  153. package/dist/terraform/modules/app/agentcore-platform/main.tf +68 -0
  154. package/dist/terraform/modules/app/agentcore-runtime/main.tf +4 -20
  155. package/dist/terraform/modules/app/appsync-subscriptions/main.tf +127 -21
  156. package/dist/terraform/modules/app/appsync-subscriptions/outputs.tf +0 -6
  157. package/dist/terraform/modules/app/appsync-subscriptions/variables.tf +5 -0
  158. package/dist/terraform/modules/app/capability-broker/main.tf +2 -2
  159. package/dist/terraform/modules/app/capability-broker/variables.tf +11 -0
  160. package/dist/terraform/modules/app/deployment-control-plane/README.md +264 -0
  161. package/dist/terraform/modules/app/deployment-control-plane/buildspec.yml +4 -1
  162. package/dist/terraform/modules/app/deployment-control-plane/main.tf +94 -0
  163. package/dist/terraform/modules/app/deployment-control-plane/outputs.tf +5 -0
  164. package/dist/terraform/modules/app/deployment-control-plane/runner.py +3689 -233
  165. package/dist/terraform/modules/app/deployment-control-plane/test_runner_bundle.py +2579 -140
  166. package/dist/terraform/modules/app/deployment-control-plane/variables.tf +33 -0
  167. package/dist/terraform/modules/app/lambda-api/auth-state.tf +72 -0
  168. package/dist/terraform/modules/app/lambda-api/chat-latency-observability.tf +466 -0
  169. package/dist/terraform/modules/app/lambda-api/dispatch-dlq.tf +55 -0
  170. package/dist/terraform/modules/app/lambda-api/handlers.tf +531 -619
  171. package/dist/terraform/modules/app/lambda-api/iam-grouped.tf +350 -241
  172. package/dist/terraform/modules/app/lambda-api/main.tf +75 -13
  173. package/dist/terraform/modules/app/lambda-api/memory-alarms.tf +3 -28
  174. package/dist/terraform/modules/app/lambda-api/oauth-secrets.tf +1 -2
  175. package/dist/terraform/modules/app/lambda-api/outputs.tf +17 -10
  176. package/dist/terraform/modules/app/lambda-api/runtime-config.tf +3 -21
  177. package/dist/terraform/modules/app/lambda-api/turn-assertion.tf +45 -0
  178. package/dist/terraform/modules/app/lambda-api/variables.tf +307 -121
  179. package/dist/{plugins/n8n/terraform → terraform/modules/app}/n8n/README.md +1 -1
  180. package/dist/{plugins/n8n/terraform → terraform/modules/app}/n8n/main.tf +18 -18
  181. package/dist/terraform/modules/app/sandbox-log-scrubber/README.md +11 -10
  182. package/dist/terraform/modules/app/sandbox-log-scrubber/main.tf +5 -5
  183. package/dist/terraform/modules/app/static-site/main.tf +1 -1
  184. package/dist/terraform/modules/app/www-dns/main.tf +9 -27
  185. package/dist/terraform/modules/app/www-dns/variables.tf +4 -10
  186. package/dist/terraform/modules/data/aurora-postgres/README.md +34 -0
  187. package/dist/terraform/modules/data/aurora-postgres/alarms.tf +82 -0
  188. package/dist/terraform/modules/data/aurora-postgres/main.tf +27 -57
  189. package/dist/terraform/modules/data/aurora-postgres/outputs.tf +0 -9
  190. package/dist/terraform/modules/data/aurora-postgres/variables.tf +41 -0
  191. package/dist/terraform/modules/data/s3-buckets/main.tf +5 -6
  192. package/dist/terraform/modules/foundation/cognito/main.tf +367 -72
  193. package/dist/terraform/modules/foundation/cognito/outputs.tf +47 -0
  194. package/dist/terraform/modules/foundation/cognito/variables.tf +131 -9
  195. package/dist/terraform/modules/thinkwork/README.md +5 -1
  196. package/dist/terraform/modules/thinkwork/main.tf +459 -234
  197. package/dist/terraform/modules/thinkwork/outputs.tf +44 -62
  198. package/dist/terraform/modules/thinkwork/variables.tf +353 -89
  199. package/dist/terraform/schema.graphql +69 -36
  200. package/dist/workspace-defaults/files/INSTRUCTIONS.md +9 -11
  201. package/dist/workspace-defaults/files/MEMORY_GUIDE.md +38 -35
  202. package/dist/workspace-defaults/files/ROUTER.md +1 -1
  203. package/dist/workspace-defaults/files/TOOLS.md +9 -39
  204. package/dist/workspace-defaults/files/USER.md +1 -0
  205. package/dist/workspace-defaults/files/agents/analyst/INSTRUCTIONS.md +6 -3
  206. package/dist/workspace-defaults/files/catalog-skills/brain-brief-builder/SKILL.md +165 -0
  207. package/dist/workspace-defaults/files/catalog-skills/n8n-workflow-operator/SKILL.md +75 -0
  208. package/dist/workspace-defaults/files/catalog-skills/n8n-workflow-operator/references/mcp-tooling.md +40 -0
  209. package/dist/workspace-defaults/files/catalog-skills/n8n-workflow-operator/references/validation-and-handoff.md +40 -0
  210. package/dist/workspace-defaults/files/catalog-skills/n8n-workflow-operator/references/workflow-authoring.md +46 -0
  211. package/dist/workspace-defaults/files/skills/artifact-builder/references/crm-dashboard.md +1 -1
  212. package/dist/workspace-defaults/files/skills/document-composer/SKILL.md +22 -3
  213. package/package.json +3 -2
  214. package/dist/drizzle/0261_thread_turns_origin_turn_index.sql +0 -11
  215. package/dist/plugins/company-data/README.md +0 -49
  216. package/dist/plugins/company-data/package.json +0 -21
  217. package/dist/plugins/company-data/src/index.ts +0 -30
  218. package/dist/plugins/company-data/src/manifest.ts +0 -26
  219. package/dist/plugins/company-data/test/manifest.test.ts +0 -116
  220. package/dist/plugins/company-data/tsconfig.json +0 -8
  221. package/dist/plugins/company-etl/README.md +0 -46
  222. package/dist/plugins/company-etl/package.json +0 -21
  223. package/dist/plugins/company-etl/src/index.ts +0 -29
  224. package/dist/plugins/company-etl/src/manifest.ts +0 -26
  225. package/dist/plugins/company-etl/test/manifest.test.ts +0 -108
  226. package/dist/plugins/company-etl/tsconfig.json +0 -8
  227. package/dist/plugins/lastmile/README.md +0 -50
  228. package/dist/plugins/lastmile/package.json +0 -23
  229. package/dist/plugins/lastmile/smoke/lastmile-plugin-smoke.mjs +0 -661
  230. package/dist/plugins/lastmile/src/api/tasks-adapter.ts +0 -572
  231. package/dist/plugins/lastmile/src/discovery.fixture.ts +0 -64
  232. package/dist/plugins/lastmile/src/index.ts +0 -46
  233. package/dist/plugins/lastmile/src/manifest.ts +0 -139
  234. package/dist/plugins/lastmile/test/api/tasks-adapter.test.ts +0 -266
  235. package/dist/plugins/lastmile/test/discovery.test.ts +0 -88
  236. package/dist/plugins/lastmile/tsconfig.json +0 -8
  237. package/dist/plugins/n8n/smoke/n8n-managed-app-smoke.mjs +0 -409
  238. package/dist/plugins/twenty/smoke/twenty-managed-app-smoke.mjs +0 -359
  239. package/dist/plugins/workos-auth/package.json +0 -22
  240. package/dist/plugins/workos-auth/src/index.ts +0 -30
  241. package/dist/plugins/workos-auth/src/manifest.ts +0 -40
  242. package/dist/plugins/workos-auth/src/provider-contract.ts +0 -39
  243. package/dist/plugins/workos-auth/test/manifest.test.ts +0 -94
  244. package/dist/plugins/workos-auth/tsconfig.json +0 -8
  245. package/dist/terraform/modules/app/agentcore-code-interpreter/Dockerfile.sandbox-base +0 -61
  246. package/dist/terraform/modules/app/agentcore-code-interpreter/sandbox/sitecustomize.py +0 -227
  247. package/dist/terraform/modules/app/agentcore-code-interpreter/sandbox/test_sitecustomize.py +0 -277
  248. package/dist/terraform/modules/app/agentcore-code-interpreter/scripts/build_and_push_sandbox_base.sh +0 -70
  249. package/dist/terraform/modules/app/agentcore-harness/main.tf +0 -101
  250. package/dist/terraform/modules/app/agentcore-harness/outputs.tf +0 -9
  251. package/dist/terraform/modules/app/agentcore-harness/variables.tf +0 -25
  252. package/dist/terraform/modules/app/hindsight-memory/README.md +0 -89
  253. package/dist/terraform/modules/app/hindsight-memory/main.tf +0 -411
  254. package/dist/terraform/modules/data/bedrock-knowledge-base/main.tf +0 -102
  255. /package/dist/{plugins/n8n/terraform → terraform/modules/app}/n8n/outputs.tf +0 -0
  256. /package/dist/{plugins/n8n/terraform → terraform/modules/app}/n8n/scripts/sync-database.py +0 -0
  257. /package/dist/{plugins/n8n/terraform → terraform/modules/app}/n8n/scripts/test_sync_database.py +0 -0
  258. /package/dist/{plugins/n8n/terraform → terraform/modules/app}/n8n/variables.tf +0 -0
  259. /package/dist/{plugins/twenty/terraform → terraform/modules/app}/twenty/README.md +0 -0
  260. /package/dist/{plugins/twenty/terraform → terraform/modules/app}/twenty/main.tf +0 -0
  261. /package/dist/{plugins/twenty/terraform → terraform/modules/app}/twenty/outputs.tf +0 -0
  262. /package/dist/{plugins/twenty/terraform → terraform/modules/app}/twenty/variables.tf +0 -0
@@ -0,0 +1,115 @@
1
+ -- creates: public.tool_execution_events
2
+ -- creates: public.idx_tool_execution_turn
3
+ -- creates: public.uq_tool_execution_started
4
+ -- creates: public.uq_tool_execution_terminal
5
+ -- creates-function: public.reject_tool_execution_event_mutation
6
+ -- creates-function: public.validate_tool_execution_event_insert
7
+ -- creates-trigger: public.tool_execution_events.trg_reject_tool_execution_event_mutation
8
+ -- creates-trigger: public.tool_execution_events.trg_validate_tool_execution_event_insert
9
+ -- Pi runtime tool-execution ledger (THINK-324 Wave-3 C17). Sanitized
10
+ -- append-only event stream: one `started` row per tool call and at most one
11
+ -- terminal row, emitted by the runtime via POST /api/runtime/tool-executions.
12
+ -- Succeeds the retired harness_tool_execution_events contract (0264);
13
+ -- policy columns are nullable until per-call re-authorization (C19) lands.
14
+
15
+ CREATE TABLE IF NOT EXISTS public.tool_execution_events (
16
+ id bigserial PRIMARY KEY,
17
+ tenant_id uuid NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,
18
+ thread_id uuid NOT NULL REFERENCES public.threads(id) ON DELETE CASCADE,
19
+ turn_id uuid NOT NULL REFERENCES public.thread_turns(id) ON DELETE CASCADE,
20
+ principal_type text NOT NULL CHECK (principal_type IN ('user', 'service')),
21
+ principal_id text NOT NULL,
22
+ tool_use_id text NOT NULL,
23
+ operation text NOT NULL,
24
+ policy_revision text,
25
+ policy_decision_id text,
26
+ idempotency_key text NOT NULL,
27
+ credential_owner_alias text,
28
+ event_type text NOT NULL
29
+ CHECK (event_type IN ('started','completed','failed','uncertain')),
30
+ input_preview jsonb,
31
+ output_preview jsonb,
32
+ error_preview jsonb,
33
+ provider_request_id text,
34
+ duration_ms integer CHECK (duration_ms IS NULL OR duration_ms >= 0),
35
+ provider_cost_usd numeric(18,8)
36
+ CHECK (provider_cost_usd IS NULL OR provider_cost_usd >= 0),
37
+ created_at timestamptz NOT NULL DEFAULT now(),
38
+ CHECK (
39
+ (
40
+ event_type = 'started'
41
+ AND input_preview IS NOT NULL
42
+ AND output_preview IS NULL
43
+ AND error_preview IS NULL
44
+ AND provider_request_id IS NULL
45
+ AND duration_ms IS NULL
46
+ AND provider_cost_usd IS NULL
47
+ )
48
+ OR (
49
+ event_type IN ('completed','failed','uncertain')
50
+ AND input_preview IS NULL
51
+ )
52
+ )
53
+ );
54
+
55
+ CREATE UNIQUE INDEX IF NOT EXISTS uq_tool_execution_started
56
+ ON public.tool_execution_events (tenant_id, idempotency_key)
57
+ WHERE event_type = 'started';
58
+
59
+ CREATE UNIQUE INDEX IF NOT EXISTS uq_tool_execution_terminal
60
+ ON public.tool_execution_events (tenant_id, idempotency_key)
61
+ WHERE event_type IN ('completed','failed','uncertain');
62
+
63
+ CREATE INDEX IF NOT EXISTS idx_tool_execution_turn
64
+ ON public.tool_execution_events (tenant_id, thread_id, turn_id, id);
65
+
66
+ CREATE OR REPLACE FUNCTION public.validate_tool_execution_event_insert()
67
+ RETURNS trigger
68
+ LANGUAGE plpgsql
69
+ AS $$
70
+ BEGIN
71
+ IF NEW.event_type = 'started' THEN
72
+ RETURN NEW;
73
+ END IF;
74
+
75
+ IF NOT EXISTS (
76
+ SELECT 1
77
+ FROM public.tool_execution_events started
78
+ WHERE started.tenant_id = NEW.tenant_id
79
+ AND started.idempotency_key = NEW.idempotency_key
80
+ AND started.event_type = 'started'
81
+ AND started.thread_id = NEW.thread_id
82
+ AND started.turn_id = NEW.turn_id
83
+ AND started.principal_type = NEW.principal_type
84
+ AND started.principal_id = NEW.principal_id
85
+ AND started.tool_use_id = NEW.tool_use_id
86
+ AND started.operation = NEW.operation
87
+ AND started.policy_revision IS NOT DISTINCT FROM NEW.policy_revision
88
+ ) THEN
89
+ RAISE EXCEPTION 'tool_execution_terminal_without_matching_start';
90
+ END IF;
91
+
92
+ RETURN NEW;
93
+ END;
94
+ $$;
95
+
96
+ DROP TRIGGER IF EXISTS trg_validate_tool_execution_event_insert
97
+ ON public.tool_execution_events;
98
+ CREATE TRIGGER trg_validate_tool_execution_event_insert
99
+ BEFORE INSERT ON public.tool_execution_events
100
+ FOR EACH ROW EXECUTE FUNCTION public.validate_tool_execution_event_insert();
101
+
102
+ CREATE OR REPLACE FUNCTION public.reject_tool_execution_event_mutation()
103
+ RETURNS trigger
104
+ LANGUAGE plpgsql
105
+ AS $$
106
+ BEGIN
107
+ RAISE EXCEPTION 'tool_execution_events_are_append_only';
108
+ END;
109
+ $$;
110
+
111
+ DROP TRIGGER IF EXISTS trg_reject_tool_execution_event_mutation
112
+ ON public.tool_execution_events;
113
+ CREATE TRIGGER trg_reject_tool_execution_event_mutation
114
+ BEFORE UPDATE OR DELETE ON public.tool_execution_events
115
+ FOR EACH ROW EXECUTE FUNCTION public.reject_tool_execution_event_mutation();
@@ -0,0 +1,47 @@
1
+ -- Purpose: Company Brain twin declarations (plan 2026-07-21-001 U3 / KTD-3) —
2
+ -- per-entity-type facet declarations (clone policy + cadence + attribute
3
+ -- mappings) and page-section declarations, per-relationship-type source
4
+ -- bindings (deterministic FK edge population), plus the three change-set
5
+ -- item types that govern edits (`facet_declaration`, `relationship_binding`,
6
+ -- `page_section`). The compiled twin mapping export is regenerated from
7
+ -- these columns on every change-set apply.
8
+ -- Plan: docs/plans/2026-07-21-001-feat-company-brain-digital-twin-plan.md (U3)
9
+ -- Apply manually: psql "$DATABASE_URL" -v ON_ERROR_STOP=1 -f packages/database-pg/drizzle/0271_ontology_twin_declarations.sql
10
+ -- creates-column: ontology.entity_types.twin_facets
11
+ -- creates-column: ontology.entity_types.twin_facets_version
12
+ -- creates-column: ontology.entity_types.page_sections
13
+ -- creates-column: ontology.entity_types.page_sections_version
14
+ -- creates-column: ontology.relationship_types.source_binding
15
+ -- creates-column: ontology.relationship_types.source_binding_version
16
+ -- creates-constraint: ontology.change_set_items.ontology_change_set_items_type_allowed
17
+
18
+ \set ON_ERROR_STOP on
19
+
20
+ BEGIN;
21
+
22
+ SET LOCAL lock_timeout = '5s';
23
+ SET LOCAL statement_timeout = '120s';
24
+
25
+ ALTER TABLE ontology.entity_types
26
+ ADD COLUMN IF NOT EXISTS twin_facets jsonb NOT NULL DEFAULT '[]'::jsonb;
27
+ ALTER TABLE ontology.entity_types
28
+ ADD COLUMN IF NOT EXISTS twin_facets_version integer NOT NULL DEFAULT 0;
29
+ ALTER TABLE ontology.entity_types
30
+ ADD COLUMN IF NOT EXISTS page_sections jsonb NOT NULL DEFAULT '[]'::jsonb;
31
+ ALTER TABLE ontology.entity_types
32
+ ADD COLUMN IF NOT EXISTS page_sections_version integer NOT NULL DEFAULT 0;
33
+
34
+ ALTER TABLE ontology.relationship_types
35
+ ADD COLUMN IF NOT EXISTS source_binding jsonb NOT NULL DEFAULT '{}'::jsonb;
36
+ ALTER TABLE ontology.relationship_types
37
+ ADD COLUMN IF NOT EXISTS source_binding_version integer NOT NULL DEFAULT 0;
38
+
39
+ -- Widen the item-type CHECK to admit the three twin declaration item types
40
+ -- (constraint-widening deploys before writer code per house convention).
41
+ ALTER TABLE ontology.change_set_items
42
+ DROP CONSTRAINT IF EXISTS ontology_change_set_items_type_allowed;
43
+ ALTER TABLE ontology.change_set_items
44
+ ADD CONSTRAINT ontology_change_set_items_type_allowed
45
+ CHECK (item_type IN ('entity_type','relationship_type','facet_template','external_mapping','identity_map','facet_declaration','relationship_binding','page_section'));
46
+
47
+ COMMIT;
@@ -0,0 +1,23 @@
1
+ -- Purpose: twin graph projector consumer state (Company Brain U5 / KTD-4) —
2
+ -- per-tenant cursor over identity.entity_resolution_events. The cursor is
3
+ -- the source of truth for the projector; nudge invokes are latency only.
4
+ -- Plan: docs/plans/2026-07-21-001-feat-company-brain-digital-twin-plan.md (U5)
5
+ -- Apply manually: psql "$DATABASE_URL" -v ON_ERROR_STOP=1 -f packages/database-pg/drizzle/0272_identity_graph_projection_cursor.sql
6
+ -- creates: identity.graph_projection_cursors
7
+
8
+ \set ON_ERROR_STOP on
9
+
10
+ BEGIN;
11
+
12
+ SET LOCAL lock_timeout = '5s';
13
+ SET LOCAL statement_timeout = '60s';
14
+
15
+ CREATE TABLE IF NOT EXISTS identity.graph_projection_cursors (
16
+ tenant_id UUID PRIMARY KEY REFERENCES public.tenants(id) ON DELETE CASCADE,
17
+ last_event_created_at TIMESTAMPTZ,
18
+ last_event_id UUID,
19
+ last_snapshot_cursor TEXT,
20
+ updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
21
+ );
22
+
23
+ COMMIT;
@@ -0,0 +1,29 @@
1
+ -- Purpose: materialization suggestions (Company Brain U8 / R8) — when a
2
+ -- cohort question needs a limited/unclonable facet, the gap surfaces to
3
+ -- operators on the ontology surface as a persisted, deduped, dismissible
4
+ -- suggestion with a hit counter (one row per tenant + entity type + facet).
5
+ -- Plan: docs/plans/2026-07-21-001-feat-company-brain-digital-twin-plan.md (U8)
6
+ -- Apply manually: psql "$DATABASE_URL" -v ON_ERROR_STOP=1 -f packages/database-pg/drizzle/0273_twin_materialization_suggestions.sql
7
+ -- creates: public.twin_materialization_suggestions
8
+
9
+ \set ON_ERROR_STOP on
10
+
11
+ BEGIN;
12
+
13
+ SET LOCAL lock_timeout = '5s';
14
+ SET LOCAL statement_timeout = '60s';
15
+
16
+ CREATE TABLE IF NOT EXISTS public.twin_materialization_suggestions (
17
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
18
+ tenant_id UUID NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,
19
+ entity_type_slug TEXT NOT NULL,
20
+ facet_slug TEXT NOT NULL,
21
+ hit_count INTEGER NOT NULL DEFAULT 1,
22
+ last_question TEXT,
23
+ dismissed_at TIMESTAMPTZ,
24
+ created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
25
+ updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
26
+ UNIQUE (tenant_id, entity_type_slug, facet_slug)
27
+ );
28
+
29
+ COMMIT;
@@ -0,0 +1,59 @@
1
+ -- tenant_mcp_twin_keys — per-tenant Bearer keys for the Company Brain MCP
2
+ -- server (THINK-333).
3
+ --
4
+ -- The agent path to /mcp/twin authenticates with a `tkt_`-prefixed key.
5
+ -- The mcp-twin handler hashes the incoming Bearer with SHA-256 and looks
6
+ -- it up here where revoked_at IS NULL — the matched row IS the tenant
7
+ -- selection (no tenant id is embedded in the token, so there is no
8
+ -- select-then-verify ambiguity). Raw keys are never stored — only the
9
+ -- hash + metadata. Rotation inserts a fresh row and revokes the old one.
10
+ --
11
+ -- Mirrors tenant_mcp_admin_keys (drizzle/0024) structurally; a separate
12
+ -- table so twin revocation never entangles the admin-ops scope.
13
+ --
14
+ -- Apply manually (matches the 0018+ hand-rolled convention):
15
+ -- psql "$DATABASE_URL" -f packages/database-pg/drizzle/0274_tenant_mcp_twin_keys.sql
16
+ --
17
+ -- Drift detection:
18
+ -- pnpm db:migrate-manual
19
+ --
20
+ -- Pre-migration invariants:
21
+ -- - tenants exists.
22
+ -- - tenant_mcp_twin_keys does not yet exist.
23
+ -- SELECT to_regclass('public.tenant_mcp_twin_keys'); -- must be NULL
24
+ --
25
+ -- creates: public.tenant_mcp_twin_keys
26
+ -- creates: public.uq_tenant_mcp_twin_keys_hash
27
+ -- creates: public.uq_tenant_mcp_twin_keys_active_name
28
+ -- creates: public.idx_tenant_mcp_twin_keys_tenant
29
+
30
+ CREATE TABLE "tenant_mcp_twin_keys" (
31
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
32
+ "tenant_id" uuid NOT NULL REFERENCES "tenants"("id") ON DELETE CASCADE,
33
+ -- SHA-256 hex digest of the raw key. 64 chars; text keeps tooling friendly.
34
+ "key_hash" text NOT NULL,
35
+ -- Human label; "default" for the provisioned connector key.
36
+ "name" text NOT NULL,
37
+ "created_at" timestamptz NOT NULL DEFAULT now(),
38
+ -- Who created the key. Nullable for service-provisioned keys.
39
+ "created_by_user_id" uuid,
40
+ -- Bumped on every successful auth by the mcp-twin handler. Async,
41
+ -- best-effort (failure to update does not block the request).
42
+ "last_used_at" timestamptz,
43
+ -- Soft-delete. NULL = active. Rotation sets now() on the old row; the
44
+ -- row is retained for audit + to prevent hash reuse.
45
+ "revoked_at" timestamptz
46
+ );
47
+
48
+ -- Global uniqueness on hash — a single-row lookup resolves the tenant.
49
+ CREATE UNIQUE INDEX "uq_tenant_mcp_twin_keys_hash"
50
+ ON "tenant_mcp_twin_keys" ("key_hash");
51
+
52
+ -- Per-tenant uniqueness on name among active rows. Partial index so a
53
+ -- rotated/revoked "default" does not block minting a fresh "default".
54
+ CREATE UNIQUE INDEX "uq_tenant_mcp_twin_keys_active_name"
55
+ ON "tenant_mcp_twin_keys" ("tenant_id", "name")
56
+ WHERE "revoked_at" IS NULL;
57
+
58
+ CREATE INDEX "idx_tenant_mcp_twin_keys_tenant"
59
+ ON "tenant_mcp_twin_keys" ("tenant_id", "created_at");
@@ -0,0 +1,30 @@
1
+ -- Purpose: bulk-rebuild lane fence + extract-time watermark (THINK-331) —
2
+ -- per-tenant CAS fence on the projector cursor row. bulk_load_started_at
3
+ -- non-null = a bulk-rebuild holds the fence (heartbeat, refreshed on every
4
+ -- resume/poll); bulk_load_id is the Neptune loader job id (null until the
5
+ -- loader starts). The watermark pair is captured SQL-side BEFORE the
6
+ -- Postgres extract so the success tail fast-forwards the cursor only past
7
+ -- events the extract reflected — events committed during the load window
8
+ -- replay through the nudge lane. Additive-only; lands before the code that
9
+ -- reads it (safe ordering).
10
+ -- Plan: docs/plans/2026-07-22-004-feat-identity-projector-bulk-rebuild-plan.md (U2)
11
+ -- Apply manually: psql "$DATABASE_URL" -v ON_ERROR_STOP=1 -f packages/database-pg/drizzle/0275_identity_bulk_rebuild_fence.sql
12
+ -- creates-column: identity.graph_projection_cursors.bulk_load_id
13
+ -- creates-column: identity.graph_projection_cursors.bulk_load_started_at
14
+ -- creates-column: identity.graph_projection_cursors.bulk_watermark_created_at
15
+ -- creates-column: identity.graph_projection_cursors.bulk_watermark_event_id
16
+
17
+ \set ON_ERROR_STOP on
18
+
19
+ BEGIN;
20
+
21
+ SET LOCAL lock_timeout = '5s';
22
+ SET LOCAL statement_timeout = '60s';
23
+
24
+ ALTER TABLE identity.graph_projection_cursors
25
+ ADD COLUMN IF NOT EXISTS bulk_load_id TEXT,
26
+ ADD COLUMN IF NOT EXISTS bulk_load_started_at TIMESTAMPTZ,
27
+ ADD COLUMN IF NOT EXISTS bulk_watermark_created_at TIMESTAMPTZ,
28
+ ADD COLUMN IF NOT EXISTS bulk_watermark_event_id UUID;
29
+
30
+ COMMIT;
@@ -0,0 +1,18 @@
1
+ -- creates-trigger: public.tool_execution_events.trg_reject_tool_execution_event_mutation
2
+ -- Thread deletion was impossible for any thread whose agent ran tools: the
3
+ -- ledger declares thread_id/turn_id/tenant_id FKs ON DELETE CASCADE, but the
4
+ -- append-only guard trigger fired on the cascaded DELETE too and aborted the
5
+ -- whole deleteThread transaction with `tool_execution_events_are_append_only`.
6
+ --
7
+ -- Recreate the guard with WHEN (pg_trigger_depth() = 0): direct UPDATE/DELETE
8
+ -- statements are still rejected (the WHEN clause sees depth 0 and the guard
9
+ -- raises), while deletes arriving through FK referential-action triggers run
10
+ -- at depth >= 1 and are allowed — which is exactly the lifecycle the CASCADE
11
+ -- clauses on this table already promised.
12
+ DROP TRIGGER IF EXISTS trg_reject_tool_execution_event_mutation
13
+ ON public.tool_execution_events;
14
+ CREATE TRIGGER trg_reject_tool_execution_event_mutation
15
+ BEFORE UPDATE OR DELETE ON public.tool_execution_events
16
+ FOR EACH ROW
17
+ WHEN (pg_trigger_depth() = 0)
18
+ EXECUTE FUNCTION public.reject_tool_execution_event_mutation();
@@ -0,0 +1,107 @@
1
+ -- External S3 KB source U1: a Knowledge Base holds N data sources instead of
2
+ -- one implied upload prefix.
3
+ -- Contents:
4
+ -- * public.knowledge_base_sources — one row per Bedrock data source of a
5
+ -- KB. kind 'managed-upload' is the platform upload prefix (backfilled as
6
+ -- source #0 from the KB's implied prefix + aws_data_source_id);
7
+ -- 's3-connect' points at an existing customer bucket/prefix read in
8
+ -- place; 'snapshot' is a reserved enum value only. `bucket` is NULL for
9
+ -- managed-upload (workspace bucket resolved at runtime).
10
+ -- * uq_kb_sources_managed_upload — one managed-upload source per KB.
11
+ -- * public.knowledge_base_documents.source_id — nullable FK to the source
12
+ -- row (data_source_id keeps the AWS identity; this is the row reference),
13
+ -- backfilled to the managed-upload source.
14
+ --
15
+ -- Hand-rolled (drizzle meta journal is not in use for this change);
16
+ -- apply with: psql "$DATABASE_URL" -f drizzle/0277_knowledge_base_sources.sql
17
+ -- creates: public.knowledge_base_sources
18
+ -- creates: public.idx_kb_sources_kb
19
+ -- creates: public.idx_kb_sources_tenant
20
+ -- creates: public.uq_kb_sources_managed_upload
21
+ -- creates: public.idx_kb_documents_source
22
+ -- creates-column: public.knowledge_base_documents.source_id
23
+ -- creates-constraint: public.knowledge_base_sources.knowledge_base_sources_kind_check
24
+ -- creates-constraint: public.knowledge_base_sources.knowledge_base_sources_access_status_check
25
+ -- creates-constraint: public.knowledge_base_sources.knowledge_base_sources_s3_connect_location_check
26
+
27
+ \set ON_ERROR_STOP on
28
+
29
+ BEGIN;
30
+
31
+ CREATE TABLE IF NOT EXISTS public.knowledge_base_sources (
32
+ id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
33
+ tenant_id uuid NOT NULL REFERENCES public.tenants(id),
34
+ knowledge_base_id uuid NOT NULL REFERENCES public.knowledge_bases(id) ON DELETE CASCADE,
35
+ kind text NOT NULL,
36
+ bucket text,
37
+ prefix text,
38
+ filter_patterns jsonb,
39
+ bucket_owner_account_id text,
40
+ parsing_strategy text NOT NULL DEFAULT 'DEFAULT',
41
+ aws_data_source_id text,
42
+ access_status text NOT NULL DEFAULT 'pending',
43
+ last_sync_at timestamptz,
44
+ last_sync_status text,
45
+ document_count integer DEFAULT 0,
46
+ error_message text,
47
+ sentinel_document_key text,
48
+ sentinel_phrase text,
49
+ created_at timestamptz NOT NULL DEFAULT now(),
50
+ updated_at timestamptz NOT NULL DEFAULT now(),
51
+ CONSTRAINT knowledge_base_sources_kind_check
52
+ CHECK (kind IN ('managed-upload', 's3-connect', 'snapshot')),
53
+ CONSTRAINT knowledge_base_sources_access_status_check
54
+ CHECK (access_status IN ('pending', 'healthy', 'degraded', 'access_revoked', 'failed')),
55
+ CONSTRAINT knowledge_base_sources_s3_connect_location_check
56
+ CHECK (kind <> 's3-connect' OR (bucket IS NOT NULL AND prefix IS NOT NULL))
57
+ );
58
+
59
+ CREATE INDEX IF NOT EXISTS idx_kb_sources_kb
60
+ ON public.knowledge_base_sources (knowledge_base_id);
61
+
62
+ CREATE INDEX IF NOT EXISTS idx_kb_sources_tenant
63
+ ON public.knowledge_base_sources (tenant_id);
64
+
65
+ CREATE UNIQUE INDEX IF NOT EXISTS uq_kb_sources_managed_upload
66
+ ON public.knowledge_base_sources (knowledge_base_id)
67
+ WHERE kind = 'managed-upload';
68
+
69
+ ALTER TABLE public.knowledge_base_documents
70
+ ADD COLUMN IF NOT EXISTS source_id uuid
71
+ REFERENCES public.knowledge_base_sources(id) ON DELETE SET NULL;
72
+
73
+ CREATE INDEX IF NOT EXISTS idx_kb_documents_source
74
+ ON public.knowledge_base_documents (source_id);
75
+
76
+ -- Backfill source #0: one managed-upload row per existing KB, carrying the
77
+ -- KB's implied upload prefix and its current Bedrock data-source identity.
78
+ -- Backfilled sources are the platform's own bucket — access is 'healthy'.
79
+ INSERT INTO public.knowledge_base_sources
80
+ (tenant_id, knowledge_base_id, kind, prefix, aws_data_source_id,
81
+ access_status, last_sync_at, last_sync_status, document_count)
82
+ SELECT
83
+ kb.tenant_id,
84
+ kb.id,
85
+ 'managed-upload',
86
+ 'tenants/' || t.slug || '/knowledge-bases/' || kb.slug || '/documents/',
87
+ kb.aws_data_source_id,
88
+ 'healthy',
89
+ kb.last_sync_at,
90
+ kb.last_sync_status,
91
+ kb.document_count
92
+ FROM public.knowledge_bases kb
93
+ JOIN public.tenants t ON t.id = kb.tenant_id
94
+ WHERE NOT EXISTS (
95
+ SELECT 1 FROM public.knowledge_base_sources s
96
+ WHERE s.knowledge_base_id = kb.id AND s.kind = 'managed-upload'
97
+ );
98
+
99
+ -- Attribute existing manifest rows to their KB's managed-upload source.
100
+ UPDATE public.knowledge_base_documents d
101
+ SET source_id = s.id
102
+ FROM public.knowledge_base_sources s
103
+ WHERE d.source_id IS NULL
104
+ AND s.knowledge_base_id = d.knowledge_base_id
105
+ AND s.kind = 'managed-upload';
106
+
107
+ COMMIT;
@@ -0,0 +1,55 @@
1
+ -- KB page transcription U1: image-bearing source documents are transcribed
2
+ -- page-by-page before ingestion, so the manifest has to record what the
3
+ -- preprocessor produced.
4
+ --
5
+ -- Background: Bedrock's default parser "only parses text in text files" and
6
+ -- the platform never sends a parsingConfiguration, so scanned pages and
7
+ -- embedded screenshots index as nothing. 71 of McPherson's 80 CX SOP PDFs
8
+ -- (89%) keep most of their substance inside images. The fix is a preprocessor
9
+ -- that splits each PDF page and transcribes it with a Claude vision model,
10
+ -- then ingests one IN_LINE document per page under id '<key>#p=<n>'.
11
+ --
12
+ -- Contents:
13
+ -- * knowledge_base_sources.parsing_strategy CHECK widened from the implicit
14
+ -- 'DEFAULT' to ('DEFAULT','TRANSCRIBE'). The column already exists and
15
+ -- defaults to 'DEFAULT'; it was previously wired to nothing.
16
+ -- * knowledge_base_documents gains the preprocessor result: derived_prefix
17
+ -- (workspace-bucket location of pages/<n>.md + report.json), page_count,
18
+ -- preprocessor_version (joins the change-detection predicate so a
19
+ -- pipeline bump forces reprocessing), page_report (per-page route, model
20
+ -- used, flags) and needs_review (any page the preprocessor flagged as
21
+ -- low-signal — indexed with a warning, never silently dropped).
22
+ --
23
+ -- Manifest identity is unchanged: ONE row per source document. Page documents
24
+ -- are an ingestion-level fan-out; their Bedrock statuses fold back up to the
25
+ -- base document_key.
26
+ --
27
+ -- Hand-rolled (drizzle meta journal is not in use for this change);
28
+ -- apply with: psql "$DATABASE_URL" -f drizzle/0278_kb_page_transcription.sql
29
+ -- creates-column: public.knowledge_base_documents.derived_prefix
30
+ -- creates-column: public.knowledge_base_documents.page_count
31
+ -- creates-column: public.knowledge_base_documents.preprocessor_version
32
+ -- creates-column: public.knowledge_base_documents.page_report
33
+ -- creates-column: public.knowledge_base_documents.needs_review
34
+ -- creates: public.idx_kb_documents_needs_review
35
+ -- creates-constraint: public.knowledge_base_sources.knowledge_base_sources_parsing_strategy_check
36
+
37
+ ALTER TABLE public.knowledge_base_documents
38
+ ADD COLUMN IF NOT EXISTS derived_prefix text,
39
+ ADD COLUMN IF NOT EXISTS page_count integer,
40
+ ADD COLUMN IF NOT EXISTS preprocessor_version text,
41
+ ADD COLUMN IF NOT EXISTS page_report jsonb,
42
+ ADD COLUMN IF NOT EXISTS needs_review boolean NOT NULL DEFAULT false;
43
+
44
+ -- Operator surface: "which documents came back with pages the preprocessor
45
+ -- was unsure about". Partial — the overwhelming majority are false.
46
+ CREATE INDEX IF NOT EXISTS idx_kb_documents_needs_review
47
+ ON public.knowledge_base_documents (knowledge_base_id)
48
+ WHERE needs_review;
49
+
50
+ ALTER TABLE public.knowledge_base_sources
51
+ DROP CONSTRAINT IF EXISTS knowledge_base_sources_parsing_strategy_check;
52
+
53
+ ALTER TABLE public.knowledge_base_sources
54
+ ADD CONSTRAINT knowledge_base_sources_parsing_strategy_check
55
+ CHECK (parsing_strategy IN ('DEFAULT', 'TRANSCRIBE'));
@@ -0,0 +1,93 @@
1
+ -- Hand-rolled — apply manually to each stage via:
2
+ -- psql "$DATABASE_URL" -f packages/database-pg/drizzle/0279_mcp_servers_off_plugin_provenance.sql
3
+ --
4
+ -- See docs/solutions/workflow-issues/manually-applied-drizzle-migrations-drift-from-dev-2026-04-21.md
5
+ --
6
+ -- Plugin-system removal. The plugin engine's MCP component handler adopted
7
+ -- surviving MCP servers as management_source='plugin' + plugin_install_id
8
+ -- (migrations 0159/0161). Twenty CRM and n8n keep running after the plugin
9
+ -- system is deleted, so their MCP rows move back to plain 'manual'
10
+ -- registration — the same shape lastmile-dispatch and digital-twin already
11
+ -- use.
12
+ --
13
+ -- data-only-migration
14
+ -- No durable schema objects: this only rewrites provenance columns. The
15
+ -- in-transaction assertions below are the correctness gate, and the
16
+ -- verification queries at the bottom are the post-apply check.
17
+ --
18
+ -- Why this is safe:
19
+ --
20
+ -- * Credentials do not move. packages/api/src/lib/mcp-configs.ts resolves
21
+ -- service_credential from auth_config.secretRef and oauth from
22
+ -- user_mcp_tokens — in the plugin branch and the manual branch alike.
23
+ -- plugin_install_id is used for dispatch *ordering* (plugin rows win a
24
+ -- URL dedupe pass), never for auth.
25
+ -- * Both target shapes are already proven on the manual path:
26
+ -- manual|oauth (lastmile-dispatch, with live per-user tokens) and
27
+ -- manual|service_credential (digital-twin, thinkwork-hindsight,
28
+ -- postgres-dev).
29
+ -- * Nothing re-adopts these rows. The only writers of
30
+ -- management_source='plugin' are lib/plugins/handlers/mcp.ts and
31
+ -- lib/plugins/cutover/deps.ts, both reached only by an explicit plugin
32
+ -- install/activate — and both are deleted with the plugin system.
33
+ --
34
+ -- The CHECK constraint tenant_mcp_servers_managed_application_shape_check_v2
35
+ -- requires manual rows to carry NO ownership key, so managed_application_key
36
+ -- is cleared alongside plugin_install_id. Only dev's twenty--crm still has
37
+ -- one (its pre-plugin identity, retained through the 0161 cutover); the
38
+ -- customer stages already have it NULL.
39
+ --
40
+ -- Per-stage effect at time of writing:
41
+ -- dev twenty--crm (oauth, 2 tokens), n8n--workflow-management,
42
+ -- company-brain--brain, plane--issues
43
+ -- tei-e2e twenty--crm (oauth, 3 tokens)
44
+ -- mcpherson n8n--workflow-management
45
+ --
46
+ -- company-brain--brain and plane--issues are flipped too rather than left
47
+ -- dangling: their plugin_install_id would become a broken reference once the
48
+ -- plugin tables drop. Their own removal is a separate decision.
49
+
50
+ BEGIN;
51
+
52
+ UPDATE tenant_mcp_servers
53
+ SET management_source = 'manual',
54
+ plugin_install_id = NULL,
55
+ managed_application_key = NULL,
56
+ updated_at = now()
57
+ WHERE management_source = 'plugin';
58
+
59
+ -- Fail loudly rather than commit a half-migration: no row anywhere may still
60
+ -- claim plugin provenance, and none may violate the manual shape.
61
+ DO $$
62
+ DECLARE
63
+ leftover integer;
64
+ malformed integer;
65
+ BEGIN
66
+ SELECT count(*) INTO leftover
67
+ FROM tenant_mcp_servers
68
+ WHERE management_source = 'plugin' OR plugin_install_id IS NOT NULL;
69
+ IF leftover > 0 THEN
70
+ RAISE EXCEPTION 'plugin provenance still present on % tenant_mcp_servers row(s)', leftover;
71
+ END IF;
72
+
73
+ SELECT count(*) INTO malformed
74
+ FROM tenant_mcp_servers
75
+ WHERE management_source = 'manual' AND managed_application_key IS NOT NULL;
76
+ IF malformed > 0 THEN
77
+ RAISE EXCEPTION 'manual rows still carry managed_application_key on % row(s)', malformed;
78
+ END IF;
79
+ END $$;
80
+
81
+ COMMIT;
82
+
83
+ -- Verification (run after applying):
84
+ --
85
+ -- SELECT slug, management_source, auth_type,
86
+ -- (plugin_install_id IS NOT NULL) AS has_plugin
87
+ -- FROM tenant_mcp_servers ORDER BY slug;
88
+ --
89
+ -- -- per-user OAuth tokens must be untouched
90
+ -- SELECT s.slug, count(t.id)
91
+ -- FROM tenant_mcp_servers s
92
+ -- LEFT JOIN user_mcp_tokens t ON t.mcp_server_id = s.id
93
+ -- GROUP BY s.slug ORDER BY s.slug;
@@ -0,0 +1,46 @@
1
+ -- 0280_work_item_external_refs_drop_plane_provider.sql
2
+ --
3
+ -- Purpose: drop 'plane' from the work_item_external_refs provider allowlist.
4
+ -- Plane is retired — its deployment, DNS, S3 bucket, database, credentials and
5
+ -- MCP registration are all gone, so the provider can never be written again.
6
+ -- Apply manually:
7
+ -- psql "$DATABASE_URL" -v ON_ERROR_STOP=1 -f packages/database-pg/drizzle/0280_work_item_external_refs_drop_plane_provider.sql
8
+ --
9
+ -- Recreates an existing constraint rather than adding a new object, so the
10
+ -- drift reporter is given the constraint it should find afterwards.
11
+ --
12
+ -- creates-constraint: public.work_item_external_refs.work_item_external_refs_provider_allowed
13
+
14
+ \set ON_ERROR_STOP on
15
+
16
+ BEGIN;
17
+
18
+ SET LOCAL lock_timeout = '5s';
19
+
20
+ -- Fail loudly rather than silently dropping rows the narrowed CHECK would
21
+ -- reject. dev had zero 'plane' rows when this was written; another stage
22
+ -- carrying them is a signal to migrate that data first, not to force through.
23
+ DO $$
24
+ DECLARE
25
+ offending bigint;
26
+ BEGIN
27
+ SELECT count(*) INTO offending
28
+ FROM public.work_item_external_refs
29
+ WHERE provider = 'plane';
30
+
31
+ IF offending > 0 THEN
32
+ RAISE EXCEPTION
33
+ 'work_item_external_refs still has % row(s) with provider=''plane''; migrate or delete them before narrowing the constraint',
34
+ offending;
35
+ END IF;
36
+ END
37
+ $$;
38
+
39
+ ALTER TABLE public.work_item_external_refs
40
+ DROP CONSTRAINT IF EXISTS work_item_external_refs_provider_allowed;
41
+
42
+ ALTER TABLE public.work_item_external_refs
43
+ ADD CONSTRAINT work_item_external_refs_provider_allowed
44
+ CHECK (provider IN ('thinkwork', 'lastmile', 'linear', 'twenty'));
45
+
46
+ COMMIT;
@@ -0,0 +1,9 @@
1
+ -- Brain API keys: display suffix + expiry on tenant_mcp_twin_keys.
2
+ -- Hand-rolled (mirrors 0274 convention; not registered in meta/_journal.json).
3
+ -- Apply via: psql "$DATABASE_URL" -f drizzle/0281_tenant_mcp_twin_keys_expiry_suffix.sql
4
+ -- creates-column: public.tenant_mcp_twin_keys.key_suffix
5
+ -- creates-column: public.tenant_mcp_twin_keys.expires_at
6
+
7
+ ALTER TABLE public.tenant_mcp_twin_keys
8
+ ADD COLUMN IF NOT EXISTS key_suffix text,
9
+ ADD COLUMN IF NOT EXISTS expires_at timestamptz;
@@ -0,0 +1,24 @@
1
+ -- Brain API keys: per-key grants (security groups + KB collections) on
2
+ -- tenant_mcp_twin_keys — the write side of key manifest v2
3
+ -- (twin-mcp-keys/v2; reader is company-brain brain-mcp/src/auth.ts).
4
+ -- Hand-rolled (mirrors 0274/0281 convention; not registered in
5
+ -- meta/_journal.json).
6
+ -- Apply via: psql "$DATABASE_URL" -f drizzle/0282_tenant_mcp_twin_keys_grants.sql
7
+ -- creates-column: public.tenant_mcp_twin_keys.security_groups
8
+ -- creates-column: public.tenant_mcp_twin_keys.kb_collections
9
+
10
+ ALTER TABLE public.tenant_mcp_twin_keys
11
+ ADD COLUMN IF NOT EXISTS security_groups text[] NOT NULL DEFAULT ARRAY[]::text[],
12
+ ADD COLUMN IF NOT EXISTS kb_collections text[] NOT NULL DEFAULT ARRAY[]::text[];
13
+
14
+ -- The platform-provisioned connector key ("default") backs the console
15
+ -- proxy and must never be narrowed by this migration: grandfather every
16
+ -- active one to the wildcard grant that re-provisioning would write
17
+ -- anyway. User-minted keys stay empty = PUBLIC graph only, no KB.
18
+ UPDATE public.tenant_mcp_twin_keys
19
+ SET security_groups = ARRAY['*']::text[],
20
+ kb_collections = ARRAY['*']::text[]
21
+ WHERE name = 'default'
22
+ AND revoked_at IS NULL
23
+ AND security_groups = ARRAY[]::text[]
24
+ AND kb_collections = ARRAY[]::text[];