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
|
@@ -43,15 +43,6 @@ locals {
|
|
|
43
43
|
"msteams-install-complete",
|
|
44
44
|
"msteams-account-link-complete",
|
|
45
45
|
],
|
|
46
|
-
var.enable_agentcore_multiplayer_proof ? [] : [
|
|
47
|
-
"turn-assertion-mint",
|
|
48
|
-
"agentcore-proof-oauth-provider",
|
|
49
|
-
"agentcore-identity-boundary-target",
|
|
50
|
-
"harness-capability-mcp",
|
|
51
|
-
"harness-code-interpreter-target",
|
|
52
|
-
"harness-builtin-tools-target",
|
|
53
|
-
"harness-platform-tools-target",
|
|
54
|
-
],
|
|
55
46
|
)
|
|
56
47
|
|
|
57
48
|
# Config-class configuration shared by all API handlers. As of plan
|
|
@@ -75,33 +66,39 @@ locals {
|
|
|
75
66
|
SUBSCRIPTION_TICKET_PUBLIC_KEYS = var.subscription_ticket_public_keys
|
|
76
67
|
SUBSCRIPTION_TICKET_PRIVATE_KEY_SECRET = var.subscription_ticket_private_key_secret
|
|
77
68
|
APPSYNC_API_ID = var.appsync_api_id
|
|
78
|
-
# THINK-
|
|
79
|
-
#
|
|
80
|
-
#
|
|
81
|
-
#
|
|
82
|
-
|
|
83
|
-
#
|
|
84
|
-
#
|
|
85
|
-
#
|
|
86
|
-
#
|
|
87
|
-
#
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
#
|
|
91
|
-
#
|
|
92
|
-
#
|
|
93
|
-
|
|
94
|
-
#
|
|
95
|
-
#
|
|
96
|
-
#
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
69
|
+
# THINK-585 U6 (KTD3): stage kill-switch for AgentCore Runtime chat
|
|
70
|
+
# dispatch. Empty when off (stripped from the document — getConfig sees
|
|
71
|
+
# unset). The per-agent agents.agentcore_runtime_dispatch flag gates on
|
|
72
|
+
# top; both must be on for a turn to ride the dispatcher.
|
|
73
|
+
AGENTCORE_RUNTIME_DISPATCH_ENABLED = var.agentcore_runtime_dispatch_enabled ? "true" : ""
|
|
74
|
+
# Neptune endpoint for the
|
|
75
|
+
# identity-graph-projector's nudge gate (THINK-339 U15: the twin READ
|
|
76
|
+
# Lambdas retired to the platform service; the write/projection lane
|
|
77
|
+
# stays product-side — the platform identity_sync pipeline invokes it).
|
|
78
|
+
# Document, not env: graphql-http's env sits near the 4KB ceiling.
|
|
79
|
+
# Readers use getConfig; env still wins on the VPC projector.
|
|
80
|
+
NEPTUNE_ENDPOINT = var.neptune_endpoint
|
|
81
|
+
# Consolidation U14: platform-served Brain MCP endpoint. When set,
|
|
82
|
+
# mcp-twin-provision registers the twin connector against it instead
|
|
83
|
+
# of the product /mcp/twin route. Empty = legacy default.
|
|
84
|
+
BRAIN_MCP_URL = var.brain_mcp_url
|
|
85
|
+
# THINK-781: Brain ops-api base URL + the agent-identity m2m secret the
|
|
86
|
+
# flagThreadToBrain resolver posts /flags with. NOT the /mcp lane pair
|
|
87
|
+
# above — POST /flags verifies against the Brain's operator pool, so it
|
|
88
|
+
# needs the etl-platform/agent/cognito-m2m-brain credential (scope
|
|
89
|
+
# etl-agent/tasks), not the brain-mcp platform-agent lane. Empty = the
|
|
90
|
+
# "Send to the Brain" action fails with "no Brain connection configured".
|
|
91
|
+
BRAIN_OPS_API_URL = var.brain_ops_api_url
|
|
92
|
+
BRAIN_OPS_M2M_SECRET_ARN = var.brain_ops_m2m_secret_arn
|
|
93
|
+
# Same class of bug, second instance (2026-07-22): a post-apply
|
|
94
|
+
# twin-export hook read BRAIN_ARTIFACTS_BUCKET from env it never had
|
|
95
|
+
# and silently returned skipped_no_bucket on every apply.
|
|
96
|
+
# Document-served so every api handler resolves it via getConfig; the
|
|
97
|
+
# handlers that already carry it as env keep winning.
|
|
98
|
+
BRAIN_ARTIFACTS_BUCKET = aws_s3_bucket.brain_artifacts.bucket
|
|
99
|
+
DATABASE_SECRET_ARN = var.graphql_db_secret_arn
|
|
100
|
+
DATABASE_HOST = var.db_cluster_endpoint
|
|
101
|
+
DATABASE_NAME = var.database_name
|
|
105
102
|
# THINK-280 U8: the LAST rollout gate. External capability search + the
|
|
106
103
|
# Inspector governed-runtime operation layer stay inert until the broker is
|
|
107
104
|
# enabled for the stage. Off by default — read via getConfig() (env-wins).
|
|
@@ -120,9 +117,17 @@ locals {
|
|
|
120
117
|
COGNITO_AUTH_BASE_URL = local.mcp_oauth_cognito_base_url
|
|
121
118
|
MCP_OAUTH_CALLBACK_URL = "${local.mcp_oauth_api_base_url}/mcp/oauth/callback"
|
|
122
119
|
MCP_OAUTH_REVOCATIONS_TABLE = aws_dynamodb_table.mcp_oauth_revocations.name
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
120
|
+
# THINK-643: backing store for short-lived auth-flow state. While this is
|
|
121
|
+
# "postgres" the auth handlers never touch DynamoDB and AUTH_STATE_TABLE is
|
|
122
|
+
# empty (no table exists). Read via getConfig() — never process.env.
|
|
123
|
+
AUTH_STATE_STORE = var.auth_state_store
|
|
124
|
+
AUTH_STATE_TABLE = local.auth_state_enabled ? aws_dynamodb_table.auth_state[0].name : ""
|
|
125
|
+
# R16: comma-separated app-client allowlist. The optional console client id
|
|
126
|
+
# (U13) joins only when enabled; compact() drops the empty placeholder so
|
|
127
|
+
# the value is byte-identical to before while the console is off.
|
|
128
|
+
COGNITO_APP_CLIENT_IDS = join(",", compact([var.admin_client_id, var.mobile_client_id, var.console_client_id]))
|
|
129
|
+
APPSYNC_ENDPOINT = var.appsync_api_url
|
|
130
|
+
THINKWORK_API_URL = local.api_base_url
|
|
126
131
|
# Deterministic routines v1 (plan 2026-07-03-004 U6): activates the
|
|
127
132
|
# git-backed routine lifecycle tool suite on the admin-ops MCP server
|
|
128
133
|
# (routine_repo_list/read/commit, routine_run_fixtures, routine_runs).
|
|
@@ -156,13 +161,11 @@ locals {
|
|
|
156
161
|
# WORKSPACE_RENDERER_FUNCTION_NAME is derived from the per-stage naming
|
|
157
162
|
# convention by deriveFunctionName("workspace-renderer") — stored
|
|
158
163
|
# nowhere (R7).
|
|
159
|
-
WORKSPACE_BUCKET
|
|
160
|
-
|
|
161
|
-
#
|
|
162
|
-
#
|
|
163
|
-
|
|
164
|
-
AGENTCORE_MEMORY_ID = var.agentcore_memory_id
|
|
165
|
-
MEMORY_ENGINE = var.memory_engine
|
|
164
|
+
WORKSPACE_BUCKET = var.bucket_name
|
|
165
|
+
AGENTCORE_MEMORY_ID = var.agentcore_memory_id
|
|
166
|
+
# AgentCore managed memory is the only engine (THINK-407). The env var
|
|
167
|
+
# stays so the API's memory config seam keeps an explicit value.
|
|
168
|
+
MEMORY_ENGINE = "agentcore"
|
|
166
169
|
# CHAT_AGENT_INVOKE_FN_ARN (~112 serialized bytes) was dropped for the
|
|
167
170
|
# 4KB env ceiling (#2375): getChatAgentInvokeFnArn and managed-dispatch
|
|
168
171
|
# now derive the ARN from the deterministic naming pattern
|
|
@@ -178,7 +181,6 @@ locals {
|
|
|
178
181
|
# deploymentStatus reads ADMIN_URL directly — so the single canonical
|
|
179
182
|
# ADMIN_URL is sufficient. Re-add aliases only after env vars move to SSM.
|
|
180
183
|
ADMIN_URL = var.admin_url
|
|
181
|
-
DOCS_URL = var.docs_url
|
|
182
184
|
APPSYNC_REALTIME_URL = var.appsync_realtime_url
|
|
183
185
|
ECR_REPOSITORY_URL = var.ecr_repository_url
|
|
184
186
|
# Per-user OAuth wiring (Google Workspace today; Microsoft 365 follow-up).
|
|
@@ -264,20 +266,7 @@ locals {
|
|
|
264
266
|
# THINK-316 U1: the assertion mint runs on a sibling role and receives only
|
|
265
267
|
# the database connection plus immutable stage identity. In particular it
|
|
266
268
|
# does not inherit API_AUTH_SECRET or APPSYNC_API_KEY from common_env.
|
|
267
|
-
turn_assertion_mint_env = {
|
|
268
|
-
STAGE = var.stage
|
|
269
|
-
DATABASE_URL = "postgresql://${var.db_username}:${urlencode(var.db_password)}@${var.db_cluster_endpoint}:5432/${var.database_name}?sslmode=no-verify"
|
|
270
|
-
AWS_ACCOUNT_ID = var.account_id
|
|
271
|
-
NODE_OPTIONS = "--enable-source-maps"
|
|
272
|
-
}
|
|
273
269
|
|
|
274
|
-
# THINK-316 U1: the synthetic provider/target are proof-only public
|
|
275
|
-
# boundaries. They receive no database URL, platform bearer, or AppSync key.
|
|
276
|
-
agentcore_proof_boundary_env = {
|
|
277
|
-
STAGE = var.stage
|
|
278
|
-
AWS_ACCOUNT_ID = var.account_id
|
|
279
|
-
NODE_OPTIONS = "--enable-source-maps"
|
|
280
|
-
}
|
|
281
270
|
|
|
282
271
|
# Per-handler env-var overrides. ARNs are constructed from the naming
|
|
283
272
|
# pattern (same trick as the api-cross-function-invoke statement in
|
|
@@ -292,70 +281,12 @@ locals {
|
|
|
292
281
|
}
|
|
293
282
|
|
|
294
283
|
handler_extra_env = {
|
|
295
|
-
# THINK-316 U1: short-lived, server-minted identity assertions for
|
|
296
|
-
# AgentCore Harness and Gateway. The public mcp-oauth handler receives the
|
|
297
|
-
# key id only to publish GetPublicKey-derived JWKS; its role cannot Sign.
|
|
298
|
-
"mcp-oauth" = {
|
|
299
|
-
AGENTCORE_TURN_ASSERTION_ISSUER = local.agentcore_turn_assertion_issuer
|
|
300
|
-
AGENTCORE_TURN_ASSERTION_JWKS_KEYS = jsonencode([
|
|
301
|
-
for key in values(local.agentcore_turn_assertion_keys) : {
|
|
302
|
-
keyId = key.key_id
|
|
303
|
-
kid = key.kid
|
|
304
|
-
}
|
|
305
|
-
])
|
|
306
|
-
}
|
|
307
284
|
"skills" = {
|
|
308
285
|
AGENTCORE_IDENTITY_WORKLOAD_NAME = "thinkwork-${var.stage}-multiplayer-proof"
|
|
309
286
|
AGENTCORE_TWENTY_CREDENTIAL_PROVIDER_NAME = "thinkwork-${var.stage}-twenty-crm"
|
|
310
287
|
AGENTCORE_USER_OAUTH_RETURN_URL = "${local.mcp_oauth_api_base_url}/api/skills/mcp-oauth/agentcore/complete"
|
|
311
288
|
AGENTCORE_TWENTY_OAUTH_RESOURCE = "https://crm.thinkwork.ai/mcp"
|
|
312
289
|
}
|
|
313
|
-
"turn-assertion-mint" = {
|
|
314
|
-
AGENTCORE_TURN_ASSERTION_ISSUER = local.agentcore_turn_assertion_issuer
|
|
315
|
-
AGENTCORE_HARNESS_AUDIENCE = local.agentcore_harness_audience
|
|
316
|
-
AGENTCORE_GATEWAY_AUDIENCE = local.agentcore_gateway_audience
|
|
317
|
-
AGENTCORE_TURN_ASSERTION_KMS_KEY_ID = local.agentcore_turn_assertion_active_key.key_id
|
|
318
|
-
AGENTCORE_TURN_ASSERTION_KID = local.agentcore_turn_assertion_active_key.kid
|
|
319
|
-
}
|
|
320
|
-
"agentcore-proof-oauth-provider" = {
|
|
321
|
-
AGENTCORE_PROOF_OAUTH_ISSUER = "${local.mcp_oauth_api_base_url}/agentcore-proof/oauth"
|
|
322
|
-
AGENTCORE_PROOF_OAUTH_CLIENT_ID = var.agentcore_proof_oauth_client_id
|
|
323
|
-
AGENTCORE_PROOF_OAUTH_CLIENT_SECRET = var.agentcore_proof_oauth_client_secret
|
|
324
|
-
AGENTCORE_ASSERTION_ISSUER = local.agentcore_turn_assertion_issuer
|
|
325
|
-
AGENTCORE_HARNESS_AUDIENCE = local.agentcore_harness_audience
|
|
326
|
-
AGENTCORE_GATEWAY_AUDIENCE = local.agentcore_gateway_audience
|
|
327
|
-
AGENTCORE_TURN_ASSERTION_KMS_KEY_ID = local.agentcore_turn_assertion_active_key.key_id
|
|
328
|
-
AGENTCORE_TURN_ASSERTION_KID = local.agentcore_turn_assertion_active_key.kid
|
|
329
|
-
AGENTCORE_PROOF_OWNER_ALLOWLIST = var.agentcore_proof_owner_allowlist
|
|
330
|
-
}
|
|
331
|
-
"agentcore-identity-boundary-target" = {
|
|
332
|
-
AGENTCORE_PROOF_OAUTH_ISSUER = "${local.mcp_oauth_api_base_url}/agentcore-proof/oauth"
|
|
333
|
-
AGENTCORE_PROOF_OAUTH_CLIENT_SECRET = var.agentcore_proof_oauth_client_secret
|
|
334
|
-
AGENTCORE_PROOF_OWNER_ALLOWLIST = var.agentcore_proof_owner_allowlist
|
|
335
|
-
}
|
|
336
|
-
"harness-capability-mcp" = {
|
|
337
|
-
AGENTCORE_PROOF_OAUTH_ISSUER = "${local.mcp_oauth_api_base_url}/agentcore-proof/oauth"
|
|
338
|
-
AGENTCORE_PROOF_OAUTH_CLIENT_SECRET = var.agentcore_proof_oauth_client_secret
|
|
339
|
-
AGENTCORE_GATEWAY_POLICY_REVISION = "mcp-list-call-v2-tenant-admission"
|
|
340
|
-
AGENTCORE_IDENTITY_WORKLOAD_NAME = "thinkwork-${var.stage}-multiplayer-proof"
|
|
341
|
-
AGENTCORE_TWENTY_CREDENTIAL_PROVIDER_NAME = "thinkwork-${var.stage}-twenty-crm"
|
|
342
|
-
AGENTCORE_TWENTY_OAUTH_RESOURCE = "https://crm.thinkwork.ai/mcp"
|
|
343
|
-
}
|
|
344
|
-
"harness-code-interpreter-target" = {
|
|
345
|
-
AGENTCORE_PROOF_OAUTH_ISSUER = "${local.mcp_oauth_api_base_url}/agentcore-proof/oauth"
|
|
346
|
-
AGENTCORE_PROOF_OAUTH_CLIENT_SECRET = var.agentcore_proof_oauth_client_secret
|
|
347
|
-
AGENTCORE_GATEWAY_POLICY_REVISION = "sandbox-execute-v1-tenant-admission"
|
|
348
|
-
}
|
|
349
|
-
"harness-builtin-tools-target" = {
|
|
350
|
-
AGENTCORE_PROOF_OAUTH_ISSUER = "${local.mcp_oauth_api_base_url}/agentcore-proof/oauth"
|
|
351
|
-
AGENTCORE_PROOF_OAUTH_CLIENT_SECRET = var.agentcore_proof_oauth_client_secret
|
|
352
|
-
AGENTCORE_GATEWAY_POLICY_REVISION = "builtin-web-v1-tenant-admission"
|
|
353
|
-
}
|
|
354
|
-
"harness-platform-tools-target" = {
|
|
355
|
-
AGENTCORE_PROOF_OAUTH_ISSUER = "${local.mcp_oauth_api_base_url}/agentcore-proof/oauth"
|
|
356
|
-
AGENTCORE_PROOF_OAUTH_CLIENT_SECRET = var.agentcore_proof_oauth_client_secret
|
|
357
|
-
AGENTCORE_GATEWAY_POLICY_REVISION = "platform-tools-v4-user-questions"
|
|
358
|
-
}
|
|
359
290
|
"workos-auth" = {
|
|
360
291
|
# During cutover/soak the callback, bridge, and logout paths remain for
|
|
361
292
|
# already-issued state, but the handler independently refuses every new
|
|
@@ -371,40 +302,6 @@ locals {
|
|
|
371
302
|
"auth-enrollment" = {
|
|
372
303
|
AUTH_MIGRATION_RECOVERY_DEADLINE = var.auth_migration_recovery_deadline
|
|
373
304
|
}
|
|
374
|
-
# Analyst query broker (THINK-228 U3). Reader role + caller credential
|
|
375
|
-
# secrets, and the workspace bucket's analyst-staging/ prefix for
|
|
376
|
-
# large-result CSVs (lifecycle TTL lives on the bucket module). The
|
|
377
|
-
# shared writer DATABASE_SECRET_ARN also lands in this handler's env
|
|
378
|
-
# via common_env, but the broker code never uses it — SQL runs only as
|
|
379
|
-
# analyst_reader.
|
|
380
|
-
"analyst-query-broker" = {
|
|
381
|
-
ANALYST_READER_SECRET_ARN = var.analyst_reader_secret_arn
|
|
382
|
-
ANALYST_BROKER_SECRET_ARN = var.analyst_broker_secret_arn
|
|
383
|
-
ANALYST_STAGING_BUCKET = var.bucket_name
|
|
384
|
-
ANALYST_STAGING_PREFIX = "analyst-staging"
|
|
385
|
-
# THINK-229 U1: RDS IAM connect config. Endpoint presence switches
|
|
386
|
-
# analyst-reader-db.ts to the IAM-token path (password secret above
|
|
387
|
-
# is the pre-GRANT-rds_iam fallback, retired once IAM is proven).
|
|
388
|
-
# Gated on the resource ID so a stage without the IAM grant keeps
|
|
389
|
-
# the password path instead of failing into the fallback every cold
|
|
390
|
-
# start.
|
|
391
|
-
ANALYST_DB_CLUSTER_ENDPOINT = var.analyst_db_cluster_resource_id != "" ? var.db_cluster_endpoint : ""
|
|
392
|
-
ANALYST_DB_CLUSTER_RESOURCE_ID = var.analyst_db_cluster_resource_id
|
|
393
|
-
ANALYST_DB_NAME = var.database_name
|
|
394
|
-
ANALYST_DB_USER = "analyst_reader"
|
|
395
|
-
}
|
|
396
|
-
# THINK-229 U5 — the connection reconciler probes the analyst_reader
|
|
397
|
-
# connection EXACTLY as the broker does (getAnalystReaderClient), so it
|
|
398
|
-
# needs the same IAM-connect config + the password-fallback secret. The
|
|
399
|
-
# shared lambda execution role already holds rds-db:connect on the
|
|
400
|
-
# analyst_reader dbuser (iam-grouped.tf, granted in U1), so no extra IAM.
|
|
401
|
-
"analyst-connection-reconciler" = {
|
|
402
|
-
ANALYST_READER_SECRET_ARN = var.analyst_reader_secret_arn
|
|
403
|
-
ANALYST_DB_CLUSTER_ENDPOINT = var.analyst_db_cluster_resource_id != "" ? var.db_cluster_endpoint : ""
|
|
404
|
-
ANALYST_DB_CLUSTER_RESOURCE_ID = var.analyst_db_cluster_resource_id
|
|
405
|
-
ANALYST_DB_NAME = var.database_name
|
|
406
|
-
ANALYST_DB_USER = "analyst_reader"
|
|
407
|
-
}
|
|
408
305
|
# THINK-246: customer stages cannot send as the dev fallback domain
|
|
409
306
|
# (noreply@agents.thinkwork.ai is only verified in the dev account) —
|
|
410
307
|
# observed live on TEI as ses_send_failed on the deliver step.
|
|
@@ -447,46 +344,6 @@ locals {
|
|
|
447
344
|
CAPABILITY_BROKER_VPCE_DNS = var.capability_broker_vpce_dns
|
|
448
345
|
CAPABILITY_BROKER_SESSION_TABLE = var.capability_broker_session_table
|
|
449
346
|
}
|
|
450
|
-
# Compounding Memory compile Lambda. Any Converse-compatible Bedrock
|
|
451
|
-
# model works; the planner + section-writer cap themselves at ~500
|
|
452
|
-
# records / 25 new pages per invocation so a 480 s timeout covers
|
|
453
|
-
# the worst case comfortably. Env vars come from variables so
|
|
454
|
-
# unrelated deploys don't wipe them back to defaults (the aggregation
|
|
455
|
-
# flag got reset on every terraform apply before this was pinned).
|
|
456
|
-
"wiki-compile" = {
|
|
457
|
-
BEDROCK_MODEL_ID = var.wiki_compile_model_id
|
|
458
|
-
WIKI_AGGREGATION_PASS_ENABLED = var.wiki_aggregation_pass_enabled
|
|
459
|
-
WIKI_DETERMINISTIC_LINKING_ENABLED = var.wiki_deterministic_linking_enabled
|
|
460
|
-
# Wiki pipeline source dispatch (plan 2026-06-09-004 U10):
|
|
461
|
-
# 'planner' (default, LLM compile) | 'graph' (deterministic
|
|
462
|
-
# graph→wiki materializer over the knowledge-graph mirror).
|
|
463
|
-
WIKI_SOURCE = var.wiki_source
|
|
464
|
-
# Name (not value) of the SecureString SSM parameter that holds the
|
|
465
|
-
# Google Places API key. wiki-compile fetches + caches on cold start.
|
|
466
|
-
# The parameter may contain a placeholder value at apply time — the
|
|
467
|
-
# Lambda logs and degrades gracefully if decryption returns empty.
|
|
468
|
-
GOOGLE_PLACES_SSM_PARAM_NAME = "/thinkwork/${var.stage}/google-places/api-key"
|
|
469
|
-
# THINK-200 chain: a successful compile Event-invokes okf-materialize
|
|
470
|
-
# so the OKF projection (and, chained, the Pi navigator's EFS view)
|
|
471
|
-
# stays current without manual invocation.
|
|
472
|
-
OKF_MATERIALIZE_FN_NAME = "thinkwork-${var.stage}-api-okf-materialize"
|
|
473
|
-
}
|
|
474
|
-
"ontology-scan" = {
|
|
475
|
-
BEDROCK_MODEL_ID = var.wiki_compile_model_id
|
|
476
|
-
}
|
|
477
|
-
"wiki-export" = {
|
|
478
|
-
WIKI_EXPORT_BUCKET = aws_s3_bucket.wiki_exports.bucket
|
|
479
|
-
BRAIN_ARTIFACTS_BUCKET = aws_s3_bucket.brain_artifacts.bucket
|
|
480
|
-
}
|
|
481
|
-
"okf-materialize" = {
|
|
482
|
-
BRAIN_ARTIFACTS_BUCKET = aws_s3_bucket.brain_artifacts.bucket
|
|
483
|
-
# THINK-200 chain: fresh bundles fan out to the EFS current view.
|
|
484
|
-
OKF_EFS_REFRESH_FN_NAME = "thinkwork-${var.stage}-api-okf-efs-refresh"
|
|
485
|
-
}
|
|
486
|
-
"okf-efs-refresh" = {
|
|
487
|
-
BRAIN_ARTIFACTS_BUCKET = aws_s3_bucket.brain_artifacts.bucket
|
|
488
|
-
OKF_EFS_ROOT = var.okf_efs_mount_path
|
|
489
|
-
}
|
|
490
347
|
# THINK-193 U1 (Codex F6): normalized evidence snapshots live in the
|
|
491
348
|
# encrypted brain-artifacts bucket under evidence-snapshots/ — Postgres
|
|
492
349
|
# keeps only the s3:// ref + hash. 30-day lifecycle expiration below.
|
|
@@ -517,58 +374,72 @@ locals {
|
|
|
517
374
|
CONTEXT_ENGINE_MEMORY_QUERY_MODE = "reflect"
|
|
518
375
|
CONTEXT_ENGINE_MEMORY_TIMEOUT_MS = "20000"
|
|
519
376
|
}
|
|
520
|
-
|
|
521
|
-
|
|
377
|
+
"agentcore-runtime-dispatch" = {
|
|
378
|
+
# THINK-585 U6: the dispatcher resolves the Pi runtime id from SSM
|
|
379
|
+
# (5-min cache) and derives the ARN from identity env. Stage-scoped
|
|
380
|
+
# param name is config, not identity — env is the right layer.
|
|
381
|
+
AGENTCORE_PI_RUNTIME_SSM_NAME = "/thinkwork/${var.stage}/agentcore/runtime-id-pi"
|
|
382
|
+
# THINK-909: runtime session scope. "thread" (default) keys the
|
|
383
|
+
# AgentCore session per thread — today's behavior. "user" keys it per
|
|
384
|
+
# (tenant, agent, user) so a new thread reuses the warm microVM, with
|
|
385
|
+
# an immediate per-thread fallback on a 409. Flip a stage to "user"
|
|
386
|
+
# ONLY after its Pi runtime image dual-accepts both session ids.
|
|
387
|
+
AGENTCORE_SESSION_SCOPE = var.agentcore_session_scope
|
|
388
|
+
}
|
|
522
389
|
"chat-agent-invoke" = {
|
|
523
|
-
|
|
390
|
+
# THINK-324 C18: mint the signed-turn assertion with the active key.
|
|
391
|
+
AGENTCORE_TURN_ASSERTION_KMS_KEY_ID = local.turn_assertion_active_key_arn
|
|
392
|
+
# THINK-321 U5: stage gate for the Pi identity-resolution tools; the
|
|
393
|
+
# per-agent tool policy gates on top. Mirrored on wakeup-processor so
|
|
394
|
+
# wakeup turns carry the same payload flag (env-gated feature is dead
|
|
395
|
+
# in deployed stacks without the terraform var).
|
|
396
|
+
IDENTITY_RESOLUTION_ENABLED = tostring(var.identity_resolution_tool_enabled)
|
|
524
397
|
# THINK-311 U5: no HARNESS_RUNNER_FUNCTION_NAME env — derivable
|
|
525
398
|
# thinkwork-<stage>-api-* names never ride env (R1/R10 identity-only
|
|
526
399
|
# rule); resolveRuntimeFunctionName derives it from STAGE at call
|
|
527
400
|
# time, exactly like workspace-renderer.
|
|
528
401
|
}
|
|
402
|
+
# THINK-321 U5: wakeup turns read the same identity-resolution stage
|
|
403
|
+
# gate as chat-agent-invoke (both payload builders emit
|
|
404
|
+
# identity_resolution_enabled).
|
|
405
|
+
"wakeup-processor" = {
|
|
406
|
+
# THINK-324 C18: wakeup dispatches mint the same signed-turn assertion.
|
|
407
|
+
AGENTCORE_TURN_ASSERTION_KMS_KEY_ID = local.turn_assertion_active_key_arn
|
|
408
|
+
IDENTITY_RESOLUTION_ENABLED = tostring(var.identity_resolution_tool_enabled)
|
|
409
|
+
}
|
|
410
|
+
# THINK-324 C18/C19: the ledger endpoint verifies presented assertions
|
|
411
|
+
# with the cached public key of the same active mint key. Required mode:
|
|
412
|
+
# its only producer (the Pi tool-execution emitter) echoes the assertion
|
|
413
|
+
# since C18, so assertion-less ledger writes are refused. Verifier
|
|
414
|
+
# unavailability still degrades to bearer-only (never a write outage);
|
|
415
|
+
# a mint failure at dispatch costs that turn's evidence, logged loudly.
|
|
416
|
+
"tool-executions" = {
|
|
417
|
+
AGENTCORE_TURN_ASSERTION_KMS_KEY_ID = local.turn_assertion_active_key_arn
|
|
418
|
+
TURN_ASSERTION_REQUIRED = "true"
|
|
419
|
+
}
|
|
420
|
+
# THINK-324 C19: activity + finalize verify presented assertions
|
|
421
|
+
# (tolerant posture — legacy producers don't echo yet).
|
|
422
|
+
"chat-agent-activity" = {
|
|
423
|
+
AGENTCORE_TURN_ASSERTION_KMS_KEY_ID = local.turn_assertion_active_key_arn
|
|
424
|
+
}
|
|
425
|
+
"chat-agent-finalize" = {
|
|
426
|
+
AGENTCORE_TURN_ASSERTION_KMS_KEY_ID = local.turn_assertion_active_key_arn
|
|
427
|
+
}
|
|
529
428
|
# THINK-316 U5: the runner reads the server-only attested profile and
|
|
530
429
|
# invokes its named endpoint with a purpose-bound CUSTOM_JWT. It receives
|
|
531
430
|
# no Harness control-plane inputs or permissions.
|
|
532
|
-
|
|
533
|
-
#
|
|
534
|
-
#
|
|
535
|
-
#
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
# the already-near-4KB graphql-http env. Bedrock's RDS-backed KB needs the
|
|
545
|
-
# cluster ARN + the KB service role (passed at CreateKnowledgeBase time).
|
|
546
|
-
"knowledge-base-manager" = {
|
|
547
|
-
KB_SERVICE_ROLE_ARN = var.kb_service_role_arn
|
|
548
|
-
DATABASE_CLUSTER_ARN = var.db_cluster_arn
|
|
549
|
-
}
|
|
550
|
-
# Observations → Knowledge Graph worker. Extraction is now a Bedrock
|
|
551
|
-
# structured-output call inside this Lambda. KG_EXTRACTION_MODEL_ID pins
|
|
552
|
-
# the gpt-oss extraction model (Bedrock IAM via the shared lambda_bedrock
|
|
553
|
-
# invoke policy, same as the promotion-gate classifier).
|
|
554
|
-
"knowledge-graph-observations-ingest" = {
|
|
555
|
-
BRAIN_ARTIFACTS_BUCKET = aws_s3_bucket.brain_artifacts.bucket
|
|
556
|
-
OBSERVATION_CLASSIFIER_MODEL_ID = var.observation_classifier_model_id
|
|
557
|
-
KG_EXTRACTION_MODEL_ID = var.kg_extraction_model_id
|
|
558
|
-
# Per-run candidate cap bounds classifier + extraction cost; a
|
|
559
|
-
# truncated backlog drains via an in-process loop inside one
|
|
560
|
-
# invocation (never Lambda self-invoke — AWS recursive-loop
|
|
561
|
-
# detection terminates worker-to-self Event chains).
|
|
562
|
-
KG_OBS_MAX_CANDIDATES_PER_RUN = var.kg_obs_max_candidates_per_run
|
|
563
|
-
# THINK-193 U4 dead-handoff fix: a successful observations ingest
|
|
564
|
-
# enqueues the tenant graph wiki-compile job inside its own commit
|
|
565
|
-
# and Event-invokes wiki-compile post-commit. WIKI_SOURCE must match
|
|
566
|
-
# the wiki-compile handler's dispatch flag (stage-global); the
|
|
567
|
-
# per-tenant kill switch stays tenants.wiki_compile_enabled. The
|
|
568
|
-
# invoke rides the shared lambda role's existing wiki-compile
|
|
569
|
-
# lambda:InvokeFunction grant (iam-grouped.tf); the function name is
|
|
570
|
-
# derived from STAGE (common_env) at call time.
|
|
571
|
-
WIKI_SOURCE = var.wiki_source
|
|
431
|
+
# 240s: a sync memory retain (LLM extraction + consolidation) can exceed
|
|
432
|
+
# 60s; the client timeout must stay below the Lambda timeout.
|
|
433
|
+
# Company Brain U5: Neptune coordinates for the twin graph projector.
|
|
434
|
+
# Empty endpoint leaves the projector inert (nudge helper skips too).
|
|
435
|
+
"identity-graph-projector" = {
|
|
436
|
+
NEPTUNE_ENDPOINT = var.neptune_endpoint
|
|
437
|
+
NEPTUNE_PORT = "8182"
|
|
438
|
+
BRAIN_ARTIFACTS_BUCKET = aws_s3_bucket.brain_artifacts.bucket
|
|
439
|
+
# Bulk-rebuild lane (THINK-331): loader staging coordinates. Empty =
|
|
440
|
+
# bulk-rebuild mode returns a structured "not configured" error.
|
|
441
|
+
NEPTUNE_LOAD_BUCKET = var.neptune_load_bucket
|
|
442
|
+
NEPTUNE_LOADER_ROLE_ARN = var.neptune_loader_role_arn
|
|
572
443
|
}
|
|
573
444
|
# routine-task-python (Phase B U6) needs the AgentCore code-interpreter
|
|
574
445
|
# id + the per-stage S3 routine-output bucket. The interpreter id is
|
|
@@ -704,10 +575,17 @@ resource "aws_lambda_function" "skill_trust_runner" {
|
|
|
704
575
|
# Helper: creates Lambda functions from a local zip directory or release S3 keys
|
|
705
576
|
# ---------------------------------------------------------------------------
|
|
706
577
|
|
|
707
|
-
|
|
708
|
-
|
|
578
|
+
# The set of api handlers this module deploys (the for_each source for
|
|
579
|
+
# aws_lambda_function.handler). Hoisted into a local so the per-handler VPC
|
|
580
|
+
# placement map below (THINK-1082) can be built over the same names.
|
|
581
|
+
locals {
|
|
582
|
+
handler_names = local.deploy_lambda_handlers ? setsubtract(toset([
|
|
709
583
|
"graphql-http",
|
|
710
584
|
"chat-agent-invoke",
|
|
585
|
+
# THINK-585 U6: thin waiting dispatcher (InvokeAgentRuntime, held
|
|
586
|
+
# connection) + its DLQ redrive consumer (see dispatch-dlq.tf).
|
|
587
|
+
"agentcore-runtime-dispatch",
|
|
588
|
+
"agentcore-dispatch-dlq-redrive",
|
|
711
589
|
# Mobile agent harness: cloud Bedrock Converse proxy + completed-turn
|
|
712
590
|
# persistence. Routes for these live in local.api_routes; the function
|
|
713
591
|
# names must also be listed here (this set is the for_each source for
|
|
@@ -728,13 +606,6 @@ resource "aws_lambda_function" "handler" {
|
|
|
728
606
|
# Client Engagement app API. Calls Twenty REST API directly server-side;
|
|
729
607
|
# it is not backed by ThinkWork GraphQL or the agent MCP runtime.
|
|
730
608
|
"twenty-client-engagement",
|
|
731
|
-
# Desktop-local Pi tombstone endpoints. Kept temporarily so old packaged
|
|
732
|
-
# desktop clients receive a stable 410 while all supported Pi execution
|
|
733
|
-
# routes through managed AgentCore.
|
|
734
|
-
"desktop-runtime-session",
|
|
735
|
-
"desktop-workspace-prewarm",
|
|
736
|
-
"managed-delegation",
|
|
737
|
-
"desktop-eval-runs",
|
|
738
609
|
# chat-agent-finalize — POST /api/threads/{threadId}/finalize. The
|
|
739
610
|
# AgentCore runtime POSTs here at end-of-turn so the post-AgentCore
|
|
740
611
|
# bookkeeping (cost recording, message insert, AppSync notify,
|
|
@@ -743,23 +614,14 @@ resource "aws_lambda_function" "handler" {
|
|
|
743
614
|
# Bearer API_AUTH_SECRET. Idempotent on thread_turns.finalized_at
|
|
744
615
|
# (migration 0123). Plan: 2026-05-22-006.
|
|
745
616
|
"chat-agent-finalize",
|
|
746
|
-
# harness-runner — THINK-311 U5: Event-mode target for harness-flagged
|
|
747
617
|
# agents. The chat dispatch selector (resolveRuntimeFunctionName) routes
|
|
748
618
|
# a trial agent's turn here instead of the Pi container Lambda; the
|
|
749
619
|
# runner projects the payload into an AWS AgentCore Harness config,
|
|
750
620
|
# drives InvokeHarness, fulfills emit_document, and finalizes the turn
|
|
751
621
|
# via processFinalize. No API route — direct Event invoke only.
|
|
752
|
-
"harness-runner",
|
|
753
622
|
# THINK-316 U1: direct-invoke-only assertion mint. It derives all identity
|
|
754
623
|
# claims from the persisted turn tuple and signs with a dedicated KMS key;
|
|
755
624
|
# there is intentionally no public API Gateway route.
|
|
756
|
-
"turn-assertion-mint",
|
|
757
|
-
"agentcore-proof-oauth-provider",
|
|
758
|
-
"agentcore-identity-boundary-target",
|
|
759
|
-
"harness-capability-mcp",
|
|
760
|
-
"harness-code-interpreter-target",
|
|
761
|
-
"harness-builtin-tools-target",
|
|
762
|
-
"harness-platform-tools-target",
|
|
763
625
|
# canvas-refresh — headless Living Artifacts data-refresh (THINK-145 U6).
|
|
764
626
|
# Invoked RequestResponse by the refreshCanvasData mutation (graphql-http)
|
|
765
627
|
# and by job-trigger's canvas_refresh branch (U7). Re-runs the saved
|
|
@@ -815,6 +677,9 @@ resource "aws_lambda_function" "handler" {
|
|
|
815
677
|
"mcp-open-engine",
|
|
816
678
|
# THINK-280 U8: scoped external capability search MCP facade.
|
|
817
679
|
"mcp-capability-search",
|
|
680
|
+
# THINK-333 / consolidation U14: provisions the tenant Brain MCP
|
|
681
|
+
# connector against the platform endpoint (BRAIN_MCP_URL).
|
|
682
|
+
"mcp-twin-provision",
|
|
818
683
|
"activity",
|
|
819
684
|
"routines",
|
|
820
685
|
"budgets",
|
|
@@ -829,11 +694,6 @@ resource "aws_lambda_function" "handler" {
|
|
|
829
694
|
"webhooks-admin",
|
|
830
695
|
"webhook-deliveries-cleanup",
|
|
831
696
|
"skill-runs-reconciler",
|
|
832
|
-
# THINK-229 U5 — probes the analyst_reader connection (reachability, IAM
|
|
833
|
-
# auth, SELECT-grant introspection, schema drift; all read-only) every 30
|
|
834
|
-
# min and stamps the verdict onto runtime_metadata.analyst_probe so
|
|
835
|
-
# dispatch can withhold a failing/stale connection loudly.
|
|
836
|
-
"analyst-connection-reconciler",
|
|
837
697
|
"cron-stall-monitor",
|
|
838
698
|
"webhook-crm-opportunity",
|
|
839
699
|
"webhook-task-event",
|
|
@@ -842,8 +702,6 @@ resource "aws_lambda_function" "handler" {
|
|
|
842
702
|
# 2026-06-12-002 U4). Bearer API_AUTH_SECRET + x-tenant-id; the runtime
|
|
843
703
|
# fetch tool authorizes here, then downloads the returned S3 keys itself.
|
|
844
704
|
"workspace-fetch-source",
|
|
845
|
-
"knowledge-base-manager",
|
|
846
|
-
"knowledge-base-files",
|
|
847
705
|
"email-send",
|
|
848
706
|
"email-inbound",
|
|
849
707
|
"email-provider-webhook",
|
|
@@ -854,9 +712,7 @@ resource "aws_lambda_function" "handler" {
|
|
|
854
712
|
"msteams-install-complete",
|
|
855
713
|
"msteams-account-link-complete",
|
|
856
714
|
"github-app",
|
|
857
|
-
"memory",
|
|
858
715
|
"memory-retain",
|
|
859
|
-
"brain-dream-state",
|
|
860
716
|
"memory-stage-worker",
|
|
861
717
|
# THINK-193 U2 (Codex P1 #3): scheduled retry drainer for the retraction
|
|
862
718
|
# saga ledger. Claims due/stale memory_retraction_attempts rows with the
|
|
@@ -871,15 +727,15 @@ resource "aws_lambda_function" "handler" {
|
|
|
871
727
|
# terminal step event + SendTaskFailure. rate(15 minutes) schedule
|
|
872
728
|
# (dedicated resource below).
|
|
873
729
|
"memory-stage-sweeper",
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
"
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
"
|
|
730
|
+
# THINK-321 U7: bootstrap/drift identity matching job. Event-invoked by
|
|
731
|
+
# startIdentityMatchJob; the drift EventBridge Scheduler rule targets it
|
|
732
|
+
# directly (identity_drift_match_enabled, ships DISABLED).
|
|
733
|
+
"identity-match",
|
|
734
|
+
# Company Brain U5 (KTD-4): identity → twin graph projector. VPC-attached
|
|
735
|
+
# (Neptune). Event-invoked as a post-commit nudge by identity mutations;
|
|
736
|
+
# RequestResponse for the rebuild command. The per-tenant cursor row is
|
|
737
|
+
# the source of truth — missed nudges are harmless.
|
|
738
|
+
"identity-graph-projector",
|
|
883
739
|
"artifact-deliver",
|
|
884
740
|
"recipe-refresh",
|
|
885
741
|
"agent-skills-list",
|
|
@@ -966,16 +822,14 @@ resource "aws_lambda_function" "handler" {
|
|
|
966
822
|
# Admin-Ops MCP — JSON-RPC endpoint at POST /mcp/admin, exposes the
|
|
967
823
|
# @thinkwork/admin-ops package as MCP tools for managed agents.
|
|
968
824
|
"admin-ops-mcp",
|
|
969
|
-
# Analyst query broker — first-party MCP server at POST /mcp/analyst
|
|
970
|
-
# (THINK-228 U3). One tool, query: EXPLAIN-gated, extended-protocol
|
|
971
|
-
# single-statement SQL as the analyst_reader role; large results stage
|
|
972
|
-
# to S3 under analyst-staging/; every query emits a data.query_executed
|
|
973
|
-
# compliance audit event via POST /api/compliance/events.
|
|
974
|
-
"analyst-query-broker",
|
|
975
825
|
# MCP admin key management — per-tenant Bearer tokens for admin-ops.
|
|
976
826
|
# Admin-ops-mcp authenticates incoming tokens by sha256-hash lookup
|
|
977
827
|
# against tenant_mcp_admin_keys, populated by this handler's routes.
|
|
978
828
|
"mcp-admin-keys",
|
|
829
|
+
# Brain API key management — user-minted `tkt_` Bearer tokens for the
|
|
830
|
+
# platform Company Brain MCP. Create/revoke republish the hashed-key
|
|
831
|
+
# manifest the platform verifier reads (twin-mcp-keys/<tenantId>/).
|
|
832
|
+
"brain-api-keys",
|
|
979
833
|
# One-shot tenant provisioning: mints a tkm_ key + stores in Secrets
|
|
980
834
|
# Manager at thinkwork/<stage>/mcp/<tenantId>/admin-ops + upserts
|
|
981
835
|
# tenant_mcp_servers. SM IAM is already granted on thinkwork/* by
|
|
@@ -990,6 +844,16 @@ resource "aws_lambda_function" "handler" {
|
|
|
990
844
|
# Daily sweeper: auto-rejects MCP servers pending > 30 days. Triggered
|
|
991
845
|
# by EventBridge schedule (mcp-approval-sweeper-daily).
|
|
992
846
|
"mcp-approval-sweeper",
|
|
847
|
+
# Daily sweeper: cancels computer_approval inbox items past expires_at
|
|
848
|
+
# (or older than the TTL, for rows predating it). Keeps the approvals
|
|
849
|
+
# queue a list of live decisions instead of a months-deep graveyard.
|
|
850
|
+
"inbox-approval-sweeper",
|
|
851
|
+
# Hourly retention sweeper for auth_subscription_tickets. Tickets are
|
|
852
|
+
# single-use and expire 60s after mint but were never deleted; the
|
|
853
|
+
# table reached 551k rows / 306 MB (idx_scan=0) on a customer stage.
|
|
854
|
+
# Batched ctid DELETEs, 1h grace past expires_at. Triggered by
|
|
855
|
+
# EventBridge (aws_scheduler_schedule.auth_ticket_sweeper).
|
|
856
|
+
"auth-ticket-sweeper",
|
|
993
857
|
# Finance pilot U2 — thread-attachment upload (presign + finalize).
|
|
994
858
|
# presign issues a 5-min PUT URL the end-user client uses to push
|
|
995
859
|
# Excel/CSV bytes directly to S3; finalize sniffs magic bytes, scans
|
|
@@ -999,6 +863,11 @@ resource "aws_lambda_function" "handler" {
|
|
|
999
863
|
# threads.tenant_id lookup. Needs WORKSPACE_BUCKET env for S3.
|
|
1000
864
|
"thread-attachments-presign",
|
|
1001
865
|
"thread-attachments-finalize",
|
|
866
|
+
# Runtime-generated file registration (execute_code output_files).
|
|
867
|
+
# Bearer API_AUTH_SECRET + x-tenant-id; the Pi runtime uploads the
|
|
868
|
+
# sandbox file to the same staging prefix and registers it here with
|
|
869
|
+
# the same magic-byte + OOXML validation as finalize.
|
|
870
|
+
"thread-attachments-register",
|
|
1002
871
|
# U9-remainder of finance pilot — tenant-pinned download endpoint.
|
|
1003
872
|
# GET /api/threads/{tid}/attachments/{aid}/download returns a 302
|
|
1004
873
|
# to a 5-minute presigned S3 GET URL with ResponseContentDisposition:
|
|
@@ -1013,14 +882,10 @@ resource "aws_lambda_function" "handler" {
|
|
|
1013
882
|
# POSTs one row per agent-session-start. Shared
|
|
1014
883
|
# API_AUTH_SECRET bearer (runtime→API; no tenant OAuth).
|
|
1015
884
|
"manifest-log",
|
|
1016
|
-
#
|
|
1017
|
-
#
|
|
1018
|
-
#
|
|
1019
|
-
|
|
1020
|
-
# exclusively from the Ed25519-signed capability caller context (the
|
|
1021
|
-
# CAPABILITY_SIGNING_PUBLIC_KEY in the shared runtime-config document
|
|
1022
|
-
# verifies it); plaintext payload fields are never trusted.
|
|
1023
|
-
"capability-control-service",
|
|
885
|
+
# Pi tool-execution ledger write endpoint (THINK-324 C17). The runtime
|
|
886
|
+
# POSTs paired started/terminal evidence rows per tool call. Shared
|
|
887
|
+
# API_AUTH_SECRET bearer (runtime→API; no tenant OAuth).
|
|
888
|
+
"tool-executions",
|
|
1024
889
|
# SI-7 catalog-list read endpoint (plan §U15 pt 3/3). The runtime
|
|
1025
890
|
# fetches the allowed builtin-tool slug set once per
|
|
1026
891
|
# session-start + feature-flag-gated enforcement filter drops
|
|
@@ -1060,12 +925,44 @@ resource "aws_lambda_function" "handler" {
|
|
|
1060
925
|
# new standalone resource (see U8b plan operator-step section).
|
|
1061
926
|
]), toset(local.optional_integration_handler_names)) : toset([])
|
|
1062
927
|
|
|
928
|
+
# THINK-1082: one vpc_config per function, resolved here so the resource
|
|
929
|
+
# block stays a single dynamic block. Three shapes:
|
|
930
|
+
# - identity-graph-projector with Neptune wired: the Neptune subnets (the
|
|
931
|
+
# projector must reach the Neptune cluster), security groups = the
|
|
932
|
+
# Neptune client SGs UNION the api-lambda SGs when lambdas_in_vpc is on
|
|
933
|
+
# (the projector also opens DATABASE_URL, so it needs the DB grant too).
|
|
934
|
+
# - any handler when lambdas_in_vpc: the VPC subnets + api-lambda SGs.
|
|
935
|
+
# - otherwise null: no vpc_config, byte-identical to today.
|
|
936
|
+
handler_vpc = {
|
|
937
|
+
for name in local.handler_names : name => (
|
|
938
|
+
name == "identity-graph-projector" && local.neptune_vpc_enabled ? {
|
|
939
|
+
subnet_ids = var.neptune_subnet_ids
|
|
940
|
+
security_group_ids = distinct(concat(
|
|
941
|
+
var.neptune_security_group_ids,
|
|
942
|
+
var.lambdas_in_vpc ? var.vpc_security_group_ids : [],
|
|
943
|
+
))
|
|
944
|
+
} : var.lambdas_in_vpc ? {
|
|
945
|
+
subnet_ids = var.vpc_subnet_ids
|
|
946
|
+
security_group_ids = var.vpc_security_group_ids
|
|
947
|
+
} : null
|
|
948
|
+
)
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
|
|
952
|
+
resource "aws_lambda_function" "handler" {
|
|
953
|
+
for_each = local.handler_names
|
|
954
|
+
|
|
1063
955
|
function_name = "thinkwork-${var.stage}-api-${each.key}"
|
|
956
|
+
# THINK-583 U3: publish a numbered version for the two chat-critical
|
|
957
|
+
# handlers only — provisioned concurrency requires a published version
|
|
958
|
+
# behind the `live` alias (resources below). Scoped so the other ~90
|
|
959
|
+
# handlers don't accumulate a version per apply.
|
|
960
|
+
publish = contains(local.provisioned_concurrency_handlers, each.key)
|
|
1064
961
|
# S2 (THINK-193 U2): memory-retraction-drainer runs under a DEDICATED role
|
|
1065
962
|
# so its destructive evidence-snapshot S3 capability (version enumeration +
|
|
1066
963
|
# bulk version deletion) never leaks into the 90+ handlers on the shared
|
|
1067
964
|
# role. Everything else keeps the shared role.
|
|
1068
|
-
role = each.key == "memory-retraction-drainer" ? aws_iam_role.memory_retraction_drainer.arn :
|
|
965
|
+
role = each.key == "memory-retraction-drainer" ? aws_iam_role.memory_retraction_drainer.arn : aws_iam_role.lambda.arn
|
|
1069
966
|
handler = "index.handler"
|
|
1070
967
|
runtime = local.runtime
|
|
1071
968
|
# Parameters and Secrets extension: container-local cache for the SSM
|
|
@@ -1082,9 +979,6 @@ resource "aws_lambda_function" "handler" {
|
|
|
1082
979
|
# eval-runner walks every test case sequentially, invoking an agent +
|
|
1083
980
|
# waiting up to 2 min for spans to propagate per test, so a 10-test run
|
|
1084
981
|
# can easily exceed the 30 s default. 900 s covers ~5-15 min sweeps.
|
|
1085
|
-
# wiki-bootstrap-import runs a full Hindsight ingest for ~3,000 records;
|
|
1086
|
-
# the LLM-backed retain path makes it the longest-running Lambda in the
|
|
1087
|
-
# set. 900 s is Lambda's per-invocation max and matches eval-runner's ceiling.
|
|
1088
982
|
# routine-task-python wraps a 300s sandbox session and needs headroom
|
|
1089
983
|
# for the Start/Invoke/Stop/S3-offload round trip; 360s leaves ~60s
|
|
1090
984
|
# for AWS-call setup and offload after the sandbox's own ceiling.
|
|
@@ -1092,11 +986,16 @@ resource "aws_lambda_function" "handler" {
|
|
|
1092
986
|
# validates the agent, builds the AgentCore invoke payload, dispatches
|
|
1093
987
|
# Event-mode, and returns. Setup is ~5s in practice; 60s gives 12×
|
|
1094
988
|
# headroom for transient slowness.
|
|
1095
|
-
# harness-runner holds the Lambda open for the full Harness turn (the
|
|
1096
989
|
# reference QBR run was ~2 min; 900s is the ceiling — a longer run is a
|
|
1097
990
|
# legitimate trial limitation, recorded, not engineered around).
|
|
1098
|
-
timeout
|
|
1099
|
-
|
|
991
|
+
timeout = each.key == "wakeup-processor" ? 300 : each.key == "chat-agent-invoke" ? 60 : each.key == "agentcore-runtime-dispatch" ? 900 : each.key == "agentcore-dispatch-dlq-redrive" ? 60 : each.key == "chat-agent-finalize" ? 60 : each.key == "workspace-event-dispatcher" ? 60 : each.key == "eval-runner" ? 900 : each.key == "eval-worker" ? 240 : each.key == "requester-memory-dreaming" ? 300 : each.key == "identity-match" ? 300 : each.key == "identity-graph-projector" ? 900 : each.key == "folder-bundle-import" ? 300 : each.key == "routine-task-python" ? 360 : each.key == "routine-exec-git" ? 360 : each.key == "job-trigger" ? 600 : each.key == "model-converse" ? 60 : each.key == "memory-retain" ? 300 : each.key == "memory-stage-worker" ? 900 : each.key == "memory-stage-sweeper" ? 120 : each.key == "auth-ticket-sweeper" ? 120 : each.key == "memory-retraction-drainer" ? 300 : each.key == "canvas-refresh" ? 120 : each.key == "document-conformance-judge" ? 300 : each.key == "workflow-step-dispatch" ? 600 : each.key == "workflow-execution-callback" ? 60 : each.key == "workflow-resume" ? 60 : 30
|
|
992
|
+
# THINK-583 U2: chat-agent-invoke and workspace-renderer get a full vCPU
|
|
993
|
+
# (1769 MB). At 256 MB (~1/7 vCPU) the parallelized setup awaits starved on
|
|
994
|
+
# CPU — per-leg timing showed three independent {1 DB read + 1 S3/Secrets
|
|
995
|
+
# read} legs each taking ~1.5 s in parallel while sequential stage-1 reads
|
|
996
|
+
# were fast. Memory is priced per GB-s, but wall-clock drops far more than
|
|
997
|
+
# 7x cost rises on these short, provisioned-concurrency-warmed functions.
|
|
998
|
+
memory_size = each.key == "graphql-http" ? 512 : each.key == "wakeup-processor" ? 512 : each.key == "workspace-event-dispatcher" ? 512 : each.key == "eval-runner" ? 512 : each.key == "eval-worker" ? 512 : each.key == "requester-memory-dreaming" ? 512 : each.key == "identity-match" ? 512 : each.key == "identity-graph-projector" ? min(8192, var.lambda_max_memory_mb) : each.key == "folder-bundle-import" ? 1024 : each.key == "chat-agent-invoke" ? 1769 : each.key == "workspace-renderer" ? 1769 : each.key == "agentcore-runtime-dispatch" ? 512 : 256
|
|
1100
999
|
|
|
1101
1000
|
filename = local.use_local_zips ? "${var.lambda_zips_dir}/${each.key}.zip" : null
|
|
1102
1001
|
source_code_hash = local.use_local_zips ? filebase64sha256("${var.lambda_zips_dir}/${each.key}.zip") : null
|
|
@@ -1114,64 +1013,32 @@ resource "aws_lambda_function" "handler" {
|
|
|
1114
1013
|
# document-conformance-judge is also a single-writer: direct
|
|
1115
1014
|
# process-and-complete with no in-flight claim status depends on never
|
|
1116
1015
|
# having two sweepers race the same pending rows (THINK-189 KTD4).
|
|
1117
|
-
|
|
1118
|
-
# dedicated analyst_reader Postgres connection and runs model-authored
|
|
1119
|
-
# SQL — the cap bounds both connection pressure and the blast radius of
|
|
1120
|
-
# a runaway delegation (THINK-228 U3).
|
|
1121
|
-
# analyst-connection-reconciler is capped at 1: the probe holds one
|
|
1122
|
-
# analyst_reader connection and overlapping probes are pointless (the
|
|
1123
|
-
# cluster-global reader has one grant surface / one live schema).
|
|
1124
|
-
reserved_concurrent_executions = each.key == "compliance-outbox-drainer" ? 1 : each.key == "document-conformance-judge" ? 1 : each.key == "eval-worker" ? 40 : each.key == "analyst-query-broker" ? 4 : each.key == "analyst-connection-reconciler" ? 1 : -1
|
|
1016
|
+
reserved_concurrent_executions = each.key == "compliance-outbox-drainer" ? 1 : each.key == "document-conformance-judge" ? 1 : each.key == "eval-worker" ? 40 : -1
|
|
1125
1017
|
|
|
1126
1018
|
environment {
|
|
1127
1019
|
variables = merge(
|
|
1128
|
-
|
|
1129
|
-
"agentcore-proof-oauth-provider",
|
|
1130
|
-
"agentcore-identity-boundary-target",
|
|
1131
|
-
], each.key) ? local.agentcore_proof_boundary_env : local.common_env,
|
|
1020
|
+
local.common_env,
|
|
1132
1021
|
{ FUNCTION_NAME = each.key },
|
|
1133
1022
|
lookup(local.handler_extra_env, each.key, {}),
|
|
1134
1023
|
)
|
|
1135
1024
|
}
|
|
1136
1025
|
|
|
1026
|
+
# Company Brain U5 + THINK-1082: at most one vpc_config per function. The
|
|
1027
|
+
# placement (Neptune projector, whole-module VPC lane, or none) is resolved
|
|
1028
|
+
# in local.handler_vpc above; absent entirely when that entry is null.
|
|
1137
1029
|
dynamic "vpc_config" {
|
|
1138
|
-
for_each = each.key ==
|
|
1139
|
-
|
|
1140
|
-
content {
|
|
1141
|
-
subnet_ids = var.okf_efs_subnet_ids
|
|
1142
|
-
security_group_ids = var.okf_efs_security_group_ids
|
|
1143
|
-
}
|
|
1144
|
-
}
|
|
1145
|
-
|
|
1146
|
-
# Analyst data-path handlers get a stable NAT egress IP when
|
|
1147
|
-
# analyst_egress_subnet_ids is set — external Postgres sources behind an IP
|
|
1148
|
-
# allowlist admit that one EIP. Disjoint from the okf-efs-refresh block
|
|
1149
|
-
# above (a function takes at most one vpc_config).
|
|
1150
|
-
dynamic "vpc_config" {
|
|
1151
|
-
for_each = contains(local.analyst_vpc_handlers, each.key) && local.analyst_vpc_enabled ? [1] : []
|
|
1152
|
-
|
|
1153
|
-
content {
|
|
1154
|
-
subnet_ids = var.analyst_egress_subnet_ids
|
|
1155
|
-
security_group_ids = var.analyst_egress_security_group_ids
|
|
1156
|
-
}
|
|
1157
|
-
}
|
|
1158
|
-
|
|
1159
|
-
dynamic "file_system_config" {
|
|
1160
|
-
for_each = each.key == "okf-efs-refresh" && local.okf_efs_vpc_enabled ? [1] : []
|
|
1030
|
+
for_each = local.handler_vpc[each.key] == null ? [] : [local.handler_vpc[each.key]]
|
|
1161
1031
|
|
|
1162
1032
|
content {
|
|
1163
|
-
|
|
1164
|
-
|
|
1033
|
+
subnet_ids = vpc_config.value.subnet_ids
|
|
1034
|
+
security_group_ids = vpc_config.value.security_group_ids
|
|
1165
1035
|
}
|
|
1166
1036
|
}
|
|
1167
1037
|
|
|
1168
1038
|
lifecycle {
|
|
1169
1039
|
precondition {
|
|
1170
|
-
condition
|
|
1171
|
-
|
|
1172
|
-
alltrue([for id in var.okf_efs_mount_target_ids : id != ""])
|
|
1173
|
-
)
|
|
1174
|
-
error_message = "okf-efs-refresh requires an available EFS mount target dependency for every configured subnet."
|
|
1040
|
+
condition = local.lambda_vpc_inputs_complete
|
|
1041
|
+
error_message = "lambdas_in_vpc requires non-empty vpc_subnet_ids and vpc_security_group_ids."
|
|
1175
1042
|
}
|
|
1176
1043
|
}
|
|
1177
1044
|
|
|
@@ -1182,31 +1049,59 @@ resource "aws_lambda_function" "handler" {
|
|
|
1182
1049
|
}
|
|
1183
1050
|
|
|
1184
1051
|
# ---------------------------------------------------------------------------
|
|
1185
|
-
#
|
|
1052
|
+
# Warm sessions (THINK-583 U3): published version + `live` alias +
|
|
1053
|
+
# provisioned concurrency for chat-agent-invoke and workspace-renderer
|
|
1186
1054
|
# ---------------------------------------------------------------------------
|
|
1055
|
+
# KTD5: these two zip Lambdas ONLY — never the Pi Lambda (its warmth is
|
|
1056
|
+
# superseded by AgentCore session reuse, and deploy.yml publishes Pi code
|
|
1057
|
+
# to $LATEST out-of-band).
|
|
1187
1058
|
#
|
|
1188
|
-
#
|
|
1189
|
-
#
|
|
1190
|
-
#
|
|
1191
|
-
#
|
|
1192
|
-
#
|
|
1193
|
-
#
|
|
1194
|
-
#
|
|
1195
|
-
# Pin retries to 0 and route failures to a dedicated DLQ. The runner's
|
|
1196
|
-
# job-status short-circuit (running/succeeded/failed/skipped) is the
|
|
1197
|
-
# in-process protection against duplicate writebacks; this is the
|
|
1198
|
-
# infrastructure-level belt-and-suspenders.
|
|
1059
|
+
# Provisioned concurrency only serves invokes addressed to the alias, so
|
|
1060
|
+
# EVERY invoker resolves `<fn>:live` (graphql/utils.ts, mobile-turns/
|
|
1061
|
+
# managed-dispatch.ts, and the workspaceRendererFunctionName helpers in
|
|
1062
|
+
# chat-agent-invoke.ts / wakeup-processor.ts). The alias exists even when
|
|
1063
|
+
# the concurrency count is 0 — an alias with no PC config serves normally
|
|
1064
|
+
# from $LATEST-equivalent cold starts — so disabled stages keep working
|
|
1065
|
+
# unchanged and opt in purely by raising the count variable.
|
|
1199
1066
|
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1067
|
+
locals {
|
|
1068
|
+
provisioned_concurrency_handlers = toset([
|
|
1069
|
+
"chat-agent-invoke",
|
|
1070
|
+
"workspace-renderer",
|
|
1071
|
+
])
|
|
1072
|
+
provisioned_concurrency_counts = {
|
|
1073
|
+
"chat-agent-invoke" = var.chat_agent_invoke_provisioned_concurrency
|
|
1074
|
+
"workspace-renderer" = var.workspace_renderer_provisioned_concurrency
|
|
1207
1075
|
}
|
|
1208
1076
|
}
|
|
1209
1077
|
|
|
1078
|
+
resource "aws_lambda_alias" "live" {
|
|
1079
|
+
for_each = local.deploy_lambda_handlers ? local.provisioned_concurrency_handlers : toset([])
|
|
1080
|
+
|
|
1081
|
+
name = "live"
|
|
1082
|
+
description = "Warm-session alias (THINK-583 U3) — provisioned-concurrency target; all invokers alias-qualify."
|
|
1083
|
+
function_name = aws_lambda_function.handler[each.key].function_name
|
|
1084
|
+
function_version = aws_lambda_function.handler[each.key].version
|
|
1085
|
+
}
|
|
1086
|
+
|
|
1087
|
+
resource "aws_lambda_provisioned_concurrency_config" "live" {
|
|
1088
|
+
# aws_lambda_provisioned_concurrency_config rejects a count of 0, so a
|
|
1089
|
+
# disabled handler simply has no config resource (the alias remains).
|
|
1090
|
+
for_each = local.deploy_lambda_handlers ? {
|
|
1091
|
+
for name in local.provisioned_concurrency_handlers :
|
|
1092
|
+
name => local.provisioned_concurrency_counts[name]
|
|
1093
|
+
if local.provisioned_concurrency_counts[name] > 0
|
|
1094
|
+
} : {}
|
|
1095
|
+
|
|
1096
|
+
function_name = aws_lambda_function.handler[each.key].function_name
|
|
1097
|
+
qualifier = aws_lambda_alias.live[each.key].name
|
|
1098
|
+
provisioned_concurrent_executions = each.value
|
|
1099
|
+
}
|
|
1100
|
+
|
|
1101
|
+
# ---------------------------------------------------------------------------
|
|
1102
|
+
# Async retry configuration
|
|
1103
|
+
# ---------------------------------------------------------------------------
|
|
1104
|
+
|
|
1210
1105
|
# chat-agent-invoke retry-0 (plan 2026-05-22-006 U3). After the
|
|
1211
1106
|
# direct-callback finalize refactor, chat-agent-invoke is Event-mode-
|
|
1212
1107
|
# dispatched by the GraphQL resolver and itself dispatches AgentCore
|
|
@@ -1225,80 +1120,41 @@ resource "aws_lambda_function_event_invoke_config" "chat_agent_invoke" {
|
|
|
1225
1120
|
maximum_event_age_in_seconds = 3600
|
|
1226
1121
|
}
|
|
1227
1122
|
|
|
1228
|
-
#
|
|
1229
|
-
#
|
|
1230
|
-
#
|
|
1231
|
-
#
|
|
1232
|
-
|
|
1233
|
-
# chat-agent-invoke above: the shared role's inline policy budget is at
|
|
1234
|
-
# the AWS cap, and the stall monitor is the operational surface.
|
|
1235
|
-
resource "aws_lambda_function_event_invoke_config" "harness_runner" {
|
|
1236
|
-
count = local.deploy_lambda_handlers ? 1 : 0
|
|
1237
|
-
function_name = aws_lambda_function.handler["harness-runner"].function_name
|
|
1238
|
-
maximum_retry_attempts = 0
|
|
1239
|
-
maximum_event_age_in_seconds = 3600
|
|
1240
|
-
}
|
|
1241
|
-
|
|
1242
|
-
resource "aws_lambda_function_event_invoke_config" "wiki_compile" {
|
|
1123
|
+
# THINK-583 U3: the resolver now Event-invokes the `live` alias, and async
|
|
1124
|
+
# invoke config is per-qualifier — without this duplicate on the alias the
|
|
1125
|
+
# alias path would regress to AWS's default 2 retries and the 5-min stall
|
|
1126
|
+
# cascade above could recur. Same retry-0 posture, pinned explicitly.
|
|
1127
|
+
resource "aws_lambda_function_event_invoke_config" "chat_agent_invoke_live" {
|
|
1243
1128
|
count = local.deploy_lambda_handlers ? 1 : 0
|
|
1244
|
-
function_name = aws_lambda_function.handler["
|
|
1245
|
-
|
|
1246
|
-
maximum_event_age_in_seconds = 3600
|
|
1247
|
-
|
|
1248
|
-
destination_config {
|
|
1249
|
-
on_failure {
|
|
1250
|
-
destination = aws_sqs_queue.wiki_compile_dlq[0].arn
|
|
1251
|
-
}
|
|
1252
|
-
}
|
|
1253
|
-
}
|
|
1254
|
-
|
|
1255
|
-
# Ontology suggestion scans are durable-job driven. Disable AWS async
|
|
1256
|
-
# retries so duplicate scan invocations do not create duplicate review
|
|
1257
|
-
# proposals; the scan job row is the retry/observability surface.
|
|
1258
|
-
resource "aws_sqs_queue" "ontology_scan_dlq" {
|
|
1259
|
-
count = local.deploy_lambda_handlers ? 1 : 0
|
|
1260
|
-
name = "thinkwork-${var.stage}-ontology-scan-dlq"
|
|
1261
|
-
message_retention_seconds = 1209600 # 14 days
|
|
1262
|
-
|
|
1263
|
-
tags = {
|
|
1264
|
-
Name = "thinkwork-${var.stage}-ontology-scan-dlq"
|
|
1265
|
-
}
|
|
1266
|
-
}
|
|
1267
|
-
|
|
1268
|
-
resource "aws_lambda_function_event_invoke_config" "ontology_scan" {
|
|
1269
|
-
count = local.deploy_lambda_handlers ? 1 : 0
|
|
1270
|
-
function_name = aws_lambda_function.handler["ontology-scan"].function_name
|
|
1129
|
+
function_name = aws_lambda_function.handler["chat-agent-invoke"].function_name
|
|
1130
|
+
qualifier = aws_lambda_alias.live["chat-agent-invoke"].name
|
|
1271
1131
|
maximum_retry_attempts = 0
|
|
1272
1132
|
maximum_event_age_in_seconds = 3600
|
|
1273
|
-
|
|
1274
|
-
destination_config {
|
|
1275
|
-
on_failure {
|
|
1276
|
-
destination = aws_sqs_queue.ontology_scan_dlq[0].arn
|
|
1277
|
-
}
|
|
1278
|
-
}
|
|
1279
1133
|
}
|
|
1280
1134
|
|
|
1281
|
-
#
|
|
1282
|
-
#
|
|
1283
|
-
|
|
1135
|
+
# Identity match jobs (THINK-321 U7) are durable-job driven. Disable AWS
|
|
1136
|
+
# async retries so duplicate match invocations do not
|
|
1137
|
+
# double-write mappings/cases; identity.match_jobs is the retry/
|
|
1138
|
+
# observability surface.
|
|
1139
|
+
resource "aws_sqs_queue" "identity_match_dlq" {
|
|
1284
1140
|
count = local.deploy_lambda_handlers ? 1 : 0
|
|
1285
|
-
name = "thinkwork-${var.stage}-
|
|
1141
|
+
name = "thinkwork-${var.stage}-identity-match-dlq"
|
|
1286
1142
|
message_retention_seconds = 1209600 # 14 days
|
|
1287
1143
|
|
|
1288
1144
|
tags = {
|
|
1289
|
-
Name = "thinkwork-${var.stage}-
|
|
1145
|
+
Name = "thinkwork-${var.stage}-identity-match-dlq"
|
|
1290
1146
|
}
|
|
1291
1147
|
}
|
|
1292
1148
|
|
|
1293
|
-
resource "aws_lambda_function_event_invoke_config" "
|
|
1149
|
+
resource "aws_lambda_function_event_invoke_config" "identity_match" {
|
|
1294
1150
|
count = local.deploy_lambda_handlers ? 1 : 0
|
|
1295
|
-
function_name = aws_lambda_function.handler["
|
|
1151
|
+
function_name = aws_lambda_function.handler["identity-match"].function_name
|
|
1296
1152
|
maximum_retry_attempts = 0
|
|
1297
1153
|
maximum_event_age_in_seconds = 3600
|
|
1298
1154
|
|
|
1299
1155
|
destination_config {
|
|
1300
1156
|
on_failure {
|
|
1301
|
-
destination = aws_sqs_queue.
|
|
1157
|
+
destination = aws_sqs_queue.identity_match_dlq[0].arn
|
|
1302
1158
|
}
|
|
1303
1159
|
}
|
|
1304
1160
|
}
|
|
@@ -1322,7 +1178,7 @@ resource "aws_lambda_function_event_invoke_config" "routine_approval_callback" {
|
|
|
1322
1178
|
# memory-retain after every chat turn. AWS Lambda's default async-retry
|
|
1323
1179
|
# policy is 2 attempts; without overriding it, a transient failure on the
|
|
1324
1180
|
# canonical-transcript fetch or adapter write retries the entire writeback
|
|
1325
|
-
# and can multi-write the same per-turn document into
|
|
1181
|
+
# and can multi-write the same per-turn document into memory. The
|
|
1326
1182
|
# longest-suffix-prefix merge in memory-retain.ts dedupes content but the
|
|
1327
1183
|
# retain-cost path (Bedrock tokens charged in adapter.retainConversation)
|
|
1328
1184
|
# is NOT idempotent — retries multiply LLM cost. Per
|
|
@@ -1632,21 +1488,6 @@ locals {
|
|
|
1632
1488
|
# Agent actions (start/stop/heartbeat/budget)
|
|
1633
1489
|
"ANY /api/agent-actions/{proxy+}" = "agent-actions"
|
|
1634
1490
|
|
|
1635
|
-
# Desktop-local Pi tombstones. Specific routes before broad REST handlers;
|
|
1636
|
-
# OPTIONS is handled inside the Lambda before auth.
|
|
1637
|
-
"POST /api/desktop/runtime-session" = "desktop-runtime-session"
|
|
1638
|
-
"OPTIONS /api/desktop/runtime-session" = "desktop-runtime-session"
|
|
1639
|
-
"POST /api/desktop/workspace-prewarm" = "desktop-workspace-prewarm"
|
|
1640
|
-
"OPTIONS /api/desktop/workspace-prewarm" = "desktop-workspace-prewarm"
|
|
1641
|
-
"POST /api/desktop/managed-delegation" = "managed-delegation"
|
|
1642
|
-
"OPTIONS /api/desktop/managed-delegation" = "managed-delegation"
|
|
1643
|
-
"POST /api/desktop/eval-runs" = "desktop-eval-runs"
|
|
1644
|
-
"OPTIONS /api/desktop/eval-runs" = "desktop-eval-runs"
|
|
1645
|
-
"POST /api/desktop/eval-runs/{runId}/sessions" = "desktop-eval-runs"
|
|
1646
|
-
"OPTIONS /api/desktop/eval-runs/{runId}/sessions" = "desktop-eval-runs"
|
|
1647
|
-
"POST /api/desktop/eval-runs/{runId}/results" = "desktop-eval-runs"
|
|
1648
|
-
"OPTIONS /api/desktop/eval-runs/{runId}/results" = "desktop-eval-runs"
|
|
1649
|
-
|
|
1650
1491
|
# Mobile agent harness model proxy (cloud Bedrock Converse). OPTIONS is
|
|
1651
1492
|
# handled inside the Lambda before auth.
|
|
1652
1493
|
"POST /api/model/converse" = "model-converse"
|
|
@@ -1719,34 +1560,6 @@ locals {
|
|
|
1719
1560
|
# under /agentcore so the existing user-memory OAuth issuer is unchanged.
|
|
1720
1561
|
"GET /agentcore/.well-known/openid-configuration" = "mcp-oauth"
|
|
1721
1562
|
"GET /agentcore/oauth/jwks" = "mcp-oauth"
|
|
1722
|
-
# THINK-316 U1 proof-only provider and downstream HTTPS target. Both
|
|
1723
|
-
# handlers validate their own credentials; the route filter removes all
|
|
1724
|
-
# five when enable_agentcore_multiplayer_proof is false.
|
|
1725
|
-
"GET /agentcore-proof/oauth/.well-known/openid-configuration" = "agentcore-proof-oauth-provider"
|
|
1726
|
-
"GET /agentcore-proof/oauth/authorize" = "agentcore-proof-oauth-provider"
|
|
1727
|
-
"POST /agentcore-proof/oauth/token" = "agentcore-proof-oauth-provider"
|
|
1728
|
-
"GET /agentcore-proof/target/owner" = "agentcore-identity-boundary-target"
|
|
1729
|
-
"GET /agentcore-proof/target/mixed" = "agentcore-identity-boundary-target"
|
|
1730
|
-
"POST /agentcore/capabilities/mcp/tools/list" = "harness-capability-mcp"
|
|
1731
|
-
"POST /agentcore/capabilities/mcp/tools/call" = "harness-capability-mcp"
|
|
1732
|
-
"POST /agentcore/capabilities/sandbox/execute" = "harness-code-interpreter-target"
|
|
1733
|
-
"POST /agentcore/capabilities/web/search" = "harness-builtin-tools-target"
|
|
1734
|
-
"POST /agentcore/capabilities/web/extract" = "harness-builtin-tools-target"
|
|
1735
|
-
"POST /agentcore/capabilities/brain/query" = "harness-platform-tools-target"
|
|
1736
|
-
"POST /agentcore/capabilities/workspace/skills/list" = "harness-platform-tools-target"
|
|
1737
|
-
"POST /agentcore/capabilities/workspace/skills/load" = "harness-platform-tools-target"
|
|
1738
|
-
"POST /agentcore/capabilities/message/attachments/list" = "harness-platform-tools-target"
|
|
1739
|
-
"POST /agentcore/capabilities/message/attachments/read" = "harness-platform-tools-target"
|
|
1740
|
-
"POST /agentcore/capabilities/user/questions/ask" = "harness-platform-tools-target"
|
|
1741
|
-
"POST /agentcore/capabilities/email/send" = "harness-platform-tools-target"
|
|
1742
|
-
"POST /mcp/oauth/register" = "mcp-oauth"
|
|
1743
|
-
"GET /mcp/oauth/authorize" = "mcp-oauth"
|
|
1744
|
-
"GET /mcp/oauth/callback" = "mcp-oauth"
|
|
1745
|
-
"POST /mcp/oauth/token" = "mcp-oauth"
|
|
1746
|
-
"POST /mcp/oauth/revoke" = "mcp-oauth"
|
|
1747
|
-
"ANY /mcp/user-memory" = "mcp-user-memory"
|
|
1748
|
-
"ANY /mcp/context-engine" = "mcp-context-engine"
|
|
1749
|
-
"ANY /mcp/open-engine" = "mcp-open-engine"
|
|
1750
1563
|
# THINK-280 U8: scoped external capability search facade. The handler is
|
|
1751
1564
|
# inert unless CAPABILITY_EXTERNAL_SEARCH_ENABLED (gated on
|
|
1752
1565
|
# enable_capability_broker) is on — routing it while disabled returns an
|
|
@@ -1861,9 +1674,6 @@ locals {
|
|
|
1861
1674
|
# Workspace files
|
|
1862
1675
|
"ANY /api/workspaces/{proxy+}" = "workspace-files"
|
|
1863
1676
|
|
|
1864
|
-
# Knowledge bases
|
|
1865
|
-
"ANY /api/knowledge-bases/{proxy+}" = "knowledge-base-files"
|
|
1866
|
-
|
|
1867
1677
|
# Email
|
|
1868
1678
|
"POST /api/email/send" = "email-send"
|
|
1869
1679
|
"POST /api/email/provider-webhook/{providerInstallId}" = "email-provider-webhook"
|
|
@@ -1885,7 +1695,6 @@ locals {
|
|
|
1885
1695
|
"POST /msteams/account-link/complete" = "msteams-account-link-complete"
|
|
1886
1696
|
|
|
1887
1697
|
# Memory
|
|
1888
|
-
"ANY /api/memory/{proxy+}" = "memory"
|
|
1889
1698
|
|
|
1890
1699
|
# Artifacts
|
|
1891
1700
|
"POST /api/artifacts/{proxy+}" = "artifact-deliver"
|
|
@@ -1951,20 +1760,6 @@ locals {
|
|
|
1951
1760
|
# retained as a break-glass superuser path for bootstrap/debug.
|
|
1952
1761
|
"POST /mcp/admin" = "admin-ops-mcp"
|
|
1953
1762
|
|
|
1954
|
-
# Analyst query broker — first-party MCP server exposing query
|
|
1955
|
-
# (THINK-228 U3). Callers present the tenant-wide broker service
|
|
1956
|
-
# credential as Bearer; SQL executes as the hardened analyst_reader
|
|
1957
|
-
# role. The seeded postgres-dev connector row points at this route.
|
|
1958
|
-
"POST /mcp/analyst" = "analyst-query-broker"
|
|
1959
|
-
|
|
1960
|
-
# Sourced analyst broker route (THINK-239) — the same handler serves a
|
|
1961
|
-
# registered EXTERNAL Postgres source at /mcp/analyst/<slug>. The broker
|
|
1962
|
-
# requires a signed caller context whose sourceClaims.slug matches the
|
|
1963
|
-
# path (the legacy bearer is never accepted here) and connects using the
|
|
1964
|
-
# per-source reader credential (thinkwork/<stage>/analyst/*, covered by
|
|
1965
|
-
# the shared secretsmanager:GetSecretValue on thinkwork/*).
|
|
1966
|
-
"POST /mcp/analyst/{sourceSlug}" = "analyst-query-broker"
|
|
1967
|
-
|
|
1968
1763
|
# MCP admin key management — per-tenant Bearer token CRUD. Tokens
|
|
1969
1764
|
# are shown ONCE at creation (POST returns raw value); server stores
|
|
1970
1765
|
# sha256 hash only. These specific routes take precedence over the
|
|
@@ -1974,6 +1769,15 @@ locals {
|
|
|
1974
1769
|
"GET /api/tenants/{tenantId}/mcp-admin-keys" = "mcp-admin-keys"
|
|
1975
1770
|
"DELETE /api/tenants/{tenantId}/mcp-admin-keys/{keyId}" = "mcp-admin-keys"
|
|
1976
1771
|
|
|
1772
|
+
"POST /api/tenants/{tenantId}/brain-api-keys" = "brain-api-keys"
|
|
1773
|
+
"GET /api/tenants/{tenantId}/brain-api-keys" = "brain-api-keys"
|
|
1774
|
+
"OPTIONS /api/tenants/{tenantId}/brain-api-keys" = "brain-api-keys"
|
|
1775
|
+
"DELETE /api/tenants/{tenantId}/brain-api-keys/{keyId}" = "brain-api-keys"
|
|
1776
|
+
# Per-key grants edit (twin-mcp-keys/v2): securityGroups +
|
|
1777
|
+
# kbCollections, republishing the manifest on change.
|
|
1778
|
+
"PATCH /api/tenants/{tenantId}/brain-api-keys/{keyId}" = "brain-api-keys"
|
|
1779
|
+
"OPTIONS /api/tenants/{tenantId}/brain-api-keys/{keyId}" = "brain-api-keys"
|
|
1780
|
+
|
|
1977
1781
|
# One-shot tenant provisioning for the admin-ops MCP. Mints a fresh
|
|
1978
1782
|
# tkm_ key + stores it in Secrets Manager at
|
|
1979
1783
|
# thinkwork/<stage>/mcp/<tenantId>/admin-ops + upserts the
|
|
@@ -1981,6 +1785,13 @@ locals {
|
|
|
1981
1785
|
# any agent that gets it assigned via agent_mcp_servers.
|
|
1982
1786
|
"POST /api/tenants/{tenantId}/mcp-admin-provision" = "mcp-admin-provision"
|
|
1983
1787
|
|
|
1788
|
+
# Digital Twin MCP provisioning (THINK-333 U4): mints the tkt_ key,
|
|
1789
|
+
# writes the secret, upserts the approved digital-twin connector row
|
|
1790
|
+
# (url_hash pinned), and materializes connectors/digital-twin/ into
|
|
1791
|
+
# every agent workspace. Re-run = rotate.
|
|
1792
|
+
"POST /api/tenants/{tenantId}/mcp-twin-provision" = "mcp-twin-provision"
|
|
1793
|
+
"OPTIONS /api/tenants/{tenantId}/mcp-twin-provision" = "mcp-twin-provision"
|
|
1794
|
+
|
|
1984
1795
|
# MCP server admin approval (plan §U11, SI-5). Externally-sourced MCP
|
|
1985
1796
|
# servers land with status='pending'; these routes flip them to
|
|
1986
1797
|
# approved/rejected. Cognito JWT only (mcp-approval handler rejects
|
|
@@ -1998,6 +1809,10 @@ locals {
|
|
|
1998
1809
|
"POST /api/threads/{threadId}/attachments/finalize" = "thread-attachments-finalize"
|
|
1999
1810
|
"OPTIONS /api/threads/{threadId}/attachments/finalize" = "thread-attachments-finalize"
|
|
2000
1811
|
|
|
1812
|
+
# Runtime-generated attachments (execute_code output_files). Shared
|
|
1813
|
+
# API_AUTH_SECRET; no browser callers, so no OPTIONS route.
|
|
1814
|
+
"POST /api/threads/{threadId}/attachments/register" = "thread-attachments-register"
|
|
1815
|
+
|
|
2001
1816
|
# U9-remainder of finance pilot — tenant-pinned download endpoint.
|
|
2002
1817
|
"GET /api/threads/{threadId}/attachments/{attachmentId}/download" = "thread-attachment-download"
|
|
2003
1818
|
"OPTIONS /api/threads/{threadId}/attachments/{attachmentId}/download" = "thread-attachment-download"
|
|
@@ -2012,13 +1827,19 @@ locals {
|
|
|
2012
1827
|
"POST /api/runtime/manifests" = "manifest-log"
|
|
2013
1828
|
"OPTIONS /api/runtime/manifests" = "manifest-log"
|
|
2014
1829
|
|
|
1830
|
+
# Pi tool-execution ledger (THINK-324 C17). The runtime POSTs paired
|
|
1831
|
+
# started/terminal evidence rows per tool call. Shared API_AUTH_SECRET;
|
|
1832
|
+
# no tenant OAuth.
|
|
1833
|
+
"POST /api/runtime/tool-executions" = "tool-executions"
|
|
1834
|
+
"OPTIONS /api/runtime/tool-executions" = "tool-executions"
|
|
1835
|
+
|
|
2015
1836
|
# SI-7 catalog-list read (plan §U15 pt 3/3). The runtime fetches
|
|
2016
1837
|
# the allowed slug set once per session-start. Shared API_AUTH_SECRET.
|
|
2017
1838
|
"GET /api/runtime/capability-catalog" = "capability-catalog-list"
|
|
2018
1839
|
"OPTIONS /api/runtime/capability-catalog" = "capability-catalog-list"
|
|
2019
1840
|
} : route_key => handler_name
|
|
2020
1841
|
if !contains(local.optional_integration_handler_names, handler_name) && (
|
|
2021
|
-
|
|
1842
|
+
!startswith(route_key, "GET /agentcore/")
|
|
2022
1843
|
)
|
|
2023
1844
|
} : {}
|
|
2024
1845
|
}
|
|
@@ -2177,42 +1998,6 @@ resource "aws_scheduler_schedule" "webhook_deliveries_cleanup" {
|
|
|
2177
1998
|
# Requester memory dreaming — broad per-user memory compaction/reflection sweep
|
|
2178
1999
|
# ---------------------------------------------------------------------------
|
|
2179
2000
|
|
|
2180
|
-
# ---------------------------------------------------------------------------
|
|
2181
|
-
# Brain dream state — per-bank Hindsight consolidation with audit ledger
|
|
2182
|
-
# (THINK-133 U4). Retries are the ledger's job (staged plan -> atomic apply
|
|
2183
|
-
# -> applied markers; unfinished runs resume on the next tick), so Lambda
|
|
2184
|
-
# async retries stay at 0, mirroring memory-retain.
|
|
2185
|
-
# ---------------------------------------------------------------------------
|
|
2186
|
-
|
|
2187
|
-
resource "aws_lambda_function_event_invoke_config" "brain_dream_state" {
|
|
2188
|
-
count = local.deploy_lambda_handlers ? 1 : 0
|
|
2189
|
-
function_name = aws_lambda_function.handler["brain-dream-state"].function_name
|
|
2190
|
-
maximum_retry_attempts = 0
|
|
2191
|
-
maximum_event_age_in_seconds = 3600
|
|
2192
|
-
}
|
|
2193
|
-
|
|
2194
|
-
resource "aws_scheduler_schedule" "brain_dream_state" {
|
|
2195
|
-
count = local.deploy_lambda_handlers ? 1 : 0
|
|
2196
|
-
|
|
2197
|
-
name = "thinkwork-${var.stage}-brain-dream-state"
|
|
2198
|
-
group_name = "default"
|
|
2199
|
-
schedule_expression = var.brain_dream_state_schedule_expression
|
|
2200
|
-
state = var.brain_dream_state_enabled ? "ENABLED" : "DISABLED"
|
|
2201
|
-
|
|
2202
|
-
flexible_time_window {
|
|
2203
|
-
mode = "OFF"
|
|
2204
|
-
}
|
|
2205
|
-
|
|
2206
|
-
target {
|
|
2207
|
-
arn = aws_lambda_function.handler["brain-dream-state"].arn
|
|
2208
|
-
role_arn = aws_iam_role.scheduler.arn
|
|
2209
|
-
|
|
2210
|
-
retry_policy {
|
|
2211
|
-
maximum_retry_attempts = 0
|
|
2212
|
-
}
|
|
2213
|
-
}
|
|
2214
|
-
}
|
|
2215
|
-
|
|
2216
2001
|
resource "aws_scheduler_schedule" "requester_memory_dreaming" {
|
|
2217
2002
|
count = local.deploy_lambda_handlers ? 1 : 0
|
|
2218
2003
|
|
|
@@ -2275,20 +2060,12 @@ resource "aws_scheduler_schedule" "mcp_approval_sweeper" {
|
|
|
2275
2060
|
}
|
|
2276
2061
|
}
|
|
2277
2062
|
|
|
2278
|
-
|
|
2279
|
-
# skill_runs reconciler — transitions stuck-running rows to failed every 5 min.
|
|
2280
|
-
# Guards against agentcore Lambda crashes / OOMs that drop the
|
|
2281
|
-
# /api/skills/complete writeback and leave the row at 'running' forever,
|
|
2282
|
-
# which in turn blocks the dedup partial unique index from letting retries
|
|
2283
|
-
# through.
|
|
2284
|
-
# ---------------------------------------------------------------------------
|
|
2285
|
-
|
|
2286
|
-
resource "aws_scheduler_schedule" "skill_runs_reconciler" {
|
|
2063
|
+
resource "aws_scheduler_schedule" "inbox_approval_sweeper" {
|
|
2287
2064
|
count = local.deploy_lambda_handlers ? 1 : 0
|
|
2288
2065
|
|
|
2289
|
-
name = "thinkwork-${var.stage}-
|
|
2066
|
+
name = "thinkwork-${var.stage}-inbox-approval-sweeper"
|
|
2290
2067
|
group_name = "default"
|
|
2291
|
-
schedule_expression = "
|
|
2068
|
+
schedule_expression = "cron(30 4 * * ? *)" # daily at 04:30 UTC (offset from mcp-approval-sweeper)
|
|
2292
2069
|
state = "ENABLED"
|
|
2293
2070
|
|
|
2294
2071
|
flexible_time_window {
|
|
@@ -2296,53 +2073,50 @@ resource "aws_scheduler_schedule" "skill_runs_reconciler" {
|
|
|
2296
2073
|
}
|
|
2297
2074
|
|
|
2298
2075
|
target {
|
|
2299
|
-
arn = aws_lambda_function.handler["
|
|
2076
|
+
arn = aws_lambda_function.handler["inbox-approval-sweeper"].arn
|
|
2300
2077
|
role_arn = aws_iam_role.scheduler.arn
|
|
2301
2078
|
}
|
|
2302
2079
|
}
|
|
2303
2080
|
|
|
2304
|
-
#
|
|
2305
|
-
#
|
|
2306
|
-
#
|
|
2307
|
-
#
|
|
2308
|
-
#
|
|
2309
|
-
#
|
|
2310
|
-
#
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
# scheduler retries only adds redundant connections. A failure lands in the
|
|
2314
|
-
# DLQ for operator visibility instead.
|
|
2315
|
-
# ---------------------------------------------------------------------------
|
|
2081
|
+
# auth_subscription_tickets retention. Unlike the approval sweepers this is
|
|
2082
|
+
# a volume problem, not a queue-hygiene one: ~30 tickets/min are minted on
|
|
2083
|
+
# every connect + subscription registration and nothing deleted them
|
|
2084
|
+
# (551k rows / 306 MB and +24 MB/day on a customer stage, idx_scan=0).
|
|
2085
|
+
# Hourly rather than daily so each tick's backlog stays small enough that a
|
|
2086
|
+
# single batch usually drains it; the handler's own 45s budget bounds the
|
|
2087
|
+
# first few catch-up runs on a stage with an existing backlog.
|
|
2088
|
+
resource "aws_scheduler_schedule" "auth_ticket_sweeper" {
|
|
2089
|
+
count = local.deploy_lambda_handlers ? 1 : 0
|
|
2316
2090
|
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2091
|
+
name = "thinkwork-${var.stage}-auth-ticket-sweeper"
|
|
2092
|
+
group_name = "default"
|
|
2093
|
+
schedule_expression = "rate(1 hour)"
|
|
2094
|
+
state = "ENABLED"
|
|
2321
2095
|
|
|
2322
|
-
|
|
2323
|
-
|
|
2096
|
+
flexible_time_window {
|
|
2097
|
+
mode = "OFF"
|
|
2324
2098
|
}
|
|
2325
|
-
}
|
|
2326
2099
|
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
maximum_retry_attempts = 0
|
|
2331
|
-
maximum_event_age_in_seconds = 3600
|
|
2332
|
-
|
|
2333
|
-
destination_config {
|
|
2334
|
-
on_failure {
|
|
2335
|
-
destination = aws_sqs_queue.analyst_connection_reconciler_dlq[0].arn
|
|
2336
|
-
}
|
|
2100
|
+
target {
|
|
2101
|
+
arn = aws_lambda_function.handler["auth-ticket-sweeper"].arn
|
|
2102
|
+
role_arn = aws_iam_role.scheduler.arn
|
|
2337
2103
|
}
|
|
2338
2104
|
}
|
|
2339
2105
|
|
|
2340
|
-
|
|
2106
|
+
# ---------------------------------------------------------------------------
|
|
2107
|
+
# skill_runs reconciler — transitions stuck-running rows to failed every 5 min.
|
|
2108
|
+
# Guards against agentcore Lambda crashes / OOMs that drop the
|
|
2109
|
+
# /api/skills/complete writeback and leave the row at 'running' forever,
|
|
2110
|
+
# which in turn blocks the dedup partial unique index from letting retries
|
|
2111
|
+
# through.
|
|
2112
|
+
# ---------------------------------------------------------------------------
|
|
2113
|
+
|
|
2114
|
+
resource "aws_scheduler_schedule" "skill_runs_reconciler" {
|
|
2341
2115
|
count = local.deploy_lambda_handlers ? 1 : 0
|
|
2342
2116
|
|
|
2343
|
-
name = "thinkwork-${var.stage}-
|
|
2117
|
+
name = "thinkwork-${var.stage}-skill-runs-reconciler"
|
|
2344
2118
|
group_name = "default"
|
|
2345
|
-
schedule_expression = "rate(
|
|
2119
|
+
schedule_expression = "rate(5 minutes)"
|
|
2346
2120
|
state = "ENABLED"
|
|
2347
2121
|
|
|
2348
2122
|
flexible_time_window {
|
|
@@ -2350,12 +2124,8 @@ resource "aws_scheduler_schedule" "analyst_connection_reconciler" {
|
|
|
2350
2124
|
}
|
|
2351
2125
|
|
|
2352
2126
|
target {
|
|
2353
|
-
arn = aws_lambda_function.handler["
|
|
2127
|
+
arn = aws_lambda_function.handler["skill-runs-reconciler"].arn
|
|
2354
2128
|
role_arn = aws_iam_role.scheduler.arn
|
|
2355
|
-
|
|
2356
|
-
retry_policy {
|
|
2357
|
-
maximum_retry_attempts = 0
|
|
2358
|
-
}
|
|
2359
2129
|
}
|
|
2360
2130
|
}
|
|
2361
2131
|
|
|
@@ -2721,160 +2491,39 @@ resource "aws_scheduler_schedule" "stall_monitor" {
|
|
|
2721
2491
|
# Compounding Memory — nightly hygiene + export
|
|
2722
2492
|
# ---------------------------------------------------------------------------
|
|
2723
2493
|
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
flexible_time_window {
|
|
2733
|
-
mode = "OFF"
|
|
2734
|
-
}
|
|
2735
|
-
|
|
2736
|
-
target {
|
|
2737
|
-
arn = aws_lambda_function.handler["wiki-compile"].arn
|
|
2738
|
-
role_arn = aws_iam_role.scheduler.arn
|
|
2739
|
-
}
|
|
2740
|
-
}
|
|
2741
|
-
|
|
2742
|
-
# Observations → Knowledge Graph sweep (plan 2026-06-09-004 U5). Enumerates
|
|
2743
|
-
# tenants and runs an incremental observations ingest per tenant; the stable
|
|
2744
|
-
# source_ref's active-run dedupe drops overlap with operator-started runs and
|
|
2745
|
-
# the in-handler stale-run reaper clears stranded rows past the run ceiling.
|
|
2746
|
-
resource "aws_scheduler_schedule" "knowledge_graph_observations_ingest" {
|
|
2747
|
-
count = local.deploy_lambda_handlers ? 1 : 0
|
|
2748
|
-
|
|
2749
|
-
name = "thinkwork-${var.stage}-knowledge-graph-observations-ingest"
|
|
2750
|
-
group_name = "default"
|
|
2751
|
-
schedule_expression = "rate(30 minutes)"
|
|
2752
|
-
# Ships DISABLED (plan 2026-07-03-005 U4/KTD-6): the schedule enables on dev
|
|
2753
|
-
# only after a manual golden-set-validated run. Driven by the GHA
|
|
2754
|
-
# WIKI_KG_INGEST_ENABLED var.
|
|
2755
|
-
state = var.knowledge_graph_observations_ingest_enabled ? "ENABLED" : "DISABLED"
|
|
2756
|
-
|
|
2757
|
-
flexible_time_window {
|
|
2758
|
-
mode = "OFF"
|
|
2759
|
-
}
|
|
2760
|
-
|
|
2761
|
-
target {
|
|
2762
|
-
arn = aws_lambda_function.handler["knowledge-graph-observations-ingest"].arn
|
|
2763
|
-
role_arn = aws_iam_role.scheduler.arn
|
|
2764
|
-
input = jsonencode({ sweep = true, trigger = "scheduled" })
|
|
2765
|
-
|
|
2766
|
-
# Periodic idempotent worker: the next 30-minute tick IS the retry.
|
|
2767
|
-
# Scheduler-level retries stack extra invocations onto a cadence that
|
|
2768
|
-
# already self-corrects (cursor-guarded), compounding the invocation
|
|
2769
|
-
# volume that helped trip Lambda recursive-loop detection.
|
|
2770
|
-
retry_policy {
|
|
2771
|
-
maximum_retry_attempts = 0
|
|
2772
|
-
}
|
|
2773
|
-
}
|
|
2774
|
-
}
|
|
2775
|
-
|
|
2776
|
-
# Ontology suggestion scan sweep (THINK-320 U4/KTD-3). Enumerates tenants and
|
|
2777
|
-
# starts a suggestion scan job per tenant; tenants with a pending/running scan
|
|
2778
|
-
# are skipped in the handler, and the scan-job dedupe key drops same-bucket
|
|
2779
|
-
# duplicate starts. Ships DISABLED — enabled per stage via
|
|
2780
|
-
# ontology_scan_sweep_enabled after the Living Map review surfaces land.
|
|
2781
|
-
resource "aws_scheduler_schedule" "ontology_scan_sweep" {
|
|
2494
|
+
# Identity drift match sweep (THINK-321 U7 / KTD-7 — R10). Enumerates
|
|
2495
|
+
# tenants with registered identity sources and starts a per-tenant match
|
|
2496
|
+
# job; tenants with a pending/running job are skipped in the handler and
|
|
2497
|
+
# the job dedupe key drops same-bucket duplicate starts. Ships DISABLED —
|
|
2498
|
+
# enabled per stage via identity_drift_match_enabled once bootstrap has
|
|
2499
|
+
# been proven on the stage.
|
|
2500
|
+
resource "aws_scheduler_schedule" "identity_drift_match" {
|
|
2782
2501
|
count = local.deploy_lambda_handlers ? 1 : 0
|
|
2783
2502
|
|
|
2784
|
-
name = "thinkwork-${var.stage}-
|
|
2503
|
+
name = "thinkwork-${var.stage}-identity-drift-match"
|
|
2785
2504
|
group_name = "default"
|
|
2786
2505
|
schedule_expression = "rate(1 days)"
|
|
2787
|
-
state = var.
|
|
2506
|
+
state = var.identity_drift_match_enabled ? "ENABLED" : "DISABLED"
|
|
2788
2507
|
|
|
2789
2508
|
flexible_time_window {
|
|
2790
2509
|
mode = "OFF"
|
|
2791
2510
|
}
|
|
2792
2511
|
|
|
2793
2512
|
target {
|
|
2794
|
-
arn = aws_lambda_function.handler["
|
|
2513
|
+
arn = aws_lambda_function.handler["identity-match"].arn
|
|
2795
2514
|
role_arn = aws_iam_role.scheduler.arn
|
|
2796
|
-
input = jsonencode({
|
|
2515
|
+
input = jsonencode({ drift = true, trigger = "scheduled" })
|
|
2797
2516
|
|
|
2798
|
-
# Periodic idempotent worker: the next daily tick IS the retry
|
|
2799
|
-
#
|
|
2800
|
-
#
|
|
2517
|
+
# Periodic idempotent worker: the next daily tick IS the retry —
|
|
2518
|
+
# scheduler retries only stack invocations onto a self-correcting
|
|
2519
|
+
# cadence.
|
|
2801
2520
|
retry_policy {
|
|
2802
2521
|
maximum_retry_attempts = 0
|
|
2803
2522
|
}
|
|
2804
2523
|
}
|
|
2805
2524
|
}
|
|
2806
2525
|
|
|
2807
|
-
|
|
2808
|
-
count = local.deploy_lambda_handlers ? 1 : 0
|
|
2809
|
-
|
|
2810
|
-
name = "thinkwork-${var.stage}-wiki-lint"
|
|
2811
|
-
group_name = "default"
|
|
2812
|
-
schedule_expression = "cron(0 2 * * ? *)" # daily at 02:00 UTC
|
|
2813
|
-
state = "ENABLED"
|
|
2814
|
-
|
|
2815
|
-
flexible_time_window {
|
|
2816
|
-
mode = "OFF"
|
|
2817
|
-
}
|
|
2818
|
-
|
|
2819
|
-
target {
|
|
2820
|
-
arn = aws_lambda_function.handler["wiki-lint"].arn
|
|
2821
|
-
role_arn = aws_iam_role.scheduler.arn
|
|
2822
|
-
}
|
|
2823
|
-
}
|
|
2824
|
-
|
|
2825
|
-
resource "aws_scheduler_schedule" "wiki_export" {
|
|
2826
|
-
count = local.deploy_lambda_handlers ? 1 : 0
|
|
2827
|
-
|
|
2828
|
-
name = "thinkwork-${var.stage}-wiki-export"
|
|
2829
|
-
group_name = "default"
|
|
2830
|
-
schedule_expression = "cron(0 3 * * ? *)" # daily at 03:00 UTC (after lint)
|
|
2831
|
-
state = "ENABLED"
|
|
2832
|
-
|
|
2833
|
-
flexible_time_window {
|
|
2834
|
-
mode = "OFF"
|
|
2835
|
-
}
|
|
2836
|
-
|
|
2837
|
-
target {
|
|
2838
|
-
arn = aws_lambda_function.handler["wiki-export"].arn
|
|
2839
|
-
role_arn = aws_iam_role.scheduler.arn
|
|
2840
|
-
}
|
|
2841
|
-
}
|
|
2842
|
-
|
|
2843
|
-
# S3 bucket for markdown vault exports. One bundle per (tenant, owner, date).
|
|
2844
|
-
# Retention is handled by the lifecycle rule below (30 days).
|
|
2845
|
-
resource "aws_s3_bucket" "wiki_exports" {
|
|
2846
|
-
bucket = "thinkwork-${var.stage}-wiki-exports"
|
|
2847
|
-
force_destroy = var.stage == "dev"
|
|
2848
|
-
|
|
2849
|
-
tags = {
|
|
2850
|
-
Name = "thinkwork-${var.stage}-wiki-exports"
|
|
2851
|
-
}
|
|
2852
|
-
}
|
|
2853
|
-
|
|
2854
|
-
resource "aws_s3_bucket_public_access_block" "wiki_exports" {
|
|
2855
|
-
bucket = aws_s3_bucket.wiki_exports.id
|
|
2856
|
-
block_public_acls = true
|
|
2857
|
-
block_public_policy = true
|
|
2858
|
-
ignore_public_acls = true
|
|
2859
|
-
restrict_public_buckets = true
|
|
2860
|
-
}
|
|
2861
|
-
|
|
2862
|
-
resource "aws_s3_bucket_lifecycle_configuration" "wiki_exports" {
|
|
2863
|
-
bucket = aws_s3_bucket.wiki_exports.id
|
|
2864
|
-
|
|
2865
|
-
rule {
|
|
2866
|
-
id = "expire-old-bundles"
|
|
2867
|
-
status = "Enabled"
|
|
2868
|
-
|
|
2869
|
-
filter {}
|
|
2870
|
-
|
|
2871
|
-
expiration {
|
|
2872
|
-
days = 30
|
|
2873
|
-
}
|
|
2874
|
-
}
|
|
2875
|
-
}
|
|
2876
|
-
|
|
2877
|
-
# Canonical ThinkWork Brain artifact store. Unlike wiki_exports, this bucket
|
|
2526
|
+
# Canonical ThinkWork Brain artifact store. This bucket
|
|
2878
2527
|
# is the durable replay/projection substrate for Brain source artifacts,
|
|
2879
2528
|
# ingestion manifests, migration snapshots, vault projections, and exports.
|
|
2880
2529
|
resource "aws_s3_bucket" "brain_artifacts" {
|
|
@@ -2997,7 +2646,7 @@ resource "aws_s3_bucket_lifecycle_configuration" "brain_artifacts" {
|
|
|
2997
2646
|
|
|
2998
2647
|
# THINK-193 U1 (Codex F6): normalized evidence snapshots are short-lived
|
|
2999
2648
|
# working copies — the durable record is the evidence row (hash + ref) and
|
|
3000
|
-
# the
|
|
2649
|
+
# the memory projection. Expire content after 30 days; the app mirrors
|
|
3001
2650
|
# this via memory_evidence_items.snapshot_expires_at.
|
|
3002
2651
|
rule {
|
|
3003
2652
|
id = "expire-evidence-snapshots"
|
|
@@ -3037,6 +2686,48 @@ resource "aws_s3_bucket_lifecycle_configuration" "brain_artifacts" {
|
|
|
3037
2686
|
noncurrent_days = 365
|
|
3038
2687
|
}
|
|
3039
2688
|
}
|
|
2689
|
+
|
|
2690
|
+
# THINK-630: async brain_ask task records are a polling buffer, not an
|
|
2691
|
+
# archive — they hold answer content and principal metadata, so they must
|
|
2692
|
+
# not accumulate. Seven days far exceeds any task's useful life. The
|
|
2693
|
+
# brain-mcp module (company-brain repo) deliberately does NOT manage this
|
|
2694
|
+
# bucket's lifecycle (it would silently drop the rules above); this stack
|
|
2695
|
+
# is the bucket's single lifecycle author.
|
|
2696
|
+
rule {
|
|
2697
|
+
id = "expire-brain-ask-tasks"
|
|
2698
|
+
status = "Enabled"
|
|
2699
|
+
|
|
2700
|
+
filter {
|
|
2701
|
+
prefix = "brain-ask-tasks/"
|
|
2702
|
+
}
|
|
2703
|
+
|
|
2704
|
+
expiration {
|
|
2705
|
+
days = 7
|
|
2706
|
+
}
|
|
2707
|
+
|
|
2708
|
+
noncurrent_version_expiration {
|
|
2709
|
+
noncurrent_days = 7
|
|
2710
|
+
}
|
|
2711
|
+
}
|
|
2712
|
+
|
|
2713
|
+
# THINK-629 C2: ask exchange records (follow-up continuity) age out the
|
|
2714
|
+
# same way — the durable record is the thread itself.
|
|
2715
|
+
rule {
|
|
2716
|
+
id = "expire-brain-ask-exchanges"
|
|
2717
|
+
status = "Enabled"
|
|
2718
|
+
|
|
2719
|
+
filter {
|
|
2720
|
+
prefix = "brain-ask-exchanges/"
|
|
2721
|
+
}
|
|
2722
|
+
|
|
2723
|
+
expiration {
|
|
2724
|
+
days = 7
|
|
2725
|
+
}
|
|
2726
|
+
|
|
2727
|
+
noncurrent_version_expiration {
|
|
2728
|
+
noncurrent_days = 7
|
|
2729
|
+
}
|
|
2730
|
+
}
|
|
3040
2731
|
}
|
|
3041
2732
|
|
|
3042
2733
|
data "aws_iam_policy_document" "brain_artifacts_bucket" {
|
|
@@ -3121,33 +2812,6 @@ resource "aws_iam_role_policy" "scheduler_invoke" {
|
|
|
3121
2812
|
# SSM Parameters — Lambda ARNs for cross-function invocation
|
|
3122
2813
|
# ---------------------------------------------------------------------------
|
|
3123
2814
|
|
|
3124
|
-
########################################################################
|
|
3125
|
-
# SecureString parameter for the Google Places API key. wiki-compile reads
|
|
3126
|
-
# this on cold start via loadGooglePlacesClientFromSsm() and caches the
|
|
3127
|
-
# client at module scope. When google_places_api_key is empty (the
|
|
3128
|
-
# default), we seed the parameter with a placeholder so the Lambda init
|
|
3129
|
-
# path can distinguish "unconfigured" (skip Google entirely, degrade
|
|
3130
|
-
# gracefully) from "configured but wrong" (log + skip). lifecycle.ignore_
|
|
3131
|
-
# changes on `value` lets ops rotate via
|
|
3132
|
-
# aws ssm put-parameter --overwrite \
|
|
3133
|
-
# --name /thinkwork/<stage>/google-places/api-key \
|
|
3134
|
-
# --type SecureString --value <KEY>
|
|
3135
|
-
# without terraform fighting it on the next apply.
|
|
3136
|
-
########################################################################
|
|
3137
|
-
|
|
3138
|
-
resource "aws_ssm_parameter" "google_places_api_key" {
|
|
3139
|
-
name = "/thinkwork/${var.stage}/google-places/api-key"
|
|
3140
|
-
type = "SecureString"
|
|
3141
|
-
value = var.google_places_api_key != "" ? var.google_places_api_key : "PLACEHOLDER_SET_VIA_CLI"
|
|
3142
|
-
description = "Google Places API (New) key consumed by wiki-compile. See docs/plans/2026-04-21-005-feat-wiki-place-capability-v2-plan.md Unit 4."
|
|
3143
|
-
|
|
3144
|
-
lifecycle {
|
|
3145
|
-
# Allow `aws ssm put-parameter --overwrite` to stick across applies.
|
|
3146
|
-
# New-key rotation or initial population by ops should happen via CLI,
|
|
3147
|
-
# not via terraform var.
|
|
3148
|
-
ignore_changes = [value]
|
|
3149
|
-
}
|
|
3150
|
-
}
|
|
3151
2815
|
|
|
3152
2816
|
########################################################################
|
|
3153
2817
|
# SecureString parameter for the graphql-http Lambda's OWN Cloudflare
|
|
@@ -3191,8 +2855,10 @@ resource "aws_ssm_parameter" "cloudflare_namespace_token" {
|
|
|
3191
2855
|
|
|
3192
2856
|
resource "aws_ssm_parameter" "lambda_arns" {
|
|
3193
2857
|
for_each = local.deploy_lambda_handlers ? {
|
|
3194
|
-
|
|
3195
|
-
|
|
2858
|
+
# THINK-583 U3: alias-qualified so the SSM-fallback path in
|
|
2859
|
+
# getChatAgentInvokeFnArn (graphql/utils.ts) also lands on the
|
|
2860
|
+
# provisioned-concurrency alias, not $LATEST.
|
|
2861
|
+
"chat-agent-invoke-fn-arn" = aws_lambda_alias.live["chat-agent-invoke"].arn
|
|
3196
2862
|
"job-schedule-manager-fn-arn" = aws_lambda_function.handler["job-schedule-manager"].arn
|
|
3197
2863
|
"memory-retain-fn-arn" = aws_lambda_function.handler["memory-retain"].arn
|
|
3198
2864
|
"eval-runner-fn-arn" = aws_lambda_function.handler["eval-runner"].arn
|
|
@@ -3251,6 +2917,17 @@ resource "aws_lambda_function" "compliance_anchor" {
|
|
|
3251
2917
|
COMPLIANCE_ANCHOR_OBJECT_LOCK_MODE = var.compliance_anchor_object_lock_mode
|
|
3252
2918
|
}
|
|
3253
2919
|
}
|
|
2920
|
+
|
|
2921
|
+
# THINK-1082: this function opens a database connection (see env above), so
|
|
2922
|
+
# the whole-module VPC lane covers it too. Absent when lambdas_in_vpc is off.
|
|
2923
|
+
dynamic "vpc_config" {
|
|
2924
|
+
for_each = var.lambdas_in_vpc ? [1] : []
|
|
2925
|
+
|
|
2926
|
+
content {
|
|
2927
|
+
subnet_ids = var.vpc_subnet_ids
|
|
2928
|
+
security_group_ids = var.vpc_security_group_ids
|
|
2929
|
+
}
|
|
2930
|
+
}
|
|
3254
2931
|
}
|
|
3255
2932
|
|
|
3256
2933
|
resource "aws_sqs_queue" "compliance_anchor_dlq" {
|
|
@@ -3557,6 +3234,17 @@ resource "aws_lambda_function" "compliance_export_runner" {
|
|
|
3557
3234
|
DATABASE_NAME = var.database_name
|
|
3558
3235
|
}
|
|
3559
3236
|
}
|
|
3237
|
+
|
|
3238
|
+
# THINK-1082: this function opens a database connection (see env above), so
|
|
3239
|
+
# the whole-module VPC lane covers it too. Absent when lambdas_in_vpc is off.
|
|
3240
|
+
dynamic "vpc_config" {
|
|
3241
|
+
for_each = var.lambdas_in_vpc ? [1] : []
|
|
3242
|
+
|
|
3243
|
+
content {
|
|
3244
|
+
subnet_ids = var.vpc_subnet_ids
|
|
3245
|
+
security_group_ids = var.vpc_security_group_ids
|
|
3246
|
+
}
|
|
3247
|
+
}
|
|
3560
3248
|
}
|
|
3561
3249
|
|
|
3562
3250
|
# SQS → Lambda event source mapping. batch_size=1 so each export is a
|