thinkwork-cli 0.13.2 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (231) hide show
  1. package/README.md +3 -14
  2. package/dist/{api-client-JYZXYQJR.js → api-client-4P4JZOBX.js} +1 -1
  3. package/dist/{chunk-Z2F6RJFR.js → chunk-4OMDWYZQ.js} +4 -5
  4. package/dist/{chunk-ILZKG5WV.js → chunk-AD2NIWB5.js} +434 -69
  5. package/dist/chunk-MWQ7RO76.js +137 -0
  6. package/dist/{chunk-DVPBI5HM.js → chunk-OLUQ4U2Z.js} +26 -26
  7. package/dist/{chunk-QOERT44A.js → chunk-YQCYD6NE.js} +57 -44
  8. package/dist/cli.js +4400 -16431
  9. package/dist/commands/enterprise/templates/deploy-repo/scripts/apply-release.mjs +0 -1
  10. package/dist/commands/enterprise/templates/deploy-repo/scripts/smoke.mjs +0 -1
  11. package/dist/commands/enterprise/templates/deploy-repo/terraform/main.tf +0 -14
  12. package/dist/{dist-es-CRV46D5B.js → dist-es-2OTNTL4N.js} +4 -4
  13. package/dist/{dist-es-ENBUC3JP.js → dist-es-2XVAH4BQ.js} +2 -2
  14. package/dist/{dist-es-DCY4IC3Y.js → dist-es-3DPDUJAH.js} +2 -2
  15. package/dist/{dist-es-G7PTG75M.js → dist-es-BNZTBBVC.js} +1 -1
  16. package/dist/{dist-es-GKDBE7E6.js → dist-es-CD2RBDAC.js} +1 -1
  17. package/dist/{dist-es-R7FGL2IB.js → dist-es-I4FW57PS.js} +1 -1
  18. package/dist/{dist-es-USORBXZ5.js → dist-es-KVFWJNDY.js} +4 -4
  19. package/dist/{dist-es-HY3535OI.js → dist-es-PS73DWNL.js} +2 -2
  20. package/dist/{dist-es-LDE437AM.js → dist-es-S3NZQFGT.js} +1 -1
  21. package/dist/{dist-es-G54LBMRN.js → dist-es-SGCA4P32.js} +1 -1
  22. package/dist/{dist-es-Q57SZXZ7.js → dist-es-WBM6J4RA.js} +2 -2
  23. package/dist/{dist-es-P26FWFLT.js → dist-es-ZGVADYIF.js} +8 -8
  24. package/dist/drizzle/0227_analyst_reader_role.sql +17 -26
  25. package/dist/drizzle/0230_analyst_rls.sql +28 -45
  26. package/dist/drizzle/0261_native_auth_control_plane.sql +7 -3
  27. package/dist/drizzle/0270_tool_execution_ledger.sql +115 -0
  28. package/dist/drizzle/0271_ontology_twin_declarations.sql +47 -0
  29. package/dist/drizzle/0272_identity_graph_projection_cursor.sql +23 -0
  30. package/dist/drizzle/0273_twin_materialization_suggestions.sql +29 -0
  31. package/dist/drizzle/0274_tenant_mcp_twin_keys.sql +59 -0
  32. package/dist/drizzle/0275_identity_bulk_rebuild_fence.sql +30 -0
  33. package/dist/drizzle/0276_tool_execution_ledger_allow_cascade_delete.sql +18 -0
  34. package/dist/drizzle/0277_knowledge_base_sources.sql +107 -0
  35. package/dist/drizzle/0278_kb_page_transcription.sql +55 -0
  36. package/dist/drizzle/0279_mcp_servers_off_plugin_provenance.sql +93 -0
  37. package/dist/drizzle/0280_work_item_external_refs_drop_plane_provider.sql +46 -0
  38. package/dist/drizzle/0281_tenant_mcp_twin_keys_expiry_suffix.sql +9 -0
  39. package/dist/drizzle/0282_tenant_mcp_twin_keys_grants.sql +24 -0
  40. package/dist/drizzle/0283_agents_agentcore_runtime_dispatch.sql +13 -0
  41. package/dist/drizzle/0284_user_brain_claims.sql +69 -0
  42. package/dist/drizzle/0285_tenant_mcp_twin_keys_trusted_subsystem.sql +30 -0
  43. package/dist/drizzle/0286_brain_analytics_key.sql +26 -0
  44. package/dist/drizzle/0287_brain_subject.sql +25 -0
  45. package/dist/drizzle/0288_multi_lane_identities.sql +25 -0
  46. package/dist/{loadSso-DJVB7BXE.js → loadSso-ETCXTR4I.js} +2 -2
  47. package/dist/{loadSso-JAMNA3WY.js → loadSso-UBD7KUHE.js} +2 -2
  48. package/dist/plugins/README.md +2 -2
  49. package/dist/plugins/catalog/package.json +0 -3
  50. package/dist/plugins/catalog/src/__tests__/build-catalog.test.ts +6 -3
  51. package/dist/plugins/catalog/src/__tests__/catalog.test.ts +21 -21
  52. package/dist/plugins/catalog/src/__tests__/contracts.test.ts +102 -25
  53. package/dist/plugins/catalog/src/__tests__/plugin-package.test.ts +7 -6
  54. package/dist/plugins/catalog/src/__tests__/plugin-registry.test.ts +0 -15
  55. package/dist/plugins/catalog/src/contracts.ts +15 -0
  56. package/dist/plugins/catalog/src/registry/generated-first-party.ts +0 -18
  57. package/dist/plugins/n8n/test/integrated-app-contract.test.ts +1 -1
  58. package/dist/plugins/twenty/package.json +2 -1
  59. package/dist/plugins/twenty/scripts/LAMBDA_DEPLOY.md +114 -0
  60. package/dist/plugins/twenty/scripts/build-lambda.sh +29 -0
  61. package/dist/plugins/twenty/scripts/configure-product-views.ts +195 -0
  62. package/dist/plugins/twenty/scripts/lambda-handler.ts +49 -0
  63. package/dist/plugins/twenty/scripts/lib/__tests__/load-attachments.test.ts +38 -0
  64. package/dist/plugins/twenty/scripts/lib/__tests__/load-records.test.ts +145 -2
  65. package/dist/plugins/twenty/scripts/lib/__tests__/mappers.test.ts +397 -151
  66. package/dist/plugins/twenty/scripts/lib/__tests__/members-ensure.test.ts +28 -129
  67. package/dist/plugins/twenty/scripts/lib/__tests__/provision-members-db.test.ts +10 -0
  68. package/dist/plugins/twenty/scripts/lib/__tests__/schema-ensure.test.ts +13 -8
  69. package/dist/plugins/twenty/scripts/lib/lastmile-reader.ts +222 -2
  70. package/dist/plugins/twenty/scripts/lib/load-attachments.ts +29 -0
  71. package/dist/plugins/twenty/scripts/lib/load-records.ts +160 -43
  72. package/dist/plugins/twenty/scripts/lib/mappers.ts +368 -152
  73. package/dist/plugins/twenty/scripts/lib/members-ensure.ts +43 -268
  74. package/dist/plugins/twenty/scripts/lib/provision-members-db.ts +57 -0
  75. package/dist/plugins/twenty/scripts/lib/schema-ensure.ts +136 -31
  76. package/dist/plugins/twenty/scripts/migrate-lastmile.ts +254 -152
  77. package/dist/plugins/twenty/scripts/provision-twenty-members.ts +44 -1
  78. package/dist/plugins/twenty/scripts/purge-lastmile-import.ts +178 -0
  79. package/dist/plugins/twenty/scripts/restructure-products.ts +312 -0
  80. package/dist/plugins/twenty/scripts/retag-stage-values.ts +362 -0
  81. package/dist/plugins/twenty/test/manifest.test.ts +2 -4
  82. package/dist/scripts/post-deploy.sh +79 -1
  83. package/dist/{signin-UGDWTGS4.js → signin-5QZNRSOO.js} +2 -2
  84. package/dist/{sso-oidc-Q4VXANXY.js → sso-oidc-XK673P54.js} +2 -2
  85. package/dist/{sts-CWLSE3GH.js → sts-OXI2UALF.js} +6 -134
  86. package/dist/{sts-DNZLNVOV.js → sts-SQW4NBK3.js} +6 -134
  87. package/dist/terraform/examples/greenfield/main.tf +233 -175
  88. package/dist/terraform/examples/greenfield/terraform.tfvars.example +12 -8
  89. package/dist/terraform/modules/app/agentcore-admin/main.tf +47 -0
  90. package/dist/terraform/modules/app/agentcore-code-interpreter/README.md +39 -47
  91. package/dist/terraform/modules/app/agentcore-code-interpreter/main.tf +13 -66
  92. package/dist/terraform/modules/app/agentcore-identity/main.tf +106 -26
  93. package/dist/terraform/modules/app/agentcore-identity/outputs.tf +6 -6
  94. package/dist/terraform/modules/app/agentcore-identity/scripts/bootstrap_twenty_oauth_client.sh +216 -99
  95. package/dist/terraform/modules/app/agentcore-identity/scripts/delete_identity.sh +6 -9
  96. package/dist/terraform/modules/app/agentcore-identity/scripts/delete_workload_identity.sh +19 -0
  97. package/dist/terraform/modules/app/agentcore-identity/scripts/ensure_workload_identity.sh +29 -0
  98. package/dist/terraform/modules/app/agentcore-identity/scripts/read_identity.sh +22 -7
  99. package/dist/terraform/modules/app/agentcore-identity/scripts/reconcile_twenty_identity.sh +17 -46
  100. package/dist/terraform/modules/app/agentcore-identity/scripts/reconcile_twenty_provider.mjs +65 -3
  101. package/dist/terraform/modules/app/agentcore-identity/tests/tainted-marker/after.tf +15 -0
  102. package/dist/terraform/modules/app/agentcore-identity/tests/tainted-marker/before.tf +7 -0
  103. package/dist/terraform/modules/app/agentcore-identity/tests/tainted-marker/identity-after.tf +8 -0
  104. package/dist/terraform/modules/app/agentcore-identity/tests/tainted-marker/identity-before.tf +9 -0
  105. package/dist/terraform/modules/app/agentcore-identity/tests/tainted-marker/thinkwork-after.tf +3 -0
  106. package/dist/terraform/modules/app/agentcore-identity/tests/tainted-marker/thinkwork-before.tf +3 -0
  107. package/dist/terraform/modules/app/agentcore-identity/variables.tf +6 -0
  108. package/dist/terraform/modules/app/agentcore-memory/README.md +46 -9
  109. package/dist/terraform/modules/app/agentcore-memory/main.tf +27 -10
  110. package/dist/terraform/modules/app/agentcore-memory/scripts/create_or_find_memory.sh +156 -24
  111. package/dist/terraform/modules/app/agentcore-pi/README.md +1 -3
  112. package/dist/terraform/modules/app/agentcore-pi/main.tf +42 -52
  113. package/dist/terraform/modules/app/agentcore-pi/outputs.tf +3 -3
  114. package/dist/terraform/modules/app/agentcore-pi/scripts/reconcile_pi_runtime.mjs +175 -0
  115. package/dist/terraform/modules/app/agentcore-pi/variables.tf +35 -28
  116. package/dist/terraform/modules/app/agentcore-platform/main.tf +68 -0
  117. package/dist/terraform/modules/app/agentcore-runtime/main.tf +4 -20
  118. package/dist/terraform/modules/app/capability-broker/main.tf +2 -2
  119. package/dist/terraform/modules/app/capability-broker/variables.tf +11 -0
  120. package/dist/terraform/modules/app/deployment-control-plane/README.md +264 -0
  121. package/dist/terraform/modules/app/deployment-control-plane/buildspec.yml +4 -1
  122. package/dist/terraform/modules/app/deployment-control-plane/main.tf +94 -0
  123. package/dist/terraform/modules/app/deployment-control-plane/outputs.tf +5 -0
  124. package/dist/terraform/modules/app/deployment-control-plane/runner.py +2641 -124
  125. package/dist/terraform/modules/app/deployment-control-plane/test_runner_bundle.py +2034 -154
  126. package/dist/terraform/modules/app/deployment-control-plane/variables.tf +33 -0
  127. package/dist/terraform/modules/app/lambda-api/auth-state.tf +72 -0
  128. package/dist/terraform/modules/app/lambda-api/chat-latency-observability.tf +466 -0
  129. package/dist/terraform/modules/app/lambda-api/dispatch-dlq.tf +55 -0
  130. package/dist/terraform/modules/app/lambda-api/handlers.tf +411 -723
  131. package/dist/terraform/modules/app/lambda-api/iam-grouped.tf +262 -198
  132. package/dist/terraform/modules/app/lambda-api/main.tf +51 -13
  133. package/dist/terraform/modules/app/lambda-api/mcp-oauth.tf +4 -181
  134. package/dist/terraform/modules/app/lambda-api/memory-alarms.tf +3 -28
  135. package/dist/terraform/modules/app/lambda-api/oauth-secrets.tf +1 -2
  136. package/dist/terraform/modules/app/lambda-api/outputs.tf +17 -45
  137. package/dist/terraform/modules/app/lambda-api/turn-assertion.tf +45 -0
  138. package/dist/terraform/modules/app/lambda-api/variables.tf +219 -126
  139. package/dist/{plugins/n8n/terraform → terraform/modules/app}/n8n/README.md +1 -1
  140. package/dist/{plugins/n8n/terraform → terraform/modules/app}/n8n/main.tf +18 -18
  141. package/dist/terraform/modules/app/sandbox-log-scrubber/README.md +11 -10
  142. package/dist/terraform/modules/app/sandbox-log-scrubber/main.tf +5 -5
  143. package/dist/terraform/modules/app/static-site/main.tf +1 -1
  144. package/dist/terraform/modules/app/www-dns/main.tf +9 -27
  145. package/dist/terraform/modules/app/www-dns/variables.tf +4 -10
  146. package/dist/terraform/modules/data/aurora-postgres/README.md +34 -0
  147. package/dist/terraform/modules/data/aurora-postgres/alarms.tf +82 -0
  148. package/dist/terraform/modules/data/aurora-postgres/main.tf +27 -57
  149. package/dist/terraform/modules/data/aurora-postgres/outputs.tf +0 -9
  150. package/dist/terraform/modules/data/aurora-postgres/variables.tf +41 -0
  151. package/dist/terraform/modules/data/s3-buckets/main.tf +5 -6
  152. package/dist/terraform/modules/foundation/cognito/main.tf +81 -8
  153. package/dist/terraform/modules/foundation/cognito/outputs.tf +5 -0
  154. package/dist/terraform/modules/foundation/cognito/variables.tf +24 -12
  155. package/dist/terraform/modules/thinkwork/README.md +5 -1
  156. package/dist/terraform/modules/thinkwork/main.tf +376 -374
  157. package/dist/terraform/modules/thinkwork/outputs.tf +12 -158
  158. package/dist/terraform/modules/thinkwork/variables.tf +246 -89
  159. package/dist/workspace-defaults/files/INSTRUCTIONS.md +9 -11
  160. package/dist/workspace-defaults/files/MEMORY_GUIDE.md +38 -35
  161. package/dist/workspace-defaults/files/ROUTER.md +1 -1
  162. package/dist/workspace-defaults/files/TOOLS.md +9 -39
  163. package/dist/workspace-defaults/files/agents/analyst/INSTRUCTIONS.md +6 -3
  164. package/dist/workspace-defaults/files/catalog-skills/brain-brief-builder/SKILL.md +165 -0
  165. package/dist/workspace-defaults/files/catalog-skills/n8n-workflow-operator/SKILL.md +75 -0
  166. package/dist/workspace-defaults/files/catalog-skills/n8n-workflow-operator/references/mcp-tooling.md +40 -0
  167. package/dist/workspace-defaults/files/catalog-skills/n8n-workflow-operator/references/validation-and-handoff.md +40 -0
  168. package/dist/workspace-defaults/files/catalog-skills/n8n-workflow-operator/references/workflow-authoring.md +46 -0
  169. package/dist/workspace-defaults/files/skills/artifact-builder/references/crm-dashboard.md +1 -1
  170. package/dist/workspace-defaults/files/skills/document-composer/SKILL.md +22 -3
  171. package/package.json +1 -1
  172. package/dist/drizzle/0261_managed_harness_multiplayer.sql +0 -313
  173. package/dist/drizzle/0262_parallel_harness_threads.sql +0 -9
  174. package/dist/drizzle/0264_harness_tool_execution_ledger.sql +0 -113
  175. package/dist/plugins/company-data/README.md +0 -49
  176. package/dist/plugins/company-data/package.json +0 -21
  177. package/dist/plugins/company-data/src/index.ts +0 -30
  178. package/dist/plugins/company-data/src/manifest.ts +0 -26
  179. package/dist/plugins/company-data/test/manifest.test.ts +0 -116
  180. package/dist/plugins/company-data/tsconfig.json +0 -8
  181. package/dist/plugins/company-etl/README.md +0 -46
  182. package/dist/plugins/company-etl/package.json +0 -21
  183. package/dist/plugins/company-etl/src/index.ts +0 -29
  184. package/dist/plugins/company-etl/src/manifest.ts +0 -26
  185. package/dist/plugins/company-etl/test/manifest.test.ts +0 -108
  186. package/dist/plugins/company-etl/tsconfig.json +0 -8
  187. package/dist/plugins/lastmile/README.md +0 -50
  188. package/dist/plugins/lastmile/package.json +0 -23
  189. package/dist/plugins/lastmile/smoke/lastmile-plugin-smoke.mjs +0 -661
  190. package/dist/plugins/lastmile/src/api/tasks-adapter.ts +0 -572
  191. package/dist/plugins/lastmile/src/discovery.fixture.ts +0 -64
  192. package/dist/plugins/lastmile/src/index.ts +0 -46
  193. package/dist/plugins/lastmile/src/manifest.ts +0 -139
  194. package/dist/plugins/lastmile/test/api/tasks-adapter.test.ts +0 -266
  195. package/dist/plugins/lastmile/test/discovery.test.ts +0 -88
  196. package/dist/plugins/lastmile/tsconfig.json +0 -8
  197. package/dist/plugins/n8n/smoke/n8n-managed-app-smoke.mjs +0 -409
  198. package/dist/plugins/twenty/smoke/twenty-managed-app-smoke.mjs +0 -359
  199. package/dist/terraform/modules/app/agentcore-code-interpreter/Dockerfile.sandbox-base +0 -61
  200. package/dist/terraform/modules/app/agentcore-code-interpreter/sandbox/sitecustomize.py +0 -227
  201. package/dist/terraform/modules/app/agentcore-code-interpreter/sandbox/test_sitecustomize.py +0 -277
  202. package/dist/terraform/modules/app/agentcore-code-interpreter/scripts/build_and_push_sandbox_base.sh +0 -70
  203. package/dist/terraform/modules/app/agentcore-gateway/main.tf +0 -305
  204. package/dist/terraform/modules/app/agentcore-gateway/outputs.tf +0 -44
  205. package/dist/terraform/modules/app/agentcore-gateway/scripts/delete_gateway.sh +0 -93
  206. package/dist/terraform/modules/app/agentcore-gateway/scripts/read_gateway.sh +0 -33
  207. package/dist/terraform/modules/app/agentcore-gateway/scripts/reconcile_gateway.sh +0 -543
  208. package/dist/terraform/modules/app/agentcore-gateway/variables.tf +0 -70
  209. package/dist/terraform/modules/app/agentcore-harness/main.tf +0 -330
  210. package/dist/terraform/modules/app/agentcore-harness/outputs.tf +0 -72
  211. package/dist/terraform/modules/app/agentcore-harness/scripts/delete_harness.sh +0 -5
  212. package/dist/terraform/modules/app/agentcore-harness/scripts/harness-lifecycle.mjs +0 -430
  213. package/dist/terraform/modules/app/agentcore-harness/scripts/harness-readback.mjs +0 -180
  214. package/dist/terraform/modules/app/agentcore-harness/scripts/harness-tool-contract.mjs +0 -193
  215. package/dist/terraform/modules/app/agentcore-harness/scripts/prune_harness.sh +0 -5
  216. package/dist/terraform/modules/app/agentcore-harness/scripts/read_harness.sh +0 -5
  217. package/dist/terraform/modules/app/agentcore-harness/scripts/reconcile_harness.sh +0 -5
  218. package/dist/terraform/modules/app/agentcore-harness/variables.tf +0 -96
  219. package/dist/terraform/modules/app/hindsight-memory/README.md +0 -89
  220. package/dist/terraform/modules/app/hindsight-memory/main.tf +0 -411
  221. package/dist/terraform/modules/app/lambda-api/agentcore-harness-alarms.tf +0 -88
  222. package/dist/terraform/modules/app/lambda-api/agentcore-identity-alarms.tf +0 -91
  223. package/dist/terraform/modules/data/bedrock-knowledge-base/main.tf +0 -102
  224. /package/dist/{plugins/n8n/terraform → terraform/modules/app}/n8n/outputs.tf +0 -0
  225. /package/dist/{plugins/n8n/terraform → terraform/modules/app}/n8n/scripts/sync-database.py +0 -0
  226. /package/dist/{plugins/n8n/terraform → terraform/modules/app}/n8n/scripts/test_sync_database.py +0 -0
  227. /package/dist/{plugins/n8n/terraform → terraform/modules/app}/n8n/variables.tf +0 -0
  228. /package/dist/{plugins/twenty/terraform → terraform/modules/app}/twenty/README.md +0 -0
  229. /package/dist/{plugins/twenty/terraform → terraform/modules/app}/twenty/main.tf +0 -0
  230. /package/dist/{plugins/twenty/terraform → terraform/modules/app}/twenty/outputs.tf +0 -0
  231. /package/dist/{plugins/twenty/terraform → terraform/modules/app}/twenty/variables.tf +0 -0
@@ -19,18 +19,19 @@
19
19
  data "aws_caller_identity" "current" {}
20
20
 
21
21
  locals {
22
- okf_efs_vpc_enabled = length(var.okf_efs_subnet_ids) > 0 && length(var.okf_efs_security_group_ids) > 0
23
- # Handlers that open direct Postgres connections to registered analyst data
24
- # sources. VPC-attaching them (analyst_egress_subnet_ids) gives their egress
25
- # the NAT gateway's stable EIP, which external databases behind an IP
26
- # allowlist can admit a non-VPC Lambda egresses from the shared AWS pool
27
- # and can never satisfy such an allowlist.
28
- analyst_vpc_enabled = length(var.analyst_egress_subnet_ids) > 0 && length(var.analyst_egress_security_group_ids) > 0
29
- analyst_vpc_handlers = toset([
30
- "graphql-http",
31
- "analyst-query-broker",
32
- "analyst-connection-reconciler",
33
- ])
22
+ # Company Brain U5: the identity-graph-projector attaches to the VPC only
23
+ # when both Neptune network inputs are present (disjoint from the two
24
+ # block above a function takes at most one vpc_config).
25
+ neptune_vpc_enabled = length(var.neptune_subnet_ids) > 0 && length(var.neptune_security_group_ids) > 0
26
+ # THINK-1082: any VPC attachment in this module (Neptune projector or the
27
+ # whole-module lambdas_in_vpc lane) needs the ENI grant on the shared role.
28
+ lambda_vpc_enabled = local.neptune_vpc_enabled || var.lambdas_in_vpc
29
+ # lambdas_in_vpc needs both network inputs; checked as a precondition on the
30
+ # handler functions because cross-variable validation is not available at
31
+ # the repo's Terraform floor (1.8.5).
32
+ lambda_vpc_inputs_complete = !var.lambdas_in_vpc || (
33
+ length(var.vpc_subnet_ids) > 0 && length(var.vpc_security_group_ids) > 0
34
+ )
34
35
  # Constructed rather than read from aws_apigatewayv2_stage.default.invoke_url
35
36
  # (the two are identical for an HTTP API's $default stage). Reading it off
36
37
  # the stage made every Lambda's env depend on the stage, which forbids the
@@ -194,13 +195,50 @@ resource "aws_iam_role_policy_attachment" "lambda_basic" {
194
195
  # aggregate hit IAM's 10,240-byte cap on 2026-06-11 (#2378/#2379). New grants
195
196
  # go into the grouped managed policies, never inline.
196
197
 
198
+ # Every VPC-attached handler on the shared Lambda role needs the ENI
199
+ # create/describe/delete grant, or its invocations fail before the handler
200
+ # runs. This was gated on the OKF EFS mount alone, which was true by accident:
201
+ # okf-efs-refresh was simply the first VPC-attached handler. The
202
+ # Neptune-attached identity-graph-projector shares this role and had been
203
+ # riding that gate. Gate on the surviving VPC consumer instead — the OKF
204
+ # mount is gone as of the wiki-removal arc U3.
205
+ # THINK-1082: also gated on lambdas_in_vpc — every handler attaches then.
197
206
  resource "aws_iam_role_policy_attachment" "lambda_vpc_access" {
198
- count = local.okf_efs_vpc_enabled ? 1 : 0
207
+ count = local.lambda_vpc_enabled ? 1 : 0
199
208
 
200
209
  role = aws_iam_role.lambda.name
201
210
  policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole"
202
211
  }
203
212
 
213
+ # THINK-1082: compliance-anchor and compliance-export-runner run on sibling
214
+ # roles owned by the compliance bucket modules (not aws_iam_role.lambda). They
215
+ # carry a database connection too, so when lambdas_in_vpc attaches them the
216
+ # ENI grant has to land on those roles as well.
217
+ resource "aws_iam_role_policy_attachment" "compliance_anchor_vpc_access" {
218
+ count = var.lambdas_in_vpc && local.deploy_lambda_handlers ? 1 : 0
219
+
220
+ role = var.compliance_anchor_lambda_role_name
221
+ policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole"
222
+ }
223
+
224
+ resource "aws_iam_role_policy_attachment" "compliance_export_runner_vpc_access" {
225
+ count = var.lambdas_in_vpc && local.deploy_lambda_handlers ? 1 : 0
226
+
227
+ role = var.compliance_exports_runner_role_name
228
+ policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole"
229
+ }
230
+
231
+ # memory-retraction-drainer runs on its own role (handlers.tf) — the first
232
+ # McPherson VPC cut-over (2026-08-25) failed on exactly this function:
233
+ # "The provided execution role does not have permissions to call
234
+ # CreateNetworkInterface on EC2".
235
+ resource "aws_iam_role_policy_attachment" "memory_retraction_drainer_vpc_access" {
236
+ count = var.lambdas_in_vpc && local.deploy_lambda_handlers ? 1 : 0
237
+
238
+ role = aws_iam_role.memory_retraction_drainer.name
239
+ policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole"
240
+ }
241
+
204
242
  ################################################################################
205
243
  # Placeholder Lambda — proves the infrastructure works
206
244
  #
@@ -1,185 +1,8 @@
1
1
  locals {
2
- mcp_oauth_api_base_url = "https://${aws_apigatewayv2_api.main.id}.execute-api.${var.region}.amazonaws.com"
3
- mcp_oauth_cognito_base_url = var.cognito_auth_domain != "" ? "https://${var.cognito_auth_domain}.auth.${var.region}.amazoncognito.com" : ""
4
- mcp_oauth_identity_providers = var.google_oauth_client_id != "" ? ["Google", "COGNITO"] : ["COGNITO"]
5
- mcp_oauth_logo_path = "${path.module}/../../../../apps/web/public/logo.png"
6
- agentcore_turn_assertion_issuer = "${local.mcp_oauth_api_base_url}/agentcore"
7
- agentcore_harness_audience = "urn:thinkwork:${var.stage}:agentcore:harness"
8
- agentcore_gateway_audience = "urn:thinkwork:${var.stage}:agentcore:gateway"
9
- agentcore_turn_assertion_keys = {
10
- for version, key in aws_kms_key.agentcore_turn_assertion : version => {
11
- key_id = key.arn
12
- # A version label alone is not globally unique: destroying and
13
- # reprovisioning v1 creates different RSA material while downstream JWT
14
- # validators may still cache the old public key under the same kid.
15
- # Bind the kid to the immutable KMS key id so a reprovision is observed
16
- # as a real key rotation instead of an invalid-signature outage.
17
- kid = "thinkwork-${var.stage}-agentcore-turn-${version}-${substr(key.key_id, 0, 8)}"
18
- }
19
- }
20
- agentcore_turn_assertion_active_key = try(
21
- local.agentcore_turn_assertion_keys[var.agentcore_turn_assertion_active_key_version],
22
- { key_id = "", kid = "" },
23
- )
24
- }
25
-
26
- # THINK-316 U1: short-lived CUSTOM_JWT assertions are signed by KMS so private
27
- # key material never enters Lambda configuration or process memory. The key
28
- # policy is the capability boundary: the dedicated mint role can Sign, while
29
- # the shared mcp-oauth role can only fetch the public key for JWKS publication.
30
- resource "aws_iam_role" "turn_assertion_mint" {
31
- count = var.enable_agentcore_multiplayer_proof ? 1 : 0
32
- name = "thinkwork-${var.stage}-turn-assertion-mint-role"
33
-
34
- assume_role_policy = jsonencode({
35
- Version = "2012-10-17"
36
- Statement = [{
37
- Effect = "Allow"
38
- Principal = { Service = "lambda.amazonaws.com" }
39
- Action = "sts:AssumeRole"
40
- }]
41
- })
42
- }
43
-
44
- resource "aws_iam_role_policy_attachment" "turn_assertion_mint_basic" {
45
- count = var.enable_agentcore_multiplayer_proof ? 1 : 0
46
- role = aws_iam_role.turn_assertion_mint[0].name
47
- policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
48
- }
49
-
50
- # The synthetic OAuth provider and boundary target are public proof surfaces
51
- # but need no AWS data-plane permissions. A sibling logs-only role prevents a
52
- # parser defect from inheriting the shared API role or its platform secrets.
53
- resource "aws_iam_role" "agentcore_proof_boundary" {
54
- count = var.enable_agentcore_multiplayer_proof ? 1 : 0
55
- name = "thinkwork-${var.stage}-agentcore-proof-boundary-role"
56
-
57
- assume_role_policy = jsonencode({
58
- Version = "2012-10-17"
59
- Statement = [{
60
- Effect = "Allow"
61
- Principal = { Service = "lambda.amazonaws.com" }
62
- Action = "sts:AssumeRole"
63
- }]
64
- })
65
- }
66
-
67
- resource "aws_iam_role_policy_attachment" "agentcore_proof_boundary_basic" {
68
- count = var.enable_agentcore_multiplayer_proof ? 1 : 0
69
- role = aws_iam_role.agentcore_proof_boundary[0].name
70
- policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
71
- }
72
-
73
- # The token-exchange provider is the only proof boundary allowed to mint the
74
- # derived Gateway assertion. Keep that capability off the public target role.
75
- resource "aws_iam_role" "agentcore_proof_provider" {
76
- count = var.enable_agentcore_multiplayer_proof ? 1 : 0
77
- name = "thinkwork-${var.stage}-agentcore-proof-provider-role"
78
-
79
- assume_role_policy = jsonencode({
80
- Version = "2012-10-17"
81
- Statement = [{
82
- Effect = "Allow"
83
- Principal = { Service = "lambda.amazonaws.com" }
84
- Action = "sts:AssumeRole"
85
- }]
86
- })
87
- }
88
-
89
- resource "aws_iam_role_policy_attachment" "agentcore_proof_provider_basic" {
90
- count = var.enable_agentcore_multiplayer_proof ? 1 : 0
91
- role = aws_iam_role.agentcore_proof_provider[0].name
92
- policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
93
- }
94
-
95
- resource "aws_iam_role_policy" "agentcore_proof_provider_kms" {
96
- count = var.enable_agentcore_multiplayer_proof ? 1 : 0
97
- name = "thinkwork-${var.stage}-agentcore-proof-provider-key"
98
- role = aws_iam_role.agentcore_proof_provider[0].id
99
-
100
- policy = jsonencode({
101
- Version = "2012-10-17"
102
- Statement = [{
103
- Effect = "Allow"
104
- Action = ["kms:Sign"]
105
- Resource = [local.agentcore_turn_assertion_active_key.key_id]
106
- Condition = {
107
- StringEquals = {
108
- "kms:SigningAlgorithm" = "RSASSA_PKCS1_V1_5_SHA_256"
109
- }
110
- }
111
- }]
112
- })
113
- }
114
-
115
- resource "aws_kms_key" "agentcore_turn_assertion" {
116
- for_each = var.enable_agentcore_multiplayer_proof ? toset(var.agentcore_turn_assertion_key_versions) : toset([])
117
-
118
- description = "ThinkWork ${var.stage} AgentCore per-turn assertion signing ${each.key}"
119
- key_usage = "SIGN_VERIFY"
120
- customer_master_key_spec = "RSA_2048"
121
- deletion_window_in_days = 7
122
-
123
- policy = jsonencode({
124
- Version = "2012-10-17"
125
- Statement = [
126
- {
127
- Sid = "AccountAdministration"
128
- Effect = "Allow"
129
- Principal = { AWS = "arn:aws:iam::${var.account_id}:root" }
130
- Action = "kms:*"
131
- Resource = "*"
132
- },
133
- ]
134
- })
135
-
136
- tags = {
137
- Name = "thinkwork-${var.stage}-agentcore-turn-assertion-${each.key}"
138
- KeyVersion = each.key
139
- }
140
- }
141
-
142
- resource "aws_kms_alias" "agentcore_turn_assertion" {
143
- for_each = aws_kms_key.agentcore_turn_assertion
144
- name = "alias/thinkwork-${var.stage}-agentcore-turn-assertion-${each.key}"
145
- target_key_id = each.value.key_id
146
- }
147
-
148
- # The mint role can sign with exactly the active key. The public discovery
149
- # handler can read all currently published public keys, but can never sign.
150
- resource "aws_iam_role_policy" "turn_assertion_mint_kms" {
151
- count = var.enable_agentcore_multiplayer_proof ? 1 : 0
152
- name = "thinkwork-${var.stage}-turn-assertion-active-key"
153
- role = aws_iam_role.turn_assertion_mint[0].id
154
-
155
- policy = jsonencode({
156
- Version = "2012-10-17"
157
- Statement = [{
158
- Effect = "Allow"
159
- Action = ["kms:Sign"]
160
- Resource = [local.agentcore_turn_assertion_active_key.key_id]
161
- Condition = {
162
- StringEquals = {
163
- "kms:SigningAlgorithm" = "RSASSA_PKCS1_V1_5_SHA_256"
164
- }
165
- }
166
- }]
167
- })
168
- }
169
-
170
- resource "aws_iam_role_policy" "turn_assertion_jwks_kms" {
171
- count = var.enable_agentcore_multiplayer_proof ? 1 : 0
172
- name = "thinkwork-${var.stage}-turn-assertion-published-keys"
173
- role = aws_iam_role.lambda.id
174
-
175
- policy = jsonencode({
176
- Version = "2012-10-17"
177
- Statement = [{
178
- Effect = "Allow"
179
- Action = ["kms:GetPublicKey"]
180
- Resource = [for key in values(local.agentcore_turn_assertion_keys) : key.key_id]
181
- }]
182
- })
2
+ mcp_oauth_api_base_url = "https://${aws_apigatewayv2_api.main.id}.execute-api.${var.region}.amazonaws.com"
3
+ mcp_oauth_cognito_base_url = var.cognito_auth_domain != "" ? "https://${var.cognito_auth_domain}.auth.${var.region}.amazoncognito.com" : ""
4
+ mcp_oauth_identity_providers = var.google_oauth_client_id != "" ? ["Google", "COGNITO"] : ["COGNITO"]
5
+ mcp_oauth_logo_path = "${path.module}/../../../../apps/web/public/logo.png"
183
6
  }
184
7
 
185
8
  resource "aws_dynamodb_table" "mcp_oauth_revocations" {
@@ -2,9 +2,7 @@
2
2
  #
3
3
  # Alarms here fire from metrics that EXIST without any log-group management:
4
4
  # - AWS/Lambda Errors for the memory-stage worker and the retraction drainer
5
- # (handler crashes, including ones that never reach a log line);
6
- # - the wiki-compile DLQ depth (the only memory-path Lambda with an
7
- # on_failure destination).
5
+ # (handler crashes, including ones that never reach a log line).
8
6
  #
9
7
  # DELIBERATELY NOT HERE — log-metric filters over the drainer's structured
10
8
  # summary line and the worker's "status=failed" line. They require the
@@ -18,8 +16,8 @@
18
16
  # packages/api/scripts/external-memory-readiness.ts (which reports due,
19
17
  # failed, and dead-lettered attempts directly from the ledger).
20
18
  #
21
- # Also runbook-only (no metric exists): source checkpoint age, graph-to-wiki
22
- # lag, evidence lag, deferred identity count/age.
19
+ # Also runbook-only (no metric exists): source checkpoint age, evidence lag,
20
+ # deferred identity count/age.
23
21
  #
24
22
  # alarm_actions are empty: the only SNS topic in this module
25
23
  # (aws_sns_topic.cost_alerts) is the cost-alert channel — wiring memory alarms
@@ -67,26 +65,3 @@ resource "aws_cloudwatch_metric_alarm" "memory_retraction_drainer_lambda_errors"
67
65
  }
68
66
  }
69
67
 
70
- # ---------------------------------------------------------------------------
71
- # wiki-compile DLQ depth (graph → wiki handoff failures)
72
- # ---------------------------------------------------------------------------
73
-
74
- resource "aws_cloudwatch_metric_alarm" "wiki_compile_dlq_depth" {
75
- count = local.deploy_lambda_handlers ? 1 : 0
76
-
77
- alarm_name = "thinkwork-${var.stage}-wiki-compile-dlq-depth"
78
- alarm_description = "wiki-compile DLQ has messages — a compile invocation crashed before the job ledger recorded an outcome; canonical pages are stale until replayed."
79
- namespace = "AWS/SQS"
80
- metric_name = "ApproximateNumberOfMessagesVisible"
81
- statistic = "Maximum"
82
- period = 60
83
- evaluation_periods = 1
84
- threshold = 1
85
- comparison_operator = "GreaterThanOrEqualToThreshold"
86
- treat_missing_data = "notBreaching"
87
- alarm_actions = []
88
-
89
- dimensions = {
90
- QueueName = aws_sqs_queue.wiki_compile_dlq[0].name
91
- }
92
- }
@@ -36,8 +36,7 @@ resource "aws_secretsmanager_secret_version" "oauth_google_productivity" {
36
36
  })
37
37
 
38
38
  # If the operator rotates the secret via AWS console / CLI without touching
39
- # tfvars, terraform shouldn't clobber it on next apply. Matches the pattern
40
- # used for google_places_api_key in the wiki-compile handler.
39
+ # tfvars, terraform shouldn't clobber it on next apply.
41
40
  lifecycle {
42
41
  ignore_changes = [secret_string]
43
42
  }
@@ -8,41 +8,6 @@ output "api_endpoint" {
8
8
  value = local.api_base_url
9
9
  }
10
10
 
11
- output "agentcore_turn_assertion_issuer" {
12
- description = "Proof-only CUSTOM_JWT issuer on the regional HTTP API."
13
- value = var.enable_agentcore_multiplayer_proof ? local.agentcore_turn_assertion_issuer : ""
14
- }
15
-
16
- output "agentcore_harness_audience" {
17
- description = "Purpose-bound audience for proof Harness invocations."
18
- value = var.enable_agentcore_multiplayer_proof ? local.agentcore_harness_audience : ""
19
- }
20
-
21
- output "agentcore_gateway_audience" {
22
- description = "Purpose-bound audience for proof Gateway operations."
23
- value = var.enable_agentcore_multiplayer_proof ? local.agentcore_gateway_audience : ""
24
- }
25
-
26
- output "agentcore_turn_assertion_active_key_arn" {
27
- description = "Operator-only active proof signing key ARN used by deployed verification probes."
28
- value = var.enable_agentcore_multiplayer_proof ? local.agentcore_turn_assertion_active_key.key_id : ""
29
- }
30
-
31
- output "agentcore_turn_assertion_active_kid" {
32
- description = "Public JWKS key identifier for the active proof signing key."
33
- value = var.enable_agentcore_multiplayer_proof ? local.agentcore_turn_assertion_active_key.kid : ""
34
- }
35
-
36
- output "agentcore_proof_oauth_issuer" {
37
- description = "Synthetic proof OAuth issuer on the regional HTTP API."
38
- value = var.enable_agentcore_multiplayer_proof ? "${local.mcp_oauth_api_base_url}/agentcore-proof/oauth" : ""
39
- }
40
-
41
- output "agentcore_proof_target_base_url" {
42
- description = "Regional HTTP API base URL hosting the controlled identity target."
43
- value = var.enable_agentcore_multiplayer_proof ? local.mcp_oauth_api_base_url : ""
44
- }
45
-
46
11
  output "api_execution_arn" {
47
12
  description = "API Gateway V2 execution ARN (for Lambda permissions)"
48
13
  value = aws_apigatewayv2_api.main.execution_arn
@@ -83,16 +48,6 @@ output "workflow_execution_callback_fn_arn" {
83
48
  value = local.deploy_lambda_handlers ? aws_lambda_function.handler["workflow-execution-callback"].arn : ""
84
49
  }
85
50
 
86
- output "okf_efs_refresh_fn_name" {
87
- description = "OKF EFS refresh Lambda function name."
88
- value = local.deploy_lambda_handlers ? aws_lambda_function.handler["okf-efs-refresh"].function_name : ""
89
- }
90
-
91
- output "okf_efs_refresh_fn_arn" {
92
- description = "OKF EFS refresh Lambda ARN."
93
- value = local.deploy_lambda_handlers ? aws_lambda_function.handler["okf-efs-refresh"].arn : ""
94
- }
95
-
96
51
  output "brain_artifacts_bucket_name" {
97
52
  description = "Canonical ThinkWork Brain S3 bucket for source artifacts, ingestion manifests, migration snapshots, vault projections, and exports."
98
53
  value = aws_s3_bucket.brain_artifacts.bucket
@@ -165,6 +120,23 @@ output "mcp_custom_domain_validation" {
165
120
  ] : []
166
121
  }
167
122
 
123
+ # --- THINK-915 chat turn-latency observability -------------------------------
124
+
125
+ output "chat_turn_latency_dashboard_name" {
126
+ description = "CloudWatch dashboard carrying the chat turn-latency phase metrics, dispatch Duration p95, and turn-path Lambda invocations/errors. Empty when the feature is disabled."
127
+ value = local.chat_latency_enabled ? aws_cloudwatch_dashboard.chat_turn_latency[0].dashboard_name : ""
128
+ }
129
+
130
+ output "chat_turn_latency_metric_namespace" {
131
+ description = "CloudWatch namespace holding TurnRuntimeInvokeMs / AgentLoopMs for this stage."
132
+ value = local.chat_latency_namespace
133
+ }
134
+
135
+ output "chat_turn_runtime_log_group_name_effective" {
136
+ description = "AgentCore Pi runtime log group actually used by the AgentLoopMs metric filter and the saved turn-timeline query (explicit override, else prefix discovery). Empty when the runtime has not logged yet."
137
+ value = local.chat_latency_runtime_log_group
138
+ }
139
+
168
140
  output "mcp_custom_domain_target" {
169
141
  description = "Regional target for the final mcp.thinkwork.ai → API Gateway CNAME. Only populated on the second apply (when mcp_custom_domain_ready = true). Includes { target_domain_name, hosted_zone_id } so the CF sync script can upsert the record."
170
142
  value = var.mcp_custom_domain != "" && var.mcp_custom_domain_ready ? {
@@ -0,0 +1,45 @@
1
+ # Signed-turn identity (THINK-324 Wave-3 C18).
2
+ #
3
+ # An asymmetric SIGN_VERIFY key per published version label. The dispatch
4
+ # Lambdas (chat-agent-invoke, wakeup-processor) mint a short-lived assertion
5
+ # binding {tenant, thread, turn} into the Pi invoke payload; the runtime
6
+ # echoes it on callbacks; verifiers (tool-executions today, more in C19)
7
+ # check the signature locally against the cached public key. The private key
8
+ # never leaves KMS — a compromised Lambda cannot exfiltrate the signer.
9
+ #
10
+ # The `agentcore_turn_assertion_*` variables predate this plane's rebuild
11
+ # (the THINK-311 trial's key was destroyed with the managed harness); the
12
+ # same one-or-two-version rotation contract applies.
13
+
14
+ resource "aws_kms_key" "agentcore_turn_assertion" {
15
+ for_each = toset(var.agentcore_turn_assertion_key_versions)
16
+
17
+ description = "ThinkWork ${var.stage} signed-turn assertion key (${each.key})"
18
+ key_usage = "SIGN_VERIFY"
19
+ customer_master_key_spec = "ECC_NIST_P256"
20
+ deletion_window_in_days = 7
21
+
22
+ lifecycle {
23
+ precondition {
24
+ condition = contains(var.agentcore_turn_assertion_key_versions, var.agentcore_turn_assertion_active_key_version)
25
+ error_message = "agentcore_turn_assertion_active_key_version must be one of agentcore_turn_assertion_key_versions."
26
+ }
27
+ }
28
+
29
+ tags = {
30
+ Stage = var.stage
31
+ Component = "turn-assertion"
32
+ }
33
+ }
34
+
35
+ resource "aws_kms_alias" "agentcore_turn_assertion" {
36
+ for_each = toset(var.agentcore_turn_assertion_key_versions)
37
+
38
+ name = "alias/thinkwork-${var.stage}-turn-assertion-${each.key}"
39
+ target_key_id = aws_kms_key.agentcore_turn_assertion[each.key].key_id
40
+ }
41
+
42
+ locals {
43
+ turn_assertion_active_key_arn = aws_kms_key.agentcore_turn_assertion[var.agentcore_turn_assertion_active_key_version].arn
44
+ turn_assertion_key_arns = [for key in aws_kms_key.agentcore_turn_assertion : key.arn]
45
+ }