thinkwork-cli 0.13.1 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (262) hide show
  1. package/README.md +3 -14
  2. package/dist/{api-client-4DZ266J5.js → api-client-4P4JZOBX.js} +3 -1
  3. package/dist/bowser-6Z6JFAIR.js +2822 -0
  4. package/dist/{chunk-Y2WHJECR.js → chunk-4OMDWYZQ.js} +5 -44
  5. package/dist/chunk-AD2NIWB5.js +6516 -0
  6. package/dist/chunk-DV3MRBR5.js +43 -0
  7. package/dist/chunk-EI5ZX7CN.js +522 -0
  8. package/dist/chunk-EUJ7X6YD.js +126 -0
  9. package/dist/chunk-GG5WKBOX.js +436 -0
  10. package/dist/chunk-I64EZSU5.js +358 -0
  11. package/dist/chunk-KMIJ5KGT.js +128 -0
  12. package/dist/chunk-MWQ7RO76.js +137 -0
  13. package/dist/chunk-OCPHU34C.js +996 -0
  14. package/dist/chunk-OLUQ4U2Z.js +1728 -0
  15. package/dist/chunk-XYM7PE2A.js +2264 -0
  16. package/dist/chunk-YQCYD6NE.js +3299 -0
  17. package/dist/cli.js +49156 -31257
  18. package/dist/commands/enterprise/templates/deploy-repo/scripts/apply-release.mjs +0 -1
  19. package/dist/commands/enterprise/templates/deploy-repo/scripts/smoke.mjs +0 -1
  20. package/dist/commands/enterprise/templates/deploy-repo/terraform/main.tf +0 -14
  21. package/dist/dist-es-2OTNTL4N.js +315 -0
  22. package/dist/dist-es-2XVAH4BQ.js +14726 -0
  23. package/dist/dist-es-3DPDUJAH.js +2000 -0
  24. package/dist/dist-es-BNZTBBVC.js +176 -0
  25. package/dist/dist-es-CD2RBDAC.js +88 -0
  26. package/dist/dist-es-I4FW57PS.js +88 -0
  27. package/dist/dist-es-KL7Y5NB2.js +377 -0
  28. package/dist/dist-es-KVFWJNDY.js +318 -0
  29. package/dist/dist-es-PS73DWNL.js +70 -0
  30. package/dist/dist-es-S3NZQFGT.js +170 -0
  31. package/dist/dist-es-SGCA4P32.js +48 -0
  32. package/dist/dist-es-WBM6J4RA.js +70 -0
  33. package/dist/dist-es-ZGVADYIF.js +485 -0
  34. package/dist/dist-es-ZKC2QKD2.js +377 -0
  35. package/dist/drizzle/0076_scheduled_jobs_marco_backfill.sql +2 -1
  36. package/dist/drizzle/0079_seed_tenant_customize_catalog.sql +1 -0
  37. package/dist/drizzle/0090_brain_schema_extraction.sql +10 -0
  38. package/dist/drizzle/0132_drop_computer_tables.sql +3 -0
  39. package/dist/drizzle/0160_compliance_event_types_plugins.sql +2 -0
  40. package/dist/drizzle/0214_think137_drop_judge_evidence_roi.sql +1 -0
  41. package/dist/drizzle/0216_drop_agent_loop_versions_goal_worker_policy.sql +1 -0
  42. package/dist/drizzle/0227_analyst_reader_role.sql +17 -20
  43. package/dist/drizzle/0230_analyst_rls.sql +28 -36
  44. package/dist/drizzle/0250_kg_schema_extraction.sql +27 -0
  45. package/dist/drizzle/0251_brain_stragglers.sql +21 -0
  46. package/dist/drizzle/0253_drop_brain_substrate.sql +2 -0
  47. package/dist/drizzle/0257_agents_runtime_allow_harness.sql +24 -0
  48. package/dist/drizzle/0261_native_auth_control_plane.sql +332 -0
  49. package/dist/drizzle/0262_auth_subscription_tickets.sql +59 -0
  50. package/dist/drizzle/0263_agentcore_runtime_identifier.sql +69 -0
  51. package/dist/drizzle/0263_drop_workos_auth_runtime.sql +236 -0
  52. package/dist/drizzle/0264_auth_enrollment_attempt_limits.sql +15 -0
  53. package/dist/drizzle/0265_eval_runs_requester_identity.sql +28 -0
  54. package/dist/drizzle/0265_require_fully_valid_auth_publication.sql +27 -0
  55. package/dist/drizzle/0266_auth_identity_recovery_grants.sql +9 -0
  56. package/dist/drizzle/0266_eval_profiles_runtime_type.sql +12 -0
  57. package/dist/drizzle/0267_ontology_candidate_rejections.sql +53 -0
  58. package/dist/drizzle/0268_identity_crosswalk_routing.sql +182 -0
  59. package/dist/drizzle/0269_ontology_system_map.sql +31 -0
  60. package/dist/drizzle/0270_tool_execution_ledger.sql +115 -0
  61. package/dist/drizzle/0271_ontology_twin_declarations.sql +47 -0
  62. package/dist/drizzle/0272_identity_graph_projection_cursor.sql +23 -0
  63. package/dist/drizzle/0273_twin_materialization_suggestions.sql +29 -0
  64. package/dist/drizzle/0274_tenant_mcp_twin_keys.sql +59 -0
  65. package/dist/drizzle/0275_identity_bulk_rebuild_fence.sql +30 -0
  66. package/dist/drizzle/0276_tool_execution_ledger_allow_cascade_delete.sql +18 -0
  67. package/dist/drizzle/0277_knowledge_base_sources.sql +107 -0
  68. package/dist/drizzle/0278_kb_page_transcription.sql +55 -0
  69. package/dist/drizzle/0279_mcp_servers_off_plugin_provenance.sql +93 -0
  70. package/dist/drizzle/0280_work_item_external_refs_drop_plane_provider.sql +46 -0
  71. package/dist/drizzle/0281_tenant_mcp_twin_keys_expiry_suffix.sql +9 -0
  72. package/dist/drizzle/0282_tenant_mcp_twin_keys_grants.sql +24 -0
  73. package/dist/drizzle/0283_agents_agentcore_runtime_dispatch.sql +13 -0
  74. package/dist/drizzle/0284_user_brain_claims.sql +69 -0
  75. package/dist/drizzle/0285_tenant_mcp_twin_keys_trusted_subsystem.sql +30 -0
  76. package/dist/drizzle/0286_brain_analytics_key.sql +26 -0
  77. package/dist/drizzle/0287_brain_subject.sql +25 -0
  78. package/dist/drizzle/0288_multi_lane_identities.sql +25 -0
  79. package/dist/event-streams-7JNLJEEL.js +894 -0
  80. package/dist/event-streams-KDF5RWR6.js +1515 -0
  81. package/dist/loadSso-ETCXTR4I.js +576 -0
  82. package/dist/loadSso-UBD7KUHE.js +583 -0
  83. package/dist/plugins/README.md +2 -2
  84. package/dist/plugins/catalog/package.json +1 -5
  85. package/dist/plugins/catalog/src/__tests__/build-catalog.test.ts +6 -4
  86. package/dist/plugins/catalog/src/__tests__/catalog.test.ts +21 -21
  87. package/dist/plugins/catalog/src/__tests__/contracts.test.ts +102 -94
  88. package/dist/plugins/catalog/src/__tests__/plugin-package.test.ts +7 -8
  89. package/dist/plugins/catalog/src/__tests__/plugin-registry.test.ts +0 -20
  90. package/dist/plugins/catalog/src/contracts.ts +17 -179
  91. package/dist/plugins/catalog/src/registry/generated-first-party.ts +0 -24
  92. package/dist/plugins/n8n/test/integrated-app-contract.test.ts +1 -1
  93. package/dist/plugins/twenty/package.json +2 -1
  94. package/dist/plugins/twenty/scripts/LAMBDA_DEPLOY.md +114 -0
  95. package/dist/plugins/twenty/scripts/build-lambda.sh +29 -0
  96. package/dist/plugins/twenty/scripts/configure-product-views.ts +195 -0
  97. package/dist/plugins/twenty/scripts/lambda-handler.ts +49 -0
  98. package/dist/plugins/twenty/scripts/lib/__tests__/load-attachments.test.ts +38 -0
  99. package/dist/plugins/twenty/scripts/lib/__tests__/load-records.test.ts +145 -2
  100. package/dist/plugins/twenty/scripts/lib/__tests__/mappers.test.ts +397 -151
  101. package/dist/plugins/twenty/scripts/lib/__tests__/members-ensure.test.ts +28 -129
  102. package/dist/plugins/twenty/scripts/lib/__tests__/provision-members-db.test.ts +10 -0
  103. package/dist/plugins/twenty/scripts/lib/__tests__/schema-ensure.test.ts +13 -8
  104. package/dist/plugins/twenty/scripts/lib/lastmile-reader.ts +222 -2
  105. package/dist/plugins/twenty/scripts/lib/load-attachments.ts +29 -0
  106. package/dist/plugins/twenty/scripts/lib/load-records.ts +160 -43
  107. package/dist/plugins/twenty/scripts/lib/mappers.ts +368 -152
  108. package/dist/plugins/twenty/scripts/lib/members-ensure.ts +43 -268
  109. package/dist/plugins/twenty/scripts/lib/provision-members-db.ts +57 -0
  110. package/dist/plugins/twenty/scripts/lib/schema-ensure.ts +136 -31
  111. package/dist/plugins/twenty/scripts/migrate-lastmile.ts +254 -152
  112. package/dist/plugins/twenty/scripts/provision-twenty-members.ts +44 -1
  113. package/dist/plugins/twenty/scripts/purge-lastmile-import.ts +178 -0
  114. package/dist/plugins/twenty/scripts/restructure-products.ts +312 -0
  115. package/dist/plugins/twenty/scripts/retag-stage-values.ts +362 -0
  116. package/dist/plugins/twenty/test/manifest.test.ts +2 -4
  117. package/dist/scripts/post-deploy.sh +79 -1
  118. package/dist/signin-5QZNRSOO.js +821 -0
  119. package/dist/sso-oidc-XK673P54.js +837 -0
  120. package/dist/sts-OXI2UALF.js +1113 -0
  121. package/dist/sts-SQW4NBK3.js +1117 -0
  122. package/dist/terraform/examples/greenfield/main.tf +391 -176
  123. package/dist/terraform/examples/greenfield/terraform.tfvars.example +26 -8
  124. package/dist/terraform/modules/app/agentcore-admin/main.tf +47 -0
  125. package/dist/terraform/modules/app/agentcore-code-interpreter/README.md +39 -47
  126. package/dist/terraform/modules/app/agentcore-code-interpreter/main.tf +13 -66
  127. package/dist/terraform/modules/app/agentcore-identity/main.tf +253 -0
  128. package/dist/terraform/modules/app/agentcore-identity/outputs.tf +51 -0
  129. package/dist/terraform/modules/app/agentcore-identity/scripts/bootstrap_twenty_oauth_client.sh +239 -0
  130. package/dist/terraform/modules/app/agentcore-identity/scripts/delete_identity.sh +22 -0
  131. package/dist/terraform/modules/app/agentcore-identity/scripts/delete_twenty_identity.sh +16 -0
  132. package/dist/terraform/modules/app/agentcore-identity/scripts/delete_workload_identity.sh +19 -0
  133. package/dist/terraform/modules/app/agentcore-identity/scripts/ensure_workload_identity.sh +29 -0
  134. package/dist/terraform/modules/app/agentcore-identity/scripts/read_identity.sh +55 -0
  135. package/dist/terraform/modules/app/agentcore-identity/scripts/reconcile_identity.sh +73 -0
  136. package/dist/terraform/modules/app/agentcore-identity/scripts/reconcile_twenty_identity.sh +45 -0
  137. package/dist/terraform/modules/app/agentcore-identity/scripts/reconcile_twenty_provider.mjs +123 -0
  138. package/dist/terraform/modules/app/agentcore-identity/tests/tainted-marker/after.tf +15 -0
  139. package/dist/terraform/modules/app/agentcore-identity/tests/tainted-marker/before.tf +7 -0
  140. package/dist/terraform/modules/app/agentcore-identity/tests/tainted-marker/identity-after.tf +8 -0
  141. package/dist/terraform/modules/app/agentcore-identity/tests/tainted-marker/identity-before.tf +9 -0
  142. package/dist/terraform/modules/app/agentcore-identity/tests/tainted-marker/thinkwork-after.tf +3 -0
  143. package/dist/terraform/modules/app/agentcore-identity/tests/tainted-marker/thinkwork-before.tf +3 -0
  144. package/dist/terraform/modules/app/agentcore-identity/variables.tf +60 -0
  145. package/dist/terraform/modules/app/agentcore-memory/README.md +46 -9
  146. package/dist/terraform/modules/app/agentcore-memory/main.tf +27 -10
  147. package/dist/terraform/modules/app/agentcore-memory/scripts/create_or_find_memory.sh +156 -24
  148. package/dist/terraform/modules/app/agentcore-pi/README.md +1 -3
  149. package/dist/terraform/modules/app/agentcore-pi/main.tf +42 -52
  150. package/dist/terraform/modules/app/agentcore-pi/outputs.tf +3 -3
  151. package/dist/terraform/modules/app/agentcore-pi/scripts/reconcile_pi_runtime.mjs +175 -0
  152. package/dist/terraform/modules/app/agentcore-pi/variables.tf +35 -28
  153. package/dist/terraform/modules/app/agentcore-platform/main.tf +68 -0
  154. package/dist/terraform/modules/app/agentcore-runtime/main.tf +4 -20
  155. package/dist/terraform/modules/app/appsync-subscriptions/main.tf +127 -21
  156. package/dist/terraform/modules/app/appsync-subscriptions/outputs.tf +0 -6
  157. package/dist/terraform/modules/app/appsync-subscriptions/variables.tf +5 -0
  158. package/dist/terraform/modules/app/capability-broker/main.tf +2 -2
  159. package/dist/terraform/modules/app/capability-broker/variables.tf +11 -0
  160. package/dist/terraform/modules/app/deployment-control-plane/README.md +264 -0
  161. package/dist/terraform/modules/app/deployment-control-plane/buildspec.yml +4 -1
  162. package/dist/terraform/modules/app/deployment-control-plane/main.tf +94 -0
  163. package/dist/terraform/modules/app/deployment-control-plane/outputs.tf +5 -0
  164. package/dist/terraform/modules/app/deployment-control-plane/runner.py +3689 -233
  165. package/dist/terraform/modules/app/deployment-control-plane/test_runner_bundle.py +2579 -140
  166. package/dist/terraform/modules/app/deployment-control-plane/variables.tf +33 -0
  167. package/dist/terraform/modules/app/lambda-api/auth-state.tf +72 -0
  168. package/dist/terraform/modules/app/lambda-api/chat-latency-observability.tf +466 -0
  169. package/dist/terraform/modules/app/lambda-api/dispatch-dlq.tf +55 -0
  170. package/dist/terraform/modules/app/lambda-api/handlers.tf +531 -619
  171. package/dist/terraform/modules/app/lambda-api/iam-grouped.tf +350 -241
  172. package/dist/terraform/modules/app/lambda-api/main.tf +75 -13
  173. package/dist/terraform/modules/app/lambda-api/memory-alarms.tf +3 -28
  174. package/dist/terraform/modules/app/lambda-api/oauth-secrets.tf +1 -2
  175. package/dist/terraform/modules/app/lambda-api/outputs.tf +17 -10
  176. package/dist/terraform/modules/app/lambda-api/runtime-config.tf +3 -21
  177. package/dist/terraform/modules/app/lambda-api/turn-assertion.tf +45 -0
  178. package/dist/terraform/modules/app/lambda-api/variables.tf +307 -121
  179. package/dist/{plugins/n8n/terraform → terraform/modules/app}/n8n/README.md +1 -1
  180. package/dist/{plugins/n8n/terraform → terraform/modules/app}/n8n/main.tf +18 -18
  181. package/dist/terraform/modules/app/sandbox-log-scrubber/README.md +11 -10
  182. package/dist/terraform/modules/app/sandbox-log-scrubber/main.tf +5 -5
  183. package/dist/terraform/modules/app/static-site/main.tf +1 -1
  184. package/dist/terraform/modules/app/www-dns/main.tf +9 -27
  185. package/dist/terraform/modules/app/www-dns/variables.tf +4 -10
  186. package/dist/terraform/modules/data/aurora-postgres/README.md +34 -0
  187. package/dist/terraform/modules/data/aurora-postgres/alarms.tf +82 -0
  188. package/dist/terraform/modules/data/aurora-postgres/main.tf +27 -57
  189. package/dist/terraform/modules/data/aurora-postgres/outputs.tf +0 -9
  190. package/dist/terraform/modules/data/aurora-postgres/variables.tf +41 -0
  191. package/dist/terraform/modules/data/s3-buckets/main.tf +5 -6
  192. package/dist/terraform/modules/foundation/cognito/main.tf +367 -72
  193. package/dist/terraform/modules/foundation/cognito/outputs.tf +47 -0
  194. package/dist/terraform/modules/foundation/cognito/variables.tf +131 -9
  195. package/dist/terraform/modules/thinkwork/README.md +5 -1
  196. package/dist/terraform/modules/thinkwork/main.tf +459 -234
  197. package/dist/terraform/modules/thinkwork/outputs.tf +44 -62
  198. package/dist/terraform/modules/thinkwork/variables.tf +353 -89
  199. package/dist/terraform/schema.graphql +69 -36
  200. package/dist/workspace-defaults/files/INSTRUCTIONS.md +9 -11
  201. package/dist/workspace-defaults/files/MEMORY_GUIDE.md +38 -35
  202. package/dist/workspace-defaults/files/ROUTER.md +1 -1
  203. package/dist/workspace-defaults/files/TOOLS.md +9 -39
  204. package/dist/workspace-defaults/files/USER.md +1 -0
  205. package/dist/workspace-defaults/files/agents/analyst/INSTRUCTIONS.md +6 -3
  206. package/dist/workspace-defaults/files/catalog-skills/brain-brief-builder/SKILL.md +165 -0
  207. package/dist/workspace-defaults/files/catalog-skills/n8n-workflow-operator/SKILL.md +75 -0
  208. package/dist/workspace-defaults/files/catalog-skills/n8n-workflow-operator/references/mcp-tooling.md +40 -0
  209. package/dist/workspace-defaults/files/catalog-skills/n8n-workflow-operator/references/validation-and-handoff.md +40 -0
  210. package/dist/workspace-defaults/files/catalog-skills/n8n-workflow-operator/references/workflow-authoring.md +46 -0
  211. package/dist/workspace-defaults/files/skills/artifact-builder/references/crm-dashboard.md +1 -1
  212. package/dist/workspace-defaults/files/skills/document-composer/SKILL.md +22 -3
  213. package/package.json +3 -2
  214. package/dist/drizzle/0261_thread_turns_origin_turn_index.sql +0 -11
  215. package/dist/plugins/company-data/README.md +0 -49
  216. package/dist/plugins/company-data/package.json +0 -21
  217. package/dist/plugins/company-data/src/index.ts +0 -30
  218. package/dist/plugins/company-data/src/manifest.ts +0 -26
  219. package/dist/plugins/company-data/test/manifest.test.ts +0 -116
  220. package/dist/plugins/company-data/tsconfig.json +0 -8
  221. package/dist/plugins/company-etl/README.md +0 -46
  222. package/dist/plugins/company-etl/package.json +0 -21
  223. package/dist/plugins/company-etl/src/index.ts +0 -29
  224. package/dist/plugins/company-etl/src/manifest.ts +0 -26
  225. package/dist/plugins/company-etl/test/manifest.test.ts +0 -108
  226. package/dist/plugins/company-etl/tsconfig.json +0 -8
  227. package/dist/plugins/lastmile/README.md +0 -50
  228. package/dist/plugins/lastmile/package.json +0 -23
  229. package/dist/plugins/lastmile/smoke/lastmile-plugin-smoke.mjs +0 -661
  230. package/dist/plugins/lastmile/src/api/tasks-adapter.ts +0 -572
  231. package/dist/plugins/lastmile/src/discovery.fixture.ts +0 -64
  232. package/dist/plugins/lastmile/src/index.ts +0 -46
  233. package/dist/plugins/lastmile/src/manifest.ts +0 -139
  234. package/dist/plugins/lastmile/test/api/tasks-adapter.test.ts +0 -266
  235. package/dist/plugins/lastmile/test/discovery.test.ts +0 -88
  236. package/dist/plugins/lastmile/tsconfig.json +0 -8
  237. package/dist/plugins/n8n/smoke/n8n-managed-app-smoke.mjs +0 -409
  238. package/dist/plugins/twenty/smoke/twenty-managed-app-smoke.mjs +0 -359
  239. package/dist/plugins/workos-auth/package.json +0 -22
  240. package/dist/plugins/workos-auth/src/index.ts +0 -30
  241. package/dist/plugins/workos-auth/src/manifest.ts +0 -40
  242. package/dist/plugins/workos-auth/src/provider-contract.ts +0 -39
  243. package/dist/plugins/workos-auth/test/manifest.test.ts +0 -94
  244. package/dist/plugins/workos-auth/tsconfig.json +0 -8
  245. package/dist/terraform/modules/app/agentcore-code-interpreter/Dockerfile.sandbox-base +0 -61
  246. package/dist/terraform/modules/app/agentcore-code-interpreter/sandbox/sitecustomize.py +0 -227
  247. package/dist/terraform/modules/app/agentcore-code-interpreter/sandbox/test_sitecustomize.py +0 -277
  248. package/dist/terraform/modules/app/agentcore-code-interpreter/scripts/build_and_push_sandbox_base.sh +0 -70
  249. package/dist/terraform/modules/app/agentcore-harness/main.tf +0 -101
  250. package/dist/terraform/modules/app/agentcore-harness/outputs.tf +0 -9
  251. package/dist/terraform/modules/app/agentcore-harness/variables.tf +0 -25
  252. package/dist/terraform/modules/app/hindsight-memory/README.md +0 -89
  253. package/dist/terraform/modules/app/hindsight-memory/main.tf +0 -411
  254. package/dist/terraform/modules/data/bedrock-knowledge-base/main.tf +0 -102
  255. /package/dist/{plugins/n8n/terraform → terraform/modules/app}/n8n/outputs.tf +0 -0
  256. /package/dist/{plugins/n8n/terraform → terraform/modules/app}/n8n/scripts/sync-database.py +0 -0
  257. /package/dist/{plugins/n8n/terraform → terraform/modules/app}/n8n/scripts/test_sync_database.py +0 -0
  258. /package/dist/{plugins/n8n/terraform → terraform/modules/app}/n8n/variables.tf +0 -0
  259. /package/dist/{plugins/twenty/terraform → terraform/modules/app}/twenty/README.md +0 -0
  260. /package/dist/{plugins/twenty/terraform → terraform/modules/app}/twenty/main.tf +0 -0
  261. /package/dist/{plugins/twenty/terraform → terraform/modules/app}/twenty/outputs.tf +0 -0
  262. /package/dist/{plugins/twenty/terraform → terraform/modules/app}/twenty/variables.tf +0 -0
@@ -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(
@@ -691,75 +768,6 @@ describe("validatePluginManifest", () => {
691
768
  );
692
769
  });
693
770
 
694
- it("validates auth-provider components", () => {
695
- const ok = manifest((m) => {
696
- m.versions[0].components.push({
697
- type: "auth-provider",
698
- key: "workos-auth",
699
- displayName: "WorkOS Cognito federation",
700
- provider: "workos",
701
- settingsSurface: "settings.plugins.workos-auth",
702
- cognitoIdentityProviderName: "WorkOSAuth",
703
- configFields: [
704
- {
705
- key: "issuerUrl",
706
- displayName: "WorkOS issuer URL",
707
- required: true,
708
- storage: "metadata",
709
- },
710
- {
711
- key: "clientSecret",
712
- displayName: "WorkOS client secret",
713
- required: true,
714
- storage: "secret-ref",
715
- },
716
- ],
717
- publicOptions: [
718
- {
719
- key: "sso",
720
- displayName: "Continue with SSO",
721
- providerSpecific: false,
722
- recommended: true,
723
- },
724
- ],
725
- });
726
- });
727
- expect(() => validatePluginManifest(ok)).not.toThrow();
728
- });
729
-
730
- it("rejects auth-provider config fields that expose values in the manifest", () => {
731
- const bad = manifest((m) => {
732
- m.versions[0].components.push({
733
- type: "auth-provider",
734
- key: "workos-auth",
735
- displayName: "WorkOS Cognito federation",
736
- provider: "workos",
737
- settingsSurface: "settings.plugins.workos-auth",
738
- cognitoIdentityProviderName: "WorkOSAuth",
739
- configFields: [
740
- {
741
- key: "clientSecret",
742
- displayName: "WorkOS client secret",
743
- required: true,
744
- storage: "secret-ref",
745
- value: "do-not-ship",
746
- } as never,
747
- ],
748
- publicOptions: [
749
- {
750
- key: "sso",
751
- displayName: "Continue with SSO",
752
- providerSpecific: false,
753
- recommended: true,
754
- },
755
- ],
756
- });
757
- });
758
- expect(() => validatePluginManifest(bad)).toThrow(
759
- /value is not allowed in auth-provider manifests/,
760
- );
761
- });
762
-
763
771
  it("validates an email-channel capability with Resend, SendGrid, and SES providers", () => {
764
772
  const ok = manifest((m) => {
765
773
  m.versions[0].capabilities = [
@@ -834,7 +842,7 @@ describe("validatePluginManifest", () => {
834
842
  m.versions[0].components.push({
835
843
  type: "ui-surface",
836
844
  key: "dashboard",
837
- displayName: "LastMile dashboard",
845
+ displayName: "Fixture CRM dashboard",
838
846
  intendedMount: "",
839
847
  });
840
848
  });
@@ -847,7 +855,7 @@ describe("validatePluginManifest", () => {
847
855
  {
848
856
  schemaVersion: 2,
849
857
  type: "app",
850
- appKey: "lastmile-dashboard",
858
+ appKey: "fixture-crm-dashboard",
851
859
  routeSegment: "dashboard",
852
860
  mount: "main-shell",
853
861
  runtime: "trusted-bundled-react",
@@ -855,7 +863,7 @@ describe("validatePluginManifest", () => {
855
863
  {
856
864
  schemaVersion: 1,
857
865
  type: "widget",
858
- appKey: "lastmile-dashboard",
866
+ appKey: "fixture-crm-dashboard",
859
867
  routeSegment: "dashboard",
860
868
  mount: "main-shell",
861
869
  runtime: "trusted-bundled-react",
@@ -863,7 +871,7 @@ describe("validatePluginManifest", () => {
863
871
  {
864
872
  schemaVersion: 1,
865
873
  type: "app",
866
- appKey: "LastMile",
874
+ appKey: "Fixture_CRM",
867
875
  routeSegment: "dashboard",
868
876
  mount: "main-shell",
869
877
  runtime: "trusted-bundled-react",
@@ -871,7 +879,7 @@ describe("validatePluginManifest", () => {
871
879
  {
872
880
  schemaVersion: 1,
873
881
  type: "app",
874
- appKey: "lastmile-dashboard",
882
+ appKey: "fixture-crm-dashboard",
875
883
  routeSegment: "/dashboard",
876
884
  mount: "main-shell",
877
885
  runtime: "trusted-bundled-react",
@@ -879,7 +887,7 @@ describe("validatePluginManifest", () => {
879
887
  {
880
888
  schemaVersion: 1,
881
889
  type: "app",
882
- appKey: "lastmile-dashboard",
890
+ appKey: "fixture-crm-dashboard",
883
891
  routeSegment: "dashboard",
884
892
  mount: "settings",
885
893
  runtime: "trusted-bundled-react",
@@ -887,7 +895,7 @@ describe("validatePluginManifest", () => {
887
895
  {
888
896
  schemaVersion: 1,
889
897
  type: "app",
890
- appKey: "lastmile-dashboard",
898
+ appKey: "fixture-crm-dashboard",
891
899
  routeSegment: "dashboard",
892
900
  mount: "main-shell",
893
901
  runtime: "remote-url",
@@ -895,7 +903,7 @@ describe("validatePluginManifest", () => {
895
903
  {
896
904
  schemaVersion: 1,
897
905
  type: "app",
898
- appKey: "lastmile-dashboard",
906
+ appKey: "fixture-crm-dashboard",
899
907
  routeSegment: "dashboard",
900
908
  mount: "main-shell",
901
909
  runtime: "trusted-bundled-react",
@@ -906,7 +914,7 @@ describe("validatePluginManifest", () => {
906
914
  m.versions[0].components.push({
907
915
  type: "ui-surface",
908
916
  key: "dashboard",
909
- displayName: "LastMile dashboard",
917
+ displayName: "Fixture CRM dashboard",
910
918
  intendedMount: "settings.plugins.detail.tab",
911
919
  launch,
912
920
  } as never);
@@ -13,14 +13,10 @@ 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",
23
- "workos-auth",
24
20
  ]);
25
21
 
26
22
  expect(n8nPluginPackage.sourceRoot).toBe("plugins/n8n");
@@ -46,17 +42,20 @@ describe("first-party plugin packages", () => {
46
42
 
47
43
  it("publishes every first-party plugin manifest through the catalog aggregate", () => {
48
44
  expect(allPluginManifests.map((manifest) => manifest.pluginKey)).toEqual([
49
- "lastmile",
50
45
  "n8n",
51
46
  "email-channel",
52
47
  "sendgrid",
53
- "company-data",
54
- "company-etl",
55
48
  "twenty",
56
- "workos-auth",
57
49
  ]);
58
50
  });
59
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
+
60
59
  it("rejects package descriptors whose source root does not match the key", () => {
61
60
  expect(() =>
62
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",
@@ -53,11 +38,6 @@ describe("generated first-party plugin registry", () => {
53
38
  packageName: "@thinkwork/plugin-twenty",
54
39
  exportName: "twentyPluginPackage",
55
40
  },
56
- {
57
- packageKey: "workos-auth",
58
- packageName: "@thinkwork/plugin-workos-auth",
59
- exportName: "workosAuthPluginPackage",
60
- },
61
41
  ]);
62
42
  });
63
43