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
|
@@ -53,11 +53,6 @@ locals {
|
|
|
53
53
|
: module.vpc.private_subnet_ids
|
|
54
54
|
)
|
|
55
55
|
|
|
56
|
-
# Hindsight is the canonical user/Space memory provider for full ThinkWork
|
|
57
|
-
# installs. AgentCore managed memory remains available as an explicit
|
|
58
|
-
# low-cost/development opt-out. We still honor var.memory_engine == "hindsight"
|
|
59
|
-
# so existing tfvars keep working even when enable_hindsight was not set.
|
|
60
|
-
hindsight_enabled = var.enable_hindsight || var.memory_engine == "hindsight"
|
|
61
56
|
twenty_provisioned = var.twenty_provisioned
|
|
62
57
|
twenty_runtime_enabled = var.twenty_provisioned && var.twenty_runtime_enabled
|
|
63
58
|
twenty_domain = var.twenty_domain != "" ? var.twenty_domain : (var.www_domain != "" ? "crm.${var.www_domain}" : "")
|
|
@@ -83,8 +78,28 @@ locals {
|
|
|
83
78
|
module.vpc.private_route_table_ids,
|
|
84
79
|
module.vpc.public_route_table_ids,
|
|
85
80
|
)
|
|
86
|
-
|
|
87
|
-
|
|
81
|
+
# THINK-589 PR 1 (deprecate-to-no-op): the OKF wiki EFS feature is dead.
|
|
82
|
+
# Every EFS consumer below (client/EFS security groups, NFS rule, mount
|
|
83
|
+
# targets, access points, Pi/hydrator wiring) is hard-conditioned off via
|
|
84
|
+
# this local regardless of the deprecated okf_wiki_* inputs. The EFS
|
|
85
|
+
# filesystem itself and the NAT gateway are intentionally NOT conditioned
|
|
86
|
+
# off: destroying the filesystem is PR 2's gated delete, and the NAT is
|
|
87
|
+
# shared VPC egress that live non-OKF workloads ride.
|
|
88
|
+
#
|
|
89
|
+
# The VPC interface endpoints were re-homed out of the OKF lane on
|
|
90
|
+
# 2026-08-28 (the vpc_interface_* resources below — they were only ever
|
|
91
|
+
# "okf-wiki" by accident of being created by the first VPC-attached
|
|
92
|
+
# workload). They still ride the okf_wiki_* enable gates for stage
|
|
93
|
+
# compatibility; the SERVICE SET and ENI count are now per-stage inputs.
|
|
94
|
+
okf_wiki_efs_consumers_active = false
|
|
95
|
+
vpc_interface_endpoints_enabled = var.okf_wiki_efs_enabled && var.okf_wiki_create_vpc_endpoints
|
|
96
|
+
# Legacy full set — what every stage had before the cost review. An
|
|
97
|
+
# interface endpoint with private DNS does not grant reachability (the
|
|
98
|
+
# private subnets are NAT-routed and the Lambda SGs allow 443 out); it only
|
|
99
|
+
# keeps the call on AWS's network, at ~$7.30/mo per ENI regardless of
|
|
100
|
+
# traffic. Stages that care about posture keep the data-touching ones
|
|
101
|
+
# (secretsmanager, rds-data, bedrock-runtime) and let the rest ride the NAT.
|
|
102
|
+
vpc_interface_endpoint_services_legacy = toset(concat(
|
|
88
103
|
[
|
|
89
104
|
"bedrock",
|
|
90
105
|
"bedrock-agentcore",
|
|
@@ -106,18 +121,17 @@ locals {
|
|
|
106
121
|
"bedrock-runtime",
|
|
107
122
|
],
|
|
108
123
|
))
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
#
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
: local.hindsight_enabled ? "hindsight" : "agentcore"
|
|
124
|
+
vpc_interface_endpoint_services = (
|
|
125
|
+
var.vpc_interface_endpoint_services != null
|
|
126
|
+
? toset(var.vpc_interface_endpoint_services)
|
|
127
|
+
: local.vpc_interface_endpoint_services_legacy
|
|
128
|
+
)
|
|
129
|
+
# Single-AZ: one ENI in the lowest sorted subnet. Callers in the other AZ
|
|
130
|
+
# cross AZs at $0.01/GB — nothing at these volumes next to a second ENI.
|
|
131
|
+
vpc_interface_endpoint_subnet_ids = (
|
|
132
|
+
var.vpc_interface_endpoint_single_az
|
|
133
|
+
? slice(sort(local.okf_wiki_subnet_ids), 0, min(1, length(local.okf_wiki_subnet_ids)))
|
|
134
|
+
: local.okf_wiki_subnet_ids
|
|
121
135
|
)
|
|
122
136
|
|
|
123
137
|
# Customer-domain namespace (<name>.thinkwork.ai). The zone is created as
|
|
@@ -487,14 +501,16 @@ resource "terraform_data" "n8n_runtime_state_guardrails" {
|
|
|
487
501
|
}
|
|
488
502
|
}
|
|
489
503
|
}
|
|
490
|
-
#
|
|
491
|
-
# (
|
|
492
|
-
#
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
504
|
+
# Company Brain U5: general egress for the VPC-attached identity-graph-
|
|
505
|
+
# projector (twin-query retired to the platform service — THINK-339 U15).
|
|
506
|
+
# Pairs with the etl neptune stack's
|
|
507
|
+
# client SG (8182-only) — this one covers Aurora (5432), Secrets/S3/Lambda
|
|
508
|
+
# APIs (443) through the NAT-routed private subnets.
|
|
509
|
+
resource "aws_security_group" "twin_lambda_egress" {
|
|
510
|
+
#checkov:skip=CKV2_AWS_5: attached to the twin Lambdas via lambda-api's neptune vpc_config
|
|
511
|
+
count = var.neptune_client_security_group_id != "" ? 1 : 0
|
|
512
|
+
name = "thinkwork-${var.stage}-twin-lambda-egress"
|
|
513
|
+
description = "Twin Lambdas - general egress (Aurora, AWS APIs)"
|
|
498
514
|
vpc_id = module.vpc.vpc_id
|
|
499
515
|
|
|
500
516
|
egress {
|
|
@@ -503,20 +519,10 @@ resource "aws_security_group" "analyst_egress_lambda" {
|
|
|
503
519
|
protocol = "-1"
|
|
504
520
|
cidr_blocks = ["0.0.0.0/0"]
|
|
505
521
|
}
|
|
506
|
-
|
|
507
|
-
tags = { Name = "thinkwork-${var.stage}-analyst-egress-lambda-sg" }
|
|
508
|
-
|
|
509
|
-
lifecycle {
|
|
510
|
-
create_before_destroy = true
|
|
511
|
-
precondition {
|
|
512
|
-
condition = length(module.vpc.private_subnet_ids) > 0
|
|
513
|
-
error_message = "analyst_lambda_vpc_egress requires private (NAT-routed) subnets — a Lambda in a public subnet has no internet egress."
|
|
514
|
-
}
|
|
515
|
-
}
|
|
516
522
|
}
|
|
517
523
|
|
|
518
524
|
resource "aws_security_group" "okf_wiki_lambda" {
|
|
519
|
-
count =
|
|
525
|
+
count = local.okf_wiki_efs_consumers_active ? 1 : 0 # THINK-589: always off
|
|
520
526
|
|
|
521
527
|
name_prefix = "thinkwork-${var.stage}-okf-wiki-lambda-"
|
|
522
528
|
description = "OKF wiki EFS clients for hydrator and Pi"
|
|
@@ -534,7 +540,7 @@ resource "aws_security_group" "okf_wiki_lambda" {
|
|
|
534
540
|
}
|
|
535
541
|
|
|
536
542
|
resource "aws_security_group" "okf_wiki_efs" {
|
|
537
|
-
count =
|
|
543
|
+
count = local.okf_wiki_efs_consumers_active ? 1 : 0 # THINK-589: always off
|
|
538
544
|
|
|
539
545
|
name_prefix = "thinkwork-${var.stage}-okf-wiki-efs-"
|
|
540
546
|
description = "NFS ingress for OKF wiki current-view EFS"
|
|
@@ -544,74 +550,83 @@ resource "aws_security_group" "okf_wiki_efs" {
|
|
|
544
550
|
lifecycle { create_before_destroy = true }
|
|
545
551
|
}
|
|
546
552
|
|
|
547
|
-
|
|
548
|
-
|
|
553
|
+
# Re-homed from okf_wiki_vpc_endpoint (2026-08-28). name_prefix AND
|
|
554
|
+
# description keep their historical values on purpose: either change replaces
|
|
555
|
+
# the SG, which every live endpoint references — the Name tag carries the new
|
|
556
|
+
# identity instead.
|
|
557
|
+
resource "aws_security_group" "vpc_interface_endpoint" {
|
|
558
|
+
count = local.vpc_interface_endpoints_enabled ? 1 : 0
|
|
549
559
|
|
|
550
560
|
name_prefix = "thinkwork-${var.stage}-okf-wiki-vpce-"
|
|
551
561
|
description = "HTTPS endpoints for OKF wiki VPC-attached Lambdas"
|
|
552
562
|
vpc_id = module.vpc.vpc_id
|
|
553
563
|
|
|
554
|
-
tags = { Name = "thinkwork-${var.stage}-
|
|
564
|
+
tags = { Name = "thinkwork-${var.stage}-vpce-sg" }
|
|
555
565
|
lifecycle { create_before_destroy = true }
|
|
556
566
|
}
|
|
557
567
|
|
|
558
568
|
resource "aws_security_group_rule" "okf_wiki_vpce_from_lambda" {
|
|
559
|
-
|
|
569
|
+
# THINK-589: always off — the OKF client SG no longer exists; VPC workloads
|
|
570
|
+
# reach the endpoints via vpc_interface_endpoint_from_vpc (VPC CIDR).
|
|
571
|
+
count = local.okf_wiki_efs_consumers_active ? 1 : 0
|
|
560
572
|
|
|
561
573
|
type = "ingress"
|
|
562
574
|
from_port = 443
|
|
563
575
|
to_port = 443
|
|
564
576
|
protocol = "tcp"
|
|
565
577
|
source_security_group_id = aws_security_group.okf_wiki_lambda[0].id
|
|
566
|
-
security_group_id = aws_security_group.
|
|
578
|
+
security_group_id = aws_security_group.vpc_interface_endpoint[0].id
|
|
567
579
|
}
|
|
568
580
|
# Interface endpoints with private DNS capture the WHOLE VPC's traffic to the
|
|
569
581
|
# covered AWS APIs (logs, ssm, sts, bedrock, ...): every workload in the VPC
|
|
570
582
|
# resolves those hostnames to the endpoint's private IP, so per-source-SG
|
|
571
|
-
# rules silently black-hole anything not enumerated — harness cycle-7's
|
|
572
|
-
#
|
|
573
|
-
#
|
|
574
|
-
resource "aws_security_group_rule" "
|
|
575
|
-
count = local.
|
|
583
|
+
# rules silently black-hole anything not enumerated — harness cycle-7's ECS
|
|
584
|
+
# tasks died on "cannot find the CloudWatch log group ... connection issue"
|
|
585
|
+
# because only the Lambda SG was admitted. Allow the VPC CIDR.
|
|
586
|
+
resource "aws_security_group_rule" "vpc_interface_endpoint_from_vpc" {
|
|
587
|
+
count = local.vpc_interface_endpoints_enabled ? 1 : 0
|
|
576
588
|
|
|
577
589
|
type = "ingress"
|
|
578
590
|
from_port = 443
|
|
579
591
|
to_port = 443
|
|
580
592
|
protocol = "tcp"
|
|
581
593
|
cidr_blocks = [module.vpc.vpc_cidr_block]
|
|
582
|
-
security_group_id = aws_security_group.
|
|
594
|
+
security_group_id = aws_security_group.vpc_interface_endpoint[0].id
|
|
583
595
|
description = "All VPC workloads (private-DNS endpoints capture the whole VPC)"
|
|
584
596
|
}
|
|
585
597
|
|
|
586
|
-
resource "aws_security_group_rule" "
|
|
587
|
-
count = local.
|
|
598
|
+
resource "aws_security_group_rule" "vpc_interface_endpoint_from_twenty" {
|
|
599
|
+
count = local.vpc_interface_endpoints_enabled && local.twenty_provisioned ? 1 : 0
|
|
588
600
|
|
|
589
601
|
type = "ingress"
|
|
590
602
|
from_port = 443
|
|
591
603
|
to_port = 443
|
|
592
604
|
protocol = "tcp"
|
|
593
605
|
source_security_group_id = module.twenty[0].twenty_security_group_id
|
|
594
|
-
security_group_id = aws_security_group.
|
|
606
|
+
security_group_id = aws_security_group.vpc_interface_endpoint[0].id
|
|
595
607
|
}
|
|
596
608
|
|
|
597
|
-
resource "aws_vpc_endpoint" "
|
|
598
|
-
for_each = local.
|
|
609
|
+
resource "aws_vpc_endpoint" "vpc_interface" {
|
|
610
|
+
for_each = local.vpc_interface_endpoints_enabled ? local.vpc_interface_endpoint_services : toset([])
|
|
599
611
|
|
|
600
612
|
vpc_id = module.vpc.vpc_id
|
|
601
613
|
service_name = "com.amazonaws.${var.region}.${each.key}"
|
|
602
614
|
vpc_endpoint_type = "Interface"
|
|
603
|
-
subnet_ids = local.
|
|
604
|
-
security_group_ids = [aws_security_group.
|
|
615
|
+
subnet_ids = local.vpc_interface_endpoint_subnet_ids
|
|
616
|
+
security_group_ids = [aws_security_group.vpc_interface_endpoint[0].id]
|
|
605
617
|
private_dns_enabled = true
|
|
606
618
|
|
|
607
619
|
tags = {
|
|
608
|
-
Name = "thinkwork-${var.stage}-
|
|
609
|
-
Purpose = "
|
|
620
|
+
Name = "thinkwork-${var.stage}-vpce-${each.key}"
|
|
621
|
+
Purpose = "vpc-private-egress"
|
|
610
622
|
}
|
|
611
623
|
}
|
|
612
624
|
|
|
613
|
-
|
|
614
|
-
|
|
625
|
+
# Gateway endpoint: free, no ENIs — never part of the diet. The Brain stack
|
|
626
|
+
# mirrors these tags on the shared mcpherson endpoint (its accounts tfvars);
|
|
627
|
+
# change them in lockstep.
|
|
628
|
+
resource "aws_vpc_endpoint" "vpc_s3" {
|
|
629
|
+
count = local.vpc_interface_endpoints_enabled && length(local.okf_wiki_route_table_ids) > 0 ? 1 : 0
|
|
615
630
|
|
|
616
631
|
vpc_id = module.vpc.vpc_id
|
|
617
632
|
service_name = "com.amazonaws.${var.region}.s3"
|
|
@@ -619,12 +634,37 @@ resource "aws_vpc_endpoint" "okf_wiki_s3" {
|
|
|
619
634
|
route_table_ids = local.okf_wiki_route_table_ids
|
|
620
635
|
|
|
621
636
|
tags = {
|
|
622
|
-
Name = "thinkwork-${var.stage}-
|
|
623
|
-
Purpose = "
|
|
637
|
+
Name = "thinkwork-${var.stage}-vpce-s3"
|
|
638
|
+
Purpose = "vpc-private-egress"
|
|
624
639
|
}
|
|
625
640
|
}
|
|
641
|
+
|
|
642
|
+
# 2026-08-28 re-home: the endpoint group was created by (and named after)
|
|
643
|
+
# the dead OKF wiki lane. Same AWS resources, new addresses — a VPC endpoint
|
|
644
|
+
# Terraform destroys and recreates is a live outage for everything routing
|
|
645
|
+
# through it.
|
|
646
|
+
moved {
|
|
647
|
+
from = aws_security_group.okf_wiki_vpc_endpoint
|
|
648
|
+
to = aws_security_group.vpc_interface_endpoint
|
|
649
|
+
}
|
|
650
|
+
moved {
|
|
651
|
+
from = aws_security_group_rule.okf_wiki_vpce_from_vpc
|
|
652
|
+
to = aws_security_group_rule.vpc_interface_endpoint_from_vpc
|
|
653
|
+
}
|
|
654
|
+
moved {
|
|
655
|
+
from = aws_security_group_rule.okf_wiki_vpce_from_twenty
|
|
656
|
+
to = aws_security_group_rule.vpc_interface_endpoint_from_twenty
|
|
657
|
+
}
|
|
658
|
+
moved {
|
|
659
|
+
from = aws_vpc_endpoint.okf_wiki_interface
|
|
660
|
+
to = aws_vpc_endpoint.vpc_interface
|
|
661
|
+
}
|
|
662
|
+
moved {
|
|
663
|
+
from = aws_vpc_endpoint.okf_wiki_s3
|
|
664
|
+
to = aws_vpc_endpoint.vpc_s3
|
|
665
|
+
}
|
|
626
666
|
resource "aws_security_group_rule" "okf_wiki_efs_from_lambda" {
|
|
627
|
-
count =
|
|
667
|
+
count = local.okf_wiki_efs_consumers_active ? 1 : 0 # THINK-589: always off
|
|
628
668
|
|
|
629
669
|
type = "ingress"
|
|
630
670
|
from_port = 2049
|
|
@@ -634,6 +674,10 @@ resource "aws_security_group_rule" "okf_wiki_efs_from_lambda" {
|
|
|
634
674
|
security_group_id = aws_security_group.okf_wiki_efs[0].id
|
|
635
675
|
}
|
|
636
676
|
|
|
677
|
+
# THINK-589 PR 1: deliberately NOT conditioned off — flipping this count to 0
|
|
678
|
+
# would DESTROY the filesystem (and its data) on the next apply. All consumers
|
|
679
|
+
# (mount targets, access points, Lambda mounts, IAM) are detached below; the
|
|
680
|
+
# filesystem delete happens in PR 2 behind the destructive-step gates.
|
|
637
681
|
resource "aws_efs_file_system" "okf_wiki" {
|
|
638
682
|
count = var.okf_wiki_efs_enabled ? 1 : 0
|
|
639
683
|
|
|
@@ -651,7 +695,7 @@ resource "aws_efs_file_system" "okf_wiki" {
|
|
|
651
695
|
}
|
|
652
696
|
|
|
653
697
|
resource "aws_efs_mount_target" "okf_wiki" {
|
|
654
|
-
count =
|
|
698
|
+
count = local.okf_wiki_efs_consumers_active ? length(local.okf_wiki_subnet_ids) : 0 # THINK-589: always off
|
|
655
699
|
|
|
656
700
|
file_system_id = aws_efs_file_system.okf_wiki[0].id
|
|
657
701
|
subnet_id = local.okf_wiki_subnet_ids[count.index]
|
|
@@ -659,7 +703,7 @@ resource "aws_efs_mount_target" "okf_wiki" {
|
|
|
659
703
|
}
|
|
660
704
|
|
|
661
705
|
resource "aws_efs_access_point" "okf_wiki_refresh" {
|
|
662
|
-
count =
|
|
706
|
+
count = local.okf_wiki_efs_consumers_active ? 1 : 0 # THINK-589: always off
|
|
663
707
|
|
|
664
708
|
file_system_id = aws_efs_file_system.okf_wiki[0].id
|
|
665
709
|
|
|
@@ -684,7 +728,7 @@ resource "aws_efs_access_point" "okf_wiki_refresh" {
|
|
|
684
728
|
}
|
|
685
729
|
|
|
686
730
|
resource "aws_efs_access_point" "okf_wiki_pi_read" {
|
|
687
|
-
count =
|
|
731
|
+
count = local.okf_wiki_efs_consumers_active ? 1 : 0 # THINK-589: always off
|
|
688
732
|
|
|
689
733
|
file_system_id = aws_efs_file_system.okf_wiki[0].id
|
|
690
734
|
|
|
@@ -722,7 +766,16 @@ module "vpc" {
|
|
|
722
766
|
existing_private_subnet_ids = var.existing_private_subnet_ids
|
|
723
767
|
existing_public_route_table_ids = var.existing_public_route_table_ids
|
|
724
768
|
existing_private_route_table_ids = var.existing_private_route_table_ids
|
|
725
|
-
|
|
769
|
+
# THINK-589 PR 1: NAT egress historically rode the OKF EFS flags but is
|
|
770
|
+
# shared VPC plumbing — Neptune twin Lambdas (and any other VPC-attached
|
|
771
|
+
# workload) depend on the NAT-routed private subnets. Left gated as before
|
|
772
|
+
# so PR 1 changes no networking; PR 2 re-homes this onto the surviving VPC
|
|
773
|
+
# consumers (the lambda_vpc_access precedent in lambda-api/main.tf).
|
|
774
|
+
# THINK-1082: a VPC-attached deployment runner has no public IP and needs
|
|
775
|
+
# NAT egress (GitHub release manifest, apt/pip, STS/S3/Secrets Manager).
|
|
776
|
+
# THINK-1082: VPC-attached api Lambdas / Pi have no public IP either (AWS
|
|
777
|
+
# APIs, Bedrock, Slack, GitHub, model providers).
|
|
778
|
+
enable_nat_gateway = (var.okf_wiki_efs_enabled && var.okf_wiki_create_nat_gateway) || var.deployment_runner_in_vpc || var.api_lambdas_in_vpc
|
|
726
779
|
}
|
|
727
780
|
|
|
728
781
|
module "kms" {
|
|
@@ -787,8 +840,8 @@ module "cognito" {
|
|
|
787
840
|
# entry — login works on both domains. Flipping
|
|
788
841
|
# customer_domain_legacy_retired REMOVES the legacy (non-customer-domain)
|
|
789
842
|
# app entries — the CloudFront default domain, the legacy app/computer
|
|
790
|
-
# domains — as a reviewable Terraform change. Explicit caller-supplied
|
|
791
|
-
# localhost dev
|
|
843
|
+
# domains — as a reviewable Terraform change. Explicit caller-supplied and
|
|
844
|
+
# localhost dev entries are never retired here.
|
|
792
845
|
admin_callback_urls = distinct(concat(
|
|
793
846
|
var.admin_callback_urls,
|
|
794
847
|
local.customer_domain_legacy_retired ? [] : ["https://${module.computer_site.distribution_domain}", "https://${module.computer_site.distribution_domain}/auth/callback"],
|
|
@@ -800,7 +853,25 @@ module "cognito" {
|
|
|
800
853
|
"http://localhost:5180/auth/callback",
|
|
801
854
|
"http://127.0.0.1:5180",
|
|
802
855
|
"http://127.0.0.1:5180/auth/callback",
|
|
803
|
-
]
|
|
856
|
+
],
|
|
857
|
+
# Hosted Company Brain console origins (dev only): the console's CloudFront
|
|
858
|
+
# distribution and the future custom domain must be able to complete OAuth
|
|
859
|
+
# against the dev web-family clients. Dev-scoped so customer stacks don't
|
|
860
|
+
# carry dev console origins in their pools.
|
|
861
|
+
var.stage == "dev" ? [
|
|
862
|
+
"https://d3q9a98mhsakjf.cloudfront.net",
|
|
863
|
+
"https://d3q9a98mhsakjf.cloudfront.net/auth/callback",
|
|
864
|
+
"https://brain.thinkwork.ai",
|
|
865
|
+
"https://brain.thinkwork.ai/auth/callback",
|
|
866
|
+
] : [],
|
|
867
|
+
# Operator-supplied web-family callback origins. Customer stacks host the
|
|
868
|
+
# Company Brain console in their OWN account (separate repo/CloudFront), so
|
|
869
|
+
# the product stack can't derive those URLs — they arrive here from the
|
|
870
|
+
# deployment runner (runner-secrets `adminCallbackUrls`). Empty by default;
|
|
871
|
+
# both bare and /auth/callback entries should be supplied by the caller.
|
|
872
|
+
# This is what keeps the console origins from being stripped on every
|
|
873
|
+
# controller apply (dev has the hardcoded block above; customers use this).
|
|
874
|
+
var.additional_admin_callback_urls,
|
|
804
875
|
))
|
|
805
876
|
admin_logout_urls = distinct(concat(
|
|
806
877
|
var.admin_logout_urls,
|
|
@@ -808,13 +879,28 @@ module "cognito" {
|
|
|
808
879
|
local.customer_domain_legacy_retired ? [] : (local.legacy_end_user_app_domain != "" ? ["https://${local.legacy_end_user_app_domain}"] : []),
|
|
809
880
|
local.customer_domain_web_enabled ? ["https://${var.customer_domain}"] : [],
|
|
810
881
|
local.customer_domain_legacy_retired ? [] : (var.computer_domain != "" ? ["https://${var.computer_domain}"] : []),
|
|
811
|
-
["http://localhost:5180", "http://127.0.0.1:5180"]
|
|
882
|
+
["http://localhost:5180", "http://127.0.0.1:5180"],
|
|
883
|
+
# Hosted Company Brain console origins (dev only) — see admin_callback_urls.
|
|
884
|
+
var.stage == "dev" ? [
|
|
885
|
+
"https://d3q9a98mhsakjf.cloudfront.net",
|
|
886
|
+
"https://d3q9a98mhsakjf.cloudfront.net/auth/callback",
|
|
887
|
+
"https://brain.thinkwork.ai",
|
|
888
|
+
"https://brain.thinkwork.ai/auth/callback",
|
|
889
|
+
] : [],
|
|
890
|
+
# Operator-supplied web-family logout origins — see admin_callback_urls.
|
|
891
|
+
var.additional_admin_logout_urls,
|
|
812
892
|
))
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
893
|
+
cli_callback_urls = var.cli_callback_urls
|
|
894
|
+
cli_logout_urls = var.cli_logout_urls
|
|
895
|
+
mobile_callback_urls = var.mobile_callback_urls
|
|
896
|
+
mobile_logout_urls = var.mobile_logout_urls
|
|
897
|
+
|
|
898
|
+
# Company Brain console client (U13 — ship-inert, default off). The console's
|
|
899
|
+
# CloudFront URL must be in console_callback_urls BEFORE first login
|
|
900
|
+
# (redirect_mismatch otherwise).
|
|
901
|
+
console_client_enabled = var.console_client_enabled
|
|
902
|
+
console_callback_urls = var.console_callback_urls
|
|
903
|
+
console_logout_urls = var.console_logout_urls
|
|
818
904
|
}
|
|
819
905
|
|
|
820
906
|
module "dns" {
|
|
@@ -904,6 +990,12 @@ module "database" {
|
|
|
904
990
|
subnet_ids = module.vpc.public_subnet_ids
|
|
905
991
|
db_password = var.db_password
|
|
906
992
|
|
|
993
|
+
# THINK-1082: network exposure. Defaults = today's public endpoint + world-
|
|
994
|
+
# open 5432. Closed per stage only after the Lambdas and the runner are in
|
|
995
|
+
# the VPC (api_lambdas_in_vpc / deployment_runner_in_vpc).
|
|
996
|
+
publicly_accessible = var.db_publicly_accessible
|
|
997
|
+
public_ingress_cidrs = var.db_public_ingress_cidrs
|
|
998
|
+
|
|
907
999
|
database_name = var.database_name
|
|
908
1000
|
database_engine = var.database_engine
|
|
909
1001
|
|
|
@@ -917,13 +1009,54 @@ module "database" {
|
|
|
917
1009
|
enable_aws_s3 = var.database_engine == "aurora-serverless"
|
|
918
1010
|
}
|
|
919
1011
|
|
|
920
|
-
|
|
921
|
-
|
|
1012
|
+
################################################################################
|
|
1013
|
+
# API Lambdas inside the VPC (THINK-1082)
|
|
1014
|
+
#
|
|
1015
|
+
# Off by default (ship-inert). When on, every database-connected Lambda of the
|
|
1016
|
+
# agent (lambda-api handlers, agentcore-admin, agentcore-pi, the capability
|
|
1017
|
+
# broker) attaches to the private subnets with this security group, and the
|
|
1018
|
+
# database security group grants it tcp/5432 — the same standalone-rule
|
|
1019
|
+
# pattern the ECS modules and the deployment runner use, so the grant survives
|
|
1020
|
+
# the aurora-postgres module's `ignore_changes = [ingress]`. With this live the
|
|
1021
|
+
# world-open 0.0.0.0/0 -> 5432 rule can be revoked without taking the app down.
|
|
1022
|
+
################################################################################
|
|
1023
|
+
|
|
1024
|
+
resource "aws_security_group" "api_lambda" {
|
|
1025
|
+
count = var.api_lambdas_in_vpc ? 1 : 0
|
|
1026
|
+
|
|
1027
|
+
name = "thinkwork-${var.stage}-api-lambda-sg"
|
|
1028
|
+
description = "ThinkWork API Lambdas (VPC) for ${var.stage}."
|
|
1029
|
+
vpc_id = module.vpc.vpc_id
|
|
1030
|
+
|
|
1031
|
+
egress {
|
|
1032
|
+
from_port = 0
|
|
1033
|
+
to_port = 0
|
|
1034
|
+
protocol = "-1"
|
|
1035
|
+
cidr_blocks = ["0.0.0.0/0"]
|
|
1036
|
+
}
|
|
1037
|
+
|
|
1038
|
+
tags = {
|
|
1039
|
+
Name = "thinkwork-${var.stage}-api-lambda-sg"
|
|
1040
|
+
Stage = var.stage
|
|
1041
|
+
Purpose = "api-lambda"
|
|
1042
|
+
}
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1045
|
+
resource "aws_security_group_rule" "db_from_api_lambda" {
|
|
1046
|
+
count = var.api_lambdas_in_vpc ? 1 : 0
|
|
922
1047
|
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
1048
|
+
type = "ingress"
|
|
1049
|
+
description = "ThinkWork API Lambdas (VPC)"
|
|
1050
|
+
from_port = 5432
|
|
1051
|
+
to_port = 5432
|
|
1052
|
+
protocol = "tcp"
|
|
1053
|
+
security_group_id = module.database.db_security_group_id
|
|
1054
|
+
source_security_group_id = aws_security_group.api_lambda[0].id
|
|
1055
|
+
}
|
|
1056
|
+
|
|
1057
|
+
locals {
|
|
1058
|
+
api_lambda_vpc_subnet_ids = var.api_lambdas_in_vpc ? module.vpc.private_subnet_ids : []
|
|
1059
|
+
api_lambda_vpc_security_group_ids = var.api_lambdas_in_vpc ? [aws_security_group.api_lambda[0].id] : []
|
|
927
1060
|
}
|
|
928
1061
|
|
|
929
1062
|
################################################################################
|
|
@@ -975,6 +1108,13 @@ module "deployment_control_plane" {
|
|
|
975
1108
|
|
|
976
1109
|
log_retention_days = var.deployment_control_plane_log_retention_days
|
|
977
1110
|
create_secret_placeholders = var.deployment_control_plane_create_secret_placeholders
|
|
1111
|
+
|
|
1112
|
+
# THINK-1082: runner inside the VPC — DB access by security group, not a
|
|
1113
|
+
# world-open port. The NAT this needs is switched on module.vpc above.
|
|
1114
|
+
runner_in_vpc = var.deployment_runner_in_vpc
|
|
1115
|
+
vpc_id = module.vpc.vpc_id
|
|
1116
|
+
subnet_ids = module.vpc.private_subnet_ids
|
|
1117
|
+
db_security_group_id = module.database.db_security_group_id
|
|
978
1118
|
}
|
|
979
1119
|
|
|
980
1120
|
# ── Capability signing keypair (THINK-173 KTD-3) ──────────────────────────
|
|
@@ -989,23 +1129,6 @@ resource "tls_private_key" "capability_signing" {
|
|
|
989
1129
|
algorithm = "ED25519"
|
|
990
1130
|
}
|
|
991
1131
|
|
|
992
|
-
resource "random_password" "agentcore_proof_oauth_client_secret" {
|
|
993
|
-
count = var.enable_agentcore_multiplayer_proof ? 1 : 0
|
|
994
|
-
length = 48
|
|
995
|
-
special = false
|
|
996
|
-
}
|
|
997
|
-
|
|
998
|
-
check "agentcore_multiplayer_proof_requires_harness" {
|
|
999
|
-
assert {
|
|
1000
|
-
condition = !var.enable_agentcore_multiplayer_proof || (
|
|
1001
|
-
var.enable_agentcore_harness &&
|
|
1002
|
-
can(regex("^[a-z0-9][a-z0-9-]{0,47}$", var.agentcore_multiplayer_proof_tenant_slug)) &&
|
|
1003
|
-
length(distinct(compact([for owner in split(",", var.agentcore_multiplayer_proof_owner_allowlist) : trimspace(owner)]))) >= 2
|
|
1004
|
-
)
|
|
1005
|
-
error_message = "enable_agentcore_multiplayer_proof requires enable_agentcore_harness, an explicit lowercase tenant slug, and at least two explicit distinct proof owner subjects."
|
|
1006
|
-
}
|
|
1007
|
-
}
|
|
1008
|
-
|
|
1009
1132
|
resource "aws_secretsmanager_secret" "capability_signing_key" {
|
|
1010
1133
|
name = "thinkwork/${var.stage}/capability-signing-key"
|
|
1011
1134
|
description = "Ed25519 private key (PKCS8 PEM) signing capability sidecars and manifests (THINK-173)."
|
|
@@ -1091,37 +1214,20 @@ module "api" {
|
|
|
1091
1214
|
compliance_reader_secret_arn = module.database.compliance_reader_secret_arn
|
|
1092
1215
|
compliance_anchor_object_lock_retention_days = var.compliance_anchor_retention_days
|
|
1093
1216
|
|
|
1094
|
-
# THINK-228 — analyst query broker: hardened reader role credentials +
|
|
1095
|
-
# the broker caller credential the seeded connector row references.
|
|
1096
1217
|
# THINK-246 — artifact email delivery sender: customer stages send from
|
|
1097
1218
|
# their own verified domain (noreply@<customer_domain>); dev keeps the
|
|
1098
1219
|
# code fallback via the empty default.
|
|
1099
1220
|
artifact_delivery_from_email = var.customer_domain != "" ? "noreply@${var.customer_domain}" : ""
|
|
1100
1221
|
|
|
1101
|
-
analyst_reader_secret_arn = module.database.analyst_reader_secret_arn
|
|
1102
|
-
analyst_broker_secret_arn = module.database.analyst_broker_secret_arn
|
|
1103
|
-
# THINK-229 U1 — keys the broker's rds-db:connect grant and switches the
|
|
1104
|
-
# reader connection to per-connect RDS IAM auth tokens.
|
|
1105
|
-
analyst_db_cluster_resource_id = module.database.cluster_resource_id
|
|
1106
|
-
analyst_policy_source = var.analyst_policy_source
|
|
1107
|
-
|
|
1108
1222
|
# Governed autonomy — per-tenant self-extension opt-in allowlist (default off).
|
|
1109
|
-
capability_self_extension_tenants = var.capability_self_extension_tenants
|
|
1110
1223
|
|
|
1111
1224
|
# THINK-316 U2 — request path receives only Harness invocation. Terraform
|
|
1112
1225
|
# owns provisioning/version/endpoint control, avoiding a module cycle and
|
|
1113
1226
|
# keeping PassRole/create/update/list out of chat Lambdas.
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
#
|
|
1117
|
-
|
|
1118
|
-
# state and is passed only to the two narrow boundary Lambdas and Identity.
|
|
1119
|
-
enable_agentcore_multiplayer_proof = var.enable_agentcore_multiplayer_proof
|
|
1120
|
-
agentcore_turn_assertion_key_versions = var.agentcore_turn_assertion_key_versions
|
|
1121
|
-
agentcore_turn_assertion_active_key_version = var.agentcore_turn_assertion_active_key_version
|
|
1122
|
-
agentcore_proof_oauth_client_id = "thinkwork-${var.stage}-agentcore-proof"
|
|
1123
|
-
agentcore_proof_oauth_client_secret = var.enable_agentcore_multiplayer_proof ? random_password.agentcore_proof_oauth_client_secret[0].result : ""
|
|
1124
|
-
agentcore_proof_owner_allowlist = var.agentcore_multiplayer_proof_owner_allowlist
|
|
1227
|
+
# THINK-324: the managed-harness/proof plane is retired; its handlers,
|
|
1228
|
+
# KMS plane, and Gateway are gone. The proof flag survives only as a
|
|
1229
|
+
# declared variable so existing -var passthroughs stay valid.
|
|
1230
|
+
enable_agentcore_multiplayer_proof = false
|
|
1125
1231
|
|
|
1126
1232
|
# Phase 3 U8b — KMS key + Object Lock mode forwarded as
|
|
1127
1233
|
# COMPLIANCE_ANCHOR_KMS_KEY_ARN and COMPLIANCE_ANCHOR_OBJECT_LOCK_MODE
|
|
@@ -1143,20 +1249,24 @@ module "api" {
|
|
|
1143
1249
|
bucket_arn = module.s3.bucket_arn
|
|
1144
1250
|
|
|
1145
1251
|
plugin_catalog_github_token_secret_arn = var.plugin_catalog_github_token_secret_arn
|
|
1252
|
+
brain_m2m_platform_agent_secret_arn = var.brain_m2m_platform_agent_secret_arn
|
|
1253
|
+
brain_ops_api_url = var.brain_ops_api_url
|
|
1254
|
+
brain_ops_m2m_secret_arn = var.brain_ops_m2m_secret_arn
|
|
1146
1255
|
|
|
1147
1256
|
brain_artifacts_kms_key_arn = module.kms.key_arn
|
|
1148
1257
|
|
|
1149
|
-
user_pool_id
|
|
1150
|
-
user_pool_arn
|
|
1151
|
-
admin_client_id
|
|
1152
|
-
mobile_client_id
|
|
1258
|
+
user_pool_id = module.cognito.user_pool_id
|
|
1259
|
+
user_pool_arn = module.cognito.user_pool_arn
|
|
1260
|
+
admin_client_id = module.cognito.admin_client_id
|
|
1261
|
+
mobile_client_id = module.cognito.mobile_client_id
|
|
1262
|
+
# R16: console client id joins the COGNITO_APP_CLIENT_IDS allowlist when
|
|
1263
|
+
# enabled ("" otherwise — the lambda-api module compacts it away).
|
|
1264
|
+
console_client_id = var.console_client_enabled ? module.cognito.console_client_id : ""
|
|
1153
1265
|
cognito_auth_domain = module.cognito.auth_domain
|
|
1154
1266
|
|
|
1155
1267
|
appsync_api_id = module.appsync.graphql_api_id
|
|
1156
1268
|
appsync_api_url = module.appsync.graphql_api_url
|
|
1157
1269
|
|
|
1158
|
-
kb_service_role_arn = module.bedrock_kb.kb_service_role_arn
|
|
1159
|
-
|
|
1160
1270
|
lambda_zips_dir = var.lambda_zips_dir
|
|
1161
1271
|
api_auth_secret = var.api_auth_secret
|
|
1162
1272
|
db_password = var.db_password
|
|
@@ -1164,33 +1274,51 @@ module "api" {
|
|
|
1164
1274
|
agentcore_pi_function_name = module.agentcore_pi.agentcore_pi_function_name
|
|
1165
1275
|
agentcore_pi_function_arn = module.agentcore_pi.agentcore_pi_function_arn
|
|
1166
1276
|
enable_agentcore_pi_invoke_policy = true
|
|
1167
|
-
hindsight_endpoint = local.hindsight_enabled ? module.hindsight[0].hindsight_endpoint : ""
|
|
1168
|
-
hindsight_database_name = var.hindsight_database_name
|
|
1169
1277
|
agentcore_memory_id = module.agentcore_memory.memory_id
|
|
1170
|
-
|
|
1171
|
-
okf_efs_subnet_ids
|
|
1172
|
-
okf_efs_security_group_ids
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1278
|
+
# THINK-589: OKF EFS inputs are deprecated no-ops — always pass empty.
|
|
1279
|
+
okf_efs_subnet_ids = []
|
|
1280
|
+
okf_efs_security_group_ids = []
|
|
1281
|
+
# Company Brain U5: projector VPC attach only when the neptune-client SG
|
|
1282
|
+
# is configured (the twin's Neptune cluster lives in this same VPC). The
|
|
1283
|
+
# client SG only opens 8182→Neptune, so twin Lambdas ALSO attach the
|
|
1284
|
+
# egress SG below — without it a VPC-attached Lambda cannot reach
|
|
1285
|
+
# Aurora/Secrets/S3 and every DB connection times out (seen live on the
|
|
1286
|
+
# first dev rebuild invoke).
|
|
1287
|
+
lambda_max_memory_mb = var.lambda_max_memory_mb
|
|
1288
|
+
neptune_endpoint = var.neptune_endpoint
|
|
1289
|
+
brain_mcp_url = var.brain_mcp_url
|
|
1290
|
+
neptune_cluster_resource_id = var.neptune_cluster_resource_id
|
|
1291
|
+
neptune_subnet_ids = var.neptune_client_security_group_id != "" ? module.vpc.private_subnet_ids : []
|
|
1292
|
+
neptune_security_group_ids = var.neptune_client_security_group_id != "" ? [var.neptune_client_security_group_id, aws_security_group.twin_lambda_egress[0].id] : []
|
|
1293
|
+
# THINK-1082: every handler inside the VPC behind the api-lambda SG (merged
|
|
1294
|
+
# with the Neptune SGs on the projector). NAT is switched on module.vpc.
|
|
1295
|
+
lambdas_in_vpc = var.api_lambdas_in_vpc
|
|
1296
|
+
vpc_subnet_ids = local.api_lambda_vpc_subnet_ids
|
|
1297
|
+
vpc_security_group_ids = local.api_lambda_vpc_security_group_ids
|
|
1298
|
+
# Bulk-rebuild lane (THINK-331): loader staging bucket + cluster loader
|
|
1299
|
+
# role, both default-empty (ship inert, KTD-9).
|
|
1300
|
+
neptune_load_bucket = var.neptune_load_bucket
|
|
1301
|
+
neptune_loader_role_arn = var.neptune_loader_role_arn
|
|
1302
|
+
# Company Brain U7: twin tool seam flag (KTD-5 rollout posture).
|
|
1303
|
+
# THINK-589: OKF EFS inputs are deprecated no-ops — always pass empty.
|
|
1304
|
+
okf_efs_mount_target_ids = []
|
|
1305
|
+
okf_efs_file_system_arn = ""
|
|
1306
|
+
okf_efs_refresh_access_point_arn = ""
|
|
1307
|
+
twenty_provisioned = local.twenty_provisioned
|
|
1308
|
+
twenty_runtime_enabled = local.twenty_runtime_enabled
|
|
1309
|
+
twenty_url = local.twenty_provisioned ? module.twenty[0].twenty_url : ""
|
|
1310
|
+
twenty_alb_arn = local.twenty_provisioned ? module.twenty[0].twenty_alb_arn : ""
|
|
1311
|
+
twenty_target_group_arn = local.twenty_provisioned ? module.twenty[0].twenty_target_group_arn : ""
|
|
1312
|
+
twenty_cluster_arn = local.twenty_provisioned ? module.twenty[0].twenty_cluster_arn : ""
|
|
1313
|
+
twenty_server_service_name = local.twenty_provisioned ? module.twenty[0].twenty_server_service_name : ""
|
|
1314
|
+
twenty_worker_service_name = local.twenty_provisioned ? module.twenty[0].twenty_worker_service_name : ""
|
|
1315
|
+
twenty_server_log_group_name = local.twenty_provisioned ? module.twenty[0].twenty_server_log_group_name : ""
|
|
1316
|
+
twenty_worker_log_group_name = local.twenty_provisioned ? module.twenty[0].twenty_worker_log_group_name : ""
|
|
1317
|
+
admin_url = local.end_user_app_url
|
|
1318
|
+
www_url = var.www_domain != "" ? "https://${var.www_domain}" : "https://${module.www_site.distribution_domain}"
|
|
1319
|
+
stripe_price_ids_json = var.stripe_price_ids_json
|
|
1320
|
+
appsync_realtime_url = module.appsync.graphql_realtime_url
|
|
1321
|
+
ecr_repository_url = module.agentcore_platform.ecr_repository_url
|
|
1194
1322
|
# Static truth for count gating: agentcore_platform's ECR repo is
|
|
1195
1323
|
# unconditional, but its URL attribute is unknown until apply. The runner
|
|
1196
1324
|
# additionally needs its image tag seeded (CI does this for repo-managed
|
|
@@ -1210,15 +1338,13 @@ module "api" {
|
|
|
1210
1338
|
enable_slack_workspace_app = var.enable_slack_workspace_app
|
|
1211
1339
|
enable_msteams_app = var.enable_msteams_app
|
|
1212
1340
|
agentcore_code_interpreter_id = var.agentcore_code_interpreter_id
|
|
1213
|
-
wiki_compile_model_id = var.wiki_compile_model_id
|
|
1214
1341
|
brain_source_agent_model_id = var.brain_source_agent_model_id
|
|
1215
1342
|
wiki_aggregation_pass_enabled = var.wiki_aggregation_pass_enabled
|
|
1216
1343
|
wiki_source = var.wiki_source
|
|
1217
|
-
|
|
1218
|
-
ontology_scan_sweep_enabled = var.ontology_scan_sweep_enabled
|
|
1344
|
+
identity_drift_match_enabled = var.identity_drift_match_enabled
|
|
1219
1345
|
wiki_deterministic_linking_enabled = var.wiki_deterministic_linking_enabled
|
|
1220
|
-
google_places_api_key = var.google_places_api_key
|
|
1221
1346
|
enable_workspace_orchestration = var.enable_workspace_orchestration
|
|
1347
|
+
agentcore_session_scope = var.agentcore_session_scope
|
|
1222
1348
|
requester_idle_memory_learning_enabled = var.requester_idle_memory_learning_enabled
|
|
1223
1349
|
requester_memory_dreaming_enabled = var.requester_memory_dreaming_enabled
|
|
1224
1350
|
requester_memory_dreaming_schedule_expression = var.requester_memory_dreaming_schedule_expression
|
|
@@ -1233,6 +1359,19 @@ module "api" {
|
|
|
1233
1359
|
redirect_success_url = var.redirect_success_url
|
|
1234
1360
|
platform_operator_emails = var.platform_operator_emails
|
|
1235
1361
|
|
|
1362
|
+
# THINK-583 U3 — warm chat path (KTD5: these two handlers only).
|
|
1363
|
+
chat_agent_invoke_provisioned_concurrency = var.chat_agent_invoke_provisioned_concurrency
|
|
1364
|
+
workspace_renderer_provisioned_concurrency = var.workspace_renderer_provisioned_concurrency
|
|
1365
|
+
agentcore_runtime_dispatch_enabled = var.agentcore_runtime_dispatch_enabled
|
|
1366
|
+
|
|
1367
|
+
# THINK-915 — chat turn-latency observability.
|
|
1368
|
+
enable_chat_turn_latency_observability = var.enable_chat_turn_latency_observability
|
|
1369
|
+
enable_chat_turn_latency_metric_filters = var.enable_chat_turn_latency_metric_filters
|
|
1370
|
+
chat_turn_latency_metric_namespace = var.chat_turn_latency_metric_namespace
|
|
1371
|
+
chat_turn_runtime_log_group_name = var.chat_turn_runtime_log_group_name
|
|
1372
|
+
chat_turn_p95_alarm_threshold_ms = var.chat_turn_p95_alarm_threshold_ms
|
|
1373
|
+
chat_turn_latency_alarm_actions = var.chat_turn_latency_alarm_actions
|
|
1374
|
+
|
|
1236
1375
|
mcp_custom_domain = var.mcp_custom_domain
|
|
1237
1376
|
mcp_custom_domain_ready = var.mcp_custom_domain_ready
|
|
1238
1377
|
|
|
@@ -1247,6 +1386,8 @@ module "api" {
|
|
|
1247
1386
|
capability_broker_audience = module.capability_broker.broker_audience
|
|
1248
1387
|
capability_broker_api_id = module.capability_broker.private_api_id
|
|
1249
1388
|
capability_broker_vpce_dns = module.capability_broker.execute_api_vpce_dns_name
|
|
1389
|
+
# THINK-643 — "postgres" (default) leaves the auth-state table unprovisioned.
|
|
1390
|
+
auth_state_store = var.auth_state_store
|
|
1250
1391
|
|
|
1251
1392
|
depends_on = [module.cognito]
|
|
1252
1393
|
}
|
|
@@ -1270,7 +1411,8 @@ module "agentcore_memory" {
|
|
|
1270
1411
|
module "agentcore_platform" {
|
|
1271
1412
|
source = "../app/agentcore-platform"
|
|
1272
1413
|
|
|
1273
|
-
stage
|
|
1414
|
+
stage = var.stage
|
|
1415
|
+
release_mirror_principal_arns = var.release_image_mirror_principal_arns
|
|
1274
1416
|
}
|
|
1275
1417
|
|
|
1276
1418
|
################################################################################
|
|
@@ -1292,10 +1434,7 @@ module "agentcore_pi" {
|
|
|
1292
1434
|
source_image_uri = var.agentcore_pi_source_image_uri
|
|
1293
1435
|
async_dlq_arn = module.agentcore_platform.agentcore_async_dlq_arn
|
|
1294
1436
|
|
|
1295
|
-
hindsight_endpoint = local.hindsight_enabled ? module.hindsight[0].hindsight_endpoint : ""
|
|
1296
|
-
hindsight_database_name = var.hindsight_database_name
|
|
1297
1437
|
agentcore_memory_id = module.agentcore_memory.memory_id
|
|
1298
|
-
memory_engine = local.resolved_memory_engine
|
|
1299
1438
|
requester_idle_memory_learning_enabled = var.requester_idle_memory_learning_enabled
|
|
1300
1439
|
|
|
1301
1440
|
api_endpoint = module.api.api_endpoint
|
|
@@ -1307,151 +1446,17 @@ module "agentcore_pi" {
|
|
|
1307
1446
|
db_cluster_arn = module.database.db_cluster_arn
|
|
1308
1447
|
db_secret_arn = module.database.graphql_db_secret_arn
|
|
1309
1448
|
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
# AgentCore Harness execution role and managed tenant/profile runtime. The
|
|
1318
|
-
# public root inputs retain their rollout-era names until the example-stack
|
|
1319
|
-
# compatibility window closes; this module boundary uses managed semantics.
|
|
1320
|
-
module "agentcore_harness" {
|
|
1321
|
-
source = "../app/agentcore-harness"
|
|
1449
|
+
# THINK-589: OKF EFS inputs are deprecated no-ops — always pass disabled.
|
|
1450
|
+
okf_efs_enabled = false
|
|
1451
|
+
okf_efs_subnet_ids = []
|
|
1452
|
+
okf_efs_security_group_ids = []
|
|
1453
|
+
okf_efs_file_system_arn = ""
|
|
1454
|
+
okf_efs_read_access_point_arn = ""
|
|
1322
1455
|
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
account_id = var.account_id
|
|
1328
|
-
bucket_name = module.s3.bucket_name
|
|
1329
|
-
tenant_slug = var.agentcore_multiplayer_proof_tenant_slug
|
|
1330
|
-
discovery_url = "${module.api.agentcore_turn_assertion_issuer}/.well-known/openid-configuration"
|
|
1331
|
-
harness_audience = module.api.agentcore_harness_audience
|
|
1332
|
-
gateway_arn = module.agentcore_proof_gateway.gateway_arn
|
|
1333
|
-
oauth_credential_provider_arn = module.agentcore_proof_identity.credential_provider_arn
|
|
1334
|
-
oauth_credential_secret_arn = module.agentcore_proof_identity.credential_secret_arn
|
|
1335
|
-
oauth_return_url = module.agentcore_proof_identity.oauth_return_url
|
|
1336
|
-
}
|
|
1337
|
-
|
|
1338
|
-
# The Harness depends on the public issuer/API, so feeding its generated ARN
|
|
1339
|
-
# back into the api module would create a Terraform cycle. Publish the
|
|
1340
|
-
# non-secret, attested readiness contract under deterministic SSM keys; the
|
|
1341
|
-
# runner and DeploymentStatus resolver read it server-side. No browser token,
|
|
1342
|
-
# participant id, credential, prompt, or private result is stored here. Keep
|
|
1343
|
-
# the original address during the migration so deployed runners never lose
|
|
1344
|
-
# their profile between releases.
|
|
1345
|
-
locals {
|
|
1346
|
-
agentcore_harness_profile_value = jsonencode({
|
|
1347
|
-
tenantSlug = var.agentcore_multiplayer_proof_tenant_slug
|
|
1348
|
-
trustProfile = "default"
|
|
1349
|
-
harnessArn = module.agentcore_harness.managed_harness_arn
|
|
1350
|
-
endpointArn = module.agentcore_harness.managed_endpoint_arn
|
|
1351
|
-
endpointName = module.agentcore_harness.managed_endpoint_name
|
|
1352
|
-
expectedVersion = module.agentcore_harness.managed_target_version
|
|
1353
|
-
liveVersion = module.agentcore_harness.managed_live_version
|
|
1354
|
-
modelId = module.agentcore_harness.managed_model_id
|
|
1355
|
-
status = module.agentcore_harness.managed_status
|
|
1356
|
-
configurationFingerprint = module.agentcore_harness.managed_configuration_fingerprint
|
|
1357
|
-
authorizerAudience = module.api.agentcore_harness_audience
|
|
1358
|
-
sessionStrategy = "fresh"
|
|
1359
|
-
gatewayArn = module.agentcore_proof_gateway.gateway_arn
|
|
1360
|
-
gatewayUrl = module.agentcore_proof_gateway.gateway_url
|
|
1361
|
-
gatewayTargetName = module.agentcore_proof_gateway.target_name
|
|
1362
|
-
identityWorkloadName = module.agentcore_proof_identity.workload_identity_name
|
|
1363
|
-
identityCredentialProviderName = module.agentcore_proof_identity.credential_provider_name
|
|
1364
|
-
identityCredentialProviderArn = module.agentcore_proof_identity.credential_provider_arn
|
|
1365
|
-
invocationToolsContract = "control-plane-attested-full-override-v1"
|
|
1366
|
-
invocationToolsFingerprint = module.agentcore_harness.managed_invocation_tools_fingerprint
|
|
1367
|
-
invocationTools = jsondecode(module.agentcore_harness.managed_invocation_tools_json)
|
|
1368
|
-
strategyDecisionRule = "reuse_only_if_correct_and_20_percent_benefit"
|
|
1369
|
-
capacityEnvelope = {
|
|
1370
|
-
activeSessions = 100
|
|
1371
|
-
newSessionsPerSecond = 10
|
|
1372
|
-
minimumHeadroom = 0.50
|
|
1373
|
-
}
|
|
1374
|
-
})
|
|
1375
|
-
}
|
|
1376
|
-
|
|
1377
|
-
resource "aws_ssm_parameter" "agentcore_harness_proof_profile" {
|
|
1378
|
-
count = var.enable_agentcore_multiplayer_proof ? 1 : 0
|
|
1379
|
-
|
|
1380
|
-
name = "/thinkwork/${var.stage}/agentcore-harness-proof-profile"
|
|
1381
|
-
type = "String"
|
|
1382
|
-
# The exact immutable Harness tool schemas sit close to Standard's 4 KiB
|
|
1383
|
-
# ceiling. Intelligent-Tiering stays Standard while possible and safely
|
|
1384
|
-
# promotes only when a legitimate governed schema requires more room.
|
|
1385
|
-
tier = "Intelligent-Tiering"
|
|
1386
|
-
value = local.agentcore_harness_profile_value
|
|
1387
|
-
|
|
1388
|
-
lifecycle {
|
|
1389
|
-
precondition {
|
|
1390
|
-
# Base64 expands every three UTF-8 bytes to four ASCII characters. A
|
|
1391
|
-
# conservative 10,920-character ceiling admits at most 8,190 bytes and
|
|
1392
|
-
# cannot cross SSM's 8 KiB Advanced parameter limit.
|
|
1393
|
-
condition = length(base64encode(local.agentcore_harness_profile_value)) <= 10920
|
|
1394
|
-
error_message = "The AgentCore Harness managed profile exceeds SSM's 8 KiB parameter limit."
|
|
1395
|
-
}
|
|
1396
|
-
}
|
|
1397
|
-
|
|
1398
|
-
tags = {
|
|
1399
|
-
Name = "thinkwork-${var.stage}-agentcore-harness-proof-profile"
|
|
1400
|
-
"thinkwork:proof" = "THINK-316"
|
|
1401
|
-
"thinkwork:tenant" = var.agentcore_multiplayer_proof_tenant_slug
|
|
1402
|
-
"thinkwork:profile" = "default"
|
|
1403
|
-
"thinkwork:visibility" = "server-only-nonsecret"
|
|
1404
|
-
}
|
|
1405
|
-
}
|
|
1406
|
-
|
|
1407
|
-
# Managed per-tenant profile address. Runtime lookup reads this first and only
|
|
1408
|
-
# falls back to the original single-tenant key during the migration window.
|
|
1409
|
-
# Adding the scoped key is non-destructive and lets later tenants receive their
|
|
1410
|
-
# own attested profile without changing Lambda configuration or hot-path
|
|
1411
|
-
# control-plane resources.
|
|
1412
|
-
resource "aws_ssm_parameter" "agentcore_harness_profile" {
|
|
1413
|
-
count = var.enable_agentcore_multiplayer_proof ? 1 : 0
|
|
1414
|
-
|
|
1415
|
-
name = "/thinkwork/${var.stage}/agentcore-harness-profiles/${var.agentcore_multiplayer_proof_tenant_slug}"
|
|
1416
|
-
type = aws_ssm_parameter.agentcore_harness_proof_profile[0].type
|
|
1417
|
-
tier = "Intelligent-Tiering"
|
|
1418
|
-
value = aws_ssm_parameter.agentcore_harness_proof_profile[0].value
|
|
1419
|
-
|
|
1420
|
-
tags = {
|
|
1421
|
-
Name = "thinkwork-${var.stage}-agentcore-harness-profile-${var.agentcore_multiplayer_proof_tenant_slug}"
|
|
1422
|
-
"thinkwork:managed-by" = "terraform"
|
|
1423
|
-
"thinkwork:tenant" = var.agentcore_multiplayer_proof_tenant_slug
|
|
1424
|
-
"thinkwork:profile" = "default"
|
|
1425
|
-
"thinkwork:visibility" = "server-only-nonsecret"
|
|
1426
|
-
}
|
|
1427
|
-
}
|
|
1428
|
-
|
|
1429
|
-
# Publish the new immutable endpoint/profile first, then reclaim older
|
|
1430
|
-
# endpoint versions. Retain the active endpoint plus exactly one prior endpoint
|
|
1431
|
-
# for guarded rollback; the dedicated Harness owns no unrelated endpoints.
|
|
1432
|
-
resource "terraform_data" "agentcore_harness_endpoint_retention" {
|
|
1433
|
-
count = var.enable_agentcore_multiplayer_proof ? 1 : 0
|
|
1434
|
-
|
|
1435
|
-
triggers_replace = {
|
|
1436
|
-
active_endpoint = module.agentcore_harness.managed_endpoint_name
|
|
1437
|
-
profile_digest = module.agentcore_harness.managed_configuration_fingerprint
|
|
1438
|
-
}
|
|
1439
|
-
|
|
1440
|
-
provisioner "local-exec" {
|
|
1441
|
-
command = "bash ${path.module}/../app/agentcore-harness/scripts/prune_harness.sh"
|
|
1442
|
-
environment = {
|
|
1443
|
-
AWS_REGION = var.region
|
|
1444
|
-
HARNESS_ID = module.agentcore_harness.managed_harness_id
|
|
1445
|
-
ACTIVE_ENDPOINT_NAME = module.agentcore_harness.managed_endpoint_name
|
|
1446
|
-
ENDPOINT_PREFIX = "ThinkworkProofV"
|
|
1447
|
-
LEGACY_ENDPOINT_NAME = "ThinkworkProof"
|
|
1448
|
-
}
|
|
1449
|
-
}
|
|
1450
|
-
|
|
1451
|
-
depends_on = [
|
|
1452
|
-
aws_ssm_parameter.agentcore_harness_proof_profile,
|
|
1453
|
-
aws_ssm_parameter.agentcore_harness_profile,
|
|
1454
|
-
]
|
|
1456
|
+
# THINK-1082: network-only VPC attachment alongside the api handlers.
|
|
1457
|
+
in_vpc = var.api_lambdas_in_vpc
|
|
1458
|
+
vpc_subnet_ids = local.api_lambda_vpc_subnet_ids
|
|
1459
|
+
vpc_security_group_ids = local.api_lambda_vpc_security_group_ids
|
|
1455
1460
|
}
|
|
1456
1461
|
|
|
1457
1462
|
# THINK-316 U1 proof-only Identity and Gateway plane. These resources use the
|
|
@@ -1460,39 +1465,41 @@ resource "terraform_data" "agentcore_harness_endpoint_retention" {
|
|
|
1460
1465
|
module "agentcore_proof_identity" {
|
|
1461
1466
|
source = "../app/agentcore-identity"
|
|
1462
1467
|
|
|
1463
|
-
|
|
1468
|
+
# THINK-324: the proof plane is retired — permanently off. The module's
|
|
1469
|
+
# proof half (workload-identity lifecycle + proof credential provider) no
|
|
1470
|
+
# longer reconciles; delete_identity.sh retains the shared workload
|
|
1471
|
+
# identity for the Twenty half below.
|
|
1472
|
+
enabled = false
|
|
1473
|
+
# THINK-324 — the Twenty user-federation identity (shared workload
|
|
1474
|
+
# identity + twenty-crm credential provider + DCR client secret) survives
|
|
1475
|
+
# the proof plane's retirement: it stays enabled wherever a Twenty
|
|
1476
|
+
# instance is provisioned, and — while the proof flag is still on — on
|
|
1477
|
+
# proof stages too, so flipping the proof flag off later destroys only
|
|
1478
|
+
# proof resources. After the harness retirement removes the proof flag,
|
|
1479
|
+
# this reduces to twenty_provisioned alone.
|
|
1480
|
+
twenty_enabled = local.twenty_provisioned || var.enable_agentcore_multiplayer_proof
|
|
1464
1481
|
stage = var.stage
|
|
1465
1482
|
region = var.region
|
|
1466
1483
|
account_id = var.account_id
|
|
1467
|
-
oauth_issuer =
|
|
1484
|
+
oauth_issuer = ""
|
|
1468
1485
|
oauth_client_id = "thinkwork-${var.stage}-agentcore-proof"
|
|
1469
|
-
oauth_client_secret =
|
|
1486
|
+
oauth_client_secret = ""
|
|
1470
1487
|
user_federation_return_urls = [
|
|
1471
1488
|
"${module.api.api_endpoint}/api/skills/mcp-oauth/agentcore/complete",
|
|
1472
1489
|
]
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
stage = var.stage
|
|
1480
|
-
region = var.region
|
|
1481
|
-
account_id = var.account_id
|
|
1482
|
-
discovery_url = "${module.api.agentcore_turn_assertion_issuer}/.well-known/openid-configuration"
|
|
1483
|
-
gateway_audience = module.api.agentcore_gateway_audience
|
|
1484
|
-
target_base_url = module.api.agentcore_proof_target_base_url
|
|
1485
|
-
oauth_credential_provider_arn = module.agentcore_proof_identity.credential_provider_arn
|
|
1486
|
-
oauth_credential_secret_arn = module.agentcore_proof_identity.credential_secret_arn
|
|
1487
|
-
oauth_return_url = module.agentcore_proof_identity.oauth_return_url
|
|
1488
|
-
proof_owner_allowlist = var.agentcore_multiplayer_proof_owner_allowlist
|
|
1490
|
+
# The identity module's issuer/resource defaults are dev's CRM domain;
|
|
1491
|
+
# every stage must point at its own Twenty instance or the credential
|
|
1492
|
+
# provider is reconciled with a foreign issuer (observed live on tei-e2e:
|
|
1493
|
+
# Connect-AgentCore 404'd against crm.thinkwork.ai).
|
|
1494
|
+
twenty_oauth_issuer = local.twenty_public_url != "" ? trimsuffix(local.twenty_public_url, "/") : "https://crm.thinkwork.ai"
|
|
1495
|
+
twenty_oauth_resource = local.twenty_public_url != "" ? "${trimsuffix(local.twenty_public_url, "/")}/mcp" : "https://crm.thinkwork.ai/mcp"
|
|
1489
1496
|
}
|
|
1490
1497
|
|
|
1491
1498
|
# Capability Broker (THINK-280 U3) — ship-inert, gated by
|
|
1492
1499
|
# var.enable_capability_broker (default false). When off, this module creates
|
|
1493
1500
|
# nothing; the broker Lambda code also fails closed. Owns a DEDICATED
|
|
1494
1501
|
# execute-api VPCE with private DNS disabled — never folded into
|
|
1495
|
-
#
|
|
1502
|
+
# vpc_interface_endpoint_services (THINK-144).
|
|
1496
1503
|
module "capability_broker" {
|
|
1497
1504
|
source = "../app/capability-broker"
|
|
1498
1505
|
|
|
@@ -1511,6 +1518,10 @@ module "capability_broker" {
|
|
|
1511
1518
|
db_password = var.db_password
|
|
1512
1519
|
database_name = var.database_name
|
|
1513
1520
|
|
|
1521
|
+
# THINK-1082: the broker is already VPC-attached; give it the api-lambda SG
|
|
1522
|
+
# so it keeps its DB path once the public 5432 rule closes.
|
|
1523
|
+
additional_security_group_ids = local.api_lambda_vpc_security_group_ids
|
|
1524
|
+
|
|
1514
1525
|
lambda_zips_dir = var.lambda_zips_dir
|
|
1515
1526
|
lambda_artifact_bucket = var.lambda_artifact_bucket
|
|
1516
1527
|
lambda_artifact_prefix = var.lambda_artifact_prefix
|
|
@@ -1557,6 +1568,11 @@ module "agentcore_admin" {
|
|
|
1557
1568
|
|
|
1558
1569
|
capability_private_subnet_ids = module.agentcore_code_interpreter.capability_private_subnet_ids
|
|
1559
1570
|
capability_private_security_group_ids = module.agentcore_code_interpreter.capability_private_security_group_ids
|
|
1571
|
+
|
|
1572
|
+
# THINK-1082: the admin handler opens DATABASE_URL — same VPC lane.
|
|
1573
|
+
in_vpc = var.api_lambdas_in_vpc
|
|
1574
|
+
vpc_subnet_ids = local.api_lambda_vpc_subnet_ids
|
|
1575
|
+
vpc_security_group_ids = local.api_lambda_vpc_security_group_ids
|
|
1560
1576
|
}
|
|
1561
1577
|
|
|
1562
1578
|
# Runtime identity rename: the former dedicated Flue module is now the Pi
|
|
@@ -1682,25 +1698,9 @@ module "workflow_interpreter_stepfunctions" {
|
|
|
1682
1698
|
execution_callback_lambda_arn = module.api.workflow_execution_callback_fn_arn
|
|
1683
1699
|
}
|
|
1684
1700
|
|
|
1685
|
-
module "hindsight" {
|
|
1686
|
-
count = local.hindsight_enabled ? 1 : 0
|
|
1687
|
-
source = "../app/hindsight-memory"
|
|
1688
|
-
|
|
1689
|
-
stage = var.stage
|
|
1690
|
-
vpc_id = module.vpc.vpc_id
|
|
1691
|
-
subnet_ids = module.vpc.public_subnet_ids
|
|
1692
|
-
db_security_group_id = module.database.db_security_group_id
|
|
1693
|
-
database_url = module.database.database_url
|
|
1694
|
-
database_name = var.hindsight_database_name
|
|
1695
|
-
image_tag = var.hindsight_image_tag
|
|
1696
|
-
|
|
1697
|
-
enable_auto_consolidation = var.hindsight_enable_auto_consolidation
|
|
1698
|
-
consolidation_dedup_threshold = var.hindsight_consolidation_dedup_threshold
|
|
1699
|
-
observations_mission = var.hindsight_observations_mission
|
|
1700
|
-
}
|
|
1701
1701
|
module "twenty" {
|
|
1702
1702
|
count = local.twenty_provisioned ? 1 : 0
|
|
1703
|
-
source = "
|
|
1703
|
+
source = "../app/twenty"
|
|
1704
1704
|
|
|
1705
1705
|
stage = var.stage
|
|
1706
1706
|
vpc_id = module.vpc.vpc_id
|
|
@@ -1738,7 +1738,7 @@ module "twenty" {
|
|
|
1738
1738
|
|
|
1739
1739
|
module "n8n" {
|
|
1740
1740
|
count = local.n8n_provisioned ? 1 : 0
|
|
1741
|
-
source = "
|
|
1741
|
+
source = "../app/n8n"
|
|
1742
1742
|
|
|
1743
1743
|
stage = var.stage
|
|
1744
1744
|
vpc_id = module.vpc.vpc_id
|
|
@@ -1818,14 +1818,38 @@ locals {
|
|
|
1818
1818
|
# Host CSP for the Computer SPA (plan-012 U10 / contract v1 §CSP profile).
|
|
1819
1819
|
# Generated apps always execute in the sandbox iframe shell, so the parent
|
|
1820
1820
|
# origin never needs blob: script/worker execution for transformed modules.
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1821
|
+
#
|
|
1822
|
+
# 'wasm-unsafe-eval' permits WebAssembly compilation only (not JS eval) —
|
|
1823
|
+
# the in-app knowledge document viewer (Zrimo) renders Office files with
|
|
1824
|
+
# client-side WASM.
|
|
1825
|
+
computer_host_script_src = "'self' 'wasm-unsafe-eval'"
|
|
1826
|
+
# blob: workers are how Zrimo (knowledge document viewer) spawns its
|
|
1827
|
+
# render workers. With script-src carrying no blob:/eval, only
|
|
1828
|
+
# first-party page code can mint a blob worker, and blob workers
|
|
1829
|
+
# inherit this document's CSP — the U10 blob-execution escape hatch
|
|
1830
|
+
# (generated-app script on the host origin) stays closed.
|
|
1831
|
+
computer_host_worker_src = "'self' blob:"
|
|
1832
|
+
# frame-src carries the sandbox shell plus the cited-knowledge-document
|
|
1833
|
+
# frames: browser-native formats (pdf/txt/md) render in an iframe on the
|
|
1834
|
+
# signed /kb/doc link — a *.thinkwork.ai brain host that 302s to the
|
|
1835
|
+
# customer's evidence bucket presign, and CSP re-checks every redirect
|
|
1836
|
+
# hop, so both origins must be allowed (mirroring what connect-src
|
|
1837
|
+
# already trusts for the Zrimo fetch path).
|
|
1838
|
+
computer_host_frame_src = join(" ", compact([
|
|
1839
|
+
local.computer_sandbox_enabled ? "https://${var.computer_sandbox_domain}" : "",
|
|
1840
|
+
"https://*.thinkwork.ai",
|
|
1841
|
+
"https://*.s3.${var.region}.amazonaws.com",
|
|
1842
|
+
"https://s3.${var.region}.amazonaws.com",
|
|
1843
|
+
]))
|
|
1824
1844
|
computer_host_frame_ancestors = join(" ", compact([
|
|
1825
1845
|
"'self'",
|
|
1826
1846
|
]))
|
|
1827
1847
|
|
|
1828
|
-
|
|
1848
|
+
# connect-src includes https://*.thinkwork.ai for the knowledge document
|
|
1849
|
+
# viewer: signed /kb/doc citation links live on brain MCP hosts
|
|
1850
|
+
# (mcp.brain.<customer>.thinkwork.ai), and a tenant may register another
|
|
1851
|
+
# stage's brain, so the host cannot be pinned per-stage.
|
|
1852
|
+
computer_host_csp = "default-src 'self'; script-src ${local.computer_host_script_src}; style-src 'self' 'unsafe-inline'; worker-src ${local.computer_host_worker_src}; frame-src ${local.computer_host_frame_src}; connect-src 'self' https://*.thinkwork.ai https://*.execute-api.${var.region}.amazonaws.com https://*.appsync-api.${var.region}.amazonaws.com wss://*.appsync-realtime-api.${var.region}.amazonaws.com https://cognito-idp.${var.region}.amazonaws.com https://*.auth.${var.region}.amazoncognito.com https://*.s3.${var.region}.amazonaws.com https://s3.${var.region}.amazonaws.com; img-src 'self' data: blob: ${local.computer_sandbox_map_img_src}; font-src 'self' data:; object-src 'none'; base-uri 'self'; frame-ancestors ${local.computer_host_frame_ancestors};"
|
|
1829
1853
|
}
|
|
1830
1854
|
|
|
1831
1855
|
module "computer_site" {
|
|
@@ -1927,7 +1951,7 @@ module "customer_domain" {
|
|
|
1927
1951
|
# https://*.tile.openstreetmap.org https://api.mapbox.com;
|
|
1928
1952
|
# font-src 'self' data:; connect-src 'none';
|
|
1929
1953
|
# frame-src https://www.openstreetmap.org; object-src 'none';
|
|
1930
|
-
# base-uri 'self'; frame-ancestors <web parents
|
|
1954
|
+
# base-uri 'self'; frame-ancestors <web parents>;
|
|
1931
1955
|
#
|
|
1932
1956
|
# Provisioning is gated on var.computer_sandbox_domain — leave empty in
|
|
1933
1957
|
# stages that haven't allocated the subdomain yet.
|
|
@@ -1936,18 +1960,10 @@ module "customer_domain" {
|
|
|
1936
1960
|
locals {
|
|
1937
1961
|
computer_sandbox_enabled = var.computer_sandbox_domain != ""
|
|
1938
1962
|
|
|
1939
|
-
|
|
1940
|
-
"
|
|
1941
|
-
"
|
|
1942
|
-
|
|
1943
|
-
]
|
|
1944
|
-
computer_sandbox_allowed_parent_origin_list = distinct(concat(
|
|
1945
|
-
[
|
|
1946
|
-
for origin in split(",", replace(var.computer_sandbox_allowed_parent_origins, " ", "")) :
|
|
1947
|
-
origin if origin != ""
|
|
1948
|
-
],
|
|
1949
|
-
local.computer_sandbox_desktop_parent_origins
|
|
1950
|
-
))
|
|
1963
|
+
computer_sandbox_allowed_parent_origin_list = distinct([
|
|
1964
|
+
for origin in split(",", replace(var.computer_sandbox_allowed_parent_origins, " ", "")) :
|
|
1965
|
+
origin if origin != ""
|
|
1966
|
+
])
|
|
1951
1967
|
computer_sandbox_allowed_parent_origins_effective = join(",", local.computer_sandbox_allowed_parent_origin_list)
|
|
1952
1968
|
computer_sandbox_frame_ancestors = local.computer_sandbox_enabled && length(local.computer_sandbox_allowed_parent_origin_list) > 0 ? join(" ", local.computer_sandbox_allowed_parent_origin_list) : "'none'"
|
|
1953
1969
|
|
|
@@ -1999,20 +2015,6 @@ module "computer_sandbox_site" {
|
|
|
1999
2015
|
}
|
|
2000
2016
|
}
|
|
2001
2017
|
|
|
2002
|
-
################################################################################
|
|
2003
|
-
# Docs Static Site
|
|
2004
|
-
################################################################################
|
|
2005
|
-
|
|
2006
|
-
module "docs_site" {
|
|
2007
|
-
source = "../app/static-site"
|
|
2008
|
-
|
|
2009
|
-
stage = var.stage
|
|
2010
|
-
site_name = "docs"
|
|
2011
|
-
bucket_name = "thinkwork-${var.stage}-${var.account_id}-docs"
|
|
2012
|
-
custom_domain = var.docs_domain
|
|
2013
|
-
certificate_arn = var.docs_certificate_arn
|
|
2014
|
-
}
|
|
2015
|
-
|
|
2016
2018
|
################################################################################
|
|
2017
2019
|
# Public Website (www)
|
|
2018
2020
|
################################################################################
|