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.
- package/README.md +3 -14
- package/dist/{api-client-JYZXYQJR.js → api-client-4P4JZOBX.js} +1 -1
- package/dist/{chunk-Z2F6RJFR.js → chunk-4OMDWYZQ.js} +4 -5
- package/dist/{chunk-ILZKG5WV.js → chunk-AD2NIWB5.js} +434 -69
- package/dist/chunk-MWQ7RO76.js +137 -0
- package/dist/{chunk-DVPBI5HM.js → chunk-OLUQ4U2Z.js} +26 -26
- package/dist/{chunk-QOERT44A.js → chunk-YQCYD6NE.js} +57 -44
- package/dist/cli.js +4400 -16431
- package/dist/commands/enterprise/templates/deploy-repo/scripts/apply-release.mjs +0 -1
- package/dist/commands/enterprise/templates/deploy-repo/scripts/smoke.mjs +0 -1
- package/dist/commands/enterprise/templates/deploy-repo/terraform/main.tf +0 -14
- package/dist/{dist-es-CRV46D5B.js → dist-es-2OTNTL4N.js} +4 -4
- package/dist/{dist-es-ENBUC3JP.js → dist-es-2XVAH4BQ.js} +2 -2
- package/dist/{dist-es-DCY4IC3Y.js → dist-es-3DPDUJAH.js} +2 -2
- package/dist/{dist-es-G7PTG75M.js → dist-es-BNZTBBVC.js} +1 -1
- package/dist/{dist-es-GKDBE7E6.js → dist-es-CD2RBDAC.js} +1 -1
- package/dist/{dist-es-R7FGL2IB.js → dist-es-I4FW57PS.js} +1 -1
- package/dist/{dist-es-USORBXZ5.js → dist-es-KVFWJNDY.js} +4 -4
- package/dist/{dist-es-HY3535OI.js → dist-es-PS73DWNL.js} +2 -2
- package/dist/{dist-es-LDE437AM.js → dist-es-S3NZQFGT.js} +1 -1
- package/dist/{dist-es-G54LBMRN.js → dist-es-SGCA4P32.js} +1 -1
- package/dist/{dist-es-Q57SZXZ7.js → dist-es-WBM6J4RA.js} +2 -2
- package/dist/{dist-es-P26FWFLT.js → dist-es-ZGVADYIF.js} +8 -8
- package/dist/drizzle/0227_analyst_reader_role.sql +17 -26
- package/dist/drizzle/0230_analyst_rls.sql +28 -45
- package/dist/drizzle/0261_native_auth_control_plane.sql +7 -3
- package/dist/drizzle/0270_tool_execution_ledger.sql +115 -0
- package/dist/drizzle/0271_ontology_twin_declarations.sql +47 -0
- package/dist/drizzle/0272_identity_graph_projection_cursor.sql +23 -0
- package/dist/drizzle/0273_twin_materialization_suggestions.sql +29 -0
- package/dist/drizzle/0274_tenant_mcp_twin_keys.sql +59 -0
- package/dist/drizzle/0275_identity_bulk_rebuild_fence.sql +30 -0
- package/dist/drizzle/0276_tool_execution_ledger_allow_cascade_delete.sql +18 -0
- package/dist/drizzle/0277_knowledge_base_sources.sql +107 -0
- package/dist/drizzle/0278_kb_page_transcription.sql +55 -0
- package/dist/drizzle/0279_mcp_servers_off_plugin_provenance.sql +93 -0
- package/dist/drizzle/0280_work_item_external_refs_drop_plane_provider.sql +46 -0
- package/dist/drizzle/0281_tenant_mcp_twin_keys_expiry_suffix.sql +9 -0
- package/dist/drizzle/0282_tenant_mcp_twin_keys_grants.sql +24 -0
- package/dist/drizzle/0283_agents_agentcore_runtime_dispatch.sql +13 -0
- package/dist/drizzle/0284_user_brain_claims.sql +69 -0
- package/dist/drizzle/0285_tenant_mcp_twin_keys_trusted_subsystem.sql +30 -0
- package/dist/drizzle/0286_brain_analytics_key.sql +26 -0
- package/dist/drizzle/0287_brain_subject.sql +25 -0
- package/dist/drizzle/0288_multi_lane_identities.sql +25 -0
- package/dist/{loadSso-DJVB7BXE.js → loadSso-ETCXTR4I.js} +2 -2
- package/dist/{loadSso-JAMNA3WY.js → loadSso-UBD7KUHE.js} +2 -2
- package/dist/plugins/README.md +2 -2
- package/dist/plugins/catalog/package.json +0 -3
- package/dist/plugins/catalog/src/__tests__/build-catalog.test.ts +6 -3
- package/dist/plugins/catalog/src/__tests__/catalog.test.ts +21 -21
- package/dist/plugins/catalog/src/__tests__/contracts.test.ts +102 -25
- package/dist/plugins/catalog/src/__tests__/plugin-package.test.ts +7 -6
- package/dist/plugins/catalog/src/__tests__/plugin-registry.test.ts +0 -15
- package/dist/plugins/catalog/src/contracts.ts +15 -0
- package/dist/plugins/catalog/src/registry/generated-first-party.ts +0 -18
- package/dist/plugins/n8n/test/integrated-app-contract.test.ts +1 -1
- package/dist/plugins/twenty/package.json +2 -1
- package/dist/plugins/twenty/scripts/LAMBDA_DEPLOY.md +114 -0
- package/dist/plugins/twenty/scripts/build-lambda.sh +29 -0
- package/dist/plugins/twenty/scripts/configure-product-views.ts +195 -0
- package/dist/plugins/twenty/scripts/lambda-handler.ts +49 -0
- package/dist/plugins/twenty/scripts/lib/__tests__/load-attachments.test.ts +38 -0
- package/dist/plugins/twenty/scripts/lib/__tests__/load-records.test.ts +145 -2
- package/dist/plugins/twenty/scripts/lib/__tests__/mappers.test.ts +397 -151
- package/dist/plugins/twenty/scripts/lib/__tests__/members-ensure.test.ts +28 -129
- package/dist/plugins/twenty/scripts/lib/__tests__/provision-members-db.test.ts +10 -0
- package/dist/plugins/twenty/scripts/lib/__tests__/schema-ensure.test.ts +13 -8
- package/dist/plugins/twenty/scripts/lib/lastmile-reader.ts +222 -2
- package/dist/plugins/twenty/scripts/lib/load-attachments.ts +29 -0
- package/dist/plugins/twenty/scripts/lib/load-records.ts +160 -43
- package/dist/plugins/twenty/scripts/lib/mappers.ts +368 -152
- package/dist/plugins/twenty/scripts/lib/members-ensure.ts +43 -268
- package/dist/plugins/twenty/scripts/lib/provision-members-db.ts +57 -0
- package/dist/plugins/twenty/scripts/lib/schema-ensure.ts +136 -31
- package/dist/plugins/twenty/scripts/migrate-lastmile.ts +254 -152
- package/dist/plugins/twenty/scripts/provision-twenty-members.ts +44 -1
- package/dist/plugins/twenty/scripts/purge-lastmile-import.ts +178 -0
- package/dist/plugins/twenty/scripts/restructure-products.ts +312 -0
- package/dist/plugins/twenty/scripts/retag-stage-values.ts +362 -0
- package/dist/plugins/twenty/test/manifest.test.ts +2 -4
- package/dist/scripts/post-deploy.sh +79 -1
- package/dist/{signin-UGDWTGS4.js → signin-5QZNRSOO.js} +2 -2
- package/dist/{sso-oidc-Q4VXANXY.js → sso-oidc-XK673P54.js} +2 -2
- package/dist/{sts-CWLSE3GH.js → sts-OXI2UALF.js} +6 -134
- package/dist/{sts-DNZLNVOV.js → sts-SQW4NBK3.js} +6 -134
- package/dist/terraform/examples/greenfield/main.tf +233 -175
- package/dist/terraform/examples/greenfield/terraform.tfvars.example +12 -8
- package/dist/terraform/modules/app/agentcore-admin/main.tf +47 -0
- package/dist/terraform/modules/app/agentcore-code-interpreter/README.md +39 -47
- package/dist/terraform/modules/app/agentcore-code-interpreter/main.tf +13 -66
- package/dist/terraform/modules/app/agentcore-identity/main.tf +106 -26
- package/dist/terraform/modules/app/agentcore-identity/outputs.tf +6 -6
- package/dist/terraform/modules/app/agentcore-identity/scripts/bootstrap_twenty_oauth_client.sh +216 -99
- package/dist/terraform/modules/app/agentcore-identity/scripts/delete_identity.sh +6 -9
- package/dist/terraform/modules/app/agentcore-identity/scripts/delete_workload_identity.sh +19 -0
- package/dist/terraform/modules/app/agentcore-identity/scripts/ensure_workload_identity.sh +29 -0
- package/dist/terraform/modules/app/agentcore-identity/scripts/read_identity.sh +22 -7
- package/dist/terraform/modules/app/agentcore-identity/scripts/reconcile_twenty_identity.sh +17 -46
- package/dist/terraform/modules/app/agentcore-identity/scripts/reconcile_twenty_provider.mjs +65 -3
- package/dist/terraform/modules/app/agentcore-identity/tests/tainted-marker/after.tf +15 -0
- package/dist/terraform/modules/app/agentcore-identity/tests/tainted-marker/before.tf +7 -0
- package/dist/terraform/modules/app/agentcore-identity/tests/tainted-marker/identity-after.tf +8 -0
- package/dist/terraform/modules/app/agentcore-identity/tests/tainted-marker/identity-before.tf +9 -0
- package/dist/terraform/modules/app/agentcore-identity/tests/tainted-marker/thinkwork-after.tf +3 -0
- package/dist/terraform/modules/app/agentcore-identity/tests/tainted-marker/thinkwork-before.tf +3 -0
- package/dist/terraform/modules/app/agentcore-identity/variables.tf +6 -0
- package/dist/terraform/modules/app/agentcore-memory/README.md +46 -9
- package/dist/terraform/modules/app/agentcore-memory/main.tf +27 -10
- package/dist/terraform/modules/app/agentcore-memory/scripts/create_or_find_memory.sh +156 -24
- package/dist/terraform/modules/app/agentcore-pi/README.md +1 -3
- package/dist/terraform/modules/app/agentcore-pi/main.tf +42 -52
- package/dist/terraform/modules/app/agentcore-pi/outputs.tf +3 -3
- package/dist/terraform/modules/app/agentcore-pi/scripts/reconcile_pi_runtime.mjs +175 -0
- package/dist/terraform/modules/app/agentcore-pi/variables.tf +35 -28
- package/dist/terraform/modules/app/agentcore-platform/main.tf +68 -0
- package/dist/terraform/modules/app/agentcore-runtime/main.tf +4 -20
- package/dist/terraform/modules/app/capability-broker/main.tf +2 -2
- package/dist/terraform/modules/app/capability-broker/variables.tf +11 -0
- package/dist/terraform/modules/app/deployment-control-plane/README.md +264 -0
- package/dist/terraform/modules/app/deployment-control-plane/buildspec.yml +4 -1
- package/dist/terraform/modules/app/deployment-control-plane/main.tf +94 -0
- package/dist/terraform/modules/app/deployment-control-plane/outputs.tf +5 -0
- package/dist/terraform/modules/app/deployment-control-plane/runner.py +2641 -124
- package/dist/terraform/modules/app/deployment-control-plane/test_runner_bundle.py +2034 -154
- package/dist/terraform/modules/app/deployment-control-plane/variables.tf +33 -0
- package/dist/terraform/modules/app/lambda-api/auth-state.tf +72 -0
- package/dist/terraform/modules/app/lambda-api/chat-latency-observability.tf +466 -0
- package/dist/terraform/modules/app/lambda-api/dispatch-dlq.tf +55 -0
- package/dist/terraform/modules/app/lambda-api/handlers.tf +411 -723
- package/dist/terraform/modules/app/lambda-api/iam-grouped.tf +262 -198
- package/dist/terraform/modules/app/lambda-api/main.tf +51 -13
- package/dist/terraform/modules/app/lambda-api/mcp-oauth.tf +4 -181
- package/dist/terraform/modules/app/lambda-api/memory-alarms.tf +3 -28
- package/dist/terraform/modules/app/lambda-api/oauth-secrets.tf +1 -2
- package/dist/terraform/modules/app/lambda-api/outputs.tf +17 -45
- package/dist/terraform/modules/app/lambda-api/turn-assertion.tf +45 -0
- package/dist/terraform/modules/app/lambda-api/variables.tf +219 -126
- package/dist/{plugins/n8n/terraform → terraform/modules/app}/n8n/README.md +1 -1
- package/dist/{plugins/n8n/terraform → terraform/modules/app}/n8n/main.tf +18 -18
- package/dist/terraform/modules/app/sandbox-log-scrubber/README.md +11 -10
- package/dist/terraform/modules/app/sandbox-log-scrubber/main.tf +5 -5
- package/dist/terraform/modules/app/static-site/main.tf +1 -1
- package/dist/terraform/modules/app/www-dns/main.tf +9 -27
- package/dist/terraform/modules/app/www-dns/variables.tf +4 -10
- package/dist/terraform/modules/data/aurora-postgres/README.md +34 -0
- package/dist/terraform/modules/data/aurora-postgres/alarms.tf +82 -0
- package/dist/terraform/modules/data/aurora-postgres/main.tf +27 -57
- package/dist/terraform/modules/data/aurora-postgres/outputs.tf +0 -9
- package/dist/terraform/modules/data/aurora-postgres/variables.tf +41 -0
- package/dist/terraform/modules/data/s3-buckets/main.tf +5 -6
- package/dist/terraform/modules/foundation/cognito/main.tf +81 -8
- package/dist/terraform/modules/foundation/cognito/outputs.tf +5 -0
- package/dist/terraform/modules/foundation/cognito/variables.tf +24 -12
- package/dist/terraform/modules/thinkwork/README.md +5 -1
- package/dist/terraform/modules/thinkwork/main.tf +376 -374
- package/dist/terraform/modules/thinkwork/outputs.tf +12 -158
- package/dist/terraform/modules/thinkwork/variables.tf +246 -89
- package/dist/workspace-defaults/files/INSTRUCTIONS.md +9 -11
- package/dist/workspace-defaults/files/MEMORY_GUIDE.md +38 -35
- package/dist/workspace-defaults/files/ROUTER.md +1 -1
- package/dist/workspace-defaults/files/TOOLS.md +9 -39
- package/dist/workspace-defaults/files/agents/analyst/INSTRUCTIONS.md +6 -3
- package/dist/workspace-defaults/files/catalog-skills/brain-brief-builder/SKILL.md +165 -0
- package/dist/workspace-defaults/files/catalog-skills/n8n-workflow-operator/SKILL.md +75 -0
- package/dist/workspace-defaults/files/catalog-skills/n8n-workflow-operator/references/mcp-tooling.md +40 -0
- package/dist/workspace-defaults/files/catalog-skills/n8n-workflow-operator/references/validation-and-handoff.md +40 -0
- package/dist/workspace-defaults/files/catalog-skills/n8n-workflow-operator/references/workflow-authoring.md +46 -0
- package/dist/workspace-defaults/files/skills/artifact-builder/references/crm-dashboard.md +1 -1
- package/dist/workspace-defaults/files/skills/document-composer/SKILL.md +22 -3
- package/package.json +1 -1
- package/dist/drizzle/0261_managed_harness_multiplayer.sql +0 -313
- package/dist/drizzle/0262_parallel_harness_threads.sql +0 -9
- package/dist/drizzle/0264_harness_tool_execution_ledger.sql +0 -113
- package/dist/plugins/company-data/README.md +0 -49
- package/dist/plugins/company-data/package.json +0 -21
- package/dist/plugins/company-data/src/index.ts +0 -30
- package/dist/plugins/company-data/src/manifest.ts +0 -26
- package/dist/plugins/company-data/test/manifest.test.ts +0 -116
- package/dist/plugins/company-data/tsconfig.json +0 -8
- package/dist/plugins/company-etl/README.md +0 -46
- package/dist/plugins/company-etl/package.json +0 -21
- package/dist/plugins/company-etl/src/index.ts +0 -29
- package/dist/plugins/company-etl/src/manifest.ts +0 -26
- package/dist/plugins/company-etl/test/manifest.test.ts +0 -108
- package/dist/plugins/company-etl/tsconfig.json +0 -8
- package/dist/plugins/lastmile/README.md +0 -50
- package/dist/plugins/lastmile/package.json +0 -23
- package/dist/plugins/lastmile/smoke/lastmile-plugin-smoke.mjs +0 -661
- package/dist/plugins/lastmile/src/api/tasks-adapter.ts +0 -572
- package/dist/plugins/lastmile/src/discovery.fixture.ts +0 -64
- package/dist/plugins/lastmile/src/index.ts +0 -46
- package/dist/plugins/lastmile/src/manifest.ts +0 -139
- package/dist/plugins/lastmile/test/api/tasks-adapter.test.ts +0 -266
- package/dist/plugins/lastmile/test/discovery.test.ts +0 -88
- package/dist/plugins/lastmile/tsconfig.json +0 -8
- package/dist/plugins/n8n/smoke/n8n-managed-app-smoke.mjs +0 -409
- package/dist/plugins/twenty/smoke/twenty-managed-app-smoke.mjs +0 -359
- package/dist/terraform/modules/app/agentcore-code-interpreter/Dockerfile.sandbox-base +0 -61
- package/dist/terraform/modules/app/agentcore-code-interpreter/sandbox/sitecustomize.py +0 -227
- package/dist/terraform/modules/app/agentcore-code-interpreter/sandbox/test_sitecustomize.py +0 -277
- package/dist/terraform/modules/app/agentcore-code-interpreter/scripts/build_and_push_sandbox_base.sh +0 -70
- package/dist/terraform/modules/app/agentcore-gateway/main.tf +0 -305
- package/dist/terraform/modules/app/agentcore-gateway/outputs.tf +0 -44
- package/dist/terraform/modules/app/agentcore-gateway/scripts/delete_gateway.sh +0 -93
- package/dist/terraform/modules/app/agentcore-gateway/scripts/read_gateway.sh +0 -33
- package/dist/terraform/modules/app/agentcore-gateway/scripts/reconcile_gateway.sh +0 -543
- package/dist/terraform/modules/app/agentcore-gateway/variables.tf +0 -70
- package/dist/terraform/modules/app/agentcore-harness/main.tf +0 -330
- package/dist/terraform/modules/app/agentcore-harness/outputs.tf +0 -72
- package/dist/terraform/modules/app/agentcore-harness/scripts/delete_harness.sh +0 -5
- package/dist/terraform/modules/app/agentcore-harness/scripts/harness-lifecycle.mjs +0 -430
- package/dist/terraform/modules/app/agentcore-harness/scripts/harness-readback.mjs +0 -180
- package/dist/terraform/modules/app/agentcore-harness/scripts/harness-tool-contract.mjs +0 -193
- package/dist/terraform/modules/app/agentcore-harness/scripts/prune_harness.sh +0 -5
- package/dist/terraform/modules/app/agentcore-harness/scripts/read_harness.sh +0 -5
- package/dist/terraform/modules/app/agentcore-harness/scripts/reconcile_harness.sh +0 -5
- package/dist/terraform/modules/app/agentcore-harness/variables.tf +0 -96
- package/dist/terraform/modules/app/hindsight-memory/README.md +0 -89
- package/dist/terraform/modules/app/hindsight-memory/main.tf +0 -411
- package/dist/terraform/modules/app/lambda-api/agentcore-harness-alarms.tf +0 -88
- package/dist/terraform/modules/app/lambda-api/agentcore-identity-alarms.tf +0 -91
- package/dist/terraform/modules/data/bedrock-knowledge-base/main.tf +0 -102
- /package/dist/{plugins/n8n/terraform → terraform/modules/app}/n8n/outputs.tf +0 -0
- /package/dist/{plugins/n8n/terraform → terraform/modules/app}/n8n/scripts/sync-database.py +0 -0
- /package/dist/{plugins/n8n/terraform → terraform/modules/app}/n8n/scripts/test_sync_database.py +0 -0
- /package/dist/{plugins/n8n/terraform → terraform/modules/app}/n8n/variables.tf +0 -0
- /package/dist/{plugins/twenty/terraform → terraform/modules/app}/twenty/README.md +0 -0
- /package/dist/{plugins/twenty/terraform → terraform/modules/app}/twenty/main.tf +0 -0
- /package/dist/{plugins/twenty/terraform → terraform/modules/app}/twenty/outputs.tf +0 -0
- /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-
|
|
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-
|
|
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-
|
|
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-
|
|
54
|
+
} from "./chunk-YQCYD6NE.js";
|
|
55
55
|
import {
|
|
56
56
|
NODE_REGION_CONFIG_FILE_OPTIONS,
|
|
57
57
|
NODE_REGION_CONFIG_OPTIONS,
|
package/dist/plugins/README.md
CHANGED
|
@@ -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
|
-
|
|
156
|
-
|
|
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 {
|
|
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: [
|
|
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: [
|
|
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("
|
|
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(
|
|
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: [
|
|
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: [
|
|
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: [
|
|
94
|
-
).toThrow(/Duplicate plugin key in catalog:
|
|
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: [
|
|
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
|
-
...
|
|
110
|
+
...twentyManifest,
|
|
111
111
|
premium: {
|
|
112
|
-
entitlementProductKey: "
|
|
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("
|
|
118
|
+
expect(catalog.plugins[0].pluginKey).toBe("twenty");
|
|
119
119
|
expect(catalog.plugins[0].premium).toEqual({
|
|
120
|
-
entitlementProductKey: "
|
|
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(
|
|
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: [
|
|
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: [
|
|
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("
|
|
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 {
|
|
198
|
-
component.
|
|
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
|
-
|
|
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(
|
|
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
|
|
27
|
-
const validated = validatePluginManifest(
|
|
28
|
-
expect(validated.pluginKey).toBe("
|
|
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("
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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 = "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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",
|