thinkwork-cli 0.12.16 → 0.12.17
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/dist/cli.js +517 -10403
- package/dist/commands/enterprise/templates/deploy-repo/docs/runbook.md +3 -8
- package/dist/commands/enterprise/templates/deploy-repo/terraform/main.tf +1 -184
- package/dist/drizzle/0050_brain_v0_entity_subtype.sql +2 -2
- package/dist/drizzle/0051_brain_v0_tenant_entity_pages.sql +6 -6
- package/dist/drizzle/0052_brain_v0_external_refs.sql +2 -2
- package/dist/drizzle/0053_brain_v0_unresolved_mentions_subtype.sql +2 -2
- package/dist/drizzle/0145_knowledge_graph_thread_ingest.sql +14 -14
- package/dist/drizzle/0146_knowledge_graph_source_scope.sql +1 -1
- package/dist/drizzle/0157_knowledge_graph_observations_source.sql +2 -2
- package/dist/drizzle/0158_wiki_tenant_scope.sql +1 -1
- package/dist/drizzle/0165_plugin_premium_entitlements.sql +2 -2
- package/dist/drizzle/{0166_company_brain_substrate_contract.sql → 0166_brain_substrate_contract.sql} +9 -9
- package/dist/drizzle/{0167_company_brain_artifact_manifest_runtime.sql → 0167_brain_artifact_manifest_runtime.sql} +5 -5
- package/dist/drizzle/0168_eval_skill_gate.sql +1 -1
- package/dist/drizzle/0183_okf_artifact_manifests.sql +1 -1
- package/dist/drizzle/0200_eval_results_execution_tier.sql +40 -0
- package/dist/drizzle/0201_brain_dream_runs.sql +72 -0
- package/dist/drizzle/0202_backfill_thread_participants_from_senders.sql +110 -0
- package/dist/drizzle/0203_threads_mode_override.sql +61 -0
- package/dist/drizzle/0204_thread_turns_triggering_message_id.sql +48 -0
- package/dist/drizzle/0205_routines_git_python.sql +185 -0
- package/dist/drizzle/0206_agent_loop_versions_routine_actions.sql +40 -0
- package/dist/drizzle/0207_tenant_credentials_github_repo_kind.sql +52 -0
- package/dist/drizzle/0208_knowledge_graph_neutral_identifiers.sql +253 -0
- package/dist/drizzle/0209_living_artifacts_schema.sql +109 -0
- package/dist/drizzle/0210_think137_automations_additive_schema.sql +113 -0
- package/dist/drizzle/0211_backfill_agent_loop_versions_target_spec.sql +120 -0
- package/dist/drizzle/0212_fold_webhooks_into_automations.sql +312 -0
- package/dist/drizzle/0213_agent_loop_versions_judge_evidence_nullable.sql +63 -0
- package/dist/drizzle/0214_think137_drop_judge_evidence_roi.sql +99 -0
- package/dist/drizzle/0215_agent_loop_versions_goal_worker_policy_nullable.sql +70 -0
- package/dist/drizzle/0216_drop_agent_loop_versions_goal_worker_policy.sql +81 -0
- package/dist/drizzle/0217_agents_capability_folder_dispatch.sql +12 -0
- package/dist/drizzle/0218_document_plates.sql +30 -0
- package/dist/drizzle/0219_document_section_waivers.sql +29 -0
- package/dist/drizzle/0220_artifacts_created_by_user.sql +21 -0
- package/dist/drizzle/0221_artifact_shares.sql +29 -0
- package/dist/drizzle/0221_workflow_interpreter_thin_slice.sql +71 -0
- package/dist/drizzle/0222_compliance_drainer_select_audit_events.sql +21 -0
- package/dist/drizzle/0223_document_conformance_reports.sql +38 -0
- package/dist/drizzle/0224_artifact_refresh_state.sql +11 -0
- package/dist/drizzle/0225_think216_agent_loop_convergence.sql +21 -0
- package/dist/drizzle/0226_drop_n8n_agent_step_runs.sql +6 -0
- package/dist/drizzle/0227_analyst_reader_role.sql +1055 -0
- package/dist/drizzle/0228_tenant_credentials_rds_iam_kind.sql +62 -0
- package/dist/drizzle/0229_analyst_reader_rds_iam_grant.sql +79 -0
- package/dist/drizzle/0230_analyst_rls.sql +1613 -0
- package/dist/drizzle/0231_cost_events_cache_write_enforcement_exempt.sql +11 -0
- package/dist/plugins/catalog/package.json +0 -1
- package/dist/plugins/catalog/src/__tests__/build-catalog.test.ts +0 -1
- package/dist/plugins/catalog/src/__tests__/catalog.test.ts +16 -8
- package/dist/plugins/catalog/src/__tests__/contracts.test.ts +56 -0
- package/dist/plugins/catalog/src/__tests__/plugin-package.test.ts +0 -2
- package/dist/plugins/catalog/src/__tests__/plugin-registry.test.ts +0 -5
- package/dist/plugins/catalog/src/contracts.ts +112 -0
- package/dist/plugins/catalog/src/registry/generated-first-party.ts +0 -6
- package/dist/plugins/n8n/README.md +4 -36
- package/dist/plugins/n8n/src/deployment/managed-app.ts +0 -17
- package/dist/plugins/n8n/src/manifest.ts +0 -5
- package/dist/plugins/n8n/terraform/n8n/main.tf +0 -26
- package/dist/plugins/n8n/terraform/n8n/outputs.tf +0 -5
- package/dist/plugins/n8n/terraform/n8n/variables.tf +0 -6
- package/dist/plugins/n8n/test/manifest.test.ts +0 -1
- package/dist/plugins/twenty/package.json +5 -0
- package/dist/plugins/twenty/scripts/lib/__tests__/load-records.test.ts +232 -0
- package/dist/plugins/twenty/scripts/lib/__tests__/mappers.test.ts +489 -0
- package/dist/plugins/twenty/scripts/lib/__tests__/members-ensure.test.ts +199 -0
- package/dist/plugins/twenty/scripts/lib/__tests__/provision-members-db.test.ts +43 -0
- package/dist/plugins/twenty/scripts/lib/__tests__/schema-ensure.test.ts +230 -0
- package/dist/plugins/twenty/scripts/lib/__tests__/twenty-client.test.ts +207 -0
- package/dist/plugins/twenty/scripts/lib/lastmile-reader.ts +282 -0
- package/dist/plugins/twenty/scripts/lib/load-attachments.ts +220 -0
- package/dist/plugins/twenty/scripts/lib/load-records.ts +680 -0
- package/dist/plugins/twenty/scripts/lib/mappers.ts +559 -0
- package/dist/plugins/twenty/scripts/lib/members-ensure.ts +381 -0
- package/dist/plugins/twenty/scripts/lib/provision-members-db.ts +191 -0
- package/dist/plugins/twenty/scripts/lib/schema-ensure.ts +425 -0
- package/dist/plugins/twenty/scripts/lib/twenty-client.ts +246 -0
- package/dist/plugins/twenty/scripts/migrate-lastmile.ts +610 -0
- package/dist/plugins/twenty/scripts/provision-twenty-members.ts +214 -0
- package/dist/plugins/twenty/src/manifest.ts +99 -0
- package/dist/plugins/twenty/terraform/twenty/README.md +1 -1
- package/dist/plugins/twenty/test/manifest.test.ts +12 -2
- package/dist/terraform/examples/greenfield/main.tf +90 -380
- package/dist/terraform/examples/greenfield/terraform.tfvars.example +0 -1
- package/dist/terraform/modules/app/agentcore-pi/README.md +1 -3
- package/dist/terraform/modules/app/agentcore-pi/main.tf +29 -38
- package/dist/terraform/modules/app/agentcore-pi/variables.tf +23 -15
- package/dist/terraform/modules/app/agentcore-runtime/main.tf +3 -3
- package/dist/terraform/modules/app/customer-domain/main.tf +16 -2
- package/dist/terraform/modules/app/deployment-control-plane/main.tf +5 -0
- package/dist/terraform/modules/app/deployment-control-plane/runner.py +85 -207
- package/dist/terraform/modules/app/deployment-control-plane/test_runner_bundle.py +56 -2
- package/dist/terraform/modules/app/hindsight-memory/main.tf +52 -4
- package/dist/terraform/modules/app/lambda-api/eval-fanout.tf +7 -0
- package/dist/terraform/modules/app/lambda-api/handlers.tf +493 -89
- package/dist/terraform/modules/app/lambda-api/iam-grouped.tf +215 -96
- package/dist/terraform/modules/app/lambda-api/main.tf +24 -5
- package/dist/terraform/modules/app/lambda-api/outputs.tf +19 -11
- package/dist/terraform/modules/app/lambda-api/variables.tf +94 -67
- package/dist/terraform/modules/app/ses-email/main.tf +14 -2
- package/dist/terraform/modules/app/workflow-interpreter-stepfunctions/main.tf +493 -0
- package/dist/terraform/modules/app/workflow-interpreter-stepfunctions/outputs.tf +34 -0
- package/dist/terraform/modules/app/workflow-interpreter-stepfunctions/variables.tf +32 -0
- package/dist/terraform/modules/data/aurora-postgres/main.tf +55 -0
- package/dist/terraform/modules/data/aurora-postgres/outputs.tf +15 -0
- package/dist/terraform/modules/data/s3-buckets/main.tf +26 -0
- package/dist/terraform/modules/thinkwork/README.md +0 -1
- package/dist/terraform/modules/thinkwork/main.tf +167 -446
- package/dist/terraform/modules/thinkwork/outputs.tf +2 -142
- package/dist/terraform/modules/thinkwork/variables.tf +55 -309
- package/dist/terraform/schema.graphql +4 -0
- package/dist/workspace-defaults/files/AGENTS.md +45 -31
- package/dist/workspace-defaults/files/CONTEXT.md +48 -4
- package/dist/workspace-defaults/files/GUARDRAILS.md +18 -0
- package/dist/workspace-defaults/files/MEMORY_GUIDE.md +32 -4
- package/dist/workspace-defaults/files/SPACE.md +34 -19
- package/dist/workspace-defaults/files/TOOLS.md +30 -0
- package/dist/workspace-defaults/files/skills/document-composer/SKILL.md +154 -0
- package/dist/workspace-defaults/files/skills/document-composer/references/authoring-rules.md +101 -0
- package/package.json +1 -1
- package/dist/plugins/company-brain/README.md +0 -37
- package/dist/plugins/company-brain/package.json +0 -33
- package/dist/plugins/company-brain/runtime/cognee/Dockerfile +0 -11
- package/dist/plugins/company-brain/smoke/cognee-managed-app-smoke.mjs +0 -458
- package/dist/plugins/company-brain/smoke/cognee-memory-cutover-smoke.mjs +0 -539
- package/dist/plugins/company-brain/smoke/company-brain-context-engine-smoke.mjs +0 -312
- package/dist/plugins/company-brain/smoke/company-brain-operations-smoke.mjs +0 -449
- package/dist/plugins/company-brain/smoke/company-brain-plugin-smoke.mjs +0 -655
- package/dist/plugins/company-brain/smoke/hindsight-memory-isolation-smoke.mjs +0 -474
- package/dist/plugins/company-brain/src/api/cognee-client.ts +0 -896
- package/dist/plugins/company-brain/src/api/cognee-cluster-identity.ts +0 -49
- package/dist/plugins/company-brain/src/api/cognee-memory-scope.ts +0 -84
- package/dist/plugins/company-brain/src/api/context-engine-provider.ts +0 -888
- package/dist/plugins/company-brain/src/api/migration.ts +0 -665
- package/dist/plugins/company-brain/src/deployment/cognee-managed-app.ts +0 -396
- package/dist/plugins/company-brain/src/index.ts +0 -62
- package/dist/plugins/company-brain/src/manifest.ts +0 -112
- package/dist/plugins/company-brain/terraform/cognee/README.md +0 -263
- package/dist/plugins/company-brain/terraform/cognee/main.tf +0 -766
- package/dist/plugins/company-brain/terraform/cognee/outputs.tf +0 -144
- package/dist/plugins/company-brain/terraform/cognee/variables.tf +0 -402
- package/dist/plugins/company-brain/test/api/cognee-client.test.ts +0 -562
- package/dist/plugins/company-brain/test/api/cognee-memory-scope.test.ts +0 -74
- package/dist/plugins/company-brain/test/api/context-engine-provider.test.ts +0 -447
- package/dist/plugins/company-brain/test/api/migration.test.ts +0 -465
- package/dist/plugins/company-brain/test/manifest.test.ts +0 -95
- package/dist/plugins/company-brain/tsconfig.json +0 -8
|
@@ -10,14 +10,9 @@ locals {
|
|
|
10
10
|
use_local_zips = var.lambda_zips_dir != ""
|
|
11
11
|
eval_fanout_queue_url = local.deploy_lambda_handlers ? aws_sqs_queue.eval_fanout[0].url : ""
|
|
12
12
|
runtime = "nodejs20.x"
|
|
13
|
-
cognee_env = var.cognee_enabled ? {
|
|
14
|
-
# graphql-http is close to Lambda's 4 KB environment ceiling. Keep Cognee
|
|
15
|
-
# status in one compact value; stable names are derived in the resolver.
|
|
16
|
-
COGNEE = "${var.cognee_backend_mode}|${var.cognee_endpoint}"
|
|
17
|
-
} : {}
|
|
18
13
|
# Twenty managed-app status is DB-served (managed_applications +
|
|
19
14
|
# deployment jobs — plan 2026-06-12-001 U10); the TWENTY config key is
|
|
20
|
-
# retired.
|
|
15
|
+
# retired.
|
|
21
16
|
optional_integration_handler_names = concat(
|
|
22
17
|
var.deployment_control_plane_enabled ? [] : [
|
|
23
18
|
# Host-only onboarding/deployment API. Customer foundations disable the
|
|
@@ -53,9 +48,32 @@ locals {
|
|
|
53
48
|
# env forever, secrets live in Secrets Manager (R4), never in the String
|
|
54
49
|
# document.
|
|
55
50
|
config_env = merge({
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
51
|
+
# THINK-173: PUBLIC verification key (not a secret) + the NAME of the
|
|
52
|
+
# private-key secret (resolved via runtime-config's secret loader —
|
|
53
|
+
# the PEM itself never enters the env or the String document).
|
|
54
|
+
CAPABILITY_SIGNING_PUBLIC_KEY = var.capability_signing_public_key
|
|
55
|
+
CAPABILITY_SIGNING_PRIVATE_KEY_SECRET = var.capability_signing_private_key_secret
|
|
56
|
+
# THINK-229 U3/KTD5 — the analyst policy-source enforcement flip.
|
|
57
|
+
# "row" (default) keeps sidecar policy shadow-only; "sidecar" makes the
|
|
58
|
+
# signed sidecar block authoritative (budgets/policyClaims flow). Flip
|
|
59
|
+
# ONLY after clean shadow parity on live traffic.
|
|
60
|
+
ANALYST_POLICY_SOURCE = var.analyst_policy_source
|
|
61
|
+
# THINK-230 — the operator-facing provisionAnalystConnector mutation runs
|
|
62
|
+
# the analyst connector provisioning ceremony inside graphql-http, so the
|
|
63
|
+
# shared api handlers read the same broker-secret ARN + rds_iam connect
|
|
64
|
+
# config the analyst-query-broker handler carries per-handler. Read via
|
|
65
|
+
# getConfig() (env-wins), never process.env (runtime-config fixture gate).
|
|
66
|
+
# ANALYST_DB_CLUSTER_ENDPOINT gates on the resource id so a stage without
|
|
67
|
+
# the IAM grant leaves rds_iam provisioning off (resolveAnalystRdsIamConfig
|
|
68
|
+
# returns null) instead of half-seeding a credential row.
|
|
69
|
+
ANALYST_BROKER_SECRET_ARN = var.analyst_broker_secret_arn
|
|
70
|
+
ANALYST_DB_CLUSTER_ENDPOINT = var.analyst_db_cluster_resource_id != "" ? var.db_cluster_endpoint : ""
|
|
71
|
+
ANALYST_DB_CLUSTER_RESOURCE_ID = var.analyst_db_cluster_resource_id
|
|
72
|
+
ANALYST_DB_NAME = var.database_name
|
|
73
|
+
ANALYST_DB_USER = "analyst_reader"
|
|
74
|
+
DATABASE_SECRET_ARN = var.graphql_db_secret_arn
|
|
75
|
+
DATABASE_HOST = var.db_cluster_endpoint
|
|
76
|
+
DATABASE_NAME = var.database_name
|
|
59
77
|
# BUCKET_NAME and USER_POOL_ID were duplicate aliases of WORKSPACE_BUCKET
|
|
60
78
|
# and COGNITO_USER_POOL_ID; GRAPHQL_API_KEY duplicated APPSYNC_API_KEY;
|
|
61
79
|
# THINKWORK_API_SECRET and EMAIL_HMAC_SECRET duplicated API_AUTH_SECRET
|
|
@@ -72,6 +90,27 @@ locals {
|
|
|
72
90
|
COGNITO_APP_CLIENT_IDS = "${var.admin_client_id},${var.mobile_client_id}"
|
|
73
91
|
APPSYNC_ENDPOINT = var.appsync_api_url
|
|
74
92
|
THINKWORK_API_URL = local.api_base_url
|
|
93
|
+
# Deterministic routines v1 (plan 2026-07-03-004 U6): activates the
|
|
94
|
+
# git-backed routine lifecycle tool suite on the admin-ops MCP server
|
|
95
|
+
# (routine_repo_list/read/commit, routine_run_fixtures, routine_runs).
|
|
96
|
+
# Read via getConfig() in admin-ops-mcp.ts; without this the tools are
|
|
97
|
+
# listed but every call returns not_yet_enabled.
|
|
98
|
+
ROUTINES_AGENT_TOOLS_ENABLED = "true"
|
|
99
|
+
# THINK-137 Automations U9 (R15): activates the read-only Automation
|
|
100
|
+
# agent tools on the admin-ops MCP server (automations_list,
|
|
101
|
+
# automation_get). Read via getConfig() in admin-ops-mcp.ts; without
|
|
102
|
+
# this the tools are listed but every call returns not_yet_enabled.
|
|
103
|
+
AUTOMATIONS_AGENT_TOOLS_ENABLED = "true"
|
|
104
|
+
# THINK-227 U10 (KTD11): DEDICATED inert gate for the automation WRITE
|
|
105
|
+
# tools (automation_save, automation_delete). Deliberately "false" at
|
|
106
|
+
# merge — the read flag above has been live stage-wide since THINK-137,
|
|
107
|
+
# so reusing it would pre-activate writes on every already-assigned
|
|
108
|
+
# tenant. Flipped per-stage as the U12 rollout step (dev dogfood first,
|
|
109
|
+
# then TEI) after the pre-deploy assignment enumeration. Flipped for dev
|
|
110
|
+
# 2026-07-09: enumeration found admin-ops assigned to two internal
|
|
111
|
+
# tenants only (sleek-squirrel-230, academic-bobcat-897); AE1-AE4 smokes
|
|
112
|
+
# green on the deployed U1-U11 stack.
|
|
113
|
+
AUTOMATIONS_AGENT_WRITE_TOOLS_ENABLED = "true"
|
|
75
114
|
# Comma-separated allowlist of caller emails permitted to invoke
|
|
76
115
|
# operator-gated mutations (updateTenantPolicy, sandbox fixture
|
|
77
116
|
# setup, etc.). Resolved against ctx.auth.email, which is pulled
|
|
@@ -84,10 +123,13 @@ locals {
|
|
|
84
123
|
# WORKSPACE_RENDERER_FUNCTION_NAME is derived from the per-stage naming
|
|
85
124
|
# convention by deriveFunctionName("workspace-renderer") — stored
|
|
86
125
|
# nowhere (R7).
|
|
87
|
-
WORKSPACE_BUCKET
|
|
88
|
-
HINDSIGHT_ENDPOINT
|
|
89
|
-
|
|
90
|
-
|
|
126
|
+
WORKSPACE_BUCKET = var.bucket_name
|
|
127
|
+
HINDSIGHT_ENDPOINT = var.hindsight_endpoint
|
|
128
|
+
# THINK-220 cutover flag: empty = hindsight schema on the primary DB;
|
|
129
|
+
# set = that database's public schema via the database-pg seam.
|
|
130
|
+
HINDSIGHT_DATABASE_NAME = var.hindsight_database_name
|
|
131
|
+
AGENTCORE_MEMORY_ID = var.agentcore_memory_id
|
|
132
|
+
MEMORY_ENGINE = var.memory_engine
|
|
91
133
|
# CHAT_AGENT_INVOKE_FN_ARN (~112 serialized bytes) was dropped for the
|
|
92
134
|
# 4KB env ceiling (#2375): getChatAgentInvokeFnArn and managed-dispatch
|
|
93
135
|
# now derive the ARN from the deterministic naming pattern
|
|
@@ -113,13 +155,11 @@ locals {
|
|
|
113
155
|
# OAUTH_CALLBACK_URL is the URL registered with Google/Azure OAuth apps.
|
|
114
156
|
# REDIRECT_SUCCESS_URL is the fallback post-OAuth redirect when the
|
|
115
157
|
# caller doesn't pass a per-request returnUrl (mobile passes thinkwork://).
|
|
116
|
-
GOOGLE_PRODUCTIVITY_OAUTH_SECRET_ARN
|
|
117
|
-
OAUTH_CALLBACK_URL
|
|
118
|
-
REDIRECT_SUCCESS_URL
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
COMPANY_BRAIN_BACKDOOR_INSTALL_KEY_STAGES = var.company_brain_backdoor_install_key_stages
|
|
122
|
-
WWW_URL = var.www_url
|
|
158
|
+
GOOGLE_PRODUCTIVITY_OAUTH_SECRET_ARN = aws_secretsmanager_secret.oauth_google_productivity.arn
|
|
159
|
+
OAUTH_CALLBACK_URL = "https://${aws_apigatewayv2_api.main.id}.execute-api.${var.region}.amazonaws.com/api/oauth/callback"
|
|
160
|
+
REDIRECT_SUCCESS_URL = var.redirect_success_url
|
|
161
|
+
BRAIN_SOURCE_AGENT_MODEL_ID = var.brain_source_agent_model_id
|
|
162
|
+
WWW_URL = var.www_url
|
|
123
163
|
},
|
|
124
164
|
# Stripe billing — see stripe-secrets.tf. The ARN is the indirection;
|
|
125
165
|
# the actual keys live in Secrets Manager and are fetched by
|
|
@@ -139,7 +179,6 @@ locals {
|
|
|
139
179
|
# set to hello@thinkwork.ai once the bare-apex identity is verified in SES.
|
|
140
180
|
STRIPE_WELCOME_FROM_EMAIL = var.stripe_welcome_from_email
|
|
141
181
|
} : {},
|
|
142
|
-
local.cognee_env,
|
|
143
182
|
)
|
|
144
183
|
|
|
145
184
|
# graphql-http-only config that also belongs in the runtime-config
|
|
@@ -152,13 +191,6 @@ locals {
|
|
|
152
191
|
# Settings > General starts release updates from the GraphQL API.
|
|
153
192
|
DEPLOYMENT_STATE_MACHINE_ARN = var.deployment_state_machine_arn
|
|
154
193
|
DEPLOYMENT_EVIDENCE_BUCKET = var.deployment_evidence_bucket
|
|
155
|
-
# Cognee user + Space memory captures use explicit add+cognify so accepted
|
|
156
|
-
# documents enter the scoped graph. GraphQL has a 30s Lambda ceiling, so
|
|
157
|
-
# indexing wait is intentionally short/best-effort; callers poll search for
|
|
158
|
-
# eventual retrieval instead of pinning the capture request.
|
|
159
|
-
COGNEE_INGEST_MODE = "add_cognify"
|
|
160
|
-
COGNEE_INDEX_TIMEOUT_MS = "8000"
|
|
161
|
-
COGNEE_INDEX_POLL_MS = "2000"
|
|
162
194
|
# THNK-37 — the GraphQL API is the runtime trust boundary for the
|
|
163
195
|
# GitHub-hosted signed plugin catalog. Browsers keep reading through
|
|
164
196
|
# GraphQL; API verifies the release asset with the trusted public key
|
|
@@ -206,6 +238,46 @@ locals {
|
|
|
206
238
|
}
|
|
207
239
|
|
|
208
240
|
handler_extra_env = {
|
|
241
|
+
# Analyst query broker (THINK-228 U3). Reader role + caller credential
|
|
242
|
+
# secrets, and the workspace bucket's analyst-staging/ prefix for
|
|
243
|
+
# large-result CSVs (lifecycle TTL lives on the bucket module). The
|
|
244
|
+
# shared writer DATABASE_SECRET_ARN also lands in this handler's env
|
|
245
|
+
# via common_env, but the broker code never uses it — SQL runs only as
|
|
246
|
+
# analyst_reader.
|
|
247
|
+
"analyst-query-broker" = {
|
|
248
|
+
ANALYST_READER_SECRET_ARN = var.analyst_reader_secret_arn
|
|
249
|
+
ANALYST_BROKER_SECRET_ARN = var.analyst_broker_secret_arn
|
|
250
|
+
ANALYST_STAGING_BUCKET = var.bucket_name
|
|
251
|
+
ANALYST_STAGING_PREFIX = "analyst-staging"
|
|
252
|
+
# THINK-229 U1: RDS IAM connect config. Endpoint presence switches
|
|
253
|
+
# analyst-reader-db.ts to the IAM-token path (password secret above
|
|
254
|
+
# is the pre-GRANT-rds_iam fallback, retired once IAM is proven).
|
|
255
|
+
# Gated on the resource ID so a stage without the IAM grant keeps
|
|
256
|
+
# the password path instead of failing into the fallback every cold
|
|
257
|
+
# start.
|
|
258
|
+
ANALYST_DB_CLUSTER_ENDPOINT = var.analyst_db_cluster_resource_id != "" ? var.db_cluster_endpoint : ""
|
|
259
|
+
ANALYST_DB_CLUSTER_RESOURCE_ID = var.analyst_db_cluster_resource_id
|
|
260
|
+
ANALYST_DB_NAME = var.database_name
|
|
261
|
+
ANALYST_DB_USER = "analyst_reader"
|
|
262
|
+
}
|
|
263
|
+
# THINK-229 U5 — the connection reconciler probes the analyst_reader
|
|
264
|
+
# connection EXACTLY as the broker does (getAnalystReaderClient), so it
|
|
265
|
+
# needs the same IAM-connect config + the password-fallback secret. The
|
|
266
|
+
# shared lambda execution role already holds rds-db:connect on the
|
|
267
|
+
# analyst_reader dbuser (iam-grouped.tf, granted in U1), so no extra IAM.
|
|
268
|
+
"analyst-connection-reconciler" = {
|
|
269
|
+
ANALYST_READER_SECRET_ARN = var.analyst_reader_secret_arn
|
|
270
|
+
ANALYST_DB_CLUSTER_ENDPOINT = var.analyst_db_cluster_resource_id != "" ? var.db_cluster_endpoint : ""
|
|
271
|
+
ANALYST_DB_CLUSTER_RESOURCE_ID = var.analyst_db_cluster_resource_id
|
|
272
|
+
ANALYST_DB_NAME = var.database_name
|
|
273
|
+
ANALYST_DB_USER = "analyst_reader"
|
|
274
|
+
}
|
|
275
|
+
# THINK-246: customer stages cannot send as the dev fallback domain
|
|
276
|
+
# (noreply@agents.thinkwork.ai is only verified in the dev account) —
|
|
277
|
+
# observed live on TEI as ses_send_failed on the deliver step.
|
|
278
|
+
"artifact-deliver" = {
|
|
279
|
+
ARTIFACT_DELIVERY_FROM_EMAIL = var.artifact_delivery_from_email
|
|
280
|
+
}
|
|
209
281
|
"extension-proxy" = {
|
|
210
282
|
EXTENSION_PROXY_BACKENDS_JSON = var.extension_proxy_backends_json
|
|
211
283
|
EXTENSION_PROXY_SIGNING_SECRET = var.extension_proxy_signing_secret
|
|
@@ -250,6 +322,10 @@ locals {
|
|
|
250
322
|
# The parameter may contain a placeholder value at apply time — the
|
|
251
323
|
# Lambda logs and degrades gracefully if decryption returns empty.
|
|
252
324
|
GOOGLE_PLACES_SSM_PARAM_NAME = "/thinkwork/${var.stage}/google-places/api-key"
|
|
325
|
+
# THINK-200 chain: a successful compile Event-invokes okf-materialize
|
|
326
|
+
# so the OKF projection (and, chained, the Pi navigator's EFS view)
|
|
327
|
+
# stays current without manual invocation.
|
|
328
|
+
OKF_MATERIALIZE_FN_NAME = "thinkwork-${var.stage}-api-okf-materialize"
|
|
253
329
|
}
|
|
254
330
|
"ontology-scan" = {
|
|
255
331
|
BEDROCK_MODEL_ID = var.wiki_compile_model_id
|
|
@@ -260,6 +336,8 @@ locals {
|
|
|
260
336
|
}
|
|
261
337
|
"okf-materialize" = {
|
|
262
338
|
BRAIN_ARTIFACTS_BUCKET = aws_s3_bucket.brain_artifacts.bucket
|
|
339
|
+
# THINK-200 chain: fresh bundles fan out to the EFS current view.
|
|
340
|
+
OKF_EFS_REFRESH_FN_NAME = "thinkwork-${var.stage}-api-okf-efs-refresh"
|
|
263
341
|
}
|
|
264
342
|
"okf-efs-refresh" = {
|
|
265
343
|
BRAIN_ARTIFACTS_BUCKET = aws_s3_bucket.brain_artifacts.bucket
|
|
@@ -287,8 +365,15 @@ locals {
|
|
|
287
365
|
"chat-agent-invoke" = {
|
|
288
366
|
KNOWLEDGE_GRAPH_TOOL_ENABLED = tostring(var.knowledge_graph_tool_enabled)
|
|
289
367
|
}
|
|
368
|
+
# 240s: sync Hindsight retain (LLM extraction + auto-consolidation) can
|
|
369
|
+
# exceed 60s; the client timeout must stay below the Lambda timeout (300s)
|
|
370
|
+
# and below the Hindsight ALB idle_timeout (300s) so failures classify as
|
|
371
|
+
# client timeouts, never ALB 504s.
|
|
290
372
|
"memory-retain" = {
|
|
291
|
-
HINDSIGHT_TIMEOUT_MS = "
|
|
373
|
+
HINDSIGHT_TIMEOUT_MS = "240000"
|
|
374
|
+
}
|
|
375
|
+
"brain-dream-state" = {
|
|
376
|
+
BRAIN_DREAM_STATE_ENABLED = tostring(var.brain_dream_state_enabled)
|
|
292
377
|
}
|
|
293
378
|
# Bedrock KB provisioning. Per-handler (not common_env) so these don't bloat
|
|
294
379
|
# the already-near-4KB graphql-http env. Bedrock's RDS-backed KB needs the
|
|
@@ -297,32 +382,19 @@ locals {
|
|
|
297
382
|
KB_SERVICE_ROLE_ARN = var.kb_service_role_arn
|
|
298
383
|
DATABASE_CLUSTER_ARN = var.db_cluster_arn
|
|
299
384
|
}
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
BRAIN_ARTIFACTS_BUCKET = aws_s3_bucket.brain_artifacts.bucket
|
|
305
|
-
}
|
|
306
|
-
# Observations → Knowledge Graph worker (plan 2026-06-09-004 U5).
|
|
307
|
-
# add_cognify pins the incremental ingest path into the stable
|
|
308
|
-
# per-tenant dataset; the promotion-gate classifier reads
|
|
309
|
-
# OBSERVATION_CLASSIFIER_MODEL_ID (Bedrock IAM via the shared
|
|
310
|
-
# lambda_bedrock invoke policy).
|
|
385
|
+
# Observations → Knowledge Graph worker. Extraction is now a Bedrock
|
|
386
|
+
# structured-output call inside this Lambda. KG_EXTRACTION_MODEL_ID pins
|
|
387
|
+
# the gpt-oss extraction model (Bedrock IAM via the shared lambda_bedrock
|
|
388
|
+
# invoke policy, same as the promotion-gate classifier).
|
|
311
389
|
"knowledge-graph-observations-ingest" = {
|
|
312
|
-
COGNEE_ENDPOINT = var.cognee_endpoint
|
|
313
|
-
COGNEE_BACKEND_MODE = var.cognee_backend_mode
|
|
314
|
-
COGNEE_INGEST_MODE = "add_cognify"
|
|
315
390
|
BRAIN_ARTIFACTS_BUCKET = aws_s3_bucket.brain_artifacts.bucket
|
|
316
391
|
OBSERVATION_CLASSIFIER_MODEL_ID = var.observation_classifier_model_id
|
|
317
|
-
|
|
318
|
-
#
|
|
319
|
-
#
|
|
320
|
-
#
|
|
321
|
-
#
|
|
322
|
-
# Lambda ceiling, leaving room for graph fetch + normalize + snapshot.
|
|
392
|
+
KG_EXTRACTION_MODEL_ID = var.kg_extraction_model_id
|
|
393
|
+
# Per-run candidate cap bounds classifier + extraction cost; a
|
|
394
|
+
# truncated backlog drains via an in-process loop inside one
|
|
395
|
+
# invocation (never Lambda self-invoke — AWS recursive-loop
|
|
396
|
+
# detection terminates worker-to-self Event chains).
|
|
323
397
|
KG_OBS_MAX_CANDIDATES_PER_RUN = var.kg_obs_max_candidates_per_run
|
|
324
|
-
COGNEE_INDEX_TIMEOUT_MS = "700000"
|
|
325
|
-
COGNEE_INDEX_POLL_MS = "7000"
|
|
326
398
|
}
|
|
327
399
|
# routine-task-python (Phase B U6) needs the AgentCore code-interpreter
|
|
328
400
|
# id + the per-stage S3 routine-output bucket. The interpreter id is
|
|
@@ -335,6 +407,14 @@ locals {
|
|
|
335
407
|
ROUTINE_OUTPUT_BUCKET = "thinkwork-${var.stage}-routine-output"
|
|
336
408
|
ROUTINE_PYTHON_ENV_ALLOWLIST = "TENANT_ID,ROUTINE_ID,EXECUTION_ID"
|
|
337
409
|
}
|
|
410
|
+
# routine-exec-git (plan 2026-07-03-004 U3, KTD-10): configuration on
|
|
411
|
+
# the executor's own env, never new graphql-http env vars (4KB ceiling).
|
|
412
|
+
# The S3 SHA code cache rides the existing routine-output bucket under
|
|
413
|
+
# the routine-code-cache/ prefix.
|
|
414
|
+
"routine-exec-git" = {
|
|
415
|
+
SANDBOX_INTERPRETER_ID = var.agentcore_code_interpreter_id
|
|
416
|
+
ROUTINE_OUTPUT_BUCKET = "thinkwork-${var.stage}-routine-output"
|
|
417
|
+
}
|
|
338
418
|
# graphql-http hosts the createRoutine / publishRoutineVersion / etc.
|
|
339
419
|
# resolvers (Phase B U7) AND the routine-approval-bridge (Phase B
|
|
340
420
|
# U8) which invokes routine-resume via the AWS SDK.
|
|
@@ -349,8 +429,15 @@ locals {
|
|
|
349
429
|
# queue until U3; eval-worker is a throwing inert stub that redrives
|
|
350
430
|
# accidental traffic to the DLQ.
|
|
351
431
|
"eval-runner" = {
|
|
352
|
-
EVAL_FANOUT_QUEUE_URL
|
|
353
|
-
|
|
432
|
+
EVAL_FANOUT_QUEUE_URL = local.eval_fanout_queue_url
|
|
433
|
+
# 40 lanes to match the fan-out event source mapping's
|
|
434
|
+
# maximum_concurrency (eval-fanout.tf) — FIFO delivers at most one
|
|
435
|
+
# in-flight message per group, so lanes < concurrency wastes workers.
|
|
436
|
+
EVAL_DIRECT_AGENTCORE_MESSAGE_SHARDS = "40"
|
|
437
|
+
# Anthropic models run under a 10 RPM Bedrock quota in this account
|
|
438
|
+
# (quota increase PENDING) — pace their runs onto few lanes so they
|
|
439
|
+
# finish cleanly instead of throttling out. See evalLaneCountForModel.
|
|
440
|
+
EVAL_ANTHROPIC_MESSAGE_SHARDS = "2"
|
|
354
441
|
# SSM parameter name for the Pi Bedrock AgentCore Runtime ID. deploy.yml's
|
|
355
442
|
# runtime update job writes this in `update-agentcore-runtime-image.sh`;
|
|
356
443
|
# eval-runner reads it via `loadRuntimeId(runtimeType)`.
|
|
@@ -393,6 +480,14 @@ locals {
|
|
|
393
480
|
"compliance-outbox-drainer" = {
|
|
394
481
|
COMPLIANCE_DRAINER_SECRET_ARN = var.compliance_drainer_secret_arn
|
|
395
482
|
}
|
|
483
|
+
# THINK-189 U5: the conformance judge model pin lives on the sweeper
|
|
484
|
+
# ONLY (KTD7 — graphql-http's 4KB env ceiling is a known deploy
|
|
485
|
+
# blocker; the deterministic layer needs no configuration). The shared
|
|
486
|
+
# api_ai_statements grant already authorizes Converse with this
|
|
487
|
+
# inference-profile ID.
|
|
488
|
+
"document-conformance-judge" = {
|
|
489
|
+
CONFORMANCE_JUDGE_MODEL_ID = "us.anthropic.claude-haiku-4-5-20251001-v1:0"
|
|
490
|
+
}
|
|
396
491
|
}
|
|
397
492
|
}
|
|
398
493
|
|
|
@@ -466,6 +561,17 @@ resource "aws_lambda_function" "handler" {
|
|
|
466
561
|
# Bearer API_AUTH_SECRET. Idempotent on thread_turns.finalized_at
|
|
467
562
|
# (migration 0123). Plan: 2026-05-22-006.
|
|
468
563
|
"chat-agent-finalize",
|
|
564
|
+
# canvas-refresh — headless Living Artifacts data-refresh (THINK-145 U6).
|
|
565
|
+
# Invoked RequestResponse by the refreshCanvasData mutation (graphql-http)
|
|
566
|
+
# and by job-trigger's canvas_refresh branch (U7). Re-runs the saved
|
|
567
|
+
# tenant-scoped MCP tool call behind each bound widget and writes the fresh
|
|
568
|
+
# payload into the canvas head. Runs on the SHARED lambda role, which already
|
|
569
|
+
# grants secretsmanager:GetSecretValue on thinkwork/* (all tenants) and
|
|
570
|
+
# lambda:InvokeFunction — there is no per-Lambda role in this pool. Per-
|
|
571
|
+
# invocation TENANT scoping is enforced IN CODE: the artifact, its bindings,
|
|
572
|
+
# and the tenant_mcp_servers row are all filtered by the event's tenantId,
|
|
573
|
+
# and the only secret read is that server row's own auth_config.secretRef.
|
|
574
|
+
"canvas-refresh",
|
|
469
575
|
# chat-agent-activity — POST /api/threads/{threadId}/activity. The Pi
|
|
470
576
|
# runtime POSTs here mid-turn so live agent activity (tool/skill/phase
|
|
471
577
|
# steps, coalesced text deltas) streams to the Spaces thread via
|
|
@@ -490,6 +596,9 @@ resource "aws_lambda_function" "handler" {
|
|
|
490
596
|
"auth-me",
|
|
491
597
|
"public-auth-options",
|
|
492
598
|
"workos-auth",
|
|
599
|
+
# Public artifact share links (THINK-208): GET /share/{token}, token
|
|
600
|
+
# verified in handler code (no gateway auth, uniform 404 on any miss).
|
|
601
|
+
"artifact-share",
|
|
493
602
|
"extension-proxy",
|
|
494
603
|
"tenants",
|
|
495
604
|
"users",
|
|
@@ -510,11 +619,14 @@ resource "aws_lambda_function" "handler" {
|
|
|
510
619
|
"job-trigger",
|
|
511
620
|
"routine-task-weather-email",
|
|
512
621
|
"webhooks",
|
|
513
|
-
"n8n-agent-step-bridge",
|
|
514
|
-
"n8n-agent-step-expirer",
|
|
515
622
|
"webhooks-admin",
|
|
516
623
|
"webhook-deliveries-cleanup",
|
|
517
624
|
"skill-runs-reconciler",
|
|
625
|
+
# THINK-229 U5 — probes the analyst_reader connection (reachability, IAM
|
|
626
|
+
# auth, SELECT-grant introspection, schema drift; all read-only) every 30
|
|
627
|
+
# min and stamps the verdict onto runtime_metadata.analyst_probe so
|
|
628
|
+
# dispatch can withhold a failing/stale connection loudly.
|
|
629
|
+
"analyst-connection-reconciler",
|
|
518
630
|
"cron-stall-monitor",
|
|
519
631
|
"webhook-crm-opportunity",
|
|
520
632
|
"webhook-task-event",
|
|
@@ -536,8 +648,8 @@ resource "aws_lambda_function" "handler" {
|
|
|
536
648
|
"github-app",
|
|
537
649
|
"memory",
|
|
538
650
|
"memory-retain",
|
|
651
|
+
"brain-dream-state",
|
|
539
652
|
"wiki-compile",
|
|
540
|
-
"knowledge-graph-thread-ingest",
|
|
541
653
|
"knowledge-graph-observations-ingest",
|
|
542
654
|
"ontology-scan",
|
|
543
655
|
"ontology-reprocess",
|
|
@@ -559,6 +671,8 @@ resource "aws_lambda_function" "handler" {
|
|
|
559
671
|
# THNK-74 U3 — reconciles runtime-reported model usage against Bedrock
|
|
560
672
|
# model invocation logs and appends invocation-scope trace ledger facts.
|
|
561
673
|
"trace-invocation-reconciler",
|
|
674
|
+
# THINK-245 U10 — daily per-model drift check against Cost Explorer.
|
|
675
|
+
"cost-drift-check",
|
|
562
676
|
# AgentCore Code Sandbox narrow REST endpoints (plan Unit 10 + Unit 11).
|
|
563
677
|
# Both are service-endpoint shape: the runtime POSTs with
|
|
564
678
|
# Bearer API_AUTH_SECRET. No GraphQL resolver involvement, no extra IAM.
|
|
@@ -578,6 +692,13 @@ resource "aws_lambda_function" "handler" {
|
|
|
578
692
|
# (Start/Invoke/Stop CodeInterpreterSession) + S3 PutObject IAM —
|
|
579
693
|
# see main.tf.
|
|
580
694
|
"routine-task-python",
|
|
695
|
+
# routine-exec-git: deterministic git-backed routine executor (plan
|
|
696
|
+
# 2026-07-03-004 U3). SDK-invoked (job-trigger / dispatcher / manual
|
|
697
|
+
# async job). Pulls the tenant routine repo at branch HEAD,
|
|
698
|
+
# fixture-gates new SHAs, executes run(input) in the AgentCore code
|
|
699
|
+
# interpreter, and writes routine_executions rows directly. Shares the
|
|
700
|
+
# role-wide bedrock-agentcore + S3 + Secrets Manager grants.
|
|
701
|
+
"routine-exec-git",
|
|
581
702
|
# routine-resume: SDK-invoked by routine-approval-bridge (Phase B
|
|
582
703
|
# U8) after a HITL decision. Calls SendTaskSuccess/SendTaskFailure;
|
|
583
704
|
# idempotent on already-consumed tokens. Needs states:SendTaskSuccess
|
|
@@ -598,6 +719,22 @@ resource "aws_lambda_function" "handler" {
|
|
|
598
719
|
# for steps + on the conditional UPDATE for executions.
|
|
599
720
|
"routine-step-callback",
|
|
600
721
|
"routine-execution-callback",
|
|
722
|
+
# Workflow Interpreter Lambdas (THINK-219). One shared static state
|
|
723
|
+
# machine per stage (workflow-interpreter-stepfunctions module) drives
|
|
724
|
+
# these. workflow-step-dispatch serves EVERY interpreter ASL phase
|
|
725
|
+
# (load_next / dispatch_agent / await_approval / record_approval /
|
|
726
|
+
# record_advance) — the SFN execution role's lambda:InvokeFunction grant
|
|
727
|
+
# is scoped to this one function. workflow-execution-callback is the
|
|
728
|
+
# EventBridge SFN-state-change target that projects terminal status onto
|
|
729
|
+
# workflow_runs. workflow-resume is SDK-invoked by resolveWorkflowApproval
|
|
730
|
+
# (SendTaskSuccess/SendTaskFailure) — SendTask* is granted stage-wide in
|
|
731
|
+
# the RoutineTaskTokens statement (iam-grouped.tf), states:StartExecution
|
|
732
|
+
# on the interpreter machine is granted in api_orchestration. All three
|
|
733
|
+
# ship inert-throwing until U5/U6 wire them (plan KTD10 — a silent no-op
|
|
734
|
+
# would strand runs in queued).
|
|
735
|
+
"workflow-step-dispatch",
|
|
736
|
+
"workflow-execution-callback",
|
|
737
|
+
"workflow-resume",
|
|
601
738
|
# Skill-run dispatcher runtime-config fetch (plan
|
|
602
739
|
# docs/plans/2026-04-24-008-feat-skill-run-dispatcher-plan.md §U1). The
|
|
603
740
|
# runtime skill dispatch calls this with Bearer API_AUTH_SECRET to pull
|
|
@@ -607,6 +744,12 @@ resource "aws_lambda_function" "handler" {
|
|
|
607
744
|
# Admin-Ops MCP — JSON-RPC endpoint at POST /mcp/admin, exposes the
|
|
608
745
|
# @thinkwork/admin-ops package as MCP tools for managed agents.
|
|
609
746
|
"admin-ops-mcp",
|
|
747
|
+
# Analyst query broker — first-party MCP server at POST /mcp/analyst
|
|
748
|
+
# (THINK-228 U3). One tool, query: EXPLAIN-gated, extended-protocol
|
|
749
|
+
# single-statement SQL as the analyst_reader role; large results stage
|
|
750
|
+
# to S3 under analyst-staging/; every query emits a data.query_executed
|
|
751
|
+
# compliance audit event via POST /api/compliance/events.
|
|
752
|
+
"analyst-query-broker",
|
|
610
753
|
# MCP admin key management — per-tenant Bearer tokens for admin-ops.
|
|
611
754
|
# Admin-ops-mcp authenticates incoming tokens by sha256-hash lookup
|
|
612
755
|
# against tenant_mcp_admin_keys, populated by this handler's routes.
|
|
@@ -665,6 +808,11 @@ resource "aws_lambda_function" "handler" {
|
|
|
665
808
|
# U2). EventBridge rate(1 minute) schedule + DLQ + MaxRetryAttempts=0
|
|
666
809
|
# (defined in dedicated resources below).
|
|
667
810
|
"compliance-outbox-drainer",
|
|
811
|
+
# THINK-189 U5: conformance judge sweeper. Scheduled (rate 2 min) +
|
|
812
|
+
# reserved_concurrent_executions=1 (single-writer makes direct
|
|
813
|
+
# process-and-complete safe) + MaxRetryAttempts=0 — the sweeper's own
|
|
814
|
+
# next tick is the retry (dedicated resources below).
|
|
815
|
+
"document-conformance-judge",
|
|
668
816
|
# Phase 3 U6 of the Compliance audit-event log: runtime REST emit path.
|
|
669
817
|
# Cross-runtime emit endpoint POST /api/compliance/events — Bearer
|
|
670
818
|
# API_AUTH_SECRET, runtime clients post here with a
|
|
@@ -711,8 +859,8 @@ resource "aws_lambda_function" "handler" {
|
|
|
711
859
|
# validates the agent, builds the AgentCore invoke payload, dispatches
|
|
712
860
|
# Event-mode, and returns. Setup is ~5s in practice; 60s gives 12×
|
|
713
861
|
# headroom for transient slowness.
|
|
714
|
-
timeout = each.key == "wakeup-processor" ? 300 : each.key == "chat-agent-invoke" ? 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 == "wiki-compile" ? 480 : each.key == "knowledge-graph-
|
|
715
|
-
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 == "wiki-compile" ? 1024 : each.key == "knowledge-graph-
|
|
862
|
+
timeout = each.key == "wakeup-processor" ? 300 : each.key == "chat-agent-invoke" ? 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 == "wiki-compile" ? 480 : each.key == "knowledge-graph-observations-ingest" ? 480 : each.key == "requester-memory-dreaming" ? 300 : each.key == "ontology-scan" ? 300 : each.key == "ontology-reprocess" ? 300 : each.key == "wiki-lint" ? 300 : each.key == "wiki-export" ? 600 : each.key == "okf-materialize" ? 600 : each.key == "okf-efs-refresh" ? 600 : each.key == "wiki-bootstrap-import" ? 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 == "brain-dream-state" ? 900 : 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
|
|
863
|
+
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 == "wiki-compile" ? 1024 : each.key == "knowledge-graph-observations-ingest" ? 1024 : each.key == "requester-memory-dreaming" ? 512 : each.key == "ontology-scan" ? 512 : each.key == "wiki-export" ? 1024 : each.key == "okf-materialize" ? 1024 : each.key == "okf-efs-refresh" ? 1024 : each.key == "wiki-bootstrap-import" ? 1024 : each.key == "folder-bundle-import" ? 1024 : 256
|
|
716
864
|
|
|
717
865
|
filename = local.use_local_zips ? "${var.lambda_zips_dir}/${each.key}.zip" : null
|
|
718
866
|
source_code_hash = local.use_local_zips ? filebase64sha256("${var.lambda_zips_dir}/${each.key}.zip") : null
|
|
@@ -724,7 +872,20 @@ resource "aws_lambda_function" "handler" {
|
|
|
724
872
|
# concurrent drainers would race the chain head SELECT and produce
|
|
725
873
|
# orphan prev_hash links). All other handlers run with the default
|
|
726
874
|
# account-level concurrency pool.
|
|
727
|
-
|
|
875
|
+
# eval-worker's cap must be >= the fan-out event source mapping's
|
|
876
|
+
# maximum_concurrency (eval-fanout.tf) or UpdateEventSourceMapping
|
|
877
|
+
# rejects the apply.
|
|
878
|
+
# document-conformance-judge is also a single-writer: direct
|
|
879
|
+
# process-and-complete with no in-flight claim status depends on never
|
|
880
|
+
# having two sweepers race the same pending rows (THINK-189 KTD4).
|
|
881
|
+
# analyst-query-broker is capped low: each concurrent execution holds a
|
|
882
|
+
# dedicated analyst_reader Postgres connection and runs model-authored
|
|
883
|
+
# SQL — the cap bounds both connection pressure and the blast radius of
|
|
884
|
+
# a runaway delegation (THINK-228 U3).
|
|
885
|
+
# analyst-connection-reconciler is capped at 1: the probe holds one
|
|
886
|
+
# analyst_reader connection and overlapping probes are pointless (the
|
|
887
|
+
# cluster-global reader has one grant surface / one live schema).
|
|
888
|
+
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
|
|
728
889
|
|
|
729
890
|
environment {
|
|
730
891
|
variables = merge(
|
|
@@ -735,16 +896,11 @@ resource "aws_lambda_function" "handler" {
|
|
|
735
896
|
}
|
|
736
897
|
|
|
737
898
|
dynamic "vpc_config" {
|
|
738
|
-
for_each =
|
|
739
|
-
(
|
|
740
|
-
contains(["knowledge-graph-thread-ingest", "knowledge-graph-observations-ingest"], each.key) ||
|
|
741
|
-
(each.key == "graphql-http" && var.memory_engine == "cognee")
|
|
742
|
-
) && local.cognee_worker_vpc_enabled
|
|
743
|
-
) ? [1] : each.key == "okf-efs-refresh" && local.okf_efs_vpc_enabled ? [1] : []
|
|
899
|
+
for_each = each.key == "okf-efs-refresh" && local.okf_efs_vpc_enabled ? [1] : []
|
|
744
900
|
|
|
745
901
|
content {
|
|
746
|
-
subnet_ids =
|
|
747
|
-
security_group_ids =
|
|
902
|
+
subnet_ids = var.okf_efs_subnet_ids
|
|
903
|
+
security_group_ids = var.okf_efs_security_group_ids
|
|
748
904
|
}
|
|
749
905
|
}
|
|
750
906
|
|
|
@@ -993,6 +1149,41 @@ resource "aws_scheduler_schedule" "compliance_outbox_drainer" {
|
|
|
993
1149
|
}
|
|
994
1150
|
}
|
|
995
1151
|
|
|
1152
|
+
# ---------------------------------------------------------------------------
|
|
1153
|
+
# THINK-189 U5: document-conformance-judge schedule + retry config
|
|
1154
|
+
#
|
|
1155
|
+
# The sweeper claims judge_status='pending' conformance reports and scores
|
|
1156
|
+
# each with one Bedrock Converse call. MaxRetryAttempts=0: rows stay
|
|
1157
|
+
# pending on a crash and the next tick re-claims them — Lambda-level async
|
|
1158
|
+
# retries would just race the schedule. Reserved concurrency 1 (set above)
|
|
1159
|
+
# is the single-writer guarantee for direct process-and-complete.
|
|
1160
|
+
# ---------------------------------------------------------------------------
|
|
1161
|
+
|
|
1162
|
+
resource "aws_lambda_function_event_invoke_config" "document_conformance_judge" {
|
|
1163
|
+
count = local.deploy_lambda_handlers ? 1 : 0
|
|
1164
|
+
function_name = aws_lambda_function.handler["document-conformance-judge"].function_name
|
|
1165
|
+
maximum_retry_attempts = 0
|
|
1166
|
+
maximum_event_age_in_seconds = 3600
|
|
1167
|
+
}
|
|
1168
|
+
|
|
1169
|
+
resource "aws_scheduler_schedule" "document_conformance_judge" {
|
|
1170
|
+
count = local.deploy_lambda_handlers ? 1 : 0
|
|
1171
|
+
|
|
1172
|
+
name = "thinkwork-${var.stage}-document-conformance-judge"
|
|
1173
|
+
group_name = "default"
|
|
1174
|
+
schedule_expression = "rate(2 minutes)"
|
|
1175
|
+
state = "ENABLED"
|
|
1176
|
+
|
|
1177
|
+
flexible_time_window {
|
|
1178
|
+
mode = "OFF"
|
|
1179
|
+
}
|
|
1180
|
+
|
|
1181
|
+
target {
|
|
1182
|
+
arn = aws_lambda_function.handler["document-conformance-judge"].arn
|
|
1183
|
+
role_arn = aws_iam_role.scheduler.arn
|
|
1184
|
+
}
|
|
1185
|
+
}
|
|
1186
|
+
|
|
996
1187
|
# ---------------------------------------------------------------------------
|
|
997
1188
|
# API Gateway routes → Lambda integrations
|
|
998
1189
|
# ---------------------------------------------------------------------------
|
|
@@ -1197,10 +1388,11 @@ locals {
|
|
|
1197
1388
|
# Webhooks (public trigger) — legacy PRD-19 tokenized webhooks.
|
|
1198
1389
|
"POST /webhooks/{proxy+}" = "webhooks"
|
|
1199
1390
|
|
|
1200
|
-
#
|
|
1201
|
-
#
|
|
1202
|
-
|
|
1203
|
-
|
|
1391
|
+
# Public artifact share links (THINK-208). Unauthenticated by design:
|
|
1392
|
+
# the HMAC-signed token is the access grant, verified in handler code;
|
|
1393
|
+
# every miss returns a uniform 404. GET-only — the page is a top-level
|
|
1394
|
+
# navigation, so no OPTIONS/preflight fires (KTD-9).
|
|
1395
|
+
"GET /share/{token}" = "artifact-share"
|
|
1204
1396
|
|
|
1205
1397
|
# Webhooks admin
|
|
1206
1398
|
"ANY /api/webhooks/{proxy+}" = "webhooks-admin"
|
|
@@ -1299,6 +1491,20 @@ locals {
|
|
|
1299
1491
|
# retained as a break-glass superuser path for bootstrap/debug.
|
|
1300
1492
|
"POST /mcp/admin" = "admin-ops-mcp"
|
|
1301
1493
|
|
|
1494
|
+
# Analyst query broker — first-party MCP server exposing query
|
|
1495
|
+
# (THINK-228 U3). Callers present the tenant-wide broker service
|
|
1496
|
+
# credential as Bearer; SQL executes as the hardened analyst_reader
|
|
1497
|
+
# role. The seeded postgres-dev connector row points at this route.
|
|
1498
|
+
"POST /mcp/analyst" = "analyst-query-broker"
|
|
1499
|
+
|
|
1500
|
+
# Sourced analyst broker route (THINK-239) — the same handler serves a
|
|
1501
|
+
# registered EXTERNAL Postgres source at /mcp/analyst/<slug>. The broker
|
|
1502
|
+
# requires a signed caller context whose sourceClaims.slug matches the
|
|
1503
|
+
# path (the legacy bearer is never accepted here) and connects using the
|
|
1504
|
+
# per-source reader credential (thinkwork/<stage>/analyst/*, covered by
|
|
1505
|
+
# the shared secretsmanager:GetSecretValue on thinkwork/*).
|
|
1506
|
+
"POST /mcp/analyst/{sourceSlug}" = "analyst-query-broker"
|
|
1507
|
+
|
|
1302
1508
|
# MCP admin key management — per-tenant Bearer token CRUD. Tokens
|
|
1303
1509
|
# are shown ONCE at creation (POST returns raw value); server stores
|
|
1304
1510
|
# sha256 hash only. These specific routes take precedence over the
|
|
@@ -1448,15 +1654,15 @@ resource "aws_scheduler_schedule" "wakeup_processor" {
|
|
|
1448
1654
|
}
|
|
1449
1655
|
|
|
1450
1656
|
# ---------------------------------------------------------------------------
|
|
1451
|
-
#
|
|
1657
|
+
# webhook_deliveries retention cron — daily delete of rows older than 90 days
|
|
1452
1658
|
# ---------------------------------------------------------------------------
|
|
1453
1659
|
|
|
1454
|
-
resource "aws_scheduler_schedule" "
|
|
1660
|
+
resource "aws_scheduler_schedule" "webhook_deliveries_cleanup" {
|
|
1455
1661
|
count = local.deploy_lambda_handlers ? 1 : 0
|
|
1456
1662
|
|
|
1457
|
-
name = "thinkwork-${var.stage}-
|
|
1663
|
+
name = "thinkwork-${var.stage}-webhook-deliveries-cleanup"
|
|
1458
1664
|
group_name = "default"
|
|
1459
|
-
schedule_expression = "
|
|
1665
|
+
schedule_expression = "cron(0 4 * * ? *)" # daily at 04:00 UTC
|
|
1460
1666
|
state = "ENABLED"
|
|
1461
1667
|
|
|
1462
1668
|
flexible_time_window {
|
|
@@ -1464,37 +1670,51 @@ resource "aws_scheduler_schedule" "n8n_agent_step_expirer" {
|
|
|
1464
1670
|
}
|
|
1465
1671
|
|
|
1466
1672
|
target {
|
|
1467
|
-
arn = aws_lambda_function.handler["
|
|
1673
|
+
arn = aws_lambda_function.handler["webhook-deliveries-cleanup"].arn
|
|
1468
1674
|
role_arn = aws_iam_role.scheduler.arn
|
|
1469
1675
|
}
|
|
1470
1676
|
}
|
|
1471
1677
|
|
|
1472
1678
|
# ---------------------------------------------------------------------------
|
|
1473
|
-
#
|
|
1679
|
+
# Requester memory dreaming — broad per-user memory compaction/reflection sweep
|
|
1474
1680
|
# ---------------------------------------------------------------------------
|
|
1475
1681
|
|
|
1476
|
-
|
|
1682
|
+
# ---------------------------------------------------------------------------
|
|
1683
|
+
# Brain dream state — per-bank Hindsight consolidation with audit ledger
|
|
1684
|
+
# (THINK-133 U4). Retries are the ledger's job (staged plan -> atomic apply
|
|
1685
|
+
# -> applied markers; unfinished runs resume on the next tick), so Lambda
|
|
1686
|
+
# async retries stay at 0, mirroring memory-retain.
|
|
1687
|
+
# ---------------------------------------------------------------------------
|
|
1688
|
+
|
|
1689
|
+
resource "aws_lambda_function_event_invoke_config" "brain_dream_state" {
|
|
1690
|
+
count = local.deploy_lambda_handlers ? 1 : 0
|
|
1691
|
+
function_name = aws_lambda_function.handler["brain-dream-state"].function_name
|
|
1692
|
+
maximum_retry_attempts = 0
|
|
1693
|
+
maximum_event_age_in_seconds = 3600
|
|
1694
|
+
}
|
|
1695
|
+
|
|
1696
|
+
resource "aws_scheduler_schedule" "brain_dream_state" {
|
|
1477
1697
|
count = local.deploy_lambda_handlers ? 1 : 0
|
|
1478
1698
|
|
|
1479
|
-
name = "thinkwork-${var.stage}-
|
|
1699
|
+
name = "thinkwork-${var.stage}-brain-dream-state"
|
|
1480
1700
|
group_name = "default"
|
|
1481
|
-
schedule_expression =
|
|
1482
|
-
state = "ENABLED"
|
|
1701
|
+
schedule_expression = var.brain_dream_state_schedule_expression
|
|
1702
|
+
state = var.brain_dream_state_enabled ? "ENABLED" : "DISABLED"
|
|
1483
1703
|
|
|
1484
1704
|
flexible_time_window {
|
|
1485
1705
|
mode = "OFF"
|
|
1486
1706
|
}
|
|
1487
1707
|
|
|
1488
1708
|
target {
|
|
1489
|
-
arn = aws_lambda_function.handler["
|
|
1709
|
+
arn = aws_lambda_function.handler["brain-dream-state"].arn
|
|
1490
1710
|
role_arn = aws_iam_role.scheduler.arn
|
|
1711
|
+
|
|
1712
|
+
retry_policy {
|
|
1713
|
+
maximum_retry_attempts = 0
|
|
1714
|
+
}
|
|
1491
1715
|
}
|
|
1492
1716
|
}
|
|
1493
1717
|
|
|
1494
|
-
# ---------------------------------------------------------------------------
|
|
1495
|
-
# Requester memory dreaming — broad per-user memory compaction/reflection sweep
|
|
1496
|
-
# ---------------------------------------------------------------------------
|
|
1497
|
-
|
|
1498
1718
|
resource "aws_scheduler_schedule" "requester_memory_dreaming" {
|
|
1499
1719
|
count = local.deploy_lambda_handlers ? 1 : 0
|
|
1500
1720
|
|
|
@@ -1564,6 +1784,64 @@ resource "aws_scheduler_schedule" "skill_runs_reconciler" {
|
|
|
1564
1784
|
}
|
|
1565
1785
|
}
|
|
1566
1786
|
|
|
1787
|
+
# ---------------------------------------------------------------------------
|
|
1788
|
+
# analyst_connection_reconciler — probes the analyst_reader connection every
|
|
1789
|
+
# 30 min (reachability, IAM auth, SELECT-grant introspection, zero-write
|
|
1790
|
+
# assertion, schema-drift hash; all read-only) and stamps the verdict onto
|
|
1791
|
+
# tenant_mcp_servers.runtime_metadata.analyst_probe. Dispatch withholds a
|
|
1792
|
+
# failing/stale connection loudly (THINK-229 U5, R7/R8, KTD8).
|
|
1793
|
+
#
|
|
1794
|
+
# retry-0 + DLQ (project_async_retry_idempotency_lessons): the probe is
|
|
1795
|
+
# cheap and idempotent — the next 30-minute tick IS the retry, so stacking
|
|
1796
|
+
# scheduler retries only adds redundant connections. A failure lands in the
|
|
1797
|
+
# DLQ for operator visibility instead.
|
|
1798
|
+
# ---------------------------------------------------------------------------
|
|
1799
|
+
|
|
1800
|
+
resource "aws_sqs_queue" "analyst_connection_reconciler_dlq" {
|
|
1801
|
+
count = local.deploy_lambda_handlers ? 1 : 0
|
|
1802
|
+
name = "thinkwork-${var.stage}-analyst-connection-reconciler-dlq"
|
|
1803
|
+
message_retention_seconds = 1209600 # 14 days
|
|
1804
|
+
|
|
1805
|
+
tags = {
|
|
1806
|
+
Name = "thinkwork-${var.stage}-analyst-connection-reconciler-dlq"
|
|
1807
|
+
}
|
|
1808
|
+
}
|
|
1809
|
+
|
|
1810
|
+
resource "aws_lambda_function_event_invoke_config" "analyst_connection_reconciler" {
|
|
1811
|
+
count = local.deploy_lambda_handlers ? 1 : 0
|
|
1812
|
+
function_name = aws_lambda_function.handler["analyst-connection-reconciler"].function_name
|
|
1813
|
+
maximum_retry_attempts = 0
|
|
1814
|
+
maximum_event_age_in_seconds = 3600
|
|
1815
|
+
|
|
1816
|
+
destination_config {
|
|
1817
|
+
on_failure {
|
|
1818
|
+
destination = aws_sqs_queue.analyst_connection_reconciler_dlq[0].arn
|
|
1819
|
+
}
|
|
1820
|
+
}
|
|
1821
|
+
}
|
|
1822
|
+
|
|
1823
|
+
resource "aws_scheduler_schedule" "analyst_connection_reconciler" {
|
|
1824
|
+
count = local.deploy_lambda_handlers ? 1 : 0
|
|
1825
|
+
|
|
1826
|
+
name = "thinkwork-${var.stage}-analyst-connection-reconciler"
|
|
1827
|
+
group_name = "default"
|
|
1828
|
+
schedule_expression = "rate(30 minutes)"
|
|
1829
|
+
state = "ENABLED"
|
|
1830
|
+
|
|
1831
|
+
flexible_time_window {
|
|
1832
|
+
mode = "OFF"
|
|
1833
|
+
}
|
|
1834
|
+
|
|
1835
|
+
target {
|
|
1836
|
+
arn = aws_lambda_function.handler["analyst-connection-reconciler"].arn
|
|
1837
|
+
role_arn = aws_iam_role.scheduler.arn
|
|
1838
|
+
|
|
1839
|
+
retry_policy {
|
|
1840
|
+
maximum_retry_attempts = 0
|
|
1841
|
+
}
|
|
1842
|
+
}
|
|
1843
|
+
}
|
|
1844
|
+
|
|
1567
1845
|
# ---------------------------------------------------------------------------
|
|
1568
1846
|
# eval_runs reconciler — finalizes stuck-running eval runs every 5 min.
|
|
1569
1847
|
# Guards against worker crashes/timeouts that occur before a per-case result
|
|
@@ -1782,6 +2060,121 @@ resource "aws_scheduler_schedule" "cost_bill_reconciler" {
|
|
|
1782
2060
|
}
|
|
1783
2061
|
}
|
|
1784
2062
|
|
|
2063
|
+
# ---------------------------------------------------------------------------
|
|
2064
|
+
# cost_drift_check — THINK-245 U10/R9. Daily comparison of recorded per-model
|
|
2065
|
+
# LLM spend against Cost Explorer (day D-2; CE lags ~24h and refreshes by
|
|
2066
|
+
# early UTC afternoon). Emits CostDriftPercent / CostDriftCheckFailed EMF
|
|
2067
|
+
# metrics; the alarms below page the cost-alerts SNS topic. Drift discovered
|
|
2068
|
+
# by a customer instead of an alarm is the incident this exists to prevent.
|
|
2069
|
+
# ---------------------------------------------------------------------------
|
|
2070
|
+
|
|
2071
|
+
resource "aws_scheduler_schedule" "cost_drift_check" {
|
|
2072
|
+
count = local.deploy_lambda_handlers ? 1 : 0
|
|
2073
|
+
|
|
2074
|
+
name = "thinkwork-${var.stage}-cost-drift-check"
|
|
2075
|
+
group_name = "default"
|
|
2076
|
+
schedule_expression = "cron(0 14 * * ? *)"
|
|
2077
|
+
state = "ENABLED"
|
|
2078
|
+
|
|
2079
|
+
flexible_time_window {
|
|
2080
|
+
mode = "OFF"
|
|
2081
|
+
}
|
|
2082
|
+
|
|
2083
|
+
target {
|
|
2084
|
+
arn = aws_lambda_function.handler["cost-drift-check"].arn
|
|
2085
|
+
role_arn = aws_iam_role.scheduler.arn
|
|
2086
|
+
}
|
|
2087
|
+
}
|
|
2088
|
+
|
|
2089
|
+
# THINK-245 U10 — cost alerting channel. First notification-wired alarms in
|
|
2090
|
+
# the stack; endpoints come from var.cost_alert_emails (sensitive).
|
|
2091
|
+
resource "aws_sns_topic" "cost_alerts" {
|
|
2092
|
+
count = local.deploy_lambda_handlers ? 1 : 0
|
|
2093
|
+
name = "thinkwork-${var.stage}-cost-alerts"
|
|
2094
|
+
}
|
|
2095
|
+
|
|
2096
|
+
resource "aws_sns_topic_subscription" "cost_alert_emails" {
|
|
2097
|
+
for_each = local.deploy_lambda_handlers ? toset(nonsensitive(var.cost_alert_emails)) : toset([])
|
|
2098
|
+
|
|
2099
|
+
topic_arn = aws_sns_topic.cost_alerts[0].arn
|
|
2100
|
+
protocol = "email"
|
|
2101
|
+
endpoint = each.value
|
|
2102
|
+
}
|
|
2103
|
+
|
|
2104
|
+
# Drift > 1% for the daily datapoint, or the drift check stopped emitting
|
|
2105
|
+
# entirely (treat_missing_data = breaching — a silent checker is itself the
|
|
2106
|
+
# failure mode; see the Jun 25–Jul 9 reconciler incident).
|
|
2107
|
+
resource "aws_cloudwatch_metric_alarm" "cost_drift" {
|
|
2108
|
+
count = local.deploy_lambda_handlers ? 1 : 0
|
|
2109
|
+
|
|
2110
|
+
alarm_name = "thinkwork-${var.stage}-cost-drift"
|
|
2111
|
+
alarm_description = "Recorded per-model LLM spend diverges >1% from Cost Explorer (THINK-245 R9/AE5), or the drift check stopped emitting."
|
|
2112
|
+
namespace = "Thinkwork/Costs"
|
|
2113
|
+
metric_name = "CostDriftPercent"
|
|
2114
|
+
statistic = "Maximum"
|
|
2115
|
+
period = 86400
|
|
2116
|
+
evaluation_periods = 1
|
|
2117
|
+
threshold = 1
|
|
2118
|
+
comparison_operator = "GreaterThanThreshold"
|
|
2119
|
+
treat_missing_data = "breaching"
|
|
2120
|
+
alarm_actions = [aws_sns_topic.cost_alerts[0].arn]
|
|
2121
|
+
ok_actions = [aws_sns_topic.cost_alerts[0].arn]
|
|
2122
|
+
|
|
2123
|
+
dimensions = {
|
|
2124
|
+
Stage = var.stage
|
|
2125
|
+
}
|
|
2126
|
+
}
|
|
2127
|
+
|
|
2128
|
+
# Reconciler health (THINK-245 R8/AE4): sustained matched==0 while
|
|
2129
|
+
# unreconciled work exists, or the reconciler stopped emitting metrics at
|
|
2130
|
+
# all. Metric math because the condition spans two metrics.
|
|
2131
|
+
resource "aws_cloudwatch_metric_alarm" "cost_reconciler_stalled" {
|
|
2132
|
+
count = local.deploy_lambda_handlers ? 1 : 0
|
|
2133
|
+
|
|
2134
|
+
alarm_name = "thinkwork-${var.stage}-cost-reconciler-stalled"
|
|
2135
|
+
alarm_description = "trace-invocation-reconciler matched 0 turns across an hour while unreconciled turns exist, or stopped emitting (THINK-245 R8/AE4 — this exact condition ran silently Jun 25–Jul 9)."
|
|
2136
|
+
evaluation_periods = 12
|
|
2137
|
+
datapoints_to_alarm = 12
|
|
2138
|
+
threshold = 1
|
|
2139
|
+
comparison_operator = "GreaterThanOrEqualToThreshold"
|
|
2140
|
+
treat_missing_data = "breaching"
|
|
2141
|
+
alarm_actions = [aws_sns_topic.cost_alerts[0].arn]
|
|
2142
|
+
ok_actions = [aws_sns_topic.cost_alerts[0].arn]
|
|
2143
|
+
|
|
2144
|
+
metric_query {
|
|
2145
|
+
id = "stalled"
|
|
2146
|
+
expression = "IF(matched == 0 AND unreconciled > 0, 1, 0)"
|
|
2147
|
+
label = "reconciler stalled"
|
|
2148
|
+
return_data = true
|
|
2149
|
+
}
|
|
2150
|
+
|
|
2151
|
+
metric_query {
|
|
2152
|
+
id = "matched"
|
|
2153
|
+
metric {
|
|
2154
|
+
namespace = "Thinkwork/Costs"
|
|
2155
|
+
metric_name = "ReconcilerMatched"
|
|
2156
|
+
period = 300
|
|
2157
|
+
stat = "Sum"
|
|
2158
|
+
dimensions = {
|
|
2159
|
+
Stage = var.stage
|
|
2160
|
+
}
|
|
2161
|
+
}
|
|
2162
|
+
}
|
|
2163
|
+
|
|
2164
|
+
metric_query {
|
|
2165
|
+
id = "unreconciled"
|
|
2166
|
+
metric {
|
|
2167
|
+
namespace = "Thinkwork/Costs"
|
|
2168
|
+
metric_name = "ReconcilerUnreconciled"
|
|
2169
|
+
period = 300
|
|
2170
|
+
stat = "Sum"
|
|
2171
|
+
dimensions = {
|
|
2172
|
+
Stage = var.stage
|
|
2173
|
+
}
|
|
2174
|
+
}
|
|
2175
|
+
}
|
|
2176
|
+
}
|
|
2177
|
+
|
|
1785
2178
|
# ---------------------------------------------------------------------------
|
|
1786
2179
|
# Stall monitor — marks stalled thread turns and runbook steps failed every
|
|
1787
2180
|
# minute. This is the global backstop for agent/runtime crashes; the Computer
|
|
@@ -1839,7 +2232,10 @@ resource "aws_scheduler_schedule" "knowledge_graph_observations_ingest" {
|
|
|
1839
2232
|
name = "thinkwork-${var.stage}-knowledge-graph-observations-ingest"
|
|
1840
2233
|
group_name = "default"
|
|
1841
2234
|
schedule_expression = "rate(30 minutes)"
|
|
1842
|
-
|
|
2235
|
+
# Ships DISABLED (plan 2026-07-03-005 U4/KTD-6): the schedule enables on dev
|
|
2236
|
+
# only after a manual golden-set-validated run. Driven by the GHA
|
|
2237
|
+
# WIKI_KG_INGEST_ENABLED var.
|
|
2238
|
+
state = var.knowledge_graph_observations_ingest_enabled ? "ENABLED" : "DISABLED"
|
|
1843
2239
|
|
|
1844
2240
|
flexible_time_window {
|
|
1845
2241
|
mode = "OFF"
|
|
@@ -1849,6 +2245,14 @@ resource "aws_scheduler_schedule" "knowledge_graph_observations_ingest" {
|
|
|
1849
2245
|
arn = aws_lambda_function.handler["knowledge-graph-observations-ingest"].arn
|
|
1850
2246
|
role_arn = aws_iam_role.scheduler.arn
|
|
1851
2247
|
input = jsonencode({ sweep = true, trigger = "scheduled" })
|
|
2248
|
+
|
|
2249
|
+
# Periodic idempotent worker: the next 30-minute tick IS the retry.
|
|
2250
|
+
# Scheduler-level retries stack extra invocations onto a cadence that
|
|
2251
|
+
# already self-corrects (cursor-guarded), compounding the invocation
|
|
2252
|
+
# volume that helped trip Lambda recursive-loop detection.
|
|
2253
|
+
retry_policy {
|
|
2254
|
+
maximum_retry_attempts = 0
|
|
2255
|
+
}
|
|
1852
2256
|
}
|
|
1853
2257
|
}
|
|
1854
2258
|
|
|
@@ -1922,7 +2326,7 @@ resource "aws_s3_bucket_lifecycle_configuration" "wiki_exports" {
|
|
|
1922
2326
|
}
|
|
1923
2327
|
}
|
|
1924
2328
|
|
|
1925
|
-
# Canonical
|
|
2329
|
+
# Canonical ThinkWork Brain artifact store. Unlike wiki_exports, this bucket
|
|
1926
2330
|
# is the durable replay/projection substrate for Brain source artifacts,
|
|
1927
2331
|
# ingestion manifests, migration snapshots, vault projections, and exports.
|
|
1928
2332
|
resource "aws_s3_bucket" "brain_artifacts" {
|
|
@@ -1931,7 +2335,7 @@ resource "aws_s3_bucket" "brain_artifacts" {
|
|
|
1931
2335
|
|
|
1932
2336
|
tags = {
|
|
1933
2337
|
Name = "thinkwork-${var.stage}-brain-artifacts"
|
|
1934
|
-
Purpose = "
|
|
2338
|
+
Purpose = "brain-artifacts"
|
|
1935
2339
|
}
|
|
1936
2340
|
}
|
|
1937
2341
|
|