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.
- package/README.md +3 -14
- package/dist/{api-client-4DZ266J5.js → api-client-4P4JZOBX.js} +3 -1
- package/dist/bowser-6Z6JFAIR.js +2822 -0
- package/dist/{chunk-Y2WHJECR.js → chunk-4OMDWYZQ.js} +5 -44
- package/dist/chunk-AD2NIWB5.js +6516 -0
- package/dist/chunk-DV3MRBR5.js +43 -0
- package/dist/chunk-EI5ZX7CN.js +522 -0
- package/dist/chunk-EUJ7X6YD.js +126 -0
- package/dist/chunk-GG5WKBOX.js +436 -0
- package/dist/chunk-I64EZSU5.js +358 -0
- package/dist/chunk-KMIJ5KGT.js +128 -0
- package/dist/chunk-MWQ7RO76.js +137 -0
- package/dist/chunk-OCPHU34C.js +996 -0
- package/dist/chunk-OLUQ4U2Z.js +1728 -0
- package/dist/chunk-XYM7PE2A.js +2264 -0
- package/dist/chunk-YQCYD6NE.js +3299 -0
- package/dist/cli.js +49156 -31257
- 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-2OTNTL4N.js +315 -0
- package/dist/dist-es-2XVAH4BQ.js +14726 -0
- package/dist/dist-es-3DPDUJAH.js +2000 -0
- package/dist/dist-es-BNZTBBVC.js +176 -0
- package/dist/dist-es-CD2RBDAC.js +88 -0
- package/dist/dist-es-I4FW57PS.js +88 -0
- package/dist/dist-es-KL7Y5NB2.js +377 -0
- package/dist/dist-es-KVFWJNDY.js +318 -0
- package/dist/dist-es-PS73DWNL.js +70 -0
- package/dist/dist-es-S3NZQFGT.js +170 -0
- package/dist/dist-es-SGCA4P32.js +48 -0
- package/dist/dist-es-WBM6J4RA.js +70 -0
- package/dist/dist-es-ZGVADYIF.js +485 -0
- package/dist/dist-es-ZKC2QKD2.js +377 -0
- package/dist/drizzle/0076_scheduled_jobs_marco_backfill.sql +2 -1
- package/dist/drizzle/0079_seed_tenant_customize_catalog.sql +1 -0
- package/dist/drizzle/0090_brain_schema_extraction.sql +10 -0
- package/dist/drizzle/0132_drop_computer_tables.sql +3 -0
- package/dist/drizzle/0160_compliance_event_types_plugins.sql +2 -0
- package/dist/drizzle/0214_think137_drop_judge_evidence_roi.sql +1 -0
- package/dist/drizzle/0216_drop_agent_loop_versions_goal_worker_policy.sql +1 -0
- package/dist/drizzle/0227_analyst_reader_role.sql +17 -20
- package/dist/drizzle/0230_analyst_rls.sql +28 -36
- package/dist/drizzle/0250_kg_schema_extraction.sql +27 -0
- package/dist/drizzle/0251_brain_stragglers.sql +21 -0
- package/dist/drizzle/0253_drop_brain_substrate.sql +2 -0
- package/dist/drizzle/0257_agents_runtime_allow_harness.sql +24 -0
- package/dist/drizzle/0261_native_auth_control_plane.sql +332 -0
- package/dist/drizzle/0262_auth_subscription_tickets.sql +59 -0
- package/dist/drizzle/0263_agentcore_runtime_identifier.sql +69 -0
- package/dist/drizzle/0263_drop_workos_auth_runtime.sql +236 -0
- package/dist/drizzle/0264_auth_enrollment_attempt_limits.sql +15 -0
- package/dist/drizzle/0265_eval_runs_requester_identity.sql +28 -0
- package/dist/drizzle/0265_require_fully_valid_auth_publication.sql +27 -0
- package/dist/drizzle/0266_auth_identity_recovery_grants.sql +9 -0
- package/dist/drizzle/0266_eval_profiles_runtime_type.sql +12 -0
- package/dist/drizzle/0267_ontology_candidate_rejections.sql +53 -0
- package/dist/drizzle/0268_identity_crosswalk_routing.sql +182 -0
- package/dist/drizzle/0269_ontology_system_map.sql +31 -0
- 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/event-streams-7JNLJEEL.js +894 -0
- package/dist/event-streams-KDF5RWR6.js +1515 -0
- package/dist/loadSso-ETCXTR4I.js +576 -0
- package/dist/loadSso-UBD7KUHE.js +583 -0
- package/dist/plugins/README.md +2 -2
- package/dist/plugins/catalog/package.json +1 -5
- package/dist/plugins/catalog/src/__tests__/build-catalog.test.ts +6 -4
- package/dist/plugins/catalog/src/__tests__/catalog.test.ts +21 -21
- package/dist/plugins/catalog/src/__tests__/contracts.test.ts +102 -94
- package/dist/plugins/catalog/src/__tests__/plugin-package.test.ts +7 -8
- package/dist/plugins/catalog/src/__tests__/plugin-registry.test.ts +0 -20
- package/dist/plugins/catalog/src/contracts.ts +17 -179
- package/dist/plugins/catalog/src/registry/generated-first-party.ts +0 -24
- 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-5QZNRSOO.js +821 -0
- package/dist/sso-oidc-XK673P54.js +837 -0
- package/dist/sts-OXI2UALF.js +1113 -0
- package/dist/sts-SQW4NBK3.js +1117 -0
- package/dist/terraform/examples/greenfield/main.tf +391 -176
- package/dist/terraform/examples/greenfield/terraform.tfvars.example +26 -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 +253 -0
- package/dist/terraform/modules/app/agentcore-identity/outputs.tf +51 -0
- package/dist/terraform/modules/app/agentcore-identity/scripts/bootstrap_twenty_oauth_client.sh +239 -0
- package/dist/terraform/modules/app/agentcore-identity/scripts/delete_identity.sh +22 -0
- package/dist/terraform/modules/app/agentcore-identity/scripts/delete_twenty_identity.sh +16 -0
- 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 +55 -0
- package/dist/terraform/modules/app/agentcore-identity/scripts/reconcile_identity.sh +73 -0
- package/dist/terraform/modules/app/agentcore-identity/scripts/reconcile_twenty_identity.sh +45 -0
- package/dist/terraform/modules/app/agentcore-identity/scripts/reconcile_twenty_provider.mjs +123 -0
- 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 +60 -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/appsync-subscriptions/main.tf +127 -21
- package/dist/terraform/modules/app/appsync-subscriptions/outputs.tf +0 -6
- package/dist/terraform/modules/app/appsync-subscriptions/variables.tf +5 -0
- 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 +3689 -233
- package/dist/terraform/modules/app/deployment-control-plane/test_runner_bundle.py +2579 -140
- 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 +531 -619
- package/dist/terraform/modules/app/lambda-api/iam-grouped.tf +350 -241
- package/dist/terraform/modules/app/lambda-api/main.tf +75 -13
- 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 -10
- package/dist/terraform/modules/app/lambda-api/runtime-config.tf +3 -21
- package/dist/terraform/modules/app/lambda-api/turn-assertion.tf +45 -0
- package/dist/terraform/modules/app/lambda-api/variables.tf +307 -121
- 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 +367 -72
- package/dist/terraform/modules/foundation/cognito/outputs.tf +47 -0
- package/dist/terraform/modules/foundation/cognito/variables.tf +131 -9
- package/dist/terraform/modules/thinkwork/README.md +5 -1
- package/dist/terraform/modules/thinkwork/main.tf +459 -234
- package/dist/terraform/modules/thinkwork/outputs.tf +44 -62
- package/dist/terraform/modules/thinkwork/variables.tf +353 -89
- package/dist/terraform/schema.graphql +69 -36
- 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/USER.md +1 -0
- 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 +3 -2
- package/dist/drizzle/0261_thread_turns_origin_turn_index.sql +0 -11
- 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/plugins/workos-auth/package.json +0 -22
- package/dist/plugins/workos-auth/src/index.ts +0 -30
- package/dist/plugins/workos-auth/src/manifest.ts +0 -40
- package/dist/plugins/workos-auth/src/provider-contract.ts +0 -39
- package/dist/plugins/workos-auth/test/manifest.test.ts +0 -94
- package/dist/plugins/workos-auth/tsconfig.json +0 -8
- 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-harness/main.tf +0 -101
- package/dist/terraform/modules/app/agentcore-harness/outputs.tf +0 -9
- package/dist/terraform/modules/app/agentcore-harness/variables.tf +0 -25
- 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/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
|
@@ -1,409 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Smoke test the n8n managed application deployment.
|
|
4
|
-
*
|
|
5
|
-
* Dry-run is the default. Set SMOKE_ENABLE_N8N_MANAGED_APP=1 after installing
|
|
6
|
-
* and deploying the n8n plugin through ThinkWork to read deployment status,
|
|
7
|
-
* inspect generated evidence, and probe the public n8n health path.
|
|
8
|
-
*
|
|
9
|
-
* Optional live env:
|
|
10
|
-
* SMOKE_TERRAFORM_DIR=terraform/examples/greenfield
|
|
11
|
-
* SMOKE_N8N_URL=https://n8n.example.com
|
|
12
|
-
* SMOKE_N8N_HEALTH_PATH=/healthz
|
|
13
|
-
* SMOKE_TENANT_ID=<tenant-id>
|
|
14
|
-
* VITE_GRAPHQL_HTTP_URL, GRAPHQL_HTTP_URL, or API_GRAPHQL_URL
|
|
15
|
-
* API_AUTH_SECRET, THINKWORK_API_SECRET, VITE_GRAPHQL_API_KEY, or GRAPHQL_API_KEY
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
|
-
import { execFileSync } from "node:child_process";
|
|
19
|
-
import fs from "node:fs";
|
|
20
|
-
import path from "node:path";
|
|
21
|
-
import process from "node:process";
|
|
22
|
-
import { attachSmokeEvidence } from "../../../scripts/smoke/deployment-evidence.mjs";
|
|
23
|
-
|
|
24
|
-
const LIVE_ENABLED = process.env.SMOKE_ENABLE_N8N_MANAGED_APP === "1";
|
|
25
|
-
const TIMEOUT_MS = Number(process.env.SMOKE_TIMEOUT_MS || 15_000);
|
|
26
|
-
|
|
27
|
-
const env = {
|
|
28
|
-
...loadEnvFile(),
|
|
29
|
-
...process.env,
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
const terraformDir = env.SMOKE_TERRAFORM_DIR || "terraform/examples/greenfield";
|
|
33
|
-
const healthPath = env.SMOKE_N8N_HEALTH_PATH || "/healthz";
|
|
34
|
-
const apiUrl = first(
|
|
35
|
-
env.VITE_GRAPHQL_HTTP_URL,
|
|
36
|
-
env.GRAPHQL_HTTP_URL,
|
|
37
|
-
env.API_GRAPHQL_URL,
|
|
38
|
-
);
|
|
39
|
-
const apiSecret = first(env.API_AUTH_SECRET, env.THINKWORK_API_SECRET);
|
|
40
|
-
const apiKey = first(
|
|
41
|
-
env.VITE_GRAPHQL_API_KEY,
|
|
42
|
-
env.APPSYNC_API_KEY,
|
|
43
|
-
env.GRAPHQL_API_KEY,
|
|
44
|
-
);
|
|
45
|
-
const tenantId = first(env.SMOKE_TENANT_ID, env.TENANT_ID);
|
|
46
|
-
|
|
47
|
-
if (!LIVE_ENABLED) {
|
|
48
|
-
console.log(
|
|
49
|
-
JSON.stringify(
|
|
50
|
-
await attachSmokeEvidence(
|
|
51
|
-
"n8n-managed-app",
|
|
52
|
-
{
|
|
53
|
-
ok: true,
|
|
54
|
-
skippedLive: true,
|
|
55
|
-
reason:
|
|
56
|
-
"set SMOKE_ENABLE_N8N_MANAGED_APP=1 to run the deployed n8n managed-app smoke",
|
|
57
|
-
dryRun: {
|
|
58
|
-
terraformDir,
|
|
59
|
-
healthPath,
|
|
60
|
-
requiredWhenRunning: [
|
|
61
|
-
"n8n plugin installed and deployed through ThinkWork Settings -> Plugins",
|
|
62
|
-
"Terraform outputs in SMOKE_TERRAFORM_DIR or SMOKE_N8N_URL",
|
|
63
|
-
"n8n provisioned/runtime deployment status",
|
|
64
|
-
],
|
|
65
|
-
optionalGraphqlEnv: [
|
|
66
|
-
"SMOKE_TENANT_ID",
|
|
67
|
-
"VITE_GRAPHQL_HTTP_URL or GRAPHQL_HTTP_URL or API_GRAPHQL_URL",
|
|
68
|
-
"API_AUTH_SECRET or THINKWORK_API_SECRET or VITE_GRAPHQL_API_KEY or GRAPHQL_API_KEY",
|
|
69
|
-
],
|
|
70
|
-
verifies: [
|
|
71
|
-
"n8n_provisioned false skips cleanly",
|
|
72
|
-
"n8n_runtime_enabled true requires HTTPS n8n_url",
|
|
73
|
-
"public n8n health path responds successfully",
|
|
74
|
-
"main and worker service evidence is present",
|
|
75
|
-
"database, queue, storage, image digest, and service credential evidence is present",
|
|
76
|
-
"package configuration digest is recorded when custom packages are configured",
|
|
77
|
-
],
|
|
78
|
-
},
|
|
79
|
-
},
|
|
80
|
-
env,
|
|
81
|
-
),
|
|
82
|
-
null,
|
|
83
|
-
2,
|
|
84
|
-
),
|
|
85
|
-
);
|
|
86
|
-
process.exit(0);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
try {
|
|
90
|
-
const result = await runLiveSmoke();
|
|
91
|
-
console.log(
|
|
92
|
-
JSON.stringify(
|
|
93
|
-
await attachSmokeEvidence(
|
|
94
|
-
"n8n-managed-app",
|
|
95
|
-
{ ok: true, ...result },
|
|
96
|
-
env,
|
|
97
|
-
),
|
|
98
|
-
null,
|
|
99
|
-
2,
|
|
100
|
-
),
|
|
101
|
-
);
|
|
102
|
-
} catch (error) {
|
|
103
|
-
fail(error instanceof Error ? error.message : String(error));
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
async function runLiveSmoke() {
|
|
107
|
-
const terraform = readTerraformOutputs(terraformDir);
|
|
108
|
-
const graphql = await readGraphqlStatus().catch((error) => ({
|
|
109
|
-
error: error instanceof Error ? error.message : String(error),
|
|
110
|
-
}));
|
|
111
|
-
const status = resolveStatus({ terraform, graphql });
|
|
112
|
-
|
|
113
|
-
if (!status.provisioned) {
|
|
114
|
-
return {
|
|
115
|
-
skippedLive: true,
|
|
116
|
-
reason: "n8n is not provisioned for this stage.",
|
|
117
|
-
terraform,
|
|
118
|
-
graphql,
|
|
119
|
-
};
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
if (!status.runtimeEnabled) {
|
|
123
|
-
return {
|
|
124
|
-
skippedLive: true,
|
|
125
|
-
reason: "n8n is provisioned but runtime is parked.",
|
|
126
|
-
status,
|
|
127
|
-
terraform,
|
|
128
|
-
graphql,
|
|
129
|
-
};
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
if (!status.url) {
|
|
133
|
-
throw new Error("n8n runtime is enabled but no public URL was resolved.");
|
|
134
|
-
}
|
|
135
|
-
if (!status.url.startsWith("https://")) {
|
|
136
|
-
throw new Error(`n8n URL must be HTTPS, got ${status.url}.`);
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
validateRuntimeEvidence(status.evidence, status.source);
|
|
140
|
-
const publicHealth = await probeHealth(status.url);
|
|
141
|
-
|
|
142
|
-
if (!publicHealth.healthy) {
|
|
143
|
-
throw new Error(
|
|
144
|
-
`n8n health probe failed: HTTP ${publicHealth.statusCode ?? "none"} ${publicHealth.message}`,
|
|
145
|
-
);
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
return {
|
|
149
|
-
status,
|
|
150
|
-
publicHealth,
|
|
151
|
-
terraform,
|
|
152
|
-
graphql,
|
|
153
|
-
};
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
function resolveStatus({ terraform, graphql }) {
|
|
157
|
-
const app = graphql?.deploymentStatus?.managedApplications?.find(
|
|
158
|
-
(entry) => entry.key === "n8n",
|
|
159
|
-
);
|
|
160
|
-
const source = app ? "graphql" : terraform.available ? "terraform" : "env";
|
|
161
|
-
const evidence = {
|
|
162
|
-
mainServiceName: first(
|
|
163
|
-
terraform.n8n_main_service_name,
|
|
164
|
-
app?.serviceNames?.[0],
|
|
165
|
-
),
|
|
166
|
-
workerServiceName: first(
|
|
167
|
-
terraform.n8n_worker_service_name,
|
|
168
|
-
app?.serviceNames?.[1],
|
|
169
|
-
),
|
|
170
|
-
mainLogGroupName: terraform.n8n_main_log_group_name,
|
|
171
|
-
workerLogGroupName: terraform.n8n_worker_log_group_name,
|
|
172
|
-
databaseName: first(terraform.n8n_database_name, app?.databaseName),
|
|
173
|
-
databaseSecretArn: terraform.n8n_database_secret_arn,
|
|
174
|
-
valkeyEndpoint: terraform.n8n_valkey_endpoint,
|
|
175
|
-
storageBucketName: first(
|
|
176
|
-
terraform.n8n_storage_bucket_name,
|
|
177
|
-
app?.storageBucketName,
|
|
178
|
-
),
|
|
179
|
-
storagePrefix: terraform.n8n_storage_prefix,
|
|
180
|
-
imageDigest: terraform.n8n_image_digest,
|
|
181
|
-
packageConfigDigest: terraform.n8n_package_config_digest,
|
|
182
|
-
serviceCredentialSecretArn: terraform.n8n_service_credential_secret_arn,
|
|
183
|
-
};
|
|
184
|
-
|
|
185
|
-
return {
|
|
186
|
-
provisioned: bool(
|
|
187
|
-
firstDefined(
|
|
188
|
-
app?.provisioned,
|
|
189
|
-
terraform.n8n_provisioned,
|
|
190
|
-
!!env.SMOKE_N8N_URL,
|
|
191
|
-
),
|
|
192
|
-
),
|
|
193
|
-
runtimeEnabled: bool(
|
|
194
|
-
firstDefined(
|
|
195
|
-
app?.runtimeEnabled,
|
|
196
|
-
terraform.n8n_runtime_enabled,
|
|
197
|
-
!!env.SMOKE_N8N_URL,
|
|
198
|
-
),
|
|
199
|
-
),
|
|
200
|
-
url: first(env.SMOKE_N8N_URL, app?.url, terraform.n8n_url),
|
|
201
|
-
source,
|
|
202
|
-
status: app?.status ?? null,
|
|
203
|
-
message: app?.message ?? null,
|
|
204
|
-
evidence,
|
|
205
|
-
};
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
function validateRuntimeEvidence(evidence, source) {
|
|
209
|
-
if (env.SMOKE_N8N_ALLOW_URL_ONLY === "1") {
|
|
210
|
-
return;
|
|
211
|
-
}
|
|
212
|
-
const required = [
|
|
213
|
-
"mainServiceName",
|
|
214
|
-
"workerServiceName",
|
|
215
|
-
"databaseName",
|
|
216
|
-
"valkeyEndpoint",
|
|
217
|
-
"storageBucketName",
|
|
218
|
-
"imageDigest",
|
|
219
|
-
"serviceCredentialSecretArn",
|
|
220
|
-
];
|
|
221
|
-
const missing = required.filter((key) => !evidence[key]);
|
|
222
|
-
if (missing.length > 0) {
|
|
223
|
-
throw new Error(
|
|
224
|
-
`n8n live smoke requires managed-app evidence from Terraform or GraphQL; missing ${missing.join(", ")} from ${source}. Set SMOKE_N8N_ALLOW_URL_ONLY=1 only for endpoint-only diagnostics.`,
|
|
225
|
-
);
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
async function probeHealth(baseUrl) {
|
|
230
|
-
const endpoint = new URL(healthPath, baseUrl).toString();
|
|
231
|
-
const started = Date.now();
|
|
232
|
-
const response = await fetchWithTimeout(endpoint, {
|
|
233
|
-
headers: { accept: "text/html,application/json,*/*" },
|
|
234
|
-
});
|
|
235
|
-
const body = await response.text().catch(() => "");
|
|
236
|
-
return {
|
|
237
|
-
endpoint,
|
|
238
|
-
healthy: response.ok,
|
|
239
|
-
statusCode: response.status,
|
|
240
|
-
latencyMs: Date.now() - started,
|
|
241
|
-
message: body.slice(0, 300),
|
|
242
|
-
};
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
function readTerraformOutputs(dir) {
|
|
246
|
-
const resolved = path.resolve(dir);
|
|
247
|
-
if (!fs.existsSync(resolved)) {
|
|
248
|
-
return { available: false, reason: `Terraform dir not found: ${dir}` };
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
try {
|
|
252
|
-
const raw = execFileSync(
|
|
253
|
-
"terraform",
|
|
254
|
-
["-chdir=" + resolved, "output", "-json"],
|
|
255
|
-
{
|
|
256
|
-
encoding: "utf8",
|
|
257
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
258
|
-
},
|
|
259
|
-
);
|
|
260
|
-
const parsed = JSON.parse(raw);
|
|
261
|
-
return {
|
|
262
|
-
available: true,
|
|
263
|
-
n8n_provisioned: outputValue(parsed.n8n_provisioned),
|
|
264
|
-
n8n_runtime_enabled: outputValue(parsed.n8n_runtime_enabled),
|
|
265
|
-
n8n_url: outputValue(parsed.n8n_url),
|
|
266
|
-
n8n_alb_arn: outputValue(parsed.n8n_alb_arn),
|
|
267
|
-
n8n_target_group_arn: outputValue(parsed.n8n_target_group_arn),
|
|
268
|
-
n8n_cluster_arn: outputValue(parsed.n8n_cluster_arn),
|
|
269
|
-
n8n_main_service_name: outputValue(parsed.n8n_main_service_name),
|
|
270
|
-
n8n_worker_service_name: outputValue(parsed.n8n_worker_service_name),
|
|
271
|
-
n8n_main_log_group_name: outputValue(parsed.n8n_main_log_group_name),
|
|
272
|
-
n8n_worker_log_group_name: outputValue(parsed.n8n_worker_log_group_name),
|
|
273
|
-
n8n_database_name: outputValue(parsed.n8n_database_name),
|
|
274
|
-
n8n_database_secret_arn: outputValue(parsed.n8n_database_secret_arn),
|
|
275
|
-
n8n_valkey_endpoint: outputValue(parsed.n8n_valkey_endpoint),
|
|
276
|
-
n8n_storage_bucket_name: outputValue(parsed.n8n_storage_bucket_name),
|
|
277
|
-
n8n_storage_prefix: outputValue(parsed.n8n_storage_prefix),
|
|
278
|
-
n8n_image_digest: outputValue(parsed.n8n_image_digest),
|
|
279
|
-
n8n_package_config_digest: outputValue(parsed.n8n_package_config_digest),
|
|
280
|
-
n8n_service_credential_secret_arn: outputValue(
|
|
281
|
-
parsed.n8n_service_credential_secret_arn,
|
|
282
|
-
),
|
|
283
|
-
};
|
|
284
|
-
} catch (error) {
|
|
285
|
-
return {
|
|
286
|
-
available: false,
|
|
287
|
-
reason: error instanceof Error ? error.message : String(error),
|
|
288
|
-
};
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
async function readGraphqlStatus() {
|
|
293
|
-
if (!apiUrl || !tenantId || (!apiSecret && !apiKey)) {
|
|
294
|
-
return {
|
|
295
|
-
skipped: true,
|
|
296
|
-
reason:
|
|
297
|
-
"set API URL, tenant id, and API_AUTH_SECRET/THINKWORK_API_SECRET or GraphQL API key to compare GraphQL deployment status",
|
|
298
|
-
};
|
|
299
|
-
}
|
|
300
|
-
const data = await gql(
|
|
301
|
-
`query N8nManagedAppSmoke {
|
|
302
|
-
deploymentStatus {
|
|
303
|
-
managedApplications {
|
|
304
|
-
key
|
|
305
|
-
provisioned
|
|
306
|
-
runtimeEnabled
|
|
307
|
-
url
|
|
308
|
-
status
|
|
309
|
-
message
|
|
310
|
-
serviceNames
|
|
311
|
-
storageBucketName
|
|
312
|
-
databaseName
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
}`,
|
|
316
|
-
{},
|
|
317
|
-
);
|
|
318
|
-
return { deploymentStatus: data.deploymentStatus };
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
async function gql(query, variables) {
|
|
322
|
-
const headers = {
|
|
323
|
-
"content-type": "application/json",
|
|
324
|
-
"x-tenant-id": tenantId,
|
|
325
|
-
};
|
|
326
|
-
if (apiSecret) headers.authorization = `Bearer ${apiSecret}`;
|
|
327
|
-
if (apiKey) headers["x-api-key"] = apiKey;
|
|
328
|
-
|
|
329
|
-
const response = await fetchWithTimeout(apiUrl, {
|
|
330
|
-
method: "POST",
|
|
331
|
-
headers,
|
|
332
|
-
body: JSON.stringify({ query, variables }),
|
|
333
|
-
});
|
|
334
|
-
const text = await response.text();
|
|
335
|
-
if (!response.ok) {
|
|
336
|
-
throw new Error(`GraphQL HTTP ${response.status}: ${text.slice(0, 500)}`);
|
|
337
|
-
}
|
|
338
|
-
const body = JSON.parse(text);
|
|
339
|
-
if (body.errors?.length) {
|
|
340
|
-
throw new Error(`GraphQL errors: ${JSON.stringify(body.errors)}`);
|
|
341
|
-
}
|
|
342
|
-
return body.data;
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
async function fetchWithTimeout(url, options = {}) {
|
|
346
|
-
const controller = new AbortController();
|
|
347
|
-
const timer = setTimeout(() => controller.abort(), TIMEOUT_MS);
|
|
348
|
-
try {
|
|
349
|
-
return await fetch(url, { ...options, signal: controller.signal });
|
|
350
|
-
} finally {
|
|
351
|
-
clearTimeout(timer);
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
function fail(message) {
|
|
356
|
-
console.error(JSON.stringify({ ok: false, error: message }, null, 2));
|
|
357
|
-
process.exit(1);
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
function outputValue(output) {
|
|
361
|
-
return output && typeof output === "object" && "value" in output
|
|
362
|
-
? output.value
|
|
363
|
-
: undefined;
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
function bool(value) {
|
|
367
|
-
if (typeof value === "boolean") return value;
|
|
368
|
-
if (typeof value === "string") return value.toLowerCase() === "true";
|
|
369
|
-
return Boolean(value);
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
function firstDefined(...values) {
|
|
373
|
-
return values.find((value) => value !== undefined && value !== null);
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
function first(...values) {
|
|
377
|
-
return (
|
|
378
|
-
values.find((value) => typeof value === "string" && value.trim())?.trim() ??
|
|
379
|
-
null
|
|
380
|
-
);
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
function loadEnvFile() {
|
|
384
|
-
const explicit = process.env.COMPUTER_ENV_FILE;
|
|
385
|
-
if (explicit === "none") return {};
|
|
386
|
-
const candidates = [explicit, "apps/web/.env", ".env"].filter(Boolean);
|
|
387
|
-
|
|
388
|
-
for (const candidate of candidates) {
|
|
389
|
-
const resolved = path.resolve(candidate);
|
|
390
|
-
if (!fs.existsSync(resolved)) continue;
|
|
391
|
-
return Object.fromEntries(
|
|
392
|
-
fs
|
|
393
|
-
.readFileSync(resolved, "utf8")
|
|
394
|
-
.split(/\r?\n/)
|
|
395
|
-
.map((line) => line.trim())
|
|
396
|
-
.filter((line) => line && !line.startsWith("#") && line.includes("="))
|
|
397
|
-
.map((line) => {
|
|
398
|
-
const index = line.indexOf("=");
|
|
399
|
-
const key = line.slice(0, index).trim();
|
|
400
|
-
const value = line
|
|
401
|
-
.slice(index + 1)
|
|
402
|
-
.trim()
|
|
403
|
-
.replace(/^['"]|['"]$/g, "");
|
|
404
|
-
return [key, value];
|
|
405
|
-
}),
|
|
406
|
-
);
|
|
407
|
-
}
|
|
408
|
-
return {};
|
|
409
|
-
}
|