thinkwork-cli 0.12.16 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (149) hide show
  1. package/dist/cli.js +517 -10403
  2. package/dist/commands/enterprise/templates/deploy-repo/docs/runbook.md +3 -8
  3. package/dist/commands/enterprise/templates/deploy-repo/terraform/main.tf +1 -184
  4. package/dist/drizzle/0050_brain_v0_entity_subtype.sql +2 -2
  5. package/dist/drizzle/0051_brain_v0_tenant_entity_pages.sql +6 -6
  6. package/dist/drizzle/0052_brain_v0_external_refs.sql +2 -2
  7. package/dist/drizzle/0053_brain_v0_unresolved_mentions_subtype.sql +2 -2
  8. package/dist/drizzle/0145_knowledge_graph_thread_ingest.sql +14 -14
  9. package/dist/drizzle/0146_knowledge_graph_source_scope.sql +1 -1
  10. package/dist/drizzle/0157_knowledge_graph_observations_source.sql +2 -2
  11. package/dist/drizzle/0158_wiki_tenant_scope.sql +1 -1
  12. package/dist/drizzle/0165_plugin_premium_entitlements.sql +2 -2
  13. package/dist/drizzle/{0166_company_brain_substrate_contract.sql → 0166_brain_substrate_contract.sql} +9 -9
  14. package/dist/drizzle/{0167_company_brain_artifact_manifest_runtime.sql → 0167_brain_artifact_manifest_runtime.sql} +5 -5
  15. package/dist/drizzle/0168_eval_skill_gate.sql +1 -1
  16. package/dist/drizzle/0183_okf_artifact_manifests.sql +1 -1
  17. package/dist/drizzle/0200_eval_results_execution_tier.sql +40 -0
  18. package/dist/drizzle/0201_brain_dream_runs.sql +72 -0
  19. package/dist/drizzle/0202_backfill_thread_participants_from_senders.sql +110 -0
  20. package/dist/drizzle/0203_threads_mode_override.sql +61 -0
  21. package/dist/drizzle/0204_thread_turns_triggering_message_id.sql +48 -0
  22. package/dist/drizzle/0205_routines_git_python.sql +185 -0
  23. package/dist/drizzle/0206_agent_loop_versions_routine_actions.sql +40 -0
  24. package/dist/drizzle/0207_tenant_credentials_github_repo_kind.sql +52 -0
  25. package/dist/drizzle/0208_knowledge_graph_neutral_identifiers.sql +253 -0
  26. package/dist/drizzle/0209_living_artifacts_schema.sql +109 -0
  27. package/dist/drizzle/0210_think137_automations_additive_schema.sql +113 -0
  28. package/dist/drizzle/0211_backfill_agent_loop_versions_target_spec.sql +120 -0
  29. package/dist/drizzle/0212_fold_webhooks_into_automations.sql +312 -0
  30. package/dist/drizzle/0213_agent_loop_versions_judge_evidence_nullable.sql +63 -0
  31. package/dist/drizzle/0214_think137_drop_judge_evidence_roi.sql +99 -0
  32. package/dist/drizzle/0215_agent_loop_versions_goal_worker_policy_nullable.sql +70 -0
  33. package/dist/drizzle/0216_drop_agent_loop_versions_goal_worker_policy.sql +81 -0
  34. package/dist/drizzle/0217_agents_capability_folder_dispatch.sql +12 -0
  35. package/dist/drizzle/0218_document_plates.sql +30 -0
  36. package/dist/drizzle/0219_document_section_waivers.sql +29 -0
  37. package/dist/drizzle/0220_artifacts_created_by_user.sql +21 -0
  38. package/dist/drizzle/0221_artifact_shares.sql +29 -0
  39. package/dist/drizzle/0221_workflow_interpreter_thin_slice.sql +71 -0
  40. package/dist/drizzle/0222_compliance_drainer_select_audit_events.sql +21 -0
  41. package/dist/drizzle/0223_document_conformance_reports.sql +38 -0
  42. package/dist/drizzle/0224_artifact_refresh_state.sql +11 -0
  43. package/dist/drizzle/0225_think216_agent_loop_convergence.sql +21 -0
  44. package/dist/drizzle/0226_drop_n8n_agent_step_runs.sql +6 -0
  45. package/dist/drizzle/0227_analyst_reader_role.sql +1055 -0
  46. package/dist/drizzle/0228_tenant_credentials_rds_iam_kind.sql +62 -0
  47. package/dist/drizzle/0229_analyst_reader_rds_iam_grant.sql +79 -0
  48. package/dist/drizzle/0230_analyst_rls.sql +1613 -0
  49. package/dist/drizzle/0231_cost_events_cache_write_enforcement_exempt.sql +11 -0
  50. package/dist/plugins/catalog/package.json +0 -1
  51. package/dist/plugins/catalog/src/__tests__/build-catalog.test.ts +0 -1
  52. package/dist/plugins/catalog/src/__tests__/catalog.test.ts +16 -8
  53. package/dist/plugins/catalog/src/__tests__/contracts.test.ts +56 -0
  54. package/dist/plugins/catalog/src/__tests__/plugin-package.test.ts +0 -2
  55. package/dist/plugins/catalog/src/__tests__/plugin-registry.test.ts +0 -5
  56. package/dist/plugins/catalog/src/contracts.ts +112 -0
  57. package/dist/plugins/catalog/src/registry/generated-first-party.ts +0 -6
  58. package/dist/plugins/n8n/README.md +4 -36
  59. package/dist/plugins/n8n/src/deployment/managed-app.ts +0 -17
  60. package/dist/plugins/n8n/src/manifest.ts +0 -5
  61. package/dist/plugins/n8n/terraform/n8n/main.tf +0 -26
  62. package/dist/plugins/n8n/terraform/n8n/outputs.tf +0 -5
  63. package/dist/plugins/n8n/terraform/n8n/variables.tf +0 -6
  64. package/dist/plugins/n8n/test/manifest.test.ts +0 -1
  65. package/dist/plugins/twenty/package.json +5 -0
  66. package/dist/plugins/twenty/scripts/lib/__tests__/load-records.test.ts +232 -0
  67. package/dist/plugins/twenty/scripts/lib/__tests__/mappers.test.ts +489 -0
  68. package/dist/plugins/twenty/scripts/lib/__tests__/members-ensure.test.ts +199 -0
  69. package/dist/plugins/twenty/scripts/lib/__tests__/provision-members-db.test.ts +43 -0
  70. package/dist/plugins/twenty/scripts/lib/__tests__/schema-ensure.test.ts +230 -0
  71. package/dist/plugins/twenty/scripts/lib/__tests__/twenty-client.test.ts +207 -0
  72. package/dist/plugins/twenty/scripts/lib/lastmile-reader.ts +282 -0
  73. package/dist/plugins/twenty/scripts/lib/load-attachments.ts +220 -0
  74. package/dist/plugins/twenty/scripts/lib/load-records.ts +680 -0
  75. package/dist/plugins/twenty/scripts/lib/mappers.ts +559 -0
  76. package/dist/plugins/twenty/scripts/lib/members-ensure.ts +381 -0
  77. package/dist/plugins/twenty/scripts/lib/provision-members-db.ts +191 -0
  78. package/dist/plugins/twenty/scripts/lib/schema-ensure.ts +425 -0
  79. package/dist/plugins/twenty/scripts/lib/twenty-client.ts +246 -0
  80. package/dist/plugins/twenty/scripts/migrate-lastmile.ts +610 -0
  81. package/dist/plugins/twenty/scripts/provision-twenty-members.ts +214 -0
  82. package/dist/plugins/twenty/src/manifest.ts +99 -0
  83. package/dist/plugins/twenty/terraform/twenty/README.md +1 -1
  84. package/dist/plugins/twenty/test/manifest.test.ts +12 -2
  85. package/dist/terraform/examples/greenfield/main.tf +90 -380
  86. package/dist/terraform/examples/greenfield/terraform.tfvars.example +0 -1
  87. package/dist/terraform/modules/app/agentcore-pi/README.md +1 -3
  88. package/dist/terraform/modules/app/agentcore-pi/main.tf +29 -38
  89. package/dist/terraform/modules/app/agentcore-pi/variables.tf +23 -15
  90. package/dist/terraform/modules/app/agentcore-runtime/main.tf +3 -3
  91. package/dist/terraform/modules/app/customer-domain/main.tf +16 -2
  92. package/dist/terraform/modules/app/deployment-control-plane/main.tf +5 -0
  93. package/dist/terraform/modules/app/deployment-control-plane/runner.py +85 -207
  94. package/dist/terraform/modules/app/deployment-control-plane/test_runner_bundle.py +56 -2
  95. package/dist/terraform/modules/app/hindsight-memory/main.tf +52 -4
  96. package/dist/terraform/modules/app/lambda-api/eval-fanout.tf +7 -0
  97. package/dist/terraform/modules/app/lambda-api/handlers.tf +493 -89
  98. package/dist/terraform/modules/app/lambda-api/iam-grouped.tf +215 -96
  99. package/dist/terraform/modules/app/lambda-api/main.tf +24 -5
  100. package/dist/terraform/modules/app/lambda-api/outputs.tf +19 -11
  101. package/dist/terraform/modules/app/lambda-api/variables.tf +94 -67
  102. package/dist/terraform/modules/app/ses-email/main.tf +14 -2
  103. package/dist/terraform/modules/app/workflow-interpreter-stepfunctions/main.tf +493 -0
  104. package/dist/terraform/modules/app/workflow-interpreter-stepfunctions/outputs.tf +34 -0
  105. package/dist/terraform/modules/app/workflow-interpreter-stepfunctions/variables.tf +32 -0
  106. package/dist/terraform/modules/data/aurora-postgres/main.tf +55 -0
  107. package/dist/terraform/modules/data/aurora-postgres/outputs.tf +15 -0
  108. package/dist/terraform/modules/data/s3-buckets/main.tf +26 -0
  109. package/dist/terraform/modules/thinkwork/README.md +0 -1
  110. package/dist/terraform/modules/thinkwork/main.tf +167 -446
  111. package/dist/terraform/modules/thinkwork/outputs.tf +2 -142
  112. package/dist/terraform/modules/thinkwork/variables.tf +55 -309
  113. package/dist/terraform/schema.graphql +4 -0
  114. package/dist/workspace-defaults/files/AGENTS.md +45 -31
  115. package/dist/workspace-defaults/files/CONTEXT.md +48 -4
  116. package/dist/workspace-defaults/files/GUARDRAILS.md +18 -0
  117. package/dist/workspace-defaults/files/MEMORY_GUIDE.md +32 -4
  118. package/dist/workspace-defaults/files/SPACE.md +34 -19
  119. package/dist/workspace-defaults/files/TOOLS.md +30 -0
  120. package/dist/workspace-defaults/files/skills/document-composer/SKILL.md +154 -0
  121. package/dist/workspace-defaults/files/skills/document-composer/references/authoring-rules.md +101 -0
  122. package/package.json +1 -1
  123. package/dist/plugins/company-brain/README.md +0 -37
  124. package/dist/plugins/company-brain/package.json +0 -33
  125. package/dist/plugins/company-brain/runtime/cognee/Dockerfile +0 -11
  126. package/dist/plugins/company-brain/smoke/cognee-managed-app-smoke.mjs +0 -458
  127. package/dist/plugins/company-brain/smoke/cognee-memory-cutover-smoke.mjs +0 -539
  128. package/dist/plugins/company-brain/smoke/company-brain-context-engine-smoke.mjs +0 -312
  129. package/dist/plugins/company-brain/smoke/company-brain-operations-smoke.mjs +0 -449
  130. package/dist/plugins/company-brain/smoke/company-brain-plugin-smoke.mjs +0 -655
  131. package/dist/plugins/company-brain/smoke/hindsight-memory-isolation-smoke.mjs +0 -474
  132. package/dist/plugins/company-brain/src/api/cognee-client.ts +0 -896
  133. package/dist/plugins/company-brain/src/api/cognee-cluster-identity.ts +0 -49
  134. package/dist/plugins/company-brain/src/api/cognee-memory-scope.ts +0 -84
  135. package/dist/plugins/company-brain/src/api/context-engine-provider.ts +0 -888
  136. package/dist/plugins/company-brain/src/api/migration.ts +0 -665
  137. package/dist/plugins/company-brain/src/deployment/cognee-managed-app.ts +0 -396
  138. package/dist/plugins/company-brain/src/index.ts +0 -62
  139. package/dist/plugins/company-brain/src/manifest.ts +0 -112
  140. package/dist/plugins/company-brain/terraform/cognee/README.md +0 -263
  141. package/dist/plugins/company-brain/terraform/cognee/main.tf +0 -766
  142. package/dist/plugins/company-brain/terraform/cognee/outputs.tf +0 -144
  143. package/dist/plugins/company-brain/terraform/cognee/variables.tf +0 -402
  144. package/dist/plugins/company-brain/test/api/cognee-client.test.ts +0 -562
  145. package/dist/plugins/company-brain/test/api/cognee-memory-scope.test.ts +0 -74
  146. package/dist/plugins/company-brain/test/api/context-engine-provider.test.ts +0 -447
  147. package/dist/plugins/company-brain/test/api/migration.test.ts +0 -465
  148. package/dist/plugins/company-brain/test/manifest.test.ts +0 -95
  149. package/dist/plugins/company-brain/tsconfig.json +0 -8
@@ -25,7 +25,7 @@
25
25
  # standalone managed-policy attachment. (Managed-policy attachments have a
26
26
  # default quota of 10 per role; the steady state here is
27
27
  # AWSLambdaBasicExecutionRole + these four, plus the conditional AWS-managed
28
- # VPC-access policy when Cognee workers are enabled.)
28
+ # VPC-access policy when OKF EFS wiring is enabled.)
29
29
  #
30
30
  # Each managed policy document caps at 6,144 characters (JSON minus
31
31
  # whitespace) — check rendered size before adding large statements, and
@@ -59,13 +59,32 @@ locals {
59
59
  Action = ["secretsmanager:GetSecretValue"]
60
60
  Resource = var.graphql_db_secret_arn
61
61
  },
62
+ # THINK-239 — analystInternalClusters enumerates the environment's own
63
+ # RDS clusters (filtered to thinkwork-<stage>-* in code) so operators can
64
+ # register a database with zero credential entry. Describe-only; the
65
+ # admin credential read is covered by graphql_db_secret_arn above.
66
+ {
67
+ Sid = "AnalystInternalClustersDescribe"
68
+ Effect = "Allow"
69
+ Action = ["rds:DescribeDBClusters"]
70
+ Resource = "*"
71
+ },
62
72
  {
63
73
  Effect = "Allow"
64
74
  Action = [
65
75
  "secretsmanager:CreateSecret",
66
76
  "secretsmanager:UpdateSecret",
67
77
  "secretsmanager:DeleteSecret",
68
- "secretsmanager:GetSecretValue"
78
+ "secretsmanager:GetSecretValue",
79
+ # THINK-230 — provisionAnalystConnector writes the broker credential
80
+ # secret value (thinkwork/<stage>/analyst/broker-credential, under
81
+ # this thinkwork/* prefix) via ensureAnalystBrokerSecret's
82
+ # PutSecretValue. GetSecretValue above already covers the read; this
83
+ # role already holds Create/Update/Delete on the same prefix, so
84
+ # PutSecretValue grants no capability beyond the existing delete +
85
+ # recreate. Kept on the existing statement to stay under the 6,144
86
+ # rendered-char managed-policy cap.
87
+ "secretsmanager:PutSecretValue"
69
88
  ]
70
89
  Resource = "arn:aws:secretsmanager:${var.region}:${var.account_id}:secret:thinkwork/*"
71
90
  },
@@ -107,7 +126,7 @@ locals {
107
126
  Action = ["s3:PutObject", "s3:AbortMultipartUpload"]
108
127
  Resource = "${aws_s3_bucket.wiki_exports.arn}/*"
109
128
  },
110
- # Canonical Company Brain artifacts: durable source artifacts,
129
+ # Canonical ThinkWork Brain artifacts: durable source artifacts,
111
130
  # ingestion manifests, migration snapshots, vault projections, and
112
131
  # exports, and OKF Wiki Navigator bundles/current manifests.
113
132
  # Tenant-visible APIs redact object keys; Lambdas need object read/write
@@ -217,6 +236,31 @@ locals {
217
236
  ]
218
237
  Resource = "arn:aws:s3:::thinkwork-${var.stage}-routine-output/*"
219
238
  },
239
+ # routine-exec-git SHA code cache (plan 2026-07-03-004 U3, KTD-7):
240
+ # read-through cache under routine-code-cache/<tenant>/<routine>/<sha>/.
241
+ # GetObject for cache reads; ListBucket so a cache miss surfaces as
242
+ # NoSuchKey (404) instead of AccessDenied — without it the executor
243
+ # cannot distinguish "not cached yet" from a real permission error
244
+ # and the fixture gate fails closed (caught live in the U9 sweep).
245
+ {
246
+ Sid = "RoutineExecGitCodeCacheRead"
247
+ Effect = "Allow"
248
+ Action = [
249
+ "s3:GetObject",
250
+ ]
251
+ Resource = "arn:aws:s3:::thinkwork-${var.stage}-routine-output/routine-code-cache/*"
252
+ },
253
+ {
254
+ Sid = "RoutineExecGitCodeCacheList"
255
+ Effect = "Allow"
256
+ Action = ["s3:ListBucket"]
257
+ Resource = "arn:aws:s3:::thinkwork-${var.stage}-routine-output"
258
+ Condition = {
259
+ StringLike = {
260
+ "s3:prefix" = "routine-code-cache/*"
261
+ }
262
+ }
263
+ },
220
264
  # (was standalone managed policy "lambda_model_catalog_import_read")
221
265
  # Settings -> Model Catalog imports call Bedrock's foundation-model
222
266
  # catalog and AWS Price List APIs from graphql-http. These read/list
@@ -237,6 +281,14 @@ locals {
237
281
  ]
238
282
  Resource = "*"
239
283
  },
284
+ # THINK-245 U10 — cost-drift-check compares recorded per-model spend
285
+ # against Cost Explorer. ce:GetCostAndUsage supports no resource-level
286
+ # scoping (must be "*").
287
+ {
288
+ Effect = "Allow"
289
+ Action = ["ce:GetCostAndUsage"]
290
+ Resource = "*"
291
+ },
240
292
  ],
241
293
  var.plugin_catalog_github_token_secret_arn != "" ? [
242
294
  {
@@ -245,6 +297,19 @@ locals {
245
297
  Resource = var.plugin_catalog_github_token_secret_arn
246
298
  },
247
299
  ] : [],
300
+ # THINK-229 U1 — analyst-query-broker mints RDS IAM auth tokens for the
301
+ # analyst_reader role. The rds-db ARN keys on the immutable cluster
302
+ # RESOURCE ID (cluster-XXXX), never the cluster ARN, and the dbuser
303
+ # segment is the exact-case Postgres role name. aws:SourceIp /
304
+ # aws:SourceVpc conditions are unsupported on rds-db:connect, so the
305
+ # narrow Resource IS the control surface.
306
+ var.analyst_db_cluster_resource_id != "" ? [
307
+ {
308
+ Effect = "Allow"
309
+ Action = ["rds-db:connect"]
310
+ Resource = "arn:aws:rds-db:${var.region}:${var.account_id}:dbuser:${var.analyst_db_cluster_resource_id}/analyst_reader"
311
+ },
312
+ ] : [],
248
313
  # (was standalone managed policy "lambda_deployment_evidence_read")
249
314
  # Access to the deployment evidence bucket: graphql-http's deployments
250
315
  # resolvers read deployment/status/current.json (deployed-release pointer
@@ -281,81 +346,6 @@ locals {
281
346
  ]
282
347
  },
283
348
  ] : [],
284
- # SQS grants live here rather than in the orchestration group purely for
285
- # size balance: with every conditional on, orchestration's rendered JSON
286
- # would exceed IAM's 6,144-char per-managed-policy cap (R9 rebalance).
287
- # Handler-gated SQS grants. Each statement was a count-gated inline
288
- # policy whose queue exists only when local.deploy_lambda_handlers.
289
- local.deploy_lambda_handlers ? [
290
- # (was inline policy "thinkwork-${stage}-wiki-compile-dlq-send")
291
- {
292
- Sid = "WikiCompileDlqSend"
293
- Effect = "Allow"
294
- Action = ["sqs:SendMessage"]
295
- Resource = aws_sqs_queue.wiki_compile_dlq[0].arn
296
- },
297
- # (was inline policy "thinkwork-${stage}-ontology-scan-dlq-send")
298
- {
299
- Sid = "OntologyScanDlqSend"
300
- Effect = "Allow"
301
- Action = ["sqs:SendMessage"]
302
- Resource = aws_sqs_queue.ontology_scan_dlq[0].arn
303
- },
304
- # (was inline policy "thinkwork-${stage}-ontology-reprocess-dlq-send")
305
- {
306
- Sid = "OntologyReprocessDlqSend"
307
- Effect = "Allow"
308
- Action = ["sqs:SendMessage"]
309
- Resource = aws_sqs_queue.ontology_reprocess_dlq[0].arn
310
- },
311
- # (was inline policy "compliance-drainer-dlq-send")
312
- {
313
- Sid = "ComplianceDrainerDlqSend"
314
- Effect = "Allow"
315
- Action = ["sqs:SendMessage"]
316
- Resource = aws_sqs_queue.compliance_drainer_dlq[0].arn
317
- },
318
- # (was inline policy "compliance-exports-send")
319
- # graphql-http needs sqs:SendMessage on the exports queue to dispatch
320
- # jobIds from the createComplianceExport mutation. Attached to the
321
- # shared lambda role (which graphql-http assumes); scope is
322
- # queue-specific. (The runner's receive grants stay on the dedicated
323
- # runner role — see compliance_exports_runner_sqs in handlers.tf.)
324
- {
325
- Sid = "ComplianceExportsSend"
326
- Effect = "Allow"
327
- Action = ["sqs:SendMessage"]
328
- Resource = aws_sqs_queue.compliance_exports[0].arn
329
- },
330
- # (was inline policy "eval-fanout-send")
331
- {
332
- Sid = "EvalRunnerSendFanoutMessages"
333
- Effect = "Allow"
334
- Action = [
335
- "sqs:SendMessage",
336
- "sqs:SendMessageBatch",
337
- ]
338
- Resource = aws_sqs_queue.eval_fanout[0].arn
339
- },
340
- # (was inline policy "eval-worker-sqs")
341
- {
342
- Sid = "EvalWorkerReceiveFanoutMessages"
343
- Effect = "Allow"
344
- Action = [
345
- "sqs:ReceiveMessage",
346
- "sqs:DeleteMessage",
347
- "sqs:GetQueueAttributes",
348
- "sqs:ChangeMessageVisibility",
349
- ]
350
- Resource = aws_sqs_queue.eval_fanout[0].arn
351
- },
352
- {
353
- Sid = "EvalWorkerSendDlqMessages"
354
- Effect = "Allow"
355
- Action = ["sqs:SendMessage"]
356
- Resource = aws_sqs_queue.eval_fanout_dlq[0].arn
357
- },
358
- ] : [],
359
349
  # (was inline policy "thinkwork-${stage}-lambda-workspace-events-sqs",
360
350
  # count-gated on the same flag)
361
351
  local.workspace_event_enabled ? [
@@ -480,14 +470,11 @@ locals {
480
470
  # retainTurn when the tenant's wiki_compile_enabled flag is on.
481
471
  # compileWikiNow admin mutation also Event-invokes.
482
472
  "arn:aws:lambda:${var.region}:${var.account_id}:function:thinkwork-${var.stage}-api-wiki-compile",
483
- # knowledge-graph-thread-ingest: graphql-http's
484
- # startKnowledgeGraphThreadIngest mutation invokes this with
485
- # RequestResponse after inserting the durable ingest run.
486
- "arn:aws:lambda:${var.region}:${var.account_id}:function:thinkwork-${var.stage}-api-knowledge-graph-thread-ingest",
487
473
  # knowledge-graph-observations-ingest: graphql-http's
488
474
  # startKnowledgeGraphObservationsIngest mutation invokes this with
489
- # RequestResponse; the worker also Event-invokes ITSELF to drain a
490
- # truncated candidate backlog across successive runs.
475
+ # RequestResponse. (The worker's self-invoke drain is retired
476
+ # AWS recursive-loop detection terminated those chains; backlog
477
+ # drains in-process now.)
491
478
  "arn:aws:lambda:${var.region}:${var.account_id}:function:thinkwork-${var.stage}-api-knowledge-graph-observations-ingest",
492
479
  # wiki-bootstrap-import: bootstrapJournalImport admin mutation
493
480
  # Event-invokes this for the long-running ingest path.
@@ -498,6 +485,13 @@ locals {
498
485
  # ontology-reprocess: approveOntologyChangeSet Event-invokes this
499
486
  # after inserting a durable reprocess job row.
500
487
  "arn:aws:lambda:${var.region}:${var.account_id}:function:thinkwork-${var.stage}-api-ontology-reprocess",
488
+ # okf-materialize / okf-efs-refresh: the OKF distribution chain
489
+ # (THINK-200). wiki-compile Event-invokes okf-materialize after a
490
+ # successful compile; okf-materialize Event-invokes okf-efs-refresh
491
+ # after publishing bundles, keeping the Pi wiki navigator's EFS
492
+ # view current without manual invocation.
493
+ "arn:aws:lambda:${var.region}:${var.account_id}:function:thinkwork-${var.stage}-api-okf-materialize",
494
+ "arn:aws:lambda:${var.region}:${var.account_id}:function:thinkwork-${var.stage}-api-okf-efs-refresh",
501
495
  # routine-resume: routine-approval-bridge (Phase B U8) invokes
502
496
  # this with RequestResponse after a HITL decideInboxItem
503
497
  # decision. Calls SendTaskSuccess/SendTaskFailure on the SFN
@@ -515,6 +509,25 @@ locals {
515
509
  # invokes this with RequestResponse so SkillSpector completion is a
516
510
  # server-side publish gate, not just an operator UI affordance.
517
511
  "arn:aws:lambda:${var.region}:${var.account_id}:function:thinkwork-${var.stage}-skill-trust-runner",
512
+ # routine-exec-git (plan 2026-07-03-004 U5/U6): job-trigger
513
+ # RequestResponse-invokes it for Automation routine actions, and
514
+ # admin-ops-mcp invokes it for agent fixture runs + the
515
+ # synchronous repair gate. Caught live in the U9 sweep.
516
+ "arn:aws:lambda:${var.region}:${var.account_id}:function:thinkwork-${var.stage}-api-routine-exec-git",
517
+ # artifact-deliver (THINK-227 U5): workflow-step-dispatch's deliver
518
+ # step RequestResponse-invokes its workflow-delivery mode to email
519
+ # the maintained report to the operator-configured recipient list.
520
+ "arn:aws:lambda:${var.region}:${var.account_id}:function:thinkwork-${var.stage}-api-artifact-deliver",
521
+ # job-trigger self-target (plan 2026-07-03-004 U5, KTD-3): the
522
+ # manual GraphQL trigger Event-invokes job-trigger with the
523
+ # agent_loop_continue_dispatch event so routine actions never run
524
+ # inline in graphql-http.
525
+ "arn:aws:lambda:${var.region}:${var.account_id}:function:thinkwork-${var.stage}-api-job-trigger",
526
+ # canvas-refresh (Living Artifacts THINK-145 U6/U7): graphql-http's
527
+ # refreshCanvasData mutation RequestResponse-invokes it (user + agent
528
+ # triggers), and job-trigger's canvas_refresh branch RequestResponse-
529
+ # invokes it (scheduled trigger). Both run on this shared role.
530
+ "arn:aws:lambda:${var.region}:${var.account_id}:function:thinkwork-${var.stage}-api-canvas-refresh",
518
531
  ]
519
532
  },
520
533
  # (was standalone managed policy "workspace_renderer_invoke")
@@ -613,6 +626,29 @@ locals {
613
626
  }
614
627
  }
615
628
  },
629
+ # Workflow Interpreter (THINK-219): job-trigger (workflow_schedule
630
+ # branch) and graphql-http (manual triggerWorkflowRun / resolveWorkflow
631
+ # Approval) both run under this shared role and StartExecution the ONE
632
+ # static interpreter machine per stage. Name is fixed
633
+ # (`thinkwork-${stage}-workflow-interpreter`); the machine ARN itself is
634
+ # resolved from SSM at runtime (already readable via the stage-wide
635
+ # ssm:GetParameter grant in api_data_plane). SendTaskSuccess/Failure for
636
+ # workflow-resume rides the wildcard RoutineTaskTokens statement above.
637
+ {
638
+ Sid = "WorkflowInterpreterExecution"
639
+ Effect = "Allow"
640
+ Action = [
641
+ "states:StartExecution",
642
+ "states:StopExecution",
643
+ "states:DescribeExecution",
644
+ "states:ListExecutions",
645
+ "states:GetExecutionHistory",
646
+ ]
647
+ Resource = [
648
+ "arn:aws:states:${var.region}:${var.account_id}:stateMachine:thinkwork-${var.stage}-workflow-interpreter",
649
+ "arn:aws:states:${var.region}:${var.account_id}:execution:thinkwork-${var.stage}-workflow-interpreter:*",
650
+ ]
651
+ },
616
652
  # (was standalone managed policy "lambda_deployment_stepfunctions")
617
653
  # Allow API Lambdas to start and inspect the deployment orchestrator.
618
654
  {
@@ -787,7 +823,97 @@ locals {
787
823
  # ---------------------------------------------------------------------------
788
824
  # Group 4: observability — CloudWatch Logs reads, ECS/ALB health reads.
789
825
  # ---------------------------------------------------------------------------
790
- api_observability_statements = [
826
+ # Handler-gated SQS grants moved HERE from the data-plane group
827
+ # (THINK-229 U5 follow-up): data-plane hit IAM's 6,144-char rendered cap
828
+ # when the analyst-connection-reconciler DLQ grant landed (live size was
829
+ # 6,018 before it). Queue plumbing is operational surface; observability
830
+ # has ~5k headroom. Same statements, different envelope.
831
+ api_observability_sqs_statements = concat(
832
+ # SQS grants live here rather than in the orchestration group purely for
833
+ # size balance: with every conditional on, orchestration's rendered JSON
834
+ # would exceed IAM's 6,144-char per-managed-policy cap (R9 rebalance).
835
+ # Handler-gated SQS grants. Each statement was a count-gated inline
836
+ # policy whose queue exists only when local.deploy_lambda_handlers.
837
+ local.deploy_lambda_handlers ? [
838
+ # (was inline policy "thinkwork-${stage}-wiki-compile-dlq-send")
839
+ {
840
+ Sid = "WikiCompileDlqSend"
841
+ Effect = "Allow"
842
+ Action = ["sqs:SendMessage"]
843
+ Resource = aws_sqs_queue.wiki_compile_dlq[0].arn
844
+ },
845
+ # (was inline policy "thinkwork-${stage}-ontology-scan-dlq-send")
846
+ {
847
+ Sid = "OntologyScanDlqSend"
848
+ Effect = "Allow"
849
+ Action = ["sqs:SendMessage"]
850
+ Resource = aws_sqs_queue.ontology_scan_dlq[0].arn
851
+ },
852
+ # (was inline policy "thinkwork-${stage}-ontology-reprocess-dlq-send")
853
+ {
854
+ Sid = "OntologyReprocessDlqSend"
855
+ Effect = "Allow"
856
+ Action = ["sqs:SendMessage"]
857
+ Resource = aws_sqs_queue.ontology_reprocess_dlq[0].arn
858
+ },
859
+ # (was inline policy "compliance-drainer-dlq-send")
860
+ {
861
+ Sid = "ComplianceDrainerDlqSend"
862
+ Effect = "Allow"
863
+ Action = ["sqs:SendMessage"]
864
+ Resource = aws_sqs_queue.compliance_drainer_dlq[0].arn
865
+ },
866
+ # THINK-229 U5 — analyst-connection-reconciler async on_failure DLQ.
867
+ {
868
+ Sid = "AnalystConnectionReconcilerDlqSend"
869
+ Effect = "Allow"
870
+ Action = ["sqs:SendMessage"]
871
+ Resource = aws_sqs_queue.analyst_connection_reconciler_dlq[0].arn
872
+ },
873
+ # (was inline policy "compliance-exports-send")
874
+ # graphql-http needs sqs:SendMessage on the exports queue to dispatch
875
+ # jobIds from the createComplianceExport mutation. Attached to the
876
+ # shared lambda role (which graphql-http assumes); scope is
877
+ # queue-specific. (The runner's receive grants stay on the dedicated
878
+ # runner role — see compliance_exports_runner_sqs in handlers.tf.)
879
+ {
880
+ Sid = "ComplianceExportsSend"
881
+ Effect = "Allow"
882
+ Action = ["sqs:SendMessage"]
883
+ Resource = aws_sqs_queue.compliance_exports[0].arn
884
+ },
885
+ # (was inline policy "eval-fanout-send")
886
+ {
887
+ Sid = "EvalRunnerSendFanoutMessages"
888
+ Effect = "Allow"
889
+ Action = [
890
+ "sqs:SendMessage",
891
+ "sqs:SendMessageBatch",
892
+ ]
893
+ Resource = aws_sqs_queue.eval_fanout[0].arn
894
+ },
895
+ # (was inline policy "eval-worker-sqs")
896
+ {
897
+ Sid = "EvalWorkerReceiveFanoutMessages"
898
+ Effect = "Allow"
899
+ Action = [
900
+ "sqs:ReceiveMessage",
901
+ "sqs:DeleteMessage",
902
+ "sqs:GetQueueAttributes",
903
+ "sqs:ChangeMessageVisibility",
904
+ ]
905
+ Resource = aws_sqs_queue.eval_fanout[0].arn
906
+ },
907
+ {
908
+ Sid = "EvalWorkerSendDlqMessages"
909
+ Effect = "Allow"
910
+ Action = ["sqs:SendMessage"]
911
+ Resource = aws_sqs_queue.eval_fanout_dlq[0].arn
912
+ },
913
+ ] : [],
914
+ )
915
+
916
+ api_observability_statements = concat(local.api_observability_sqs_statements, [
791
917
  # (was inline policy "cloudwatch-logs-read")
792
918
  {
793
919
  Effect = "Allow"
@@ -818,11 +944,9 @@ locals {
818
944
  "arn:aws:logs:${var.region}:${var.account_id}:log-group:/aws/bedrock-agentcore/runtimes/*:*",
819
945
  ]
820
946
  },
821
- # (was standalone managed policy "lambda_cognee_health_read")
822
- # graphql-http's Knowledge Graph health check validates the private
823
- # Cognee service from outside the VPC by reading ECS service steadiness
824
- # and ALB target health. ELBv2 Describe* actions do not support useful
825
- # resource scoping.
947
+ # Managed-application and runtime health checks read ECS service
948
+ # steadiness and ALB target health. ELBv2 Describe* actions do not
949
+ # support useful resource scoping.
826
950
  {
827
951
  Effect = "Allow"
828
952
  Action = [
@@ -832,7 +956,7 @@ locals {
832
956
  ]
833
957
  Resource = "*"
834
958
  },
835
- ]
959
+ ])
836
960
  }
837
961
 
838
962
  resource "aws_iam_policy" "api_data_plane" {
@@ -926,8 +1050,3 @@ moved {
926
1050
  from = aws_iam_role_policy_attachment.lambda_bedrock_knowledge_base
927
1051
  to = aws_iam_role_policy_attachment.api_ai
928
1052
  }
929
-
930
- moved {
931
- from = aws_iam_role_policy_attachment.lambda_cognee_health_read
932
- to = aws_iam_role_policy_attachment.api_observability
933
- }
@@ -19,9 +19,13 @@
19
19
  data "aws_caller_identity" "current" {}
20
20
 
21
21
  locals {
22
- cognee_worker_vpc_enabled = var.cognee_enabled && length(var.cognee_worker_subnet_ids) > 0 && length(var.cognee_worker_security_group_ids) > 0
23
- okf_efs_vpc_enabled = length(var.okf_efs_subnet_ids) > 0 && length(var.okf_efs_security_group_ids) > 0
24
- api_base_url = var.custom_domain != "" ? "https://${var.custom_domain}" : trimsuffix(aws_apigatewayv2_stage.default.invoke_url, "/")
22
+ okf_efs_vpc_enabled = length(var.okf_efs_subnet_ids) > 0 && length(var.okf_efs_security_group_ids) > 0
23
+ # Constructed rather than read from aws_apigatewayv2_stage.default.invoke_url
24
+ # (the two are identical for an HTTP API's $default stage). Reading it off
25
+ # the stage made every Lambda's env depend on the stage, which forbids the
26
+ # stage's route_settings depending on the routes (THINK-208 throttle) —
27
+ # UpdateStage would race route creation and 404 on fresh applies.
28
+ api_base_url = var.custom_domain != "" ? "https://${var.custom_domain}" : "https://${aws_apigatewayv2_api.main.id}.execute-api.${var.region}.amazonaws.com"
25
29
  }
26
30
 
27
31
  ################################################################################
@@ -49,6 +53,21 @@ resource "aws_apigatewayv2_stage" "default" {
49
53
  name = "$default"
50
54
  auto_deploy = true
51
55
 
56
+ # Public artifact share route (THINK-208 KTD-6): route-level throttle for
57
+ # enumeration resistance on the unauthenticated token lookup. The HMAC
58
+ # signature makes forgery impractical regardless; this bounds probe volume.
59
+ route_settings {
60
+ route_key = "GET /share/{token}"
61
+ throttling_rate_limit = 10
62
+ throttling_burst_limit = 20
63
+ }
64
+
65
+ # UpdateStage 404s ("Unable to find Route by key … within the provided
66
+ # RouteSettings") if the stage update races the route creation — Terraform
67
+ # sees no reference edge between route_settings.route_key and the route
68
+ # resource, so make the ordering explicit.
69
+ depends_on = [aws_apigatewayv2_route.handler]
70
+
52
71
  tags = {
53
72
  Name = "thinkwork-${var.stage}-api-default"
54
73
  }
@@ -156,8 +175,8 @@ resource "aws_iam_role_policy_attachment" "lambda_basic" {
156
175
  # aggregate hit IAM's 10,240-byte cap on 2026-06-11 (#2378/#2379). New grants
157
176
  # go into the grouped managed policies, never inline.
158
177
 
159
- resource "aws_iam_role_policy_attachment" "lambda_cognee_worker_vpc_access" {
160
- count = local.cognee_worker_vpc_enabled || local.okf_efs_vpc_enabled ? 1 : 0
178
+ resource "aws_iam_role_policy_attachment" "lambda_vpc_access" {
179
+ count = local.okf_efs_vpc_enabled ? 1 : 0
161
180
 
162
181
  role = aws_iam_role.lambda.name
163
182
  policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole"
@@ -43,14 +43,9 @@ output "memory_retain_fn_arn" {
43
43
  value = local.deploy_lambda_handlers ? aws_lambda_function.handler["memory-retain"].arn : ""
44
44
  }
45
45
 
46
- output "knowledge_graph_thread_ingest_fn_name" {
47
- description = "Knowledge Graph thread ingest worker Lambda function name."
48
- value = local.deploy_lambda_handlers ? aws_lambda_function.handler["knowledge-graph-thread-ingest"].function_name : ""
49
- }
50
-
51
- output "knowledge_graph_thread_ingest_fn_arn" {
52
- description = "Knowledge Graph thread ingest worker Lambda ARN."
53
- value = local.deploy_lambda_handlers ? aws_lambda_function.handler["knowledge-graph-thread-ingest"].arn : ""
46
+ output "workflow_execution_callback_fn_arn" {
47
+ description = "workflow-execution-callback Lambda ARN (THINK-219). Wired into the workflow-interpreter-stepfunctions module so its EventBridge SFN-state-change rule can target it."
48
+ value = local.deploy_lambda_handlers ? aws_lambda_function.handler["workflow-execution-callback"].arn : ""
54
49
  }
55
50
 
56
51
  output "okf_efs_refresh_fn_name" {
@@ -64,12 +59,12 @@ output "okf_efs_refresh_fn_arn" {
64
59
  }
65
60
 
66
61
  output "brain_artifacts_bucket_name" {
67
- description = "Canonical Company Brain S3 bucket for source artifacts, ingestion manifests, migration snapshots, vault projections, and exports."
62
+ description = "Canonical ThinkWork Brain S3 bucket for source artifacts, ingestion manifests, migration snapshots, vault projections, and exports."
68
63
  value = aws_s3_bucket.brain_artifacts.bucket
69
64
  }
70
65
 
71
66
  output "brain_artifacts_bucket_arn" {
72
- description = "ARN of the canonical Company Brain artifact bucket."
67
+ description = "ARN of the canonical ThinkWork Brain artifact bucket."
73
68
  value = aws_s3_bucket.brain_artifacts.arn
74
69
  }
75
70
 
@@ -94,7 +89,20 @@ output "email_inbound_fn_arn" {
94
89
  output "email_inbound_fn_name" {
95
90
  description = "email-inbound Lambda function name. Used by the SES module for lambda:InvokeFunction permissions."
96
91
  # Static for the same fresh-account plan-time reason as email_inbound_fn_arn.
97
- value = local.deploy_lambda_handlers ? "thinkwork-${var.stage}-api-email-inbound" : ""
92
+ value = local.deploy_lambda_handlers ? "thinkwork-${var.stage}-api-email-inbound" : ""
93
+ }
94
+
95
+ # Attribute-based twins: same values, but carrying the dependency edge. The
96
+ # static outputs above removed it, so a fresh-account apply raced the SES
97
+ # invoke permission ahead of the function's creation ("Function not found" —
98
+ # THINK-118 HCI test). Consumers use these ONLY in resource attributes; the
99
+ # static twins stay authoritative for count/for_each gating.
100
+ output "email_inbound_fn_name_attr" {
101
+ value = local.deploy_lambda_handlers ? try(aws_lambda_function.handler["email-inbound"].function_name, "") : ""
102
+ }
103
+
104
+ output "email_inbound_fn_arn_attr" {
105
+ value = local.deploy_lambda_handlers ? try(aws_lambda_function.handler["email-inbound"].arn, "") : ""
98
106
  }
99
107
 
100
108
  # ---------------------------------------------------------------------------