thinkwork-cli 0.12.11 → 0.12.15

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 (474) hide show
  1. package/README.md +42 -38
  2. package/dist/{api-client-ASJWIG3Z.js → api-client-4VT3FWOH.js} +1 -1
  3. package/dist/{chunk-JEHV35EU.js → chunk-H7AB42ES.js} +340 -30
  4. package/dist/cli.js +22157 -9229
  5. package/dist/commands/enterprise/templates/deploy-repo/.github/workflows/deploy.yml +17 -6
  6. package/dist/commands/enterprise/templates/deploy-repo/docs/runbook.md +81 -9
  7. package/dist/commands/enterprise/templates/deploy-repo/scripts/apply-release.mjs +183 -21
  8. package/dist/commands/enterprise/templates/deploy-repo/scripts/smoke.mjs +1 -2
  9. package/dist/commands/enterprise/templates/deploy-repo/terraform/main.tf +286 -0
  10. package/dist/drizzle/0000_petite_marvel_apes.sql +1188 -0
  11. package/dist/drizzle/0001_milky_surge.sql +103 -0
  12. package/dist/drizzle/0002_aberrant_mattie_franklin.sql +41 -0
  13. package/dist/drizzle/0003_exotic_ogun.sql +3 -0
  14. package/dist/drizzle/0004_glamorous_magneto.sql +2 -0
  15. package/dist/drizzle/0005_ancient_nocturne.sql +2 -0
  16. package/dist/drizzle/0006_new_colonel_america.sql +2 -0
  17. package/dist/drizzle/0007_unique_external_task_id.sql +31 -0
  18. package/dist/drizzle/0008_external_task_id_column.sql +43 -0
  19. package/dist/drizzle/0009_evaluations.sql +64 -0
  20. package/dist/drizzle/0010_eval_agent_template.sql +2 -0
  21. package/dist/drizzle/0011_eval_run_template.sql +2 -0
  22. package/dist/drizzle/0012_eval_seed_unique.sql +16 -0
  23. package/dist/drizzle/0013_motionless_white_queen.sql +140 -0
  24. package/dist/drizzle/0014_wiki_aggregation.sql +11 -0
  25. package/dist/drizzle/0015_pg_trgm_alias_title_indexes.sql +9 -0
  26. package/dist/drizzle/0016_wiki_schema_drops.sql +24 -0
  27. package/dist/drizzle/0017_wiki_places.sql +46 -0
  28. package/dist/drizzle/0018_agent_workspace_overlay.sql +26 -0
  29. package/dist/drizzle/0018_cool_firebird.sql +24 -0
  30. package/dist/drizzle/0018_skill_runs.sql +84 -0
  31. package/dist/drizzle/0019_condemned_dragon_man.sql +95 -0
  32. package/dist/drizzle/0019_webhook_skill_runs.sql +58 -0
  33. package/dist/drizzle/0020_crazy_the_anarchist.sql +9 -0
  34. package/dist/drizzle/0020_mutation_idempotency.sql +64 -0
  35. package/dist/drizzle/0021_crm_work_links.sql +76 -0
  36. package/dist/drizzle/0021_skill_runs_completion_hmac.sql +33 -0
  37. package/dist/drizzle/0022_add_billing_tables.sql +70 -0
  38. package/dist/drizzle/0022_seed_thinkwork_admin_permissions.sql +160 -0
  39. package/dist/drizzle/0022_stripe_billing_indexes.sql +48 -0
  40. package/dist/drizzle/0023_tenants_deactivation.sql +27 -0
  41. package/dist/drizzle/0024_tenant_mcp_admin_keys.sql +63 -0
  42. package/dist/drizzle/0025_v1_agent_architecture.sql +182 -0
  43. package/dist/drizzle/0026_thread_turns_add_kind.sql +28 -0
  44. package/dist/drizzle/0027_capability_catalog_and_manifests.sql +219 -0
  45. package/dist/drizzle/0028_aws_s3_extension.sql +26 -0
  46. package/dist/drizzle/0029_collapse_execution_types.sql +42 -0
  47. package/dist/drizzle/0030_retire_composition_primitives.sql +48 -0
  48. package/dist/drizzle/0031_thread_cleanup_drops.sql +131 -0
  49. package/dist/drizzle/0032_add_browser_automation_template_config.sql +24 -0
  50. package/dist/drizzle/0033_agent_operation_leases.sql +32 -0
  51. package/dist/drizzle/0034_agent_workspace_events.sql +116 -0
  52. package/dist/drizzle/0035_workspace_review_decisions.sql +19 -0
  53. package/dist/drizzle/0036_user_scoped_memory_wiki.sql +152 -0
  54. package/dist/drizzle/0037_user_profile_operating_model.sql +34 -0
  55. package/dist/drizzle/0042_agent_runtime_selector.sql +41 -0
  56. package/dist/drizzle/0043_wiki_search_tsv_tokenization.sql +48 -0
  57. package/dist/drizzle/0044_add_web_search_template_config.sql +7 -0
  58. package/dist/drizzle/0045_add_send_email_template_config.sql +7 -0
  59. package/dist/drizzle/0046_tenant_mcp_context_tools.sql +26 -0
  60. package/dist/drizzle/0047_add_context_engine_template_config.sql +7 -0
  61. package/dist/drizzle/0048_tenant_context_provider_settings.sql +22 -0
  62. package/dist/drizzle/0050_brain_v0_entity_subtype.sql +29 -0
  63. package/dist/drizzle/0051_brain_v0_tenant_entity_pages.sql +170 -0
  64. package/dist/drizzle/0052_brain_v0_external_refs.sql +41 -0
  65. package/dist/drizzle/0053_brain_v0_unresolved_mentions_subtype.sql +48 -0
  66. package/dist/drizzle/0054_wiki_compile_jobs_input.sql +28 -0
  67. package/dist/drizzle/0055_routines_stepfunctions_substrate.sql +202 -0
  68. package/dist/drizzle/0056_routine_step_events_dedup_idx.sql +25 -0
  69. package/dist/drizzle/0057_archive_legacy_python_routines.sql +36 -0
  70. package/dist/drizzle/0058_routines_visibility_and_owning_agent.sql +61 -0
  71. package/dist/drizzle/0061_routine_execution_asl_version_id.sql +29 -0
  72. package/dist/drizzle/0062_migrate_pi_to_flue.sql +110 -0
  73. package/dist/drizzle/0063_threads_session_data.sql +23 -0
  74. package/dist/drizzle/0064_tenant_credentials.sql +65 -0
  75. package/dist/drizzle/0067_thinkwork_computers_phase_one.sql +174 -0
  76. package/dist/drizzle/0068_drop_system_workflows_and_activation.sql +115 -0
  77. package/dist/drizzle/0069_compliance_schema.sql +364 -0
  78. package/dist/drizzle/0070_compliance_aurora_roles.sql +171 -0
  79. package/dist/drizzle/0072_threads_computer_ownership.sql +24 -0
  80. package/dist/drizzle/0073_compliance_tenant_anchor_state.sql +105 -0
  81. package/dist/drizzle/0074_compliance_event_hash_index.sql +49 -0
  82. package/dist/drizzle/0075_scheduled_jobs_computer_ownership.sql +27 -0
  83. package/dist/drizzle/0076_scheduled_jobs_marco_backfill.sql +69 -0
  84. package/dist/drizzle/0077_computers_primary_agent_id.sql +38 -0
  85. package/dist/drizzle/0078_tenant_customize_catalog.sql +46 -0
  86. package/dist/drizzle/0079_seed_tenant_customize_catalog.sql +53 -0
  87. package/dist/drizzle/0081_routines_catalog_slug.sql +42 -0
  88. package/dist/drizzle/0082_messages_parts_jsonb.sql +52 -0
  89. package/dist/drizzle/0083_computer_runbooks.sql +103 -0
  90. package/dist/drizzle/0084_artifacts_favorited_at.sql +32 -0
  91. package/dist/drizzle/0085_seed_thinkwork_computer_default_template.sql +46 -0
  92. package/dist/drizzle/0086_update_default_template_models.sql +19 -0
  93. package/dist/drizzle/0087_retire_oss_connectors.sql +77 -0
  94. package/dist/drizzle/0088_compliance_event_types_finance_pilot.sql +37 -0
  95. package/dist/drizzle/0089_remove_maniflow_eval_seeds.sql +81 -0
  96. package/dist/drizzle/0089_wiki_schema_extraction.sql +315 -0
  97. package/dist/drizzle/0090_brain_schema_extraction.sql +274 -0
  98. package/dist/drizzle/0091_drop_wiki_brain_compat_views.sql +118 -0
  99. package/dist/drizzle/0092_finish_oss_connector_retirement.sql +97 -0
  100. package/dist/drizzle/0093_eval_runs_scheduled_job_id.sql +23 -0
  101. package/dist/drizzle/0094_slack_workspace_app.sql +140 -0
  102. package/dist/drizzle/0095_eval_runs_computer_id.sql +22 -0
  103. package/dist/drizzle/0096_true_redteam_eval_seed_cleanup.sql +67 -0
  104. package/dist/drizzle/0097_shared_computers.sql +191 -0
  105. package/dist/drizzle/0098_business_ontology.sql +587 -0
  106. package/dist/drizzle/0099_thread_idle_learning.sql +145 -0
  107. package/dist/drizzle/0100_ontology_gated_brain_dynamic_subtypes.sql +7 -0
  108. package/dist/drizzle/0101_ontology_gated_unresolved_mentions_dynamic_subtypes.sql +7 -0
  109. package/dist/drizzle/0102_wiki_brain_owner_repair.sql +87 -0
  110. package/dist/drizzle/0103_brain_section_source_trigger_repair.sql +75 -0
  111. package/dist/drizzle/0104_expand_seed_ontology_for_user_memory.sql +166 -0
  112. package/dist/drizzle/0105_spaces_domain.sql +349 -0
  113. package/dist/drizzle/0106_expand_seed_ontology_for_triples.sql +173 -0
  114. package/dist/drizzle/0106_space_threads_participants.sql +197 -0
  115. package/dist/drizzle/0107_linked_task_mirror.sql +245 -0
  116. package/dist/drizzle/0108_message_mentions.sql +95 -0
  117. package/dist/drizzle/0109_space_owned_threads.sql +217 -0
  118. package/dist/drizzle/0110_thread_participant_read_state.sql +21 -0
  119. package/dist/drizzle/0111_agents_tenant_name_unique.sql +38 -0
  120. package/dist/drizzle/0112_recast_spaces_as_contextual_workrooms.sql +138 -0
  121. package/dist/drizzle/0113_agents_own_runtime_fields.sql +48 -0
  122. package/dist/drizzle/0114_migrate_templates_to_agents_and_spaces.sql +361 -0
  123. package/dist/drizzle/0115_remove_computer_eval_template_dependencies.sql +69 -0
  124. package/dist/drizzle/0116_backfill_thread_participants_access.sql +126 -0
  125. package/dist/drizzle/0117_space_access_mode.sql +40 -0
  126. package/dist/drizzle/0118_normalize_tenant_member_principal_type.sql +41 -0
  127. package/dist/drizzle/0119_space_knowledge_bases.sql +126 -0
  128. package/dist/drizzle/0120_space_automations.sql +58 -0
  129. package/dist/drizzle/0121_drop_computer_runbooks.sql +26 -0
  130. package/dist/drizzle/0122_space_email_triggers.sql +24 -0
  131. package/dist/drizzle/0123_single_platform_agent_and_overrides.sql +58 -0
  132. package/dist/drizzle/0124_thread_turns_finalized_at.sql +17 -0
  133. package/dist/drizzle/0125_drop_space_agent_assignments.sql +42 -0
  134. package/dist/drizzle/0126_migrate_flue_to_pi.sql +42 -0
  135. package/dist/drizzle/0127_runtime_type_observability.sql +28 -0
  136. package/dist/drizzle/0128_drop_eval_test_cases_agent_id.sql +37 -0
  137. package/dist/drizzle/0129_drop_code_factory_tables.sql +43 -0
  138. package/dist/drizzle/0129_eval_results_system_prompt.sql +30 -0
  139. package/dist/drizzle/0130_drop_teams_and_team_id_columns.sql +54 -0
  140. package/dist/drizzle/0131_drop_skill_catalog_and_tenant_skills.sql +33 -0
  141. package/dist/drizzle/0132_drop_computer_tables.sql +31 -0
  142. package/dist/drizzle/0133_drop_seed_view_tombstones.sql +79 -0
  143. package/dist/drizzle/0133_thread_turns_system_prompt.sql +22 -0
  144. package/dist/drizzle/0134_drop_dead_agent_runtime_tables.sql +53 -0
  145. package/dist/drizzle/0135_native_checklist_linked_tasks.sql +48 -0
  146. package/dist/drizzle/0136_goal_ledger.sql +55 -0
  147. package/dist/drizzle/0136_space_email_trigger_status.sql +66 -0
  148. package/dist/drizzle/0137_thread_participant_pins.sql +25 -0
  149. package/dist/drizzle/0138_users_cognito_sub.sql +30 -0
  150. package/dist/drizzle/0139_mobile_turn_client_id.sql +23 -0
  151. package/dist/drizzle/0140_workspace_folder_names.sql +36 -0
  152. package/dist/drizzle/0141_eval_runs_desktop_pi_provenance.sql +31 -0
  153. package/dist/drizzle/0142_pi_only_agent_runtime.sql +61 -0
  154. package/dist/drizzle/0143_add_web_extract_builtin_config.sql +28 -0
  155. package/dist/drizzle/0144_skill_catalog_index.sql +40 -0
  156. package/dist/drizzle/0145_knowledge_graph_thread_ingest.sql +512 -0
  157. package/dist/drizzle/0146_knowledge_graph_source_scope.sql +413 -0
  158. package/dist/drizzle/0147_knowledge_graph_scope_trigger_qualification.sql +211 -0
  159. package/dist/drizzle/0148_user_cost_attribution.sql +171 -0
  160. package/dist/drizzle/0149_managed_mcp_servers.sql +64 -0
  161. package/dist/drizzle/0149_user_model_approvals.sql +89 -0
  162. package/dist/drizzle/0150_bootstrap_first_admin_claim.sql +11 -0
  163. package/dist/drizzle/0151_managed_deployments.sql +91 -0
  164. package/dist/drizzle/0152_agent_profiles.sql +81 -0
  165. package/dist/drizzle/0153_message_mentions_agent_profile.sql +9 -0
  166. package/dist/drizzle/0154_customer_deployment_sessions.sql +61 -0
  167. package/dist/drizzle/0155_tenant_model_catalog.sql +152 -0
  168. package/dist/drizzle/0156_bootstrap_credential_leases.sql +52 -0
  169. package/dist/drizzle/0157_knowledge_graph_observations_source.sql +79 -0
  170. package/dist/drizzle/0158_pending_user_questions.sql +80 -0
  171. package/dist/drizzle/0158_wiki_tenant_scope.sql +38 -0
  172. package/dist/drizzle/0159_agent_profiles_space_local.sql +49 -0
  173. package/dist/drizzle/0159_application_plugins.sql +193 -0
  174. package/dist/drizzle/0159_eval_scoring_version.sql +46 -0
  175. package/dist/drizzle/0160_compliance_event_types_plugins.sql +37 -0
  176. package/dist/drizzle/0160_eval_datasets.sql +75 -0
  177. package/dist/drizzle/0160_eval_results_thread_turn.sql +35 -0
  178. package/dist/drizzle/0161_eval_run_pinning.sql +54 -0
  179. package/dist/drizzle/0161_tenant_mcp_servers_plugin_source.sql +62 -0
  180. package/dist/drizzle/0162_eval_result_override.sql +49 -0
  181. package/dist/drizzle/0163_eval_replay_tool_allowlist.sql +50 -0
  182. package/dist/drizzle/0164_eval_replay_tool_override_mode.sql +52 -0
  183. package/dist/drizzle/0165_plugin_premium_entitlements.sql +153 -0
  184. package/dist/drizzle/0166_company_brain_substrate_contract.sql +386 -0
  185. package/dist/drizzle/0167_company_brain_artifact_manifest_runtime.sql +85 -0
  186. package/dist/drizzle/0168_eval_skill_gate.sql +44 -0
  187. package/dist/drizzle/0169_release_update_jobs.sql +67 -0
  188. package/dist/drizzle/0170_email_channel_plugin.sql +291 -0
  189. package/dist/drizzle/0171_linked_task_external_providers.sql +30 -0
  190. package/dist/drizzle/0172_email_channel_sendgrid_provider.sql +8 -0
  191. package/dist/drizzle/0173_auth_provider_resources.sql +83 -0
  192. package/dist/drizzle/0174_workos_auth_bridges.sql +37 -0
  193. package/dist/drizzle/0175_workos_auth_sessions.sql +38 -0
  194. package/dist/drizzle/0176_n8n_agent_step_runs.sql +107 -0
  195. package/dist/drizzle/0177_workflow_control_plane.sql +281 -0
  196. package/dist/drizzle/0178_workflow_backfill_existing_routines.sql +525 -0
  197. package/dist/drizzle/0179_tenant_goal_budget_settings.sql +21 -0
  198. package/dist/drizzle/0180_skill_drafts.sql +89 -0
  199. package/dist/drizzle/0181_skill_draft_publish_status.sql +21 -0
  200. package/dist/drizzle/0182_agent_loops.sql +260 -0
  201. package/dist/drizzle/0183_okf_artifact_manifests.sql +52 -0
  202. package/dist/drizzle/0184_skill_catalog_trust_cache.sql +35 -0
  203. package/dist/drizzle/0185_agent_loop_space.sql +16 -0
  204. package/dist/drizzle/0186_tenant_mcp_runtime_metadata.sql +10 -0
  205. package/dist/drizzle/0187_native_work_items.sql +220 -0
  206. package/dist/drizzle/0188_company_etl_plugin_rename.sql +99 -0
  207. package/dist/drizzle/0189_trace_cost_substrate.sql +247 -0
  208. package/dist/drizzle/0190_billing_export_reconciliation.sql +101 -0
  209. package/dist/drizzle/0191_open_engine_work_item_queue.sql +66 -0
  210. package/dist/drizzle/0192_work_item_labels.sql +44 -0
  211. package/dist/drizzle/0193_work_item_documents.sql +31 -0
  212. package/dist/drizzle/0194_memory_retain_attempts.sql +103 -0
  213. package/dist/drizzle/0194_work_item_comments.sql +35 -0
  214. package/dist/drizzle/0195_plugin_app_overlays.sql +45 -0
  215. package/dist/drizzle/0196_pi_extensions.sql +118 -0
  216. package/dist/drizzle/0197_eval_profiles.sql +150 -0
  217. package/dist/drizzle/0198_eval_runs_unstable.sql +27 -0
  218. package/dist/drizzle/0199_eval_runs_cost_partial.sql +27 -0
  219. package/dist/drizzle/meta/_journal.json +160 -0
  220. package/dist/plugins/README.md +162 -0
  221. package/dist/plugins/catalog/package.json +40 -0
  222. package/dist/plugins/catalog/scripts/build-catalog.ts +120 -0
  223. package/dist/plugins/catalog/scripts/generate-plugin-registry.ts +144 -0
  224. package/dist/plugins/catalog/src/__tests__/build-catalog.test.ts +86 -0
  225. package/dist/plugins/catalog/src/__tests__/catalog.test.ts +308 -0
  226. package/dist/plugins/catalog/src/__tests__/contracts.test.ts +861 -0
  227. package/dist/plugins/catalog/src/__tests__/plugin-package.test.ts +124 -0
  228. package/dist/plugins/catalog/src/__tests__/plugin-registry.test.ts +120 -0
  229. package/dist/plugins/catalog/src/catalog.ts +434 -0
  230. package/dist/plugins/catalog/src/contracts.ts +1498 -0
  231. package/dist/plugins/catalog/src/index.ts +4 -0
  232. package/dist/plugins/catalog/src/plugin-package.ts +171 -0
  233. package/dist/plugins/catalog/src/registry/generated-first-party.ts +76 -0
  234. package/dist/plugins/catalog/src/registry/index.ts +1 -0
  235. package/dist/plugins/catalog/tsconfig.json +8 -0
  236. package/dist/plugins/company-brain/README.md +37 -0
  237. package/dist/plugins/company-brain/package.json +33 -0
  238. package/dist/plugins/company-brain/runtime/cognee/Dockerfile +11 -0
  239. package/dist/plugins/company-brain/smoke/cognee-managed-app-smoke.mjs +458 -0
  240. package/dist/plugins/company-brain/smoke/cognee-memory-cutover-smoke.mjs +539 -0
  241. package/dist/plugins/company-brain/smoke/company-brain-context-engine-smoke.mjs +312 -0
  242. package/dist/plugins/company-brain/smoke/company-brain-operations-smoke.mjs +449 -0
  243. package/dist/plugins/company-brain/smoke/company-brain-plugin-smoke.mjs +655 -0
  244. package/dist/plugins/company-brain/smoke/hindsight-memory-isolation-smoke.mjs +474 -0
  245. package/dist/plugins/company-brain/src/api/cognee-client.ts +896 -0
  246. package/dist/plugins/company-brain/src/api/cognee-cluster-identity.ts +49 -0
  247. package/dist/plugins/company-brain/src/api/cognee-memory-scope.ts +84 -0
  248. package/dist/plugins/company-brain/src/api/context-engine-provider.ts +888 -0
  249. package/dist/plugins/company-brain/src/api/migration.ts +665 -0
  250. package/dist/plugins/company-brain/src/deployment/cognee-managed-app.ts +396 -0
  251. package/dist/plugins/company-brain/src/index.ts +62 -0
  252. package/dist/plugins/company-brain/src/manifest.ts +112 -0
  253. package/dist/plugins/company-brain/terraform/cognee/README.md +263 -0
  254. package/dist/plugins/company-brain/terraform/cognee/main.tf +766 -0
  255. package/dist/plugins/company-brain/terraform/cognee/outputs.tf +144 -0
  256. package/dist/plugins/company-brain/terraform/cognee/variables.tf +402 -0
  257. package/dist/plugins/company-brain/test/api/cognee-client.test.ts +562 -0
  258. package/dist/plugins/company-brain/test/api/cognee-memory-scope.test.ts +74 -0
  259. package/dist/plugins/company-brain/test/api/context-engine-provider.test.ts +447 -0
  260. package/dist/plugins/company-brain/test/api/migration.test.ts +465 -0
  261. package/dist/plugins/company-brain/test/manifest.test.ts +95 -0
  262. package/dist/plugins/company-brain/tsconfig.json +8 -0
  263. package/dist/plugins/company-data/README.md +49 -0
  264. package/dist/plugins/company-data/package.json +21 -0
  265. package/dist/plugins/company-data/src/index.ts +30 -0
  266. package/dist/plugins/company-data/src/manifest.ts +26 -0
  267. package/dist/plugins/company-data/test/manifest.test.ts +116 -0
  268. package/dist/plugins/company-data/tsconfig.json +8 -0
  269. package/dist/plugins/company-etl/README.md +46 -0
  270. package/dist/plugins/company-etl/package.json +21 -0
  271. package/dist/plugins/company-etl/src/index.ts +29 -0
  272. package/dist/plugins/company-etl/src/manifest.ts +26 -0
  273. package/dist/plugins/company-etl/test/manifest.test.ts +108 -0
  274. package/dist/plugins/company-etl/tsconfig.json +8 -0
  275. package/dist/plugins/email-channel/README.md +41 -0
  276. package/dist/plugins/email-channel/package.json +22 -0
  277. package/dist/plugins/email-channel/src/index.ts +36 -0
  278. package/dist/plugins/email-channel/src/manifest.ts +44 -0
  279. package/dist/plugins/email-channel/src/provider-contract.ts +36 -0
  280. package/dist/plugins/email-channel/test/manifest.test.ts +119 -0
  281. package/dist/plugins/email-channel/tsconfig.json +8 -0
  282. package/dist/plugins/lastmile/README.md +50 -0
  283. package/dist/plugins/lastmile/package.json +23 -0
  284. package/dist/plugins/lastmile/smoke/lastmile-plugin-smoke.mjs +661 -0
  285. package/dist/plugins/lastmile/src/api/tasks-adapter.ts +572 -0
  286. package/dist/plugins/lastmile/src/discovery.fixture.ts +64 -0
  287. package/dist/plugins/lastmile/src/index.ts +46 -0
  288. package/dist/plugins/lastmile/src/manifest.ts +139 -0
  289. package/dist/plugins/lastmile/test/api/tasks-adapter.test.ts +266 -0
  290. package/dist/plugins/lastmile/test/discovery.test.ts +88 -0
  291. package/dist/plugins/lastmile/tsconfig.json +8 -0
  292. package/dist/plugins/n8n/README.md +201 -0
  293. package/dist/plugins/n8n/n8n-app/README.md +33 -0
  294. package/dist/plugins/n8n/n8n-app/package.json +23 -0
  295. package/dist/plugins/n8n/n8n-app/src/application-config.ts +45 -0
  296. package/dist/plugins/n8n/n8n-app/src/front-components/thinkwork-workflows.front-component.tsx +970 -0
  297. package/dist/plugins/n8n/n8n-app/src/lib/n8n-app-data.ts +190 -0
  298. package/dist/plugins/n8n/n8n-app/src/vite-env.d.ts +7 -0
  299. package/dist/plugins/n8n/n8n-app/tsconfig.json +15 -0
  300. package/dist/plugins/n8n/package.json +35 -0
  301. package/dist/plugins/n8n/runtime/Dockerfile +18 -0
  302. package/dist/plugins/n8n/runtime/n8n-task-runners.json +14 -0
  303. package/dist/plugins/n8n/runtime/n8n-task-runners.json.template +14 -0
  304. package/dist/plugins/n8n/runtime/package-lock.json +13 -0
  305. package/dist/plugins/n8n/runtime/package.json +7 -0
  306. package/dist/plugins/n8n/scripts/sync-thinkwork-app.mjs +268 -0
  307. package/dist/plugins/n8n/smoke/README.md +95 -0
  308. package/dist/plugins/n8n/smoke/n8n-agent-step-bridge-smoke.mjs +866 -0
  309. package/dist/plugins/n8n/smoke/n8n-integrated-app-smoke.mjs +262 -0
  310. package/dist/plugins/n8n/smoke/n8n-managed-app-smoke.mjs +409 -0
  311. package/dist/plugins/n8n/smoke/n8n-mcp-smoke.mjs +624 -0
  312. package/dist/plugins/n8n/src/deployment/image-build.ts +172 -0
  313. package/dist/plugins/n8n/src/deployment/managed-app.ts +429 -0
  314. package/dist/plugins/n8n/src/index.ts +79 -0
  315. package/dist/plugins/n8n/src/manifest.ts +403 -0
  316. package/dist/plugins/n8n/src/package-config.ts +186 -0
  317. package/dist/plugins/n8n/src/skills/n8n-workflow-operator/SKILL.md +76 -0
  318. package/dist/plugins/n8n/src/skills/n8n-workflow-operator/references/mcp-tooling.md +40 -0
  319. package/dist/plugins/n8n/src/skills/n8n-workflow-operator/references/validation-and-handoff.md +40 -0
  320. package/dist/plugins/n8n/src/skills/n8n-workflow-operator/references/workflow-authoring.md +45 -0
  321. package/dist/plugins/n8n/terraform/n8n/README.md +113 -0
  322. package/dist/plugins/n8n/terraform/n8n/main.tf +918 -0
  323. package/dist/plugins/n8n/terraform/n8n/outputs.tf +124 -0
  324. package/dist/plugins/n8n/terraform/n8n/scripts/sync-database.py +250 -0
  325. package/dist/plugins/n8n/terraform/n8n/scripts/test_sync_database.py +55 -0
  326. package/dist/plugins/n8n/terraform/n8n/variables.tf +354 -0
  327. package/dist/plugins/n8n/test/image-build.test.ts +118 -0
  328. package/dist/plugins/n8n/test/integrated-app-contract.test.ts +353 -0
  329. package/dist/plugins/n8n/test/manifest.test.ts +278 -0
  330. package/dist/plugins/n8n/test/package-config.test.ts +57 -0
  331. package/dist/plugins/n8n/tsconfig.json +8 -0
  332. package/dist/plugins/sendgrid/README.md +30 -0
  333. package/dist/plugins/sendgrid/package.json +22 -0
  334. package/dist/plugins/sendgrid/src/index.ts +36 -0
  335. package/dist/plugins/sendgrid/src/manifest.ts +37 -0
  336. package/dist/plugins/sendgrid/src/provider-contract.ts +14 -0
  337. package/dist/plugins/sendgrid/test/manifest.test.ts +80 -0
  338. package/dist/plugins/sendgrid/tsconfig.json +8 -0
  339. package/dist/plugins/twenty/README.md +78 -0
  340. package/dist/plugins/twenty/package.json +27 -0
  341. package/dist/plugins/twenty/scripts/__tests__/sync-thinkwork-app.test.mjs +67 -0
  342. package/dist/plugins/twenty/scripts/sync-thinkwork-app.mjs +185 -0
  343. package/dist/plugins/twenty/scripts/wire-thinkwork-workflow.mjs +658 -0
  344. package/dist/plugins/twenty/smoke/twenty-managed-app-smoke.mjs +359 -0
  345. package/dist/plugins/twenty/smoke/twenty-mcp-oauth-smoke.mjs +574 -0
  346. package/dist/plugins/twenty/src/api/cutover.ts +209 -0
  347. package/dist/plugins/twenty/src/deployment/managed-app.ts +253 -0
  348. package/dist/plugins/twenty/src/index.ts +55 -0
  349. package/dist/plugins/twenty/src/manifest.ts +259 -0
  350. package/dist/plugins/twenty/terraform/twenty/README.md +97 -0
  351. package/dist/plugins/twenty/terraform/twenty/main.tf +829 -0
  352. package/dist/plugins/twenty/terraform/twenty/outputs.tf +79 -0
  353. package/dist/plugins/twenty/terraform/twenty/variables.tf +268 -0
  354. package/dist/plugins/twenty/test/api/cutover.test.ts +183 -0
  355. package/dist/plugins/twenty/test/manifest.test.ts +463 -0
  356. package/dist/plugins/twenty/tsconfig.json +9 -0
  357. package/dist/plugins/twenty/twenty-app/.nvmrc +1 -0
  358. package/dist/plugins/twenty/twenty-app/README.md +148 -0
  359. package/dist/plugins/twenty/twenty-app/package.json +30 -0
  360. package/dist/plugins/twenty/twenty-app/src/application-config.ts +44 -0
  361. package/dist/plugins/twenty/twenty-app/src/constants/universal-identifiers.ts +18 -0
  362. package/dist/plugins/twenty/twenty-app/src/default-role.ts +24 -0
  363. package/dist/plugins/twenty/twenty-app/src/front-components/thinkwork-settings.front-component.tsx +299 -0
  364. package/dist/plugins/twenty/twenty-app/src/logic-functions/thinkwork-webhook.logic-function.ts +354 -0
  365. package/dist/plugins/twenty/twenty-app/tsconfig.json +14 -0
  366. package/dist/plugins/twenty/twenty-app/yarn.lock +4144 -0
  367. package/dist/plugins/workos-auth/package.json +22 -0
  368. package/dist/plugins/workos-auth/src/index.ts +30 -0
  369. package/dist/plugins/workos-auth/src/manifest.ts +40 -0
  370. package/dist/plugins/workos-auth/src/provider-contract.ts +39 -0
  371. package/dist/plugins/workos-auth/test/manifest.test.ts +94 -0
  372. package/dist/plugins/workos-auth/tsconfig.json +8 -0
  373. package/dist/scripts/bootstrap-workspace.sh +162 -0
  374. package/dist/scripts/post-deploy.sh +290 -0
  375. package/dist/terraform/examples/greenfield/main.tf +903 -75
  376. package/dist/terraform/examples/greenfield/terraform.tfvars.example +67 -8
  377. package/dist/terraform/modules/app/agentcore-code-interpreter/Dockerfile.sandbox-base +2 -2
  378. package/dist/terraform/modules/app/agentcore-code-interpreter/README.md +8 -9
  379. package/dist/terraform/modules/app/agentcore-code-interpreter/sandbox/sitecustomize.py +227 -0
  380. package/dist/terraform/modules/app/agentcore-code-interpreter/sandbox/test_sitecustomize.py +277 -0
  381. package/dist/terraform/modules/app/agentcore-memory/README.md +6 -6
  382. package/dist/terraform/modules/app/agentcore-memory/main.tf +1 -1
  383. package/dist/terraform/modules/app/agentcore-memory/scripts/create_or_find_memory.sh +40 -9
  384. package/dist/terraform/modules/app/agentcore-pi/README.md +61 -0
  385. package/dist/terraform/modules/app/agentcore-pi/main.tf +453 -0
  386. package/dist/terraform/modules/app/agentcore-pi/outputs.tf +38 -0
  387. package/dist/terraform/modules/app/agentcore-pi/variables.tf +145 -0
  388. package/dist/terraform/modules/app/agentcore-platform/main.tf +83 -0
  389. package/dist/terraform/modules/app/agentcore-runtime/main.tf +9 -11
  390. package/dist/terraform/modules/app/appsync-subscriptions/main.tf +5 -1
  391. package/dist/terraform/modules/app/customer-domain/main.tf +483 -0
  392. package/dist/terraform/modules/app/deployment-control-plane/README.md +47 -0
  393. package/dist/terraform/modules/app/deployment-control-plane/buildspec.yml +24 -0
  394. package/dist/terraform/modules/app/deployment-control-plane/main.tf +614 -0
  395. package/dist/terraform/modules/app/deployment-control-plane/outputs.tf +54 -0
  396. package/dist/terraform/modules/app/deployment-control-plane/runner.py +4720 -0
  397. package/dist/terraform/modules/app/deployment-control-plane/test_runner_bundle.py +3026 -0
  398. package/dist/terraform/modules/app/deployment-control-plane/variables.tf +96 -0
  399. package/dist/terraform/modules/app/hindsight-memory/README.md +25 -23
  400. package/dist/terraform/modules/app/hindsight-memory/main.tf +26 -2
  401. package/dist/terraform/modules/app/lambda-api/eval-fanout.tf +17 -50
  402. package/dist/terraform/modules/app/lambda-api/handlers.tf +1290 -679
  403. package/dist/terraform/modules/app/lambda-api/iam-grouped.tf +933 -0
  404. package/dist/terraform/modules/app/lambda-api/main.tf +14 -527
  405. package/dist/terraform/modules/app/lambda-api/mcp-oauth.tf +3 -19
  406. package/dist/terraform/modules/app/lambda-api/outputs.tf +50 -6
  407. package/dist/terraform/modules/app/lambda-api/runtime-config.tf +163 -0
  408. package/dist/terraform/modules/app/lambda-api/slack-app-secrets.tf +3 -1
  409. package/dist/terraform/modules/app/lambda-api/stripe-secrets.tf +3 -1
  410. package/dist/terraform/modules/app/lambda-api/variables.tf +240 -53
  411. package/dist/terraform/modules/app/lambda-api/workspace-events.tf +2 -25
  412. package/dist/terraform/modules/app/ses-email/main.tf +143 -30
  413. package/dist/terraform/modules/app/static-site/main.tf +4 -3
  414. package/dist/terraform/modules/app/www-dns/main.tf +45 -5
  415. package/dist/terraform/modules/app/www-dns/outputs.tf +10 -0
  416. package/dist/terraform/modules/app/www-dns/variables.tf +24 -0
  417. package/dist/terraform/modules/data/aurora-postgres/main.tf +15 -1
  418. package/dist/terraform/modules/data/compliance-exports-bucket/main.tf +1 -1
  419. package/dist/terraform/modules/data/compliance-exports-bucket/variables.tf +6 -0
  420. package/dist/terraform/modules/foundation/cognito/main.tf +167 -11
  421. package/dist/terraform/modules/foundation/cognito/outputs.tf +5 -0
  422. package/dist/terraform/modules/foundation/cognito/variables.tf +110 -0
  423. package/dist/terraform/modules/foundation/vpc/main.tf +45 -3
  424. package/dist/terraform/modules/foundation/vpc/outputs.tf +20 -0
  425. package/dist/terraform/modules/foundation/vpc/variables.tf +18 -0
  426. package/dist/terraform/modules/thinkwork/README.md +71 -0
  427. package/dist/terraform/modules/thinkwork/main.tf +1325 -174
  428. package/dist/terraform/modules/thinkwork/outputs.tf +457 -24
  429. package/dist/terraform/modules/thinkwork/variables.tf +1169 -93
  430. package/dist/terraform/schema.graphql +82 -9
  431. package/dist/workspace-defaults/files/AGENTS.md +344 -0
  432. package/dist/workspace-defaults/files/CONTEXT.md +8 -0
  433. package/dist/workspace-defaults/files/GUARDRAILS.md +51 -0
  434. package/dist/workspace-defaults/files/MEMORY_GUIDE.md +65 -0
  435. package/dist/workspace-defaults/files/ROUTER.md +24 -0
  436. package/dist/workspace-defaults/files/SPACE.md +62 -0
  437. package/dist/workspace-defaults/files/TOOLS.md +65 -0
  438. package/dist/workspace-defaults/files/USER.md +40 -0
  439. package/dist/workspace-defaults/files/mcp.json +3 -0
  440. package/dist/workspace-defaults/files/memory/contacts.md +13 -0
  441. package/dist/workspace-defaults/files/memory/lessons.md +13 -0
  442. package/dist/workspace-defaults/files/memory/preferences.md +12 -0
  443. package/dist/workspace-defaults/files/skills/.gitkeep +1 -0
  444. package/dist/workspace-defaults/files/skills/artifact-builder/SKILL.md +79 -0
  445. package/dist/workspace-defaults/files/skills/artifact-builder/references/crm-dashboard.md +166 -0
  446. package/dist/workspace-defaults/files/skills/automation-loop-designer/SKILL.md +120 -0
  447. package/dist/workspace-defaults/files/skills/skill-creator/LICENSE.txt +202 -0
  448. package/dist/workspace-defaults/files/skills/skill-creator/SKILL.md +485 -0
  449. package/dist/workspace-defaults/files/skills/skill-creator/UPSTREAM.json +124 -0
  450. package/dist/workspace-defaults/files/skills/skill-creator/agents/analyzer.md +274 -0
  451. package/dist/workspace-defaults/files/skills/skill-creator/agents/comparator.md +202 -0
  452. package/dist/workspace-defaults/files/skills/skill-creator/agents/grader.md +223 -0
  453. package/dist/workspace-defaults/files/skills/skill-creator/assets/eval_review.html +146 -0
  454. package/dist/workspace-defaults/files/skills/skill-creator/eval-viewer/generate_review.py +471 -0
  455. package/dist/workspace-defaults/files/skills/skill-creator/eval-viewer/viewer.html +1325 -0
  456. package/dist/workspace-defaults/files/skills/skill-creator/references/schemas.md +430 -0
  457. package/dist/workspace-defaults/files/skills/skill-creator/scripts/__init__.py +0 -0
  458. package/dist/workspace-defaults/files/skills/skill-creator/scripts/aggregate_benchmark.py +401 -0
  459. package/dist/workspace-defaults/files/skills/skill-creator/scripts/generate_report.py +326 -0
  460. package/dist/workspace-defaults/files/skills/skill-creator/scripts/improve_description.py +247 -0
  461. package/dist/workspace-defaults/files/skills/skill-creator/scripts/package_skill.py +136 -0
  462. package/dist/workspace-defaults/files/skills/skill-creator/scripts/quick_validate.py +103 -0
  463. package/dist/workspace-defaults/files/skills/skill-creator/scripts/run_eval.py +310 -0
  464. package/dist/workspace-defaults/files/skills/skill-creator/scripts/run_loop.py +328 -0
  465. package/dist/workspace-defaults/files/skills/skill-creator/scripts/utils.py +47 -0
  466. package/package.json +1 -1
  467. package/dist/terraform/modules/app/agentcore-flue/README.md +0 -58
  468. package/dist/terraform/modules/app/agentcore-flue/main.tf +0 -323
  469. package/dist/terraform/modules/app/agentcore-flue/outputs.tf +0 -23
  470. package/dist/terraform/modules/app/agentcore-flue/variables.tf +0 -97
  471. package/dist/terraform/modules/app/computer-runtime/README.md +0 -15
  472. package/dist/terraform/modules/app/computer-runtime/main.tf +0 -406
  473. package/dist/terraform/modules/app/computer-runtime/outputs.tf +0 -75
  474. package/dist/terraform/modules/app/computer-runtime/variables.tf +0 -66
@@ -0,0 +1,84 @@
1
+ -- skill_runs — audit log + idempotency surface for composition invocations.
2
+ --
3
+ -- See docs/plans/2026-04-21-003-feat-composable-skills-with-learnings-plan.md
4
+ -- (Unit 4). This table is an audit log, NOT an execution substrate — runs
5
+ -- complete inside a single AgentCore Runtime session and only the final
6
+ -- outcome is recorded here.
7
+ --
8
+ -- Apply manually (no CI migration runner):
9
+ -- psql "$DATABASE_URL" -f packages/database-pg/drizzle/0018_skill_runs.sql
10
+ --
11
+ -- Drift detection:
12
+ -- bash scripts/db-migrate-manual.sh
13
+ --
14
+ -- Pre-migration invariant: no existing table named skill_runs.
15
+ -- SELECT to_regclass('public.skill_runs'); must return NULL.
16
+ --
17
+ -- creates: public.skill_runs
18
+ -- creates: public.uq_skill_runs_dedup_active
19
+
20
+ CREATE TABLE "skill_runs" (
21
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
22
+ "tenant_id" uuid NOT NULL,
23
+ "agent_id" uuid,
24
+ "invoker_user_id" uuid NOT NULL,
25
+ "skill_id" text NOT NULL,
26
+ "skill_version" integer NOT NULL DEFAULT 1,
27
+ "invocation_source" text NOT NULL,
28
+ "inputs" jsonb NOT NULL DEFAULT '{}'::jsonb,
29
+ "resolved_inputs" jsonb NOT NULL DEFAULT '{}'::jsonb,
30
+ "resolved_inputs_hash" text NOT NULL,
31
+ "status" text NOT NULL DEFAULT 'running',
32
+ "delivery_channels" jsonb NOT NULL DEFAULT '[]'::jsonb,
33
+ "started_at" timestamp with time zone NOT NULL DEFAULT now(),
34
+ "finished_at" timestamp with time zone,
35
+ "delivered_artifact_ref" jsonb,
36
+ "delete_at" timestamp with time zone NOT NULL DEFAULT (now() + interval '30 days'),
37
+ "feedback_signal" text,
38
+ "feedback_note" text,
39
+ "failure_reason" text,
40
+ "created_at" timestamp with time zone NOT NULL DEFAULT now(),
41
+ "updated_at" timestamp with time zone NOT NULL DEFAULT now(),
42
+ CONSTRAINT "retention_ceiling"
43
+ CHECK (delete_at <= started_at + interval '180 days'),
44
+ CONSTRAINT "status_allowed"
45
+ CHECK (status IN ('running','complete','failed','cancelled','invoker_deprovisioned','skipped_disabled','cost_bounded_error')),
46
+ CONSTRAINT "invocation_source_allowed"
47
+ CHECK (invocation_source IN ('chat','scheduled','catalog','webhook')),
48
+ CONSTRAINT "feedback_signal_allowed"
49
+ CHECK (feedback_signal IS NULL OR feedback_signal IN ('positive','negative'))
50
+ );
51
+ --> statement-breakpoint
52
+
53
+ ALTER TABLE "skill_runs" ADD CONSTRAINT "skill_runs_tenant_id_tenants_id_fk"
54
+ FOREIGN KEY ("tenant_id") REFERENCES "public"."tenants"("id")
55
+ ON DELETE no action ON UPDATE no action;
56
+ --> statement-breakpoint
57
+
58
+ ALTER TABLE "skill_runs" ADD CONSTRAINT "skill_runs_agent_id_agents_id_fk"
59
+ FOREIGN KEY ("agent_id") REFERENCES "public"."agents"("id")
60
+ ON DELETE no action ON UPDATE no action;
61
+ --> statement-breakpoint
62
+
63
+ CREATE INDEX "idx_skill_runs_tenant_started" ON "skill_runs"
64
+ USING btree ("tenant_id","started_at");
65
+ --> statement-breakpoint
66
+
67
+ CREATE INDEX "idx_skill_runs_invoker" ON "skill_runs"
68
+ USING btree ("invoker_user_id");
69
+ --> statement-breakpoint
70
+
71
+ CREATE INDEX "idx_skill_runs_tenant_skill" ON "skill_runs"
72
+ USING btree ("tenant_id","skill_id");
73
+ --> statement-breakpoint
74
+
75
+ CREATE INDEX "idx_skill_runs_delete_at" ON "skill_runs"
76
+ USING btree ("delete_at");
77
+ --> statement-breakpoint
78
+
79
+ -- Dedup: only rows still in 'running' status can collide. Once a run
80
+ -- flips to a terminal status its slot is freed and a re-invocation with
81
+ -- the same inputs inserts cleanly as a fresh reconciler tick.
82
+ CREATE UNIQUE INDEX "uq_skill_runs_dedup_active" ON "skill_runs"
83
+ USING btree ("tenant_id","invoker_user_id","skill_id","resolved_inputs_hash")
84
+ WHERE status = 'running';
@@ -0,0 +1,95 @@
1
+ -- NOTE: mutation_idempotency table + FK + indexes were intentionally
2
+ -- stripped from this generated migration. They were already applied to every
3
+ -- stage by the hand-rolled drizzle/0020_mutation_idempotency.sql that shipped
4
+ -- in PR #405 (65da2f6); the drizzle journal simply wasn't refreshed, so when
5
+ -- db:generate ran for the sandbox schema it re-included the table. Keeping
6
+ -- them here would make this migration fail with "relation already exists" on
7
+ -- every environment. The 0019 snapshot file does include mutation_idempotency
8
+ -- so future db:generate runs stay consistent.
9
+ CREATE TABLE "sandbox_invocations" (
10
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
11
+ "tenant_id" uuid NOT NULL,
12
+ "run_id" uuid,
13
+ "agent_id" uuid,
14
+ "user_id" uuid NOT NULL,
15
+ "template_id" text,
16
+ "tool_call_id" text,
17
+ "session_id" text,
18
+ "environment_id" text NOT NULL,
19
+ "invocation_source" text,
20
+ "started_at" timestamp with time zone DEFAULT now() NOT NULL,
21
+ "finished_at" timestamp with time zone,
22
+ "duration_ms" integer,
23
+ "exit_status" text,
24
+ "stdout_bytes" bigint,
25
+ "stderr_bytes" bigint,
26
+ "stdout_truncated" boolean DEFAULT false NOT NULL,
27
+ "stderr_truncated" boolean DEFAULT false NOT NULL,
28
+ "peak_memory_mb" integer,
29
+ "outbound_hosts" jsonb,
30
+ "executed_code_hash" text,
31
+ "failure_reason" text,
32
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
33
+ "delete_at" timestamp with time zone DEFAULT now() + interval '30 days' NOT NULL,
34
+ CONSTRAINT "sandbox_invocations_retention_ceiling" CHECK ("sandbox_invocations"."delete_at" <= "sandbox_invocations"."started_at" + interval '180 days'),
35
+ CONSTRAINT "sandbox_invocations_exit_status_allowed" CHECK ("sandbox_invocations"."exit_status" IS NULL OR "sandbox_invocations"."exit_status" IN ('ok','error','timeout','oom','cap_exceeded','provisioning','connection_revoked')),
36
+ CONSTRAINT "sandbox_invocations_source_allowed" CHECK ("sandbox_invocations"."invocation_source" IS NULL OR "sandbox_invocations"."invocation_source" IN ('chat','scheduled','composition'))
37
+ );
38
+ --> statement-breakpoint
39
+ CREATE TABLE "sandbox_agent_hourly_counters" (
40
+ "tenant_id" uuid NOT NULL,
41
+ "agent_id" uuid NOT NULL,
42
+ "utc_hour" timestamp with time zone NOT NULL,
43
+ "invocations_count" integer DEFAULT 0 NOT NULL,
44
+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL,
45
+ CONSTRAINT "sandbox_agent_hourly_counters_tenant_id_agent_id_utc_hour_pk" PRIMARY KEY("tenant_id","agent_id","utc_hour")
46
+ );
47
+ --> statement-breakpoint
48
+ CREATE TABLE "sandbox_tenant_daily_counters" (
49
+ "tenant_id" uuid NOT NULL,
50
+ "utc_date" date NOT NULL,
51
+ "invocations_count" integer DEFAULT 0 NOT NULL,
52
+ "wall_clock_seconds" integer DEFAULT 0 NOT NULL,
53
+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL,
54
+ CONSTRAINT "sandbox_tenant_daily_counters_tenant_id_utc_date_pk" PRIMARY KEY("tenant_id","utc_date")
55
+ );
56
+ --> statement-breakpoint
57
+ CREATE TABLE "tenant_policy_events" (
58
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
59
+ "tenant_id" uuid NOT NULL,
60
+ "actor_user_id" uuid NOT NULL,
61
+ "event_type" text NOT NULL,
62
+ "before_value" text,
63
+ "after_value" text,
64
+ "source" text NOT NULL,
65
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
66
+ CONSTRAINT "tenant_policy_events_event_type_allowed" CHECK ("tenant_policy_events"."event_type" IN ('sandbox_enabled','compliance_tier')),
67
+ CONSTRAINT "tenant_policy_events_source_allowed" CHECK ("tenant_policy_events"."source" IN ('graphql','reconciler','sql'))
68
+ );
69
+ --> statement-breakpoint
70
+ ALTER TABLE "tenants" ADD COLUMN "sandbox_enabled" boolean DEFAULT true NOT NULL;--> statement-breakpoint
71
+ -- Rollout-safe: the DEFAULT true is forward-facing semantics (new tenants
72
+ -- created post-migration opt in automatically). Existing tenants must NOT
73
+ -- auto-opt-in before Phase 3b enforcement (pre-flight + quota + audit) lands;
74
+ -- flip them all to false in the same transaction. Operator action re-enables
75
+ -- per tenant during the staged rollout described in the plan's Operational
76
+ -- Notes.
77
+ UPDATE "tenants" SET "sandbox_enabled" = false;--> statement-breakpoint
78
+ ALTER TABLE "tenants" ADD COLUMN "compliance_tier" text DEFAULT 'standard' NOT NULL;--> statement-breakpoint
79
+ ALTER TABLE "tenants" ADD COLUMN "sandbox_interpreter_public_id" text;--> statement-breakpoint
80
+ ALTER TABLE "tenants" ADD COLUMN "sandbox_interpreter_internal_id" text;--> statement-breakpoint
81
+ ALTER TABLE "sandbox_invocations" ADD CONSTRAINT "sandbox_invocations_tenant_id_tenants_id_fk" FOREIGN KEY ("tenant_id") REFERENCES "public"."tenants"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
82
+ ALTER TABLE "sandbox_invocations" ADD CONSTRAINT "sandbox_invocations_run_id_skill_runs_id_fk" FOREIGN KEY ("run_id") REFERENCES "public"."skill_runs"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
83
+ ALTER TABLE "sandbox_invocations" ADD CONSTRAINT "sandbox_invocations_agent_id_agents_id_fk" FOREIGN KEY ("agent_id") REFERENCES "public"."agents"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
84
+ ALTER TABLE "sandbox_agent_hourly_counters" ADD CONSTRAINT "sandbox_agent_hourly_counters_tenant_id_tenants_id_fk" FOREIGN KEY ("tenant_id") REFERENCES "public"."tenants"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
85
+ ALTER TABLE "sandbox_agent_hourly_counters" ADD CONSTRAINT "sandbox_agent_hourly_counters_agent_id_agents_id_fk" FOREIGN KEY ("agent_id") REFERENCES "public"."agents"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
86
+ ALTER TABLE "sandbox_tenant_daily_counters" ADD CONSTRAINT "sandbox_tenant_daily_counters_tenant_id_tenants_id_fk" FOREIGN KEY ("tenant_id") REFERENCES "public"."tenants"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
87
+ ALTER TABLE "tenant_policy_events" ADD CONSTRAINT "tenant_policy_events_tenant_id_tenants_id_fk" FOREIGN KEY ("tenant_id") REFERENCES "public"."tenants"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
88
+ CREATE INDEX "idx_sandbox_invocations_tenant_started" ON "sandbox_invocations" USING btree ("tenant_id","started_at");--> statement-breakpoint
89
+ CREATE INDEX "idx_sandbox_invocations_tenant_agent_started" ON "sandbox_invocations" USING btree ("tenant_id","agent_id","started_at");--> statement-breakpoint
90
+ CREATE INDEX "idx_sandbox_invocations_user" ON "sandbox_invocations" USING btree ("user_id");--> statement-breakpoint
91
+ CREATE INDEX "idx_sandbox_invocations_run" ON "sandbox_invocations" USING btree ("run_id");--> statement-breakpoint
92
+ CREATE INDEX "idx_sandbox_invocations_delete_at" ON "sandbox_invocations" USING btree ("delete_at");--> statement-breakpoint
93
+ CREATE INDEX "idx_tenant_policy_events_tenant_created" ON "tenant_policy_events" USING btree ("tenant_id","created_at");--> statement-breakpoint
94
+ ALTER TABLE "tenants" ADD CONSTRAINT "tenants_compliance_tier_allowed" CHECK ("tenants"."compliance_tier" IN ('standard','regulated','hipaa'));--> statement-breakpoint
95
+ ALTER TABLE "tenants" ADD CONSTRAINT "tenants_sandbox_requires_standard_tier" CHECK (NOT ("tenants"."sandbox_enabled" = true AND "tenants"."compliance_tier" != 'standard'));
@@ -0,0 +1,58 @@
1
+ -- Unit 8 — webhook ingress pattern + tenant system-user actor.
2
+ --
3
+ -- See docs/plans/2026-04-21-003-feat-composable-skills-with-learnings-plan.md
4
+ -- (Unit 8). Two changes:
5
+ --
6
+ -- 1. skill_runs.triggered_by_run_id — optional link from one reconciler
7
+ -- tick back to the run that spawned the task whose completion fired
8
+ -- this tick. Populated by the task-event webhook handler.
9
+ -- 2. tenant_system_users — one stable uuid per tenant that owns webhook-
10
+ -- triggered composition runs. Compiled-in scope: invoke-only. See the
11
+ -- schema file for the rationale.
12
+ --
13
+ -- Apply manually (matches 0018_skill_runs.sql convention):
14
+ -- psql "$DATABASE_URL" -f packages/database-pg/drizzle/0019_webhook_skill_runs.sql
15
+ --
16
+ -- Drift detection:
17
+ -- bash scripts/db-migrate-manual.sh
18
+ --
19
+ -- Pre-migration invariants:
20
+ -- - skill_runs exists (applied via 0018_skill_runs.sql).
21
+ -- - tenant_system_users does not exist yet.
22
+ --
23
+ -- creates: public.tenant_system_users
24
+ -- creates: public.uq_tenant_system_users_tenant
25
+ -- creates: public.idx_skill_runs_triggered_by
26
+ -- creates-column: public.skill_runs.triggered_by_run_id
27
+
28
+ -- ---------------------------------------------------------------------------
29
+ -- 1. skill_runs.triggered_by_run_id
30
+ -- ---------------------------------------------------------------------------
31
+
32
+ ALTER TABLE "skill_runs"
33
+ ADD COLUMN IF NOT EXISTS "triggered_by_run_id" uuid;
34
+ --> statement-breakpoint
35
+
36
+ CREATE INDEX IF NOT EXISTS "idx_skill_runs_triggered_by"
37
+ ON "skill_runs" USING btree ("triggered_by_run_id");
38
+ --> statement-breakpoint
39
+
40
+ -- ---------------------------------------------------------------------------
41
+ -- 2. tenant_system_users
42
+ -- ---------------------------------------------------------------------------
43
+
44
+ CREATE TABLE IF NOT EXISTS "tenant_system_users" (
45
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
46
+ "tenant_id" uuid NOT NULL,
47
+ "created_at" timestamp with time zone NOT NULL DEFAULT now()
48
+ );
49
+ --> statement-breakpoint
50
+
51
+ ALTER TABLE "tenant_system_users"
52
+ ADD CONSTRAINT "tenant_system_users_tenant_id_tenants_id_fk"
53
+ FOREIGN KEY ("tenant_id") REFERENCES "public"."tenants"("id")
54
+ ON DELETE no action ON UPDATE no action;
55
+ --> statement-breakpoint
56
+
57
+ CREATE UNIQUE INDEX IF NOT EXISTS "uq_tenant_system_users_tenant"
58
+ ON "tenant_system_users" USING btree ("tenant_id");
@@ -0,0 +1,9 @@
1
+ -- NOTE: skill_runs.completion_hmac_secret was intentionally stripped from
2
+ -- this generated migration. It was already applied to every stage by the
3
+ -- hand-rolled drizzle/0021_skill_runs_completion_hmac.sql that shipped with
4
+ -- the composable-skills hardening work (#422). The drizzle journal wasn't
5
+ -- refreshed, so db:generate re-included the column when it ran for this
6
+ -- unit. Keeping that line here would fail with "column already exists" on
7
+ -- every environment. The 0020 snapshot file does capture the column so
8
+ -- future db:generate runs stay consistent.
9
+ ALTER TABLE "agent_templates" ADD COLUMN "sandbox" jsonb;
@@ -0,0 +1,64 @@
1
+ -- mutation_idempotency — server-authoritative idempotency for admin-skill mutations
2
+ --
3
+ -- See docs/plans/2026-04-22-004-feat-thinkwork-admin-skill-plan.md (Unit 4).
4
+ -- Lets the thinkwork-admin Python skill retry a mutation with the same
5
+ -- idempotency_key and receive the original result without re-executing.
6
+ -- Protects the stamp-out-an-enterprise recipe from spawning duplicate
7
+ -- rows on transient failures + replays.
8
+ --
9
+ -- Apply manually (no CI migration runner):
10
+ -- psql "$DATABASE_URL" -f packages/database-pg/drizzle/0020_mutation_idempotency.sql
11
+ --
12
+ -- Drift detection:
13
+ -- pnpm db:migrate-manual
14
+ --
15
+ -- Pre-migration invariant: no existing table named mutation_idempotency.
16
+ -- SELECT to_regclass('public.mutation_idempotency'); must return NULL.
17
+ --
18
+ -- Divergence from skill_runs: mutation_idempotency uses a FULL unique index
19
+ -- (not partial-on-status='running') because a succeeded mutation's key
20
+ -- MUST block a duplicate retry and return the stored result. skill_runs
21
+ -- can use a partial index because a failed composition is safe to re-run.
22
+ -- Full index also sidesteps the ON-CONFLICT-on-partial-index gotcha noted
23
+ -- at startSkillRun.mutation.ts:127-129.
24
+ --
25
+ -- creates: public.mutation_idempotency
26
+ -- creates: public.uq_mutation_idempotency_key
27
+
28
+ CREATE TABLE "mutation_idempotency" (
29
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
30
+ "tenant_id" uuid NOT NULL,
31
+ -- Plain uuid without FK to users — skill_runs.invoker_user_id follows
32
+ -- the same precedent. Service-auth callers may assert principalIds
33
+ -- whose users row is managed elsewhere; an FK here would foot-gun
34
+ -- that path without adding safety the row itself needs.
35
+ "invoker_user_id" uuid NOT NULL,
36
+ "mutation_name" text NOT NULL,
37
+ -- Client-supplied recipe-step key OR server-derived resolved_inputs_hash.
38
+ -- Unique per (tenant, invoker, mutation).
39
+ "idempotency_key" text NOT NULL,
40
+ -- SHA256 over canonicalized inputs, always server-computed. Kept for
41
+ -- audit/debug even when the client provided a distinct key.
42
+ "resolved_inputs_hash" text NOT NULL,
43
+ "status" text NOT NULL DEFAULT 'pending',
44
+ "result_json" jsonb,
45
+ "failure_reason" text,
46
+ "created_at" timestamp with time zone NOT NULL DEFAULT now(),
47
+ "completed_at" timestamp with time zone,
48
+ CONSTRAINT "status_allowed"
49
+ CHECK (status IN ('pending','succeeded','failed'))
50
+ );
51
+ --> statement-breakpoint
52
+
53
+ ALTER TABLE "mutation_idempotency" ADD CONSTRAINT "mutation_idempotency_tenant_id_tenants_id_fk"
54
+ FOREIGN KEY ("tenant_id") REFERENCES "public"."tenants"("id")
55
+ ON DELETE cascade ON UPDATE no action;
56
+ --> statement-breakpoint
57
+
58
+ -- FULL unique index (deliberate divergence from skill_runs' partial index).
59
+ CREATE UNIQUE INDEX "uq_mutation_idempotency_key" ON "mutation_idempotency"
60
+ USING btree ("tenant_id","invoker_user_id","mutation_name","idempotency_key");
61
+ --> statement-breakpoint
62
+
63
+ CREATE INDEX "idx_mutation_idempotency_tenant_created" ON "mutation_idempotency"
64
+ USING btree ("tenant_id","created_at");
@@ -0,0 +1,76 @@
1
+ -- CRM work links for Twenty-native launch/resume proof.
2
+ -- creates: public.crm_work_links
3
+ -- creates: public.uq_crm_work_links_active_outcome
4
+ -- creates: public.idx_crm_work_links_thread
5
+ -- creates: public.idx_crm_work_links_goal
6
+ -- creates: public.idx_crm_work_links_provider_record
7
+ -- creates-constraint: public.crm_work_links_provider_allowed
8
+ -- creates-constraint: public.crm_work_links_object_type_allowed
9
+ -- creates-constraint: public.crm_work_links_workflow_key_allowed
10
+ -- creates-constraint: public.crm_work_links_state_allowed
11
+ -- creates-constraint: public.crm_work_links_status_handle_state_allowed
12
+ -- creates-constraint: public.crm_work_links_last_writeback_state_allowed
13
+
14
+ CREATE TABLE IF NOT EXISTS public.crm_work_links (
15
+ id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
16
+ tenant_id uuid NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,
17
+ provider text NOT NULL,
18
+ object_type text NOT NULL,
19
+ object_id text NOT NULL,
20
+ object_url text,
21
+ workflow_key text NOT NULL,
22
+ outcome_key text NOT NULL DEFAULT 'default',
23
+ space_id uuid REFERENCES public.spaces(id) ON DELETE SET NULL,
24
+ thread_id uuid REFERENCES public.threads(id) ON DELETE SET NULL,
25
+ goal_id uuid REFERENCES public.goals(id) ON DELETE SET NULL,
26
+ requester_user_id uuid REFERENCES public.users(id) ON DELETE SET NULL,
27
+ last_writeback_user_id uuid REFERENCES public.users(id) ON DELETE SET NULL,
28
+ plugin_install_id uuid REFERENCES public.plugin_installs(id) ON DELETE SET NULL,
29
+ mcp_server_id uuid REFERENCES public.tenant_mcp_servers(id) ON DELETE SET NULL,
30
+ state text NOT NULL DEFAULT 'active',
31
+ status_handle_state text NOT NULL DEFAULT 'pending',
32
+ status_handle_url text,
33
+ status_handle_action text,
34
+ last_writeback_state text NOT NULL DEFAULT 'pending',
35
+ failure_code text,
36
+ failure_message text,
37
+ metadata jsonb NOT NULL DEFAULT '{}'::jsonb,
38
+ started_at timestamptz NOT NULL DEFAULT now(),
39
+ last_resumed_at timestamptz,
40
+ deactivated_at timestamptz,
41
+ archived_at timestamptz,
42
+ created_at timestamptz NOT NULL DEFAULT now(),
43
+ updated_at timestamptz NOT NULL DEFAULT now(),
44
+ CONSTRAINT crm_work_links_provider_allowed
45
+ CHECK (provider IN ('twenty')),
46
+ CONSTRAINT crm_work_links_object_type_allowed
47
+ CHECK (object_type IN ('opportunity')),
48
+ CONSTRAINT crm_work_links_workflow_key_allowed
49
+ CHECK (workflow_key IN ('customer_onboarding')),
50
+ CONSTRAINT crm_work_links_state_allowed
51
+ CHECK (state IN ('starting','active','completed','cancelled','failed','archived')),
52
+ CONSTRAINT crm_work_links_status_handle_state_allowed
53
+ CHECK (status_handle_state IN ('pending','posted','requires_reauth','writeback_blocked','failed')),
54
+ CONSTRAINT crm_work_links_last_writeback_state_allowed
55
+ CHECK (last_writeback_state IN ('pending','posted','requires_reauth','blocked','failed','skipped'))
56
+ );
57
+
58
+ CREATE UNIQUE INDEX IF NOT EXISTS uq_crm_work_links_active_outcome
59
+ ON public.crm_work_links (
60
+ tenant_id,
61
+ provider,
62
+ object_type,
63
+ object_id,
64
+ workflow_key,
65
+ outcome_key
66
+ )
67
+ WHERE state IN ('starting','active');
68
+
69
+ CREATE INDEX IF NOT EXISTS idx_crm_work_links_thread
70
+ ON public.crm_work_links (tenant_id, thread_id);
71
+
72
+ CREATE INDEX IF NOT EXISTS idx_crm_work_links_goal
73
+ ON public.crm_work_links (tenant_id, goal_id);
74
+
75
+ CREATE INDEX IF NOT EXISTS idx_crm_work_links_provider_record
76
+ ON public.crm_work_links (tenant_id, provider, object_type, object_id);
@@ -0,0 +1,33 @@
1
+ -- skill_runs.completion_hmac_secret — per-run secret for the
2
+ -- /api/skills/complete callback.
3
+ --
4
+ -- See docs/plans/2026-04-22-005-feat-composable-skills-hardening-handoff-plan.md
5
+ -- (PR #1, change 3). startSkillRunService generates a fresh secret at insert,
6
+ -- stores it in this column, and ships it to the agentcore container inside
7
+ -- the run_skill envelope. post_skill_run_complete computes
8
+ -- HMAC-SHA256(secret, runId) and sends it as X-Skill-Run-Signature:
9
+ -- sha256=<hex>. completeSkillRunService reads the secret from the row,
10
+ -- timing-safe-compares, and NULLs the column on successful terminal
11
+ -- transition (single-use). Missing-or-mismatched → 401.
12
+ --
13
+ -- The column is nullable because:
14
+ -- * rows inserted before this migration have no secret,
15
+ -- * burning the secret on completion requires setting it to NULL.
16
+ -- A NULL secret at /api/skills/complete time is treated as "already
17
+ -- completed" — repeat completion attempts get 401, which the Python
18
+ -- retry path already treats as terminal (not retried).
19
+ --
20
+ -- Apply manually (matches 0018/0019/0020 convention):
21
+ -- psql "$DATABASE_URL" -f packages/database-pg/drizzle/0021_skill_runs_completion_hmac.sql
22
+ --
23
+ -- Drift detection:
24
+ -- pnpm db:migrate-manual
25
+ --
26
+ -- Pre-migration invariants:
27
+ -- - skill_runs exists (applied via 0018_skill_runs.sql).
28
+ -- - skill_runs.completion_hmac_secret does not exist yet.
29
+ --
30
+ -- creates-column: public.skill_runs.completion_hmac_secret
31
+
32
+ ALTER TABLE "skill_runs"
33
+ ADD COLUMN IF NOT EXISTS "completion_hmac_secret" text;
@@ -0,0 +1,70 @@
1
+ -- Stripe billing tables + pending_owner_email column on tenants.
2
+ --
3
+ -- Paired with packages/database-pg/drizzle/0022_stripe_billing_indexes.sql,
4
+ -- which adds the partial unique index on tenants.pending_owner_email and the
5
+ -- single-active-subscription-per-tenant partial unique index on
6
+ -- stripe_subscriptions.
7
+ --
8
+ -- See docs/plans/2026-04-22-008-feat-stripe-pricing-and-post-checkout-onboarding-plan.md
9
+ -- (Unit 3).
10
+ --
11
+ -- Apply manually (matches 0018/0019/0020/0021 convention):
12
+ -- psql "$DATABASE_URL" -f packages/database-pg/drizzle/0022_add_billing_tables.sql
13
+ --
14
+ -- Drift detection:
15
+ -- pnpm db:migrate-manual
16
+ --
17
+ -- creates-column: public.tenants.pending_owner_email
18
+ -- creates: public.stripe_customers
19
+ -- creates: public.stripe_subscriptions
20
+ -- creates: public.stripe_events
21
+ -- creates: public.stripe_customers_stripe_customer_id_uidx
22
+ -- creates: public.stripe_subscriptions_stripe_subscription_id_uidx
23
+
24
+ ALTER TABLE "tenants" ADD COLUMN "pending_owner_email" text;
25
+
26
+ CREATE TABLE "stripe_customers" (
27
+ "tenant_id" uuid PRIMARY KEY NOT NULL,
28
+ "stripe_customer_id" text NOT NULL,
29
+ "email" text NOT NULL,
30
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
31
+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL
32
+ );
33
+
34
+ CREATE TABLE "stripe_subscriptions" (
35
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
36
+ "tenant_id" uuid NOT NULL,
37
+ "stripe_subscription_id" text NOT NULL,
38
+ "stripe_price_id" text NOT NULL,
39
+ "status" text NOT NULL,
40
+ "current_period_end" timestamp with time zone,
41
+ "cancel_at_period_end" boolean DEFAULT false NOT NULL,
42
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
43
+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL
44
+ );
45
+
46
+ CREATE TABLE "stripe_events" (
47
+ "stripe_event_id" text PRIMARY KEY NOT NULL,
48
+ "event_type" text NOT NULL,
49
+ "processed_at" timestamp with time zone DEFAULT now() NOT NULL
50
+ );
51
+
52
+ DO $$ BEGIN
53
+ ALTER TABLE "stripe_customers" ADD CONSTRAINT "stripe_customers_tenant_id_tenants_id_fk"
54
+ FOREIGN KEY ("tenant_id") REFERENCES "public"."tenants"("id") ON DELETE cascade ON UPDATE no action;
55
+ EXCEPTION
56
+ WHEN duplicate_object THEN null;
57
+ END $$;
58
+
59
+ DO $$ BEGIN
60
+ ALTER TABLE "stripe_subscriptions" ADD CONSTRAINT "stripe_subscriptions_tenant_id_tenants_id_fk"
61
+ FOREIGN KEY ("tenant_id") REFERENCES "public"."tenants"("id") ON DELETE cascade ON UPDATE no action;
62
+ EXCEPTION
63
+ WHEN duplicate_object THEN null;
64
+ END $$;
65
+
66
+ CREATE UNIQUE INDEX IF NOT EXISTS "stripe_customers_stripe_customer_id_uidx"
67
+ ON "stripe_customers" ("stripe_customer_id");
68
+
69
+ CREATE UNIQUE INDEX IF NOT EXISTS "stripe_subscriptions_stripe_subscription_id_uidx"
70
+ ON "stripe_subscriptions" ("stripe_subscription_id");
@@ -0,0 +1,160 @@
1
+ -- Unit 4 (R13/R14) — Seed `thinkwork-admin` permissions.operations on
2
+ -- every existing agent_templates row whose skills list includes the
3
+ -- skill but hasn't yet authored an operations allowlist.
4
+ --
5
+ -- See docs/plans/2026-04-22-008-feat-agent-skill-permissions-ui-plan.md
6
+ -- (Unit 4). The thinkwork-admin skill's authz middle layer requires
7
+ -- `agent_skills.permissions.operations` to be populated before any op
8
+ -- call succeeds (see packages/api/src/graphql/resolvers/core/authz.ts,
9
+ -- `requireAgentAllowsOperation`). Agents inherit from the template
10
+ -- when their own permissions is null — so seeding the template is
11
+ -- sufficient to unblock every existing agent that carries the skill.
12
+ --
13
+ -- The 29 ops below are the `default_enabled: true` entries in
14
+ -- packages/skill-catalog/thinkwork-admin/skill.yaml as of this
15
+ -- migration. Destructive opt-ins (remove_tenant_member,
16
+ -- remove_team_agent, remove_team_user, sync_template_to_all_agents)
17
+ -- are NOT seeded — operators opt into them deliberately via the UI
18
+ -- landing in Phase 4.
19
+ --
20
+ -- If the manifest's default_enabled set changes after this ships, a
21
+ -- new migration (not an edit of this one) adds or removes the ops
22
+ -- for existing templates. This file is frozen.
23
+ --
24
+ -- Apply manually (matches the 0019/0020 convention):
25
+ -- psql "$DATABASE_URL" -f packages/database-pg/drizzle/0022_seed_thinkwork_admin_permissions.sql
26
+ --
27
+ -- Drift detection:
28
+ -- bash scripts/db-migrate-manual.sh
29
+ --
30
+ -- Pre-migration invariants:
31
+ -- - agent_templates exists with a jsonb `skills` column.
32
+ -- - skill_catalog exists and has a row for slug='thinkwork-admin'.
33
+ --
34
+ -- Idempotency: the UPDATE only rewrites jsonb array elements whose
35
+ -- `permissions` is NULL, an empty object, or missing the `operations`
36
+ -- key. Running the file twice is a no-op. Operators who pre-authored
37
+ -- permissions via direct SQL retain their choices.
38
+ --
39
+ -- creates: public.view_thinkwork_admin_permissions_seeded
40
+ --
41
+ -- Sentinel view below is the drift-reporter anchor. It expresses the
42
+ -- post-migration invariant so db-migrate-manual.sh has something
43
+ -- concrete to check in CI — this is otherwise a pure-data migration
44
+ -- with no schema object.
45
+
46
+ -- Pre-flight: refuse to run against a DB that's missing the target
47
+ -- tables. Fail loudly rather than silently doing nothing.
48
+ DO $$
49
+ BEGIN
50
+ IF to_regclass('public.agent_templates') IS NULL THEN
51
+ RAISE EXCEPTION 'agent_templates not found; apply earlier migrations first';
52
+ END IF;
53
+ END $$;
54
+
55
+ -- ---------------------------------------------------------------------------
56
+ -- Seed thinkwork-admin permissions.operations on every template that
57
+ -- lists the skill.
58
+ --
59
+ -- Strategy: for each agent_templates row, rebuild `skills` by mapping
60
+ -- over the array. For entries where skill_id='thinkwork-admin' and
61
+ -- permissions is missing/empty/lacks-operations, stitch in the default
62
+ -- ops. All other entries pass through untouched.
63
+ -- ---------------------------------------------------------------------------
64
+
65
+ UPDATE agent_templates AS t
66
+ SET skills = sub.new_skills
67
+ FROM (
68
+ SELECT
69
+ id,
70
+ (
71
+ SELECT jsonb_agg(
72
+ CASE
73
+ WHEN (elem->>'skill_id') = 'thinkwork-admin'
74
+ AND (
75
+ NOT (elem ? 'permissions')
76
+ OR elem->'permissions' IS NULL
77
+ OR jsonb_typeof(elem->'permissions') = 'null'
78
+ OR elem->'permissions' = '{}'::jsonb
79
+ OR NOT (elem->'permissions' ? 'operations')
80
+ )
81
+ THEN jsonb_set(
82
+ elem,
83
+ '{permissions}',
84
+ jsonb_build_object(
85
+ 'operations',
86
+ jsonb_build_array(
87
+ 'me',
88
+ 'get_tenant',
89
+ 'get_tenant_by_slug',
90
+ 'get_user',
91
+ 'list_tenant_members',
92
+ 'list_agents',
93
+ 'get_agent',
94
+ 'list_all_tenant_agents',
95
+ 'list_templates',
96
+ 'get_template',
97
+ 'list_linked_agents_for_template',
98
+ 'list_teams',
99
+ 'get_team',
100
+ 'list_artifacts',
101
+ 'get_artifact',
102
+ 'update_tenant',
103
+ 'add_tenant_member',
104
+ 'update_tenant_member',
105
+ 'invite_member',
106
+ 'create_team',
107
+ 'add_team_agent',
108
+ 'add_team_user',
109
+ 'create_agent',
110
+ 'set_agent_skills',
111
+ 'set_agent_capabilities',
112
+ 'create_agent_template',
113
+ 'create_agent_from_template',
114
+ 'sync_template_to_agent',
115
+ 'accept_template_update'
116
+ )
117
+ )
118
+ )
119
+ ELSE elem
120
+ END
121
+ ORDER BY ordinality
122
+ )
123
+ FROM jsonb_array_elements(t.skills) WITH ORDINALITY AS arr(elem, ordinality)
124
+ ) AS new_skills
125
+ FROM agent_templates AS t
126
+ WHERE jsonb_typeof(t.skills) = 'array'
127
+ AND t.skills @> '[{"skill_id": "thinkwork-admin"}]'::jsonb
128
+ ) AS sub
129
+ WHERE t.id = sub.id
130
+ AND sub.new_skills IS NOT NULL
131
+ AND sub.new_skills IS DISTINCT FROM t.skills;
132
+
133
+ -- ---------------------------------------------------------------------------
134
+ -- Drift-reporter sentinel.
135
+ --
136
+ -- A trivial view asserting the post-migration invariant: every template
137
+ -- referencing thinkwork-admin has a non-null permissions.operations
138
+ -- array for that skill. Reporter gates on the view's existence, which
139
+ -- proves the migration ran. The view itself is cheap (no rows unless
140
+ -- there's a drift) and expresses intent in SQL rather than prose.
141
+ -- ---------------------------------------------------------------------------
142
+
143
+ CREATE OR REPLACE VIEW public.view_thinkwork_admin_permissions_seeded AS
144
+ SELECT
145
+ t.id AS template_id,
146
+ t.tenant_id,
147
+ t.slug
148
+ FROM agent_templates t,
149
+ jsonb_array_elements(t.skills) AS s
150
+ WHERE (s->>'skill_id') = 'thinkwork-admin'
151
+ AND (
152
+ NOT (s ? 'permissions')
153
+ OR s->'permissions' IS NULL
154
+ OR jsonb_typeof(s->'permissions') = 'null'
155
+ OR NOT (s->'permissions' ? 'operations')
156
+ );
157
+
158
+ COMMENT ON VIEW public.view_thinkwork_admin_permissions_seeded IS
159
+ 'Unit 4 invariant check — rows here indicate a thinkwork-admin template '
160
+ 'assignment missing permissions.operations. Expected to be empty post-seed.';