thinkwork-cli 0.13.2 → 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 (231) hide show
  1. package/README.md +3 -14
  2. package/dist/{api-client-JYZXYQJR.js → api-client-4P4JZOBX.js} +1 -1
  3. package/dist/{chunk-Z2F6RJFR.js → chunk-4OMDWYZQ.js} +4 -5
  4. package/dist/{chunk-ILZKG5WV.js → chunk-AD2NIWB5.js} +434 -69
  5. package/dist/chunk-MWQ7RO76.js +137 -0
  6. package/dist/{chunk-DVPBI5HM.js → chunk-OLUQ4U2Z.js} +26 -26
  7. package/dist/{chunk-QOERT44A.js → chunk-YQCYD6NE.js} +57 -44
  8. package/dist/cli.js +4400 -16431
  9. package/dist/commands/enterprise/templates/deploy-repo/scripts/apply-release.mjs +0 -1
  10. package/dist/commands/enterprise/templates/deploy-repo/scripts/smoke.mjs +0 -1
  11. package/dist/commands/enterprise/templates/deploy-repo/terraform/main.tf +0 -14
  12. package/dist/{dist-es-CRV46D5B.js → dist-es-2OTNTL4N.js} +4 -4
  13. package/dist/{dist-es-ENBUC3JP.js → dist-es-2XVAH4BQ.js} +2 -2
  14. package/dist/{dist-es-DCY4IC3Y.js → dist-es-3DPDUJAH.js} +2 -2
  15. package/dist/{dist-es-G7PTG75M.js → dist-es-BNZTBBVC.js} +1 -1
  16. package/dist/{dist-es-GKDBE7E6.js → dist-es-CD2RBDAC.js} +1 -1
  17. package/dist/{dist-es-R7FGL2IB.js → dist-es-I4FW57PS.js} +1 -1
  18. package/dist/{dist-es-USORBXZ5.js → dist-es-KVFWJNDY.js} +4 -4
  19. package/dist/{dist-es-HY3535OI.js → dist-es-PS73DWNL.js} +2 -2
  20. package/dist/{dist-es-LDE437AM.js → dist-es-S3NZQFGT.js} +1 -1
  21. package/dist/{dist-es-G54LBMRN.js → dist-es-SGCA4P32.js} +1 -1
  22. package/dist/{dist-es-Q57SZXZ7.js → dist-es-WBM6J4RA.js} +2 -2
  23. package/dist/{dist-es-P26FWFLT.js → dist-es-ZGVADYIF.js} +8 -8
  24. package/dist/drizzle/0227_analyst_reader_role.sql +17 -26
  25. package/dist/drizzle/0230_analyst_rls.sql +28 -45
  26. package/dist/drizzle/0261_native_auth_control_plane.sql +7 -3
  27. package/dist/drizzle/0270_tool_execution_ledger.sql +115 -0
  28. package/dist/drizzle/0271_ontology_twin_declarations.sql +47 -0
  29. package/dist/drizzle/0272_identity_graph_projection_cursor.sql +23 -0
  30. package/dist/drizzle/0273_twin_materialization_suggestions.sql +29 -0
  31. package/dist/drizzle/0274_tenant_mcp_twin_keys.sql +59 -0
  32. package/dist/drizzle/0275_identity_bulk_rebuild_fence.sql +30 -0
  33. package/dist/drizzle/0276_tool_execution_ledger_allow_cascade_delete.sql +18 -0
  34. package/dist/drizzle/0277_knowledge_base_sources.sql +107 -0
  35. package/dist/drizzle/0278_kb_page_transcription.sql +55 -0
  36. package/dist/drizzle/0279_mcp_servers_off_plugin_provenance.sql +93 -0
  37. package/dist/drizzle/0280_work_item_external_refs_drop_plane_provider.sql +46 -0
  38. package/dist/drizzle/0281_tenant_mcp_twin_keys_expiry_suffix.sql +9 -0
  39. package/dist/drizzle/0282_tenant_mcp_twin_keys_grants.sql +24 -0
  40. package/dist/drizzle/0283_agents_agentcore_runtime_dispatch.sql +13 -0
  41. package/dist/drizzle/0284_user_brain_claims.sql +69 -0
  42. package/dist/drizzle/0285_tenant_mcp_twin_keys_trusted_subsystem.sql +30 -0
  43. package/dist/drizzle/0286_brain_analytics_key.sql +26 -0
  44. package/dist/drizzle/0287_brain_subject.sql +25 -0
  45. package/dist/drizzle/0288_multi_lane_identities.sql +25 -0
  46. package/dist/{loadSso-DJVB7BXE.js → loadSso-ETCXTR4I.js} +2 -2
  47. package/dist/{loadSso-JAMNA3WY.js → loadSso-UBD7KUHE.js} +2 -2
  48. package/dist/plugins/README.md +2 -2
  49. package/dist/plugins/catalog/package.json +0 -3
  50. package/dist/plugins/catalog/src/__tests__/build-catalog.test.ts +6 -3
  51. package/dist/plugins/catalog/src/__tests__/catalog.test.ts +21 -21
  52. package/dist/plugins/catalog/src/__tests__/contracts.test.ts +102 -25
  53. package/dist/plugins/catalog/src/__tests__/plugin-package.test.ts +7 -6
  54. package/dist/plugins/catalog/src/__tests__/plugin-registry.test.ts +0 -15
  55. package/dist/plugins/catalog/src/contracts.ts +15 -0
  56. package/dist/plugins/catalog/src/registry/generated-first-party.ts +0 -18
  57. package/dist/plugins/n8n/test/integrated-app-contract.test.ts +1 -1
  58. package/dist/plugins/twenty/package.json +2 -1
  59. package/dist/plugins/twenty/scripts/LAMBDA_DEPLOY.md +114 -0
  60. package/dist/plugins/twenty/scripts/build-lambda.sh +29 -0
  61. package/dist/plugins/twenty/scripts/configure-product-views.ts +195 -0
  62. package/dist/plugins/twenty/scripts/lambda-handler.ts +49 -0
  63. package/dist/plugins/twenty/scripts/lib/__tests__/load-attachments.test.ts +38 -0
  64. package/dist/plugins/twenty/scripts/lib/__tests__/load-records.test.ts +145 -2
  65. package/dist/plugins/twenty/scripts/lib/__tests__/mappers.test.ts +397 -151
  66. package/dist/plugins/twenty/scripts/lib/__tests__/members-ensure.test.ts +28 -129
  67. package/dist/plugins/twenty/scripts/lib/__tests__/provision-members-db.test.ts +10 -0
  68. package/dist/plugins/twenty/scripts/lib/__tests__/schema-ensure.test.ts +13 -8
  69. package/dist/plugins/twenty/scripts/lib/lastmile-reader.ts +222 -2
  70. package/dist/plugins/twenty/scripts/lib/load-attachments.ts +29 -0
  71. package/dist/plugins/twenty/scripts/lib/load-records.ts +160 -43
  72. package/dist/plugins/twenty/scripts/lib/mappers.ts +368 -152
  73. package/dist/plugins/twenty/scripts/lib/members-ensure.ts +43 -268
  74. package/dist/plugins/twenty/scripts/lib/provision-members-db.ts +57 -0
  75. package/dist/plugins/twenty/scripts/lib/schema-ensure.ts +136 -31
  76. package/dist/plugins/twenty/scripts/migrate-lastmile.ts +254 -152
  77. package/dist/plugins/twenty/scripts/provision-twenty-members.ts +44 -1
  78. package/dist/plugins/twenty/scripts/purge-lastmile-import.ts +178 -0
  79. package/dist/plugins/twenty/scripts/restructure-products.ts +312 -0
  80. package/dist/plugins/twenty/scripts/retag-stage-values.ts +362 -0
  81. package/dist/plugins/twenty/test/manifest.test.ts +2 -4
  82. package/dist/scripts/post-deploy.sh +79 -1
  83. package/dist/{signin-UGDWTGS4.js → signin-5QZNRSOO.js} +2 -2
  84. package/dist/{sso-oidc-Q4VXANXY.js → sso-oidc-XK673P54.js} +2 -2
  85. package/dist/{sts-CWLSE3GH.js → sts-OXI2UALF.js} +6 -134
  86. package/dist/{sts-DNZLNVOV.js → sts-SQW4NBK3.js} +6 -134
  87. package/dist/terraform/examples/greenfield/main.tf +233 -175
  88. package/dist/terraform/examples/greenfield/terraform.tfvars.example +12 -8
  89. package/dist/terraform/modules/app/agentcore-admin/main.tf +47 -0
  90. package/dist/terraform/modules/app/agentcore-code-interpreter/README.md +39 -47
  91. package/dist/terraform/modules/app/agentcore-code-interpreter/main.tf +13 -66
  92. package/dist/terraform/modules/app/agentcore-identity/main.tf +106 -26
  93. package/dist/terraform/modules/app/agentcore-identity/outputs.tf +6 -6
  94. package/dist/terraform/modules/app/agentcore-identity/scripts/bootstrap_twenty_oauth_client.sh +216 -99
  95. package/dist/terraform/modules/app/agentcore-identity/scripts/delete_identity.sh +6 -9
  96. package/dist/terraform/modules/app/agentcore-identity/scripts/delete_workload_identity.sh +19 -0
  97. package/dist/terraform/modules/app/agentcore-identity/scripts/ensure_workload_identity.sh +29 -0
  98. package/dist/terraform/modules/app/agentcore-identity/scripts/read_identity.sh +22 -7
  99. package/dist/terraform/modules/app/agentcore-identity/scripts/reconcile_twenty_identity.sh +17 -46
  100. package/dist/terraform/modules/app/agentcore-identity/scripts/reconcile_twenty_provider.mjs +65 -3
  101. package/dist/terraform/modules/app/agentcore-identity/tests/tainted-marker/after.tf +15 -0
  102. package/dist/terraform/modules/app/agentcore-identity/tests/tainted-marker/before.tf +7 -0
  103. package/dist/terraform/modules/app/agentcore-identity/tests/tainted-marker/identity-after.tf +8 -0
  104. package/dist/terraform/modules/app/agentcore-identity/tests/tainted-marker/identity-before.tf +9 -0
  105. package/dist/terraform/modules/app/agentcore-identity/tests/tainted-marker/thinkwork-after.tf +3 -0
  106. package/dist/terraform/modules/app/agentcore-identity/tests/tainted-marker/thinkwork-before.tf +3 -0
  107. package/dist/terraform/modules/app/agentcore-identity/variables.tf +6 -0
  108. package/dist/terraform/modules/app/agentcore-memory/README.md +46 -9
  109. package/dist/terraform/modules/app/agentcore-memory/main.tf +27 -10
  110. package/dist/terraform/modules/app/agentcore-memory/scripts/create_or_find_memory.sh +156 -24
  111. package/dist/terraform/modules/app/agentcore-pi/README.md +1 -3
  112. package/dist/terraform/modules/app/agentcore-pi/main.tf +42 -52
  113. package/dist/terraform/modules/app/agentcore-pi/outputs.tf +3 -3
  114. package/dist/terraform/modules/app/agentcore-pi/scripts/reconcile_pi_runtime.mjs +175 -0
  115. package/dist/terraform/modules/app/agentcore-pi/variables.tf +35 -28
  116. package/dist/terraform/modules/app/agentcore-platform/main.tf +68 -0
  117. package/dist/terraform/modules/app/agentcore-runtime/main.tf +4 -20
  118. package/dist/terraform/modules/app/capability-broker/main.tf +2 -2
  119. package/dist/terraform/modules/app/capability-broker/variables.tf +11 -0
  120. package/dist/terraform/modules/app/deployment-control-plane/README.md +264 -0
  121. package/dist/terraform/modules/app/deployment-control-plane/buildspec.yml +4 -1
  122. package/dist/terraform/modules/app/deployment-control-plane/main.tf +94 -0
  123. package/dist/terraform/modules/app/deployment-control-plane/outputs.tf +5 -0
  124. package/dist/terraform/modules/app/deployment-control-plane/runner.py +2641 -124
  125. package/dist/terraform/modules/app/deployment-control-plane/test_runner_bundle.py +2034 -154
  126. package/dist/terraform/modules/app/deployment-control-plane/variables.tf +33 -0
  127. package/dist/terraform/modules/app/lambda-api/auth-state.tf +72 -0
  128. package/dist/terraform/modules/app/lambda-api/chat-latency-observability.tf +466 -0
  129. package/dist/terraform/modules/app/lambda-api/dispatch-dlq.tf +55 -0
  130. package/dist/terraform/modules/app/lambda-api/handlers.tf +411 -723
  131. package/dist/terraform/modules/app/lambda-api/iam-grouped.tf +262 -198
  132. package/dist/terraform/modules/app/lambda-api/main.tf +51 -13
  133. package/dist/terraform/modules/app/lambda-api/mcp-oauth.tf +4 -181
  134. package/dist/terraform/modules/app/lambda-api/memory-alarms.tf +3 -28
  135. package/dist/terraform/modules/app/lambda-api/oauth-secrets.tf +1 -2
  136. package/dist/terraform/modules/app/lambda-api/outputs.tf +17 -45
  137. package/dist/terraform/modules/app/lambda-api/turn-assertion.tf +45 -0
  138. package/dist/terraform/modules/app/lambda-api/variables.tf +219 -126
  139. package/dist/{plugins/n8n/terraform → terraform/modules/app}/n8n/README.md +1 -1
  140. package/dist/{plugins/n8n/terraform → terraform/modules/app}/n8n/main.tf +18 -18
  141. package/dist/terraform/modules/app/sandbox-log-scrubber/README.md +11 -10
  142. package/dist/terraform/modules/app/sandbox-log-scrubber/main.tf +5 -5
  143. package/dist/terraform/modules/app/static-site/main.tf +1 -1
  144. package/dist/terraform/modules/app/www-dns/main.tf +9 -27
  145. package/dist/terraform/modules/app/www-dns/variables.tf +4 -10
  146. package/dist/terraform/modules/data/aurora-postgres/README.md +34 -0
  147. package/dist/terraform/modules/data/aurora-postgres/alarms.tf +82 -0
  148. package/dist/terraform/modules/data/aurora-postgres/main.tf +27 -57
  149. package/dist/terraform/modules/data/aurora-postgres/outputs.tf +0 -9
  150. package/dist/terraform/modules/data/aurora-postgres/variables.tf +41 -0
  151. package/dist/terraform/modules/data/s3-buckets/main.tf +5 -6
  152. package/dist/terraform/modules/foundation/cognito/main.tf +81 -8
  153. package/dist/terraform/modules/foundation/cognito/outputs.tf +5 -0
  154. package/dist/terraform/modules/foundation/cognito/variables.tf +24 -12
  155. package/dist/terraform/modules/thinkwork/README.md +5 -1
  156. package/dist/terraform/modules/thinkwork/main.tf +376 -374
  157. package/dist/terraform/modules/thinkwork/outputs.tf +12 -158
  158. package/dist/terraform/modules/thinkwork/variables.tf +246 -89
  159. package/dist/workspace-defaults/files/INSTRUCTIONS.md +9 -11
  160. package/dist/workspace-defaults/files/MEMORY_GUIDE.md +38 -35
  161. package/dist/workspace-defaults/files/ROUTER.md +1 -1
  162. package/dist/workspace-defaults/files/TOOLS.md +9 -39
  163. package/dist/workspace-defaults/files/agents/analyst/INSTRUCTIONS.md +6 -3
  164. package/dist/workspace-defaults/files/catalog-skills/brain-brief-builder/SKILL.md +165 -0
  165. package/dist/workspace-defaults/files/catalog-skills/n8n-workflow-operator/SKILL.md +75 -0
  166. package/dist/workspace-defaults/files/catalog-skills/n8n-workflow-operator/references/mcp-tooling.md +40 -0
  167. package/dist/workspace-defaults/files/catalog-skills/n8n-workflow-operator/references/validation-and-handoff.md +40 -0
  168. package/dist/workspace-defaults/files/catalog-skills/n8n-workflow-operator/references/workflow-authoring.md +46 -0
  169. package/dist/workspace-defaults/files/skills/artifact-builder/references/crm-dashboard.md +1 -1
  170. package/dist/workspace-defaults/files/skills/document-composer/SKILL.md +22 -3
  171. package/package.json +1 -1
  172. package/dist/drizzle/0261_managed_harness_multiplayer.sql +0 -313
  173. package/dist/drizzle/0262_parallel_harness_threads.sql +0 -9
  174. package/dist/drizzle/0264_harness_tool_execution_ledger.sql +0 -113
  175. package/dist/plugins/company-data/README.md +0 -49
  176. package/dist/plugins/company-data/package.json +0 -21
  177. package/dist/plugins/company-data/src/index.ts +0 -30
  178. package/dist/plugins/company-data/src/manifest.ts +0 -26
  179. package/dist/plugins/company-data/test/manifest.test.ts +0 -116
  180. package/dist/plugins/company-data/tsconfig.json +0 -8
  181. package/dist/plugins/company-etl/README.md +0 -46
  182. package/dist/plugins/company-etl/package.json +0 -21
  183. package/dist/plugins/company-etl/src/index.ts +0 -29
  184. package/dist/plugins/company-etl/src/manifest.ts +0 -26
  185. package/dist/plugins/company-etl/test/manifest.test.ts +0 -108
  186. package/dist/plugins/company-etl/tsconfig.json +0 -8
  187. package/dist/plugins/lastmile/README.md +0 -50
  188. package/dist/plugins/lastmile/package.json +0 -23
  189. package/dist/plugins/lastmile/smoke/lastmile-plugin-smoke.mjs +0 -661
  190. package/dist/plugins/lastmile/src/api/tasks-adapter.ts +0 -572
  191. package/dist/plugins/lastmile/src/discovery.fixture.ts +0 -64
  192. package/dist/plugins/lastmile/src/index.ts +0 -46
  193. package/dist/plugins/lastmile/src/manifest.ts +0 -139
  194. package/dist/plugins/lastmile/test/api/tasks-adapter.test.ts +0 -266
  195. package/dist/plugins/lastmile/test/discovery.test.ts +0 -88
  196. package/dist/plugins/lastmile/tsconfig.json +0 -8
  197. package/dist/plugins/n8n/smoke/n8n-managed-app-smoke.mjs +0 -409
  198. package/dist/plugins/twenty/smoke/twenty-managed-app-smoke.mjs +0 -359
  199. package/dist/terraform/modules/app/agentcore-code-interpreter/Dockerfile.sandbox-base +0 -61
  200. package/dist/terraform/modules/app/agentcore-code-interpreter/sandbox/sitecustomize.py +0 -227
  201. package/dist/terraform/modules/app/agentcore-code-interpreter/sandbox/test_sitecustomize.py +0 -277
  202. package/dist/terraform/modules/app/agentcore-code-interpreter/scripts/build_and_push_sandbox_base.sh +0 -70
  203. package/dist/terraform/modules/app/agentcore-gateway/main.tf +0 -305
  204. package/dist/terraform/modules/app/agentcore-gateway/outputs.tf +0 -44
  205. package/dist/terraform/modules/app/agentcore-gateway/scripts/delete_gateway.sh +0 -93
  206. package/dist/terraform/modules/app/agentcore-gateway/scripts/read_gateway.sh +0 -33
  207. package/dist/terraform/modules/app/agentcore-gateway/scripts/reconcile_gateway.sh +0 -543
  208. package/dist/terraform/modules/app/agentcore-gateway/variables.tf +0 -70
  209. package/dist/terraform/modules/app/agentcore-harness/main.tf +0 -330
  210. package/dist/terraform/modules/app/agentcore-harness/outputs.tf +0 -72
  211. package/dist/terraform/modules/app/agentcore-harness/scripts/delete_harness.sh +0 -5
  212. package/dist/terraform/modules/app/agentcore-harness/scripts/harness-lifecycle.mjs +0 -430
  213. package/dist/terraform/modules/app/agentcore-harness/scripts/harness-readback.mjs +0 -180
  214. package/dist/terraform/modules/app/agentcore-harness/scripts/harness-tool-contract.mjs +0 -193
  215. package/dist/terraform/modules/app/agentcore-harness/scripts/prune_harness.sh +0 -5
  216. package/dist/terraform/modules/app/agentcore-harness/scripts/read_harness.sh +0 -5
  217. package/dist/terraform/modules/app/agentcore-harness/scripts/reconcile_harness.sh +0 -5
  218. package/dist/terraform/modules/app/agentcore-harness/variables.tf +0 -96
  219. package/dist/terraform/modules/app/hindsight-memory/README.md +0 -89
  220. package/dist/terraform/modules/app/hindsight-memory/main.tf +0 -411
  221. package/dist/terraform/modules/app/lambda-api/agentcore-harness-alarms.tf +0 -88
  222. package/dist/terraform/modules/app/lambda-api/agentcore-identity-alarms.tf +0 -91
  223. package/dist/terraform/modules/data/bedrock-knowledge-base/main.tf +0 -102
  224. /package/dist/{plugins/n8n/terraform → terraform/modules/app}/n8n/outputs.tf +0 -0
  225. /package/dist/{plugins/n8n/terraform → terraform/modules/app}/n8n/scripts/sync-database.py +0 -0
  226. /package/dist/{plugins/n8n/terraform → terraform/modules/app}/n8n/scripts/test_sync_database.py +0 -0
  227. /package/dist/{plugins/n8n/terraform → terraform/modules/app}/n8n/variables.tf +0 -0
  228. /package/dist/{plugins/twenty/terraform → terraform/modules/app}/twenty/README.md +0 -0
  229. /package/dist/{plugins/twenty/terraform → terraform/modules/app}/twenty/main.tf +0 -0
  230. /package/dist/{plugins/twenty/terraform → terraform/modules/app}/twenty/outputs.tf +0 -0
  231. /package/dist/{plugins/twenty/terraform → terraform/modules/app}/twenty/variables.tf +0 -0
@@ -0,0 +1,30 @@
1
+ -- Trusted-subsystem marker on tenant_mcp_twin_keys (THINK-626) — the write
2
+ -- side of the `trustedSubsystem` field in key manifest v2
3
+ -- (twin-mcp-keys/v2; reader is company-brain brain-mcp/src/auth.ts).
4
+ --
5
+ -- true lets the key assert `on_behalf_of` per tools/call — running the call
6
+ -- under the named signed-in human's user-claims entry instead of under the
7
+ -- key's own grants. It is NOT a grant and it can never widen anyone: the
8
+ -- asserted user's grants come from the user-claims manifest, and a tenant
9
+ -- that publishes none refuses the assertion. It belongs only on keys the
10
+ -- platform itself holds (the Pi runtime's provisioned "default" connector
11
+ -- key), never on one handed to a customer's client — hence default false
12
+ -- and no backfill for user-minted rows.
13
+ --
14
+ -- Hand-rolled (mirrors the 0274/0281/0282 convention; not registered in
15
+ -- meta/_journal.json).
16
+ -- Apply via: psql "$DATABASE_URL" -f drizzle/0285_tenant_mcp_twin_keys_trusted_subsystem.sql
17
+ -- creates-column: public.tenant_mcp_twin_keys.trusted_subsystem
18
+
19
+ ALTER TABLE public.tenant_mcp_twin_keys
20
+ ADD COLUMN IF NOT EXISTS trusted_subsystem boolean NOT NULL DEFAULT false;
21
+
22
+ -- The platform-provisioned connector key ("default") is the ThinkWork Pi
23
+ -- runtime's own key — the one and only principal that may speak for a
24
+ -- signed-in human. Grandfather every active one; re-provisioning would set
25
+ -- the same flag anyway. User-minted keys stay false.
26
+ UPDATE public.tenant_mcp_twin_keys
27
+ SET trusted_subsystem = true
28
+ WHERE name = 'default'
29
+ AND revoked_at IS NULL
30
+ AND trusted_subsystem = false;
@@ -0,0 +1,26 @@
1
+ -- Analytics-channel visibility flag on Brain principals (THINK-656 D4) —
2
+ -- the write side of the `analyticsKey` field in both published manifests:
3
+ -- user-claims/v1 (per-user entries) and twin-mcp-keys/v2 (key entries).
4
+ -- Reader is company-brain brain-mcp/src/auth.ts, which parses literal true
5
+ -- only: `analyticsKey: true` lets the principal's brain_ask loop consult
6
+ -- the mart_analytics briefing tools. Tool VISIBILITY only, never a data
7
+ -- grant — the marts hold the tenant's own data and every query still runs
8
+ -- under the account's env gates (ANALYTICS_ENABLED et al.).
9
+ --
10
+ -- Default TRUE by decision (Eric, 2026-08-08): every user and key gets the
11
+ -- analytics channel unless an operator turns it off per row. There is no
12
+ -- console UI for the flag yet; the column is the future toggle. The NOT
13
+ -- NULL DEFAULT true also backfills every existing row, which matches the
14
+ -- 2026-08-07 go-live hand-edits this migration makes durable.
15
+ --
16
+ -- Hand-rolled (mirrors the 0274/0281/0282/0284/0285 convention; not
17
+ -- registered in meta/_journal.json).
18
+ -- Apply via: psql "$DATABASE_URL" -f drizzle/0286_brain_analytics_key.sql
19
+ -- creates-column: public.tenant_mcp_twin_keys.analytics_key
20
+ -- creates-column: public.user_brain_claims.analytics_key
21
+
22
+ ALTER TABLE public.tenant_mcp_twin_keys
23
+ ADD COLUMN IF NOT EXISTS analytics_key boolean NOT NULL DEFAULT true;
24
+
25
+ ALTER TABLE public.user_brain_claims
26
+ ADD COLUMN IF NOT EXISTS analytics_key boolean NOT NULL DEFAULT true;
@@ -0,0 +1,25 @@
1
+ -- Brain-pool subject on Brain principals (THINK-625 backfill gap) — the
2
+ -- write side of the `subject` field in user-claims/v1.
3
+ --
4
+ -- The manifest published `users.cognito_sub` as `subject`, but that column
5
+ -- is the user's sub in THIS product's Cognito pool. The Brain MCP has its
6
+ -- OWN end-user pool, and a federated (Google/Microsoft) sign-in there mints
7
+ -- a DIFFERENT sub — so the published subject never matched the Brain access
8
+ -- token, claims resolution fell closed to emptyGrants(), and an HR user's
9
+ -- payroll ask was refused (TEI, 2026-08-12). Access tokens carry no email
10
+ -- claim, so the reader's email fallback cannot save the mismatch.
11
+ --
12
+ -- This column holds the sub the user's Brain tokens actually carry. It is
13
+ -- captured at the ONE place the product ever sees a Brain token: the
14
+ -- mcp-oauth callback (skills.ts), which decodes the access token it just
15
+ -- exchanged and republishes the manifest. The manifest publisher prefers
16
+ -- brain_subject over users.cognito_sub; NULL (never captured) keeps
17
+ -- today's fallback byte-identical.
18
+ --
19
+ -- Hand-rolled (mirrors the 0274/0281/0282/0284/0285/0286 convention; not
20
+ -- registered in meta/_journal.json).
21
+ -- Apply via: psql "$DATABASE_URL" -f drizzle/0287_brain_subject.sql
22
+ -- creates-column: public.user_brain_claims.brain_subject
23
+
24
+ ALTER TABLE public.user_brain_claims
25
+ ADD COLUMN IF NOT EXISTS brain_subject text;
@@ -0,0 +1,25 @@
1
+ -- Multi-lane identity enrollment (Eric 2026-08-15: "I need all three" —
2
+ -- email, Google AND Microsoft sign-in for one person).
3
+ --
4
+ -- uq_user_auth_identities_cognito_sub allowed ONE enrollment per Cognito
5
+ -- subject, total. But a Cognito user with linked providers carries one sub
6
+ -- across lanes (password + Microsoft on the same sub), so whichever lane
7
+ -- enrolled first consumed the slot and every other lane admitted to
8
+ -- "No tenant assigned". Admission already matches per-connection
9
+ -- (auth-admission.ts: identity.authProviderResourceId === route.connectionId);
10
+ -- the index was the only thing forcing one lane per person.
11
+ --
12
+ -- One row per (subject, connection) from now on. The invariant that one
13
+ -- Cognito subject maps to ONE product user is no longer carried by this
14
+ -- index — the writers enforce it (cross-user guard in auto-link, enrollment
15
+ -- consume, and invite).
16
+ --
17
+ -- Hand-rolled (mirrors the 0274..0287 convention; not registered in
18
+ -- meta/_journal.json).
19
+ -- Apply via: psql "$DATABASE_URL" -f drizzle/0288_multi_lane_identities.sql
20
+ -- drops: public.uq_user_auth_identities_cognito_sub
21
+ -- creates: public.uq_user_auth_identities_sub_connection
22
+
23
+ DROP INDEX IF EXISTS public.uq_user_auth_identities_cognito_sub;
24
+ CREATE UNIQUE INDEX IF NOT EXISTS uq_user_auth_identities_sub_connection
25
+ ON public.user_auth_identities (cognito_issuer, cognito_sub, auth_provider_resource_id);
@@ -7,7 +7,7 @@ import {
7
7
  AwsSdkSigV4Signer,
8
8
  NODE_AUTH_SCHEME_PREFERENCE_OPTIONS,
9
9
  resolveAwsSdkSigV4Config
10
- } from "./chunk-DVPBI5HM.js";
10
+ } from "./chunk-OLUQ4U2Z.js";
11
11
  import "./chunk-EI5ZX7CN.js";
12
12
  import {
13
13
  NodeHttpHandler
@@ -48,7 +48,7 @@ import {
48
48
  resolveHostHeaderConfig,
49
49
  resolveRetryConfig,
50
50
  resolveUserAgentConfig
51
- } from "./chunk-QOERT44A.js";
51
+ } from "./chunk-YQCYD6NE.js";
52
52
  import {
53
53
  NODE_REGION_CONFIG_FILE_OPTIONS,
54
54
  NODE_REGION_CONFIG_OPTIONS,
@@ -7,7 +7,7 @@ import {
7
7
  AwsSdkSigV4Signer,
8
8
  NODE_AUTH_SCHEME_PREFERENCE_OPTIONS,
9
9
  resolveAwsSdkSigV4Config
10
- } from "./chunk-DVPBI5HM.js";
10
+ } from "./chunk-OLUQ4U2Z.js";
11
11
  import "./chunk-EI5ZX7CN.js";
12
12
  import {
13
13
  Sha256Node
@@ -51,7 +51,7 @@ import {
51
51
  resolveHostHeaderConfig,
52
52
  resolveRetryConfig,
53
53
  resolveUserAgentConfig
54
- } from "./chunk-QOERT44A.js";
54
+ } from "./chunk-YQCYD6NE.js";
55
55
  import {
56
56
  NODE_REGION_CONFIG_FILE_OPTIONS,
57
57
  NODE_REGION_CONFIG_OPTIONS,
@@ -152,8 +152,8 @@ When a plugin version bump should become visible without a full app deploy:
152
152
  6. Install or upgrade through ThinkWork. Do not substitute a direct Terraform
153
153
  apply, vendor cloud login, local Docker Compose run, or manual catalog edit.
154
154
  7. Run the package-owned smoke for the plugin after install/upgrade. For
155
- LastMile, that means proving `lastmile--crm`, `lastmile--tasks`, and
156
- `lastmile--routing` through ThinkWork's MCP proxy.
155
+ Twenty, that means proving the `twenty--crm` MCP server through
156
+ ThinkWork's MCP proxy.
157
157
 
158
158
  Before closing a migration slice, run the source-boundary check:
159
159
 
@@ -21,10 +21,7 @@
21
21
  "build:catalog": "tsx scripts/generate-plugin-registry.ts --check && tsx scripts/build-catalog.ts"
22
22
  },
23
23
  "dependencies": {
24
- "@thinkwork/plugin-company-data": "workspace:*",
25
- "@thinkwork/plugin-company-etl": "workspace:*",
26
24
  "@thinkwork/plugin-email-channel": "workspace:*",
27
- "@thinkwork/plugin-lastmile": "workspace:*",
28
25
  "@thinkwork/plugin-n8n": "workspace:*",
29
26
  "@thinkwork/plugin-sendgrid": "workspace:*",
30
27
  "@thinkwork/plugin-twenty": "workspace:*"
@@ -33,15 +33,18 @@ describe("buildSignedCatalogJson", () => {
33
33
  trustedPublicKeyPem: keys.publicKeyPem,
34
34
  });
35
35
  expect(verified.plugins.map((plugin) => plugin.pluginKey)).toEqual([
36
- "lastmile",
37
36
  "n8n",
38
37
  "email-channel",
39
38
  "sendgrid",
40
- "company-data",
41
- "company-etl",
42
39
  "twenty",
43
40
  ]);
44
41
  expect(verified.generatedAt).toBe("2026-06-12T00:00:00.000Z");
42
+ // AE5 (THINK-334 U6): the built catalog must not carry the superseded data plugins.
43
+ for (const removedKey of ["lastmile", "company-data", "company-etl"]) {
44
+ expect(verified.plugins.map((plugin) => plugin.pluginKey)).not.toContain(
45
+ removedKey,
46
+ );
47
+ }
45
48
  });
46
49
 
47
50
  it("includes source provenance when provided by the publisher", () => {
@@ -14,7 +14,7 @@ import {
14
14
  type SignedPluginCatalogDocument,
15
15
  } from "../catalog";
16
16
  import type { PluginManifest } from "../contracts";
17
- import { lastmileManifest, n8nManifest } from "../registry";
17
+ import { n8nManifest, twentyManifest } from "../registry";
18
18
 
19
19
  function keyPair() {
20
20
  const pair = generateKeyPairSync("ed25519");
@@ -36,7 +36,7 @@ function clone<T>(value: T): T {
36
36
 
37
37
  function signedDocument(privateKeyPem: string): SignedPluginCatalogDocument {
38
38
  const catalog = buildPluginCatalog({
39
- manifests: [lastmileManifest],
39
+ manifests: [twentyManifest],
40
40
  generatedAt: "2026-06-12T00:00:00.000Z",
41
41
  source: {
42
42
  repository: "thinkwork-ai/thinkwork",
@@ -53,19 +53,19 @@ function signedDocument(privateKeyPem: string): SignedPluginCatalogDocument {
53
53
 
54
54
  describe("buildPluginCatalog", () => {
55
55
  it("builds an entry per manifest with per-version payload digests", () => {
56
- const catalog = buildPluginCatalog({ manifests: [lastmileManifest] });
56
+ const catalog = buildPluginCatalog({ manifests: [twentyManifest] });
57
57
  expect(catalog.schemaVersion).toBe(PLUGIN_CATALOG_SCHEMA_VERSION);
58
58
  expect(catalog.plugins).toHaveLength(1);
59
59
  const entry = catalog.plugins[0];
60
- expect(entry.pluginKey).toBe("lastmile");
60
+ expect(entry.pluginKey).toBe("twenty");
61
61
  expect(entry.versions[0].version).toBe("0.1.0");
62
62
  expect(entry.versions[0].payloadSha256).toMatch(/^[a-f0-9]{64}$/);
63
- expect(entry.versions[0].payload).toEqual(lastmileManifest.versions[0]);
63
+ expect(entry.versions[0].payload).toEqual(twentyManifest.versions[0]);
64
64
  });
65
65
 
66
66
  it("optionally signs GitHub source provenance", () => {
67
67
  const catalog = buildPluginCatalog({
68
- manifests: [lastmileManifest],
68
+ manifests: [twentyManifest],
69
69
  generatedAt: "2026-06-12T00:00:00.000Z",
70
70
  source: {
71
71
  repository: "thinkwork-ai/thinkwork",
@@ -82,7 +82,7 @@ describe("buildPluginCatalog", () => {
82
82
 
83
83
  it("keeps source provenance optional for bundled fallback catalogs", () => {
84
84
  const catalog = buildPluginCatalog({
85
- manifests: [lastmileManifest],
85
+ manifests: [twentyManifest],
86
86
  generatedAt: "2026-06-12T00:00:00.000Z",
87
87
  });
88
88
  expect(catalog.source).toBeUndefined();
@@ -90,41 +90,41 @@ describe("buildPluginCatalog", () => {
90
90
 
91
91
  it("rejects duplicate plugin keys in a catalog", () => {
92
92
  expect(() =>
93
- buildPluginCatalog({ manifests: [lastmileManifest, lastmileManifest] }),
94
- ).toThrow(/Duplicate plugin key in catalog: lastmile/);
93
+ buildPluginCatalog({ manifests: [twentyManifest, twentyManifest] }),
94
+ ).toThrow(/Duplicate plugin key in catalog: twenty/);
95
95
  });
96
96
 
97
97
  it("sorts catalog plugins alphabetically by display name", () => {
98
98
  const catalog = buildPluginCatalog({
99
- manifests: [n8nManifest, lastmileManifest],
99
+ manifests: [twentyManifest, n8nManifest],
100
100
  });
101
101
 
102
102
  expect(catalog.plugins.map((plugin) => plugin.displayName)).toEqual([
103
- "LastMile",
104
103
  "n8n",
104
+ "Twenty CRM",
105
105
  ]);
106
106
  });
107
107
 
108
108
  it("preserves premium metadata on catalog entries", () => {
109
109
  const premiumManifest: PluginManifest = {
110
- ...lastmileManifest,
110
+ ...twentyManifest,
111
111
  premium: {
112
- entitlementProductKey: "lastmile-premium",
112
+ entitlementProductKey: "twenty-premium",
113
113
  installKeyRequired: true,
114
114
  installKeyPrompt: "Enter the install key.",
115
115
  },
116
116
  };
117
117
  const catalog = buildPluginCatalog({ manifests: [premiumManifest] });
118
- expect(catalog.plugins[0].pluginKey).toBe("lastmile");
118
+ expect(catalog.plugins[0].pluginKey).toBe("twenty");
119
119
  expect(catalog.plugins[0].premium).toEqual({
120
- entitlementProductKey: "lastmile-premium",
120
+ entitlementProductKey: "twenty-premium",
121
121
  installKeyRequired: true,
122
122
  installKeyPrompt: "Enter the install key.",
123
123
  });
124
124
  });
125
125
 
126
126
  it("rejects invalid manifests", () => {
127
- const bad = clone(lastmileManifest);
127
+ const bad = clone(twentyManifest);
128
128
  bad.versions[0].version = "not-semver";
129
129
  expect(() => buildPluginCatalog({ manifests: [bad] })).toThrow(
130
130
  /not valid semver/,
@@ -134,7 +134,7 @@ describe("buildPluginCatalog", () => {
134
134
  it("rejects invalid source provenance shape", () => {
135
135
  expect(() =>
136
136
  buildPluginCatalog({
137
- manifests: [lastmileManifest],
137
+ manifests: [twentyManifest],
138
138
  source: {
139
139
  repository: "not-owner-name",
140
140
  ref: "main",
@@ -144,7 +144,7 @@ describe("buildPluginCatalog", () => {
144
144
  ).toThrow(/owner\/name/);
145
145
  expect(() =>
146
146
  buildPluginCatalog({
147
- manifests: [lastmileManifest],
147
+ manifests: [twentyManifest],
148
148
  source: {
149
149
  repository: "thinkwork-ai/thinkwork",
150
150
  ref: "main",
@@ -163,7 +163,7 @@ describe("sign → verify round-trip", () => {
163
163
  document,
164
164
  trustedPublicKeyPem: keys.publicKeyPem,
165
165
  });
166
- expect(verified.plugins[0].pluginKey).toBe("lastmile");
166
+ expect(verified.plugins[0].pluginKey).toBe("twenty");
167
167
  expect(verified.source).toEqual({
168
168
  repository: "thinkwork-ai/thinkwork",
169
169
  ref: "main",
@@ -194,8 +194,8 @@ describe("verification fails closed", () => {
194
194
  const document = signedDocument(keys.privateKeyPem);
195
195
  const tampered = clone(document);
196
196
  const component = tampered.catalog.plugins[0].versions[0].payload
197
- .components[0] as { endpointUrl?: string };
198
- component.endpointUrl = "https://evil.example.invalid/mcp";
197
+ .components[0] as { displayName?: string };
198
+ component.displayName = "Tampered CRM";
199
199
  expect(() =>
200
200
  verifyPluginCatalog({
201
201
  document: tampered,
@@ -6,14 +6,91 @@ import {
6
6
  type PluginManifest,
7
7
  type PluginVersion,
8
8
  } from "../contracts";
9
- import { lastmileManifest } from "../registry";
9
+
10
+ /**
11
+ * Local fixture manifest exercising the richest contract surface: three
12
+ * OAuth MCP servers plus a bundled skill. (Shape preserved from the
13
+ * retired LastMile catalog entry, THINK-334 U6.)
14
+ */
15
+ const FIXTURE_AUTH_DOMAIN = "https://fixture-auth.example.invalid";
16
+ const FIXTURE_MCP_BASE = "https://fixture-mcp.example.invalid";
17
+
18
+ const fixtureManifest = {
19
+ pluginKey: "fixture-crm",
20
+ displayName: "Fixture CRM",
21
+ description:
22
+ "Contract-test fixture plugin with CRM, task, and routing MCP servers.",
23
+ versions: [
24
+ {
25
+ version: "0.1.0",
26
+ requiredOauthScopes: ["openid", "email", "profile", "offline_access"],
27
+ components: [
28
+ {
29
+ type: "mcp-server",
30
+ key: "crm",
31
+ displayName: "Fixture CRM",
32
+ description: "Customer accounts and sales opportunities.",
33
+ endpointUrl: `${FIXTURE_MCP_BASE}/crm`,
34
+ auth: {
35
+ mode: "oauth",
36
+ authDomain: FIXTURE_AUTH_DOMAIN,
37
+ resourceIndicator: `${FIXTURE_MCP_BASE}/crm`,
38
+ },
39
+ },
40
+ {
41
+ type: "mcp-server",
42
+ key: "tasks",
43
+ displayName: "Fixture Tasks",
44
+ description: "Work orders and task assignments.",
45
+ endpointUrl: `${FIXTURE_MCP_BASE}/tasks`,
46
+ auth: {
47
+ mode: "oauth",
48
+ authDomain: FIXTURE_AUTH_DOMAIN,
49
+ resourceIndicator: `${FIXTURE_MCP_BASE}/tasks`,
50
+ },
51
+ },
52
+ {
53
+ type: "mcp-server",
54
+ key: "routing",
55
+ displayName: "Fixture Routing",
56
+ description: "Route planning and technician dispatch.",
57
+ endpointUrl: `${FIXTURE_MCP_BASE}/routing`,
58
+ auth: {
59
+ mode: "oauth",
60
+ authDomain: FIXTURE_AUTH_DOMAIN,
61
+ resourceIndicator: `${FIXTURE_MCP_BASE}/routing`,
62
+ },
63
+ },
64
+ {
65
+ type: "skills",
66
+ key: "skills",
67
+ skills: [
68
+ {
69
+ slug: "fixture-crm--crm-basics",
70
+ skillMd: [
71
+ "---",
72
+ "name: fixture-crm--crm-basics",
73
+ "description: Fixture skill for contract validation tests.",
74
+ "---",
75
+ "",
76
+ "# Fixture CRM basics",
77
+ "",
78
+ "Work CRM requests through the fixture MCP tools.",
79
+ ].join("\n"),
80
+ },
81
+ ],
82
+ },
83
+ ],
84
+ },
85
+ ],
86
+ } as unknown as PluginManifest;
10
87
 
11
88
  function clone<T>(value: T): T {
12
89
  return JSON.parse(JSON.stringify(value)) as T;
13
90
  }
14
91
 
15
92
  function manifest(mutate?: (manifest: PluginManifest) => void): PluginManifest {
16
- const copy = clone(lastmileManifest);
93
+ const copy = clone(fixtureManifest);
17
94
  mutate?.(copy);
18
95
  return copy;
19
96
  }
@@ -23,9 +100,9 @@ function version(m: PluginManifest): PluginVersion {
23
100
  }
24
101
 
25
102
  describe("validatePluginManifest", () => {
26
- it("validates the LastMile manifest (three OAuth MCP servers + skills)", () => {
27
- const validated = validatePluginManifest(lastmileManifest);
28
- expect(validated.pluginKey).toBe("lastmile");
103
+ it("validates the fixture manifest (three OAuth MCP servers + skills)", () => {
104
+ const validated = validatePluginManifest(fixtureManifest);
105
+ expect(validated.pluginKey).toBe("fixture-crm");
29
106
  const components = validated.versions[0].components;
30
107
  expect(
31
108
  components.filter((component) => component.type === "mcp-server"),
@@ -38,7 +115,7 @@ describe("validatePluginManifest", () => {
38
115
 
39
116
  it("rejects non-object input", () => {
40
117
  expect(() => validatePluginManifest(null)).toThrow(PluginManifestError);
41
- expect(() => validatePluginManifest("lastmile")).toThrow(
118
+ expect(() => validatePluginManifest("fixture-crm")).toThrow(
42
119
  PluginManifestError,
43
120
  );
44
121
  });
@@ -52,13 +129,13 @@ describe("validatePluginManifest", () => {
52
129
  it("validates premium metadata for key-gated plugins", () => {
53
130
  const ok = manifest((m) => {
54
131
  m.premium = {
55
- entitlementProductKey: "lastmile",
132
+ entitlementProductKey: "fixture-crm",
56
133
  installKeyRequired: true,
57
134
  installKeyPrompt: "Enter the install key provided by ThinkWork.",
58
135
  };
59
136
  });
60
137
  expect(validatePluginManifest(ok).premium).toEqual({
61
- entitlementProductKey: "lastmile",
138
+ entitlementProductKey: "fixture-crm",
62
139
  installKeyRequired: true,
63
140
  installKeyPrompt: "Enter the install key provided by ThinkWork.",
64
141
  });
@@ -67,7 +144,7 @@ describe("validatePluginManifest", () => {
67
144
  it("rejects premium metadata without a true install-key requirement", () => {
68
145
  const bad = manifest((m) => {
69
146
  m.premium = {
70
- entitlementProductKey: "lastmile",
147
+ entitlementProductKey: "fixture-crm",
71
148
  installKeyRequired: true,
72
149
  installKeyPrompt: "Enter the install key provided by ThinkWork.",
73
150
  };
@@ -82,7 +159,7 @@ describe("validatePluginManifest", () => {
82
159
  it("rejects premium metadata without an entitlement product key", () => {
83
160
  const bad = manifest((m) => {
84
161
  m.premium = {
85
- entitlementProductKey: "lastmile",
162
+ entitlementProductKey: "fixture-crm",
86
163
  installKeyRequired: true,
87
164
  installKeyPrompt: "Enter the install key provided by ThinkWork.",
88
165
  };
@@ -116,7 +193,7 @@ describe("validatePluginManifest", () => {
116
193
  (component) => component.type === "skills",
117
194
  );
118
195
  if (skills?.type !== "skills") throw new Error("missing skills component");
119
- skills.skills[0].slug = "lastmile/crm-basics";
196
+ skills.skills[0].slug = "fixture-crm/crm-basics";
120
197
  expect(() => validatePluginManifest(bad)).toThrow(/skill slug/);
121
198
  });
122
199
 
@@ -648,18 +725,18 @@ describe("validatePluginManifest", () => {
648
725
  {
649
726
  type: "ui-surface",
650
727
  key: "dashboard",
651
- displayName: "LastMile dashboard",
728
+ displayName: "Fixture CRM dashboard",
652
729
  intendedMount: "settings.plugins.detail.tab",
653
730
  launch: {
654
731
  schemaVersion: 1,
655
732
  type: "app",
656
- appKey: "lastmile-dashboard",
733
+ appKey: "fixture-crm-dashboard",
657
734
  routeSegment: "dashboard",
658
735
  mount: "main-shell",
659
736
  runtime: "trusted-bundled-react",
660
737
  description: "Account engagement dashboard.",
661
738
  icon: "layout-dashboard",
662
- entitlementProductKey: "lastmile",
739
+ entitlementProductKey: "fixture-crm",
663
740
  },
664
741
  },
665
742
  );
@@ -672,7 +749,7 @@ describe("validatePluginManifest", () => {
672
749
  m.versions[0].components.push({
673
750
  type: "ui-surface",
674
751
  key: "settings",
675
- displayName: "LastMile settings",
752
+ displayName: "Fixture CRM settings",
676
753
  intendedMount: "settings.plugins.detail.tab",
677
754
  });
678
755
  });
@@ -683,7 +760,7 @@ describe("validatePluginManifest", () => {
683
760
  expect(surface).toMatchObject({
684
761
  type: "ui-surface",
685
762
  key: "settings",
686
- displayName: "LastMile settings",
763
+ displayName: "Fixture CRM settings",
687
764
  intendedMount: "settings.plugins.detail.tab",
688
765
  });
689
766
  expect(surface?.type === "ui-surface" ? surface.launch : undefined).toBe(
@@ -765,7 +842,7 @@ describe("validatePluginManifest", () => {
765
842
  m.versions[0].components.push({
766
843
  type: "ui-surface",
767
844
  key: "dashboard",
768
- displayName: "LastMile dashboard",
845
+ displayName: "Fixture CRM dashboard",
769
846
  intendedMount: "",
770
847
  });
771
848
  });
@@ -778,7 +855,7 @@ describe("validatePluginManifest", () => {
778
855
  {
779
856
  schemaVersion: 2,
780
857
  type: "app",
781
- appKey: "lastmile-dashboard",
858
+ appKey: "fixture-crm-dashboard",
782
859
  routeSegment: "dashboard",
783
860
  mount: "main-shell",
784
861
  runtime: "trusted-bundled-react",
@@ -786,7 +863,7 @@ describe("validatePluginManifest", () => {
786
863
  {
787
864
  schemaVersion: 1,
788
865
  type: "widget",
789
- appKey: "lastmile-dashboard",
866
+ appKey: "fixture-crm-dashboard",
790
867
  routeSegment: "dashboard",
791
868
  mount: "main-shell",
792
869
  runtime: "trusted-bundled-react",
@@ -794,7 +871,7 @@ describe("validatePluginManifest", () => {
794
871
  {
795
872
  schemaVersion: 1,
796
873
  type: "app",
797
- appKey: "LastMile",
874
+ appKey: "Fixture_CRM",
798
875
  routeSegment: "dashboard",
799
876
  mount: "main-shell",
800
877
  runtime: "trusted-bundled-react",
@@ -802,7 +879,7 @@ describe("validatePluginManifest", () => {
802
879
  {
803
880
  schemaVersion: 1,
804
881
  type: "app",
805
- appKey: "lastmile-dashboard",
882
+ appKey: "fixture-crm-dashboard",
806
883
  routeSegment: "/dashboard",
807
884
  mount: "main-shell",
808
885
  runtime: "trusted-bundled-react",
@@ -810,7 +887,7 @@ describe("validatePluginManifest", () => {
810
887
  {
811
888
  schemaVersion: 1,
812
889
  type: "app",
813
- appKey: "lastmile-dashboard",
890
+ appKey: "fixture-crm-dashboard",
814
891
  routeSegment: "dashboard",
815
892
  mount: "settings",
816
893
  runtime: "trusted-bundled-react",
@@ -818,7 +895,7 @@ describe("validatePluginManifest", () => {
818
895
  {
819
896
  schemaVersion: 1,
820
897
  type: "app",
821
- appKey: "lastmile-dashboard",
898
+ appKey: "fixture-crm-dashboard",
822
899
  routeSegment: "dashboard",
823
900
  mount: "main-shell",
824
901
  runtime: "remote-url",
@@ -826,7 +903,7 @@ describe("validatePluginManifest", () => {
826
903
  {
827
904
  schemaVersion: 1,
828
905
  type: "app",
829
- appKey: "lastmile-dashboard",
906
+ appKey: "fixture-crm-dashboard",
830
907
  routeSegment: "dashboard",
831
908
  mount: "main-shell",
832
909
  runtime: "trusted-bundled-react",
@@ -837,7 +914,7 @@ describe("validatePluginManifest", () => {
837
914
  m.versions[0].components.push({
838
915
  type: "ui-surface",
839
916
  key: "dashboard",
840
- displayName: "LastMile dashboard",
917
+ displayName: "Fixture CRM dashboard",
841
918
  intendedMount: "settings.plugins.detail.tab",
842
919
  launch,
843
920
  } as never);
@@ -13,10 +13,7 @@ import {
13
13
  describe("first-party plugin packages", () => {
14
14
  it("registers n8n from its root plugin package boundary", () => {
15
15
  expect(firstPartyPluginPackages.map((entry) => entry.packageKey)).toEqual([
16
- "company-data",
17
- "company-etl",
18
16
  "email-channel",
19
- "lastmile",
20
17
  "n8n",
21
18
  "sendgrid",
22
19
  "twenty",
@@ -45,16 +42,20 @@ describe("first-party plugin packages", () => {
45
42
 
46
43
  it("publishes every first-party plugin manifest through the catalog aggregate", () => {
47
44
  expect(allPluginManifests.map((manifest) => manifest.pluginKey)).toEqual([
48
- "lastmile",
49
45
  "n8n",
50
46
  "email-channel",
51
47
  "sendgrid",
52
- "company-data",
53
- "company-etl",
54
48
  "twenty",
55
49
  ]);
56
50
  });
57
51
 
52
+ it("no longer publishes the superseded data plugins (THINK-334 U6)", () => {
53
+ const keys = allPluginManifests.map((manifest) => manifest.pluginKey);
54
+ expect(keys).not.toContain("lastmile");
55
+ expect(keys).not.toContain("company-data");
56
+ expect(keys).not.toContain("company-etl");
57
+ });
58
+
58
59
  it("rejects package descriptors whose source root does not match the key", () => {
59
60
  expect(() =>
60
61
  defineFirstPartyPluginPackage({
@@ -18,26 +18,11 @@ describe("generated first-party plugin registry", () => {
18
18
  exportName: entry.exportName,
19
19
  })),
20
20
  ).toEqual([
21
- {
22
- packageKey: "company-data",
23
- packageName: "@thinkwork/plugin-company-data",
24
- exportName: "companyDataPluginPackage",
25
- },
26
- {
27
- packageKey: "company-etl",
28
- packageName: "@thinkwork/plugin-company-etl",
29
- exportName: "companyEtlPluginPackage",
30
- },
31
21
  {
32
22
  packageKey: "email-channel",
33
23
  packageName: "@thinkwork/plugin-email-channel",
34
24
  exportName: "emailChannelPluginPackage",
35
25
  },
36
- {
37
- packageKey: "lastmile",
38
- packageName: "@thinkwork/plugin-lastmile",
39
- exportName: "lastmilePluginPackage",
40
- },
41
26
  {
42
27
  packageKey: "n8n",
43
28
  packageName: "@thinkwork/plugin-n8n",