thinkwork-cli 0.13.0 → 0.13.1
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/{api-client-JUBCQQDF.js → api-client-4DZ266J5.js} +1 -1
- package/dist/{chunk-STY44FQO.js → chunk-Y2WHJECR.js} +44 -12
- package/dist/cli.js +36715 -12965
- package/dist/drizzle/0227_analyst_reader_role.sql +100 -38
- package/dist/drizzle/0230_analyst_rls.sql +183 -66
- package/dist/drizzle/0232_memory_source_thin_ledger.sql +176 -0
- package/dist/drizzle/0232_message_source_event_id.sql +9 -0
- package/dist/drizzle/0233_msteams_install_and_links.sql +151 -0
- package/dist/drizzle/0233_workflow_memory_stage_tokens.sql +20 -0
- package/dist/drizzle/0234_memory_claim_lifecycle.sql +160 -0
- package/dist/drizzle/0235_workflow_token_execution_claim.sql +34 -0
- package/dist/drizzle/0236_memory_retraction_fencing.sql +50 -0
- package/dist/drizzle/0237_memory_claims_active_value_uidx.sql +172 -0
- package/dist/drizzle/0238_memory_erase_generation_fence.sql +97 -0
- package/dist/drizzle/0239_canonical_entity_identity.sql +257 -0
- package/dist/drizzle/0240_memory_personal_scope.sql +45 -0
- package/dist/drizzle/0241_knowledge_base_document_manifest.sql +67 -0
- package/dist/drizzle/0242_search_queries.sql +28 -0
- package/dist/drizzle/0243_section_sources_thread_refs.sql +12 -0
- package/dist/drizzle/0244_system_automations_and_memory_stage_overrides.sql +45 -0
- package/dist/drizzle/0245_wiki_page_render.sql +21 -0
- package/dist/drizzle/0246_automation_workflow_ownership.sql +30 -0
- package/dist/drizzle/0247_capability_runtime.sql +402 -0
- package/dist/drizzle/0248_capability_private_interpreter.sql +13 -0
- package/dist/drizzle/0249_capability_headless_execution_evidence.sql +40 -0
- package/dist/drizzle/0250_kg_schema_extraction.sql +549 -0
- package/dist/drizzle/0251_agents_json_render_ui.sql +25 -0
- package/dist/drizzle/0251_brain_stragglers.sql +242 -0
- package/dist/drizzle/0252_drop_kg_and_straggler_compat_views.sql +100 -0
- package/dist/drizzle/0253_drop_brain_substrate.sql +91 -0
- package/dist/drizzle/0254_capability_autonomous_admission.sql +29 -0
- package/dist/drizzle/0255_capability_autonomous_approval_mode.sql +16 -0
- package/dist/drizzle/0256_agent_profile_manifest_authority.sql +18 -0
- package/dist/drizzle/0257_capability_approvals.sql +53 -0
- package/dist/drizzle/0258_pending_tool_approvals.sql +84 -0
- package/dist/drizzle/0259_tenant_capability_registry_trust.sql +19 -0
- package/dist/drizzle/0260_scheduled_jobs_run_as_user.sql +20 -0
- package/dist/drizzle/0261_thread_turns_origin_turn_index.sql +11 -0
- package/dist/terraform/examples/greenfield/main.tf +40 -0
- package/dist/terraform/modules/app/agentcore-admin/main.tf +341 -0
- package/dist/terraform/modules/app/agentcore-admin/outputs.tf +20 -0
- package/dist/terraform/modules/app/agentcore-code-interpreter/main.tf +61 -0
- package/dist/terraform/modules/app/agentcore-harness/main.tf +101 -0
- package/dist/terraform/modules/app/agentcore-harness/outputs.tf +9 -0
- package/dist/terraform/modules/app/agentcore-harness/variables.tf +25 -0
- package/dist/terraform/modules/app/agentcore-pi/main.tf +7 -0
- package/dist/terraform/modules/app/capability-broker/main.tf +393 -0
- package/dist/terraform/modules/app/capability-broker/outputs.tf +54 -0
- package/dist/terraform/modules/app/capability-broker/variables.tf +98 -0
- package/dist/terraform/modules/app/deployment-control-plane/runner.py +46 -5
- package/dist/terraform/modules/app/deployment-control-plane/test_runner_bundle.py +94 -0
- package/dist/terraform/modules/app/lambda-api/capability-search-alarms.tf +60 -0
- package/dist/terraform/modules/app/lambda-api/handlers.tf +361 -16
- package/dist/terraform/modules/app/lambda-api/iam-grouped.tf +131 -5
- package/dist/terraform/modules/app/lambda-api/main.tf +11 -0
- package/dist/terraform/modules/app/lambda-api/memory-alarms.tf +92 -0
- package/dist/terraform/modules/app/lambda-api/msteams-app-secrets.tf +46 -0
- package/dist/terraform/modules/app/lambda-api/variables.tf +92 -0
- package/dist/terraform/modules/app/workflow-interpreter-stepfunctions/alarms.tf +47 -0
- package/dist/terraform/modules/app/workflow-interpreter-stepfunctions/main.tf +43 -2
- package/dist/terraform/modules/foundation/cognito/main.tf +32 -8
- package/dist/terraform/modules/foundation/cognito/variables.tf +12 -0
- package/dist/terraform/modules/foundation/vpc/outputs.tf +5 -0
- package/dist/terraform/modules/thinkwork/main.tf +152 -5
- package/dist/terraform/modules/thinkwork/outputs.tf +55 -0
- package/dist/terraform/modules/thinkwork/variables.tf +42 -0
- package/dist/workspace-defaults/files/TOOLS.md +39 -0
- package/dist/workspace-defaults/files/agents/analyst/INSTRUCTIONS.md +18 -0
- package/dist/workspace-defaults/files/agents/coding/INSTRUCTIONS.md +11 -0
- package/dist/workspace-defaults/files/agents/research/INSTRUCTIONS.md +12 -0
- package/dist/workspace-defaults/files/agents/reviewer/INSTRUCTIONS.md +15 -0
- package/dist/workspace-defaults/files/skills/document-composer/SKILL.md +6 -2
- package/package.json +4 -2
- /package/dist/workspace-defaults/files/{AGENTS.md → INSTRUCTIONS.md} +0 -0
|
@@ -30,10 +30,13 @@ locals {
|
|
|
30
30
|
"oauth-authorize",
|
|
31
31
|
"oauth-callback",
|
|
32
32
|
"slack-events",
|
|
33
|
-
"slack-slash-command",
|
|
34
|
-
"slack-interactivity",
|
|
35
33
|
"slack-oauth-install",
|
|
36
34
|
],
|
|
35
|
+
var.enable_msteams_app ? [] : [
|
|
36
|
+
"msteams-install-start",
|
|
37
|
+
"msteams-install-complete",
|
|
38
|
+
"msteams-account-link-complete",
|
|
39
|
+
],
|
|
37
40
|
)
|
|
38
41
|
|
|
39
42
|
# Config-class configuration shared by all API handlers. As of plan
|
|
@@ -58,6 +61,12 @@ locals {
|
|
|
58
61
|
# signed sidecar block authoritative (budgets/policyClaims flow). Flip
|
|
59
62
|
# ONLY after clean shadow parity on live traffic.
|
|
60
63
|
ANALYST_POLICY_SOURCE = var.analyst_policy_source
|
|
64
|
+
# Governed autonomy — per-tenant opt-in allowlist for autonomous capability
|
|
65
|
+
# self-extension (the two self_admit_connection / self_approve_routine
|
|
66
|
+
# actions on capability-control-service). Comma/space-separated tenant ids;
|
|
67
|
+
# empty (default) = NO tenant enabled, so self-extension ships inert and
|
|
68
|
+
# fail-closed. Read via getConfig() (env-wins) in isSelfExtensionEnabled.
|
|
69
|
+
CAPABILITY_SELF_EXTENSION_TENANTS = var.capability_self_extension_tenants
|
|
61
70
|
# THINK-230 — the operator-facing provisionAnalystConnector mutation runs
|
|
62
71
|
# the analyst connector provisioning ceremony inside graphql-http, so the
|
|
63
72
|
# shared api handlers read the same broker-secret ARN + rds_iam connect
|
|
@@ -74,6 +83,11 @@ locals {
|
|
|
74
83
|
DATABASE_SECRET_ARN = var.graphql_db_secret_arn
|
|
75
84
|
DATABASE_HOST = var.db_cluster_endpoint
|
|
76
85
|
DATABASE_NAME = var.database_name
|
|
86
|
+
# THINK-280 U8: the LAST rollout gate. External capability search + the
|
|
87
|
+
# Inspector governed-runtime operation layer stay inert until the broker is
|
|
88
|
+
# enabled for the stage. Off by default — read via getConfig() (env-wins).
|
|
89
|
+
CAPABILITY_EXTERNAL_SEARCH_ENABLED = var.enable_capability_broker ? "true" : "false"
|
|
90
|
+
ENABLE_CAPABILITY_BROKER = var.enable_capability_broker ? "true" : "false"
|
|
77
91
|
# BUCKET_NAME and USER_POOL_ID were duplicate aliases of WORKSPACE_BUCKET
|
|
78
92
|
# and COGNITO_USER_POOL_ID; GRAPHQL_API_KEY duplicated APPSYNC_API_KEY;
|
|
79
93
|
# THINKWORK_API_SECRET and EMAIL_HMAC_SECRET duplicated API_AUTH_SECRET
|
|
@@ -237,6 +251,10 @@ locals {
|
|
|
237
251
|
SLACK_APP_CREDENTIALS_SECRET_ARN = var.enable_slack_workspace_app ? aws_secretsmanager_secret.slack_app_credentials[0].arn : ""
|
|
238
252
|
}
|
|
239
253
|
|
|
254
|
+
msteams_handler_env = {
|
|
255
|
+
MSTEAMS_APP_CREDENTIALS_SECRET_ARN = var.enable_msteams_app ? aws_secretsmanager_secret.msteams_app_credentials[0].arn : ""
|
|
256
|
+
}
|
|
257
|
+
|
|
240
258
|
handler_extra_env = {
|
|
241
259
|
# Analyst query broker (THINK-228 U3). Reader role + caller credential
|
|
242
260
|
# secrets, and the workspace bucket's analyst-staging/ prefix for
|
|
@@ -302,6 +320,17 @@ locals {
|
|
|
302
320
|
THINKWORK_RELEASE_VERSION = var.deployment_release_version
|
|
303
321
|
THINKWORK_RELEASE_MANIFEST_URL = var.deployment_release_manifest_url
|
|
304
322
|
THINKWORK_RELEASE_MANIFEST_SHA256 = var.deployment_release_manifest_sha256
|
|
323
|
+
# THINK-280 — createTenant RequestResponse-invokes agentcore-admin to
|
|
324
|
+
# provision the per-tenant sandbox. sandbox-provisioning.ts reads both
|
|
325
|
+
# from process.env directly (the token is a secret → env, never the SSM
|
|
326
|
+
# String doc). Broker-session build reads the three broker values below
|
|
327
|
+
# (broker-session.ts); all EMPTY when the broker is disabled → inert.
|
|
328
|
+
AGENTCORE_ADMIN_LAMBDA_ARN = var.agentcore_admin_lambda_arn
|
|
329
|
+
AGENTCORE_ADMIN_TOKEN = var.agentcore_admin_token
|
|
330
|
+
CAPABILITY_BROKER_AUDIENCE = var.capability_broker_audience
|
|
331
|
+
CAPABILITY_BROKER_API_ID = var.capability_broker_api_id
|
|
332
|
+
CAPABILITY_BROKER_VPCE_DNS = var.capability_broker_vpce_dns
|
|
333
|
+
CAPABILITY_BROKER_SESSION_TABLE = var.capability_broker_session_table
|
|
305
334
|
}
|
|
306
335
|
# Compounding Memory compile Lambda. Any Converse-compatible Bedrock
|
|
307
336
|
# model works; the planner + section-writer cap themselves at ~500
|
|
@@ -343,12 +372,25 @@ locals {
|
|
|
343
372
|
BRAIN_ARTIFACTS_BUCKET = aws_s3_bucket.brain_artifacts.bucket
|
|
344
373
|
OKF_EFS_ROOT = var.okf_efs_mount_path
|
|
345
374
|
}
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
"
|
|
350
|
-
|
|
351
|
-
|
|
375
|
+
# THINK-193 U1 (Codex F6): normalized evidence snapshots live in the
|
|
376
|
+
# encrypted brain-artifacts bucket under evidence-snapshots/ — Postgres
|
|
377
|
+
# keeps only the s3:// ref + hash. 30-day lifecycle expiration below.
|
|
378
|
+
"memory-stage-worker" = {
|
|
379
|
+
BRAIN_ARTIFACTS_BUCKET = aws_s3_bucket.brain_artifacts.bucket
|
|
380
|
+
}
|
|
381
|
+
# THINK-193 U2 (Codex S1/S2): the retraction drainer performs the
|
|
382
|
+
# versioned evidence-snapshot deletion for source erases under its
|
|
383
|
+
# DEDICATED role (below) — the only place bulk destructive S3 runs.
|
|
384
|
+
"memory-retraction-drainer" = {
|
|
385
|
+
BRAIN_ARTIFACTS_BUCKET = aws_s3_bucket.brain_artifacts.bucket
|
|
386
|
+
}
|
|
387
|
+
"oauth-authorize" = local.slack_handler_env
|
|
388
|
+
"oauth-callback" = local.slack_handler_env
|
|
389
|
+
"slack-events" = local.slack_handler_env
|
|
390
|
+
"slack-oauth-install" = local.slack_handler_env
|
|
391
|
+
"msteams-install-start" = local.msteams_handler_env
|
|
392
|
+
"msteams-install-complete" = local.msteams_handler_env
|
|
393
|
+
"msteams-account-link-complete" = local.msteams_handler_env
|
|
352
394
|
"thread-attachments-finalize" = {
|
|
353
395
|
REQUESTER_IDLE_MEMORY_LEARNING_ENABLED = tostring(var.requester_idle_memory_learning_enabled)
|
|
354
396
|
}
|
|
@@ -375,6 +417,12 @@ locals {
|
|
|
375
417
|
"brain-dream-state" = {
|
|
376
418
|
BRAIN_DREAM_STATE_ENABLED = tostring(var.brain_dream_state_enabled)
|
|
377
419
|
}
|
|
420
|
+
# THINK-307 KTD2: the origin-freshness guard reads the same stall
|
|
421
|
+
# threshold as the stall monitor — one operational knob, two consumers,
|
|
422
|
+
# no drift between "stalled" and "recovered".
|
|
423
|
+
"cron-retry-dispatcher" = {
|
|
424
|
+
STALL_THRESHOLD_MINUTES = tostring(var.stall_threshold_minutes)
|
|
425
|
+
}
|
|
378
426
|
# Bedrock KB provisioning. Per-handler (not common_env) so these don't bloat
|
|
379
427
|
# the already-near-4KB graphql-http env. Bedrock's RDS-backed KB needs the
|
|
380
428
|
# cluster ARN + the KB service role (passed at CreateKnowledgeBase time).
|
|
@@ -395,6 +443,15 @@ locals {
|
|
|
395
443
|
# invocation (never Lambda self-invoke — AWS recursive-loop
|
|
396
444
|
# detection terminates worker-to-self Event chains).
|
|
397
445
|
KG_OBS_MAX_CANDIDATES_PER_RUN = var.kg_obs_max_candidates_per_run
|
|
446
|
+
# THINK-193 U4 dead-handoff fix: a successful observations ingest
|
|
447
|
+
# enqueues the tenant graph wiki-compile job inside its own commit
|
|
448
|
+
# and Event-invokes wiki-compile post-commit. WIKI_SOURCE must match
|
|
449
|
+
# the wiki-compile handler's dispatch flag (stage-global); the
|
|
450
|
+
# per-tenant kill switch stays tenants.wiki_compile_enabled. The
|
|
451
|
+
# invoke rides the shared lambda role's existing wiki-compile
|
|
452
|
+
# lambda:InvokeFunction grant (iam-grouped.tf); the function name is
|
|
453
|
+
# derived from STAGE (common_env) at call time.
|
|
454
|
+
WIKI_SOURCE = var.wiki_source
|
|
398
455
|
}
|
|
399
456
|
# routine-task-python (Phase B U6) needs the AgentCore code-interpreter
|
|
400
457
|
# id + the per-stage S3 routine-output bucket. The interpreter id is
|
|
@@ -414,6 +471,14 @@ locals {
|
|
|
414
471
|
"routine-exec-git" = {
|
|
415
472
|
SANDBOX_INTERPRETER_ID = var.agentcore_code_interpreter_id
|
|
416
473
|
ROUTINE_OUTPUT_BUCKET = "thinkwork-${var.stage}-routine-output"
|
|
474
|
+
# THINK-280 U7 — the headless capability executor runs inside
|
|
475
|
+
# routine-exec-git and mints broker sessions. routine-exec-git.ts +
|
|
476
|
+
# capability-headless-executor.ts read all four from process.env; all
|
|
477
|
+
# EMPTY when the broker is disabled → the executor stays inert.
|
|
478
|
+
CAPABILITY_BROKER_SESSION_TABLE = var.capability_broker_session_table
|
|
479
|
+
CAPABILITY_BROKER_AUDIENCE = var.capability_broker_audience
|
|
480
|
+
CAPABILITY_BROKER_API_ID = var.capability_broker_api_id
|
|
481
|
+
CAPABILITY_BROKER_VPCE_DNS = var.capability_broker_vpce_dns
|
|
417
482
|
}
|
|
418
483
|
# graphql-http hosts the createRoutine / publishRoutineVersion / etc.
|
|
419
484
|
# resolvers (Phase B U7) AND the routine-approval-bridge (Phase B
|
|
@@ -608,6 +673,8 @@ resource "aws_lambda_function" "handler" {
|
|
|
608
673
|
"mcp-user-memory",
|
|
609
674
|
"mcp-context-engine",
|
|
610
675
|
"mcp-open-engine",
|
|
676
|
+
# THINK-280 U8: scoped external capability search MCP facade.
|
|
677
|
+
"mcp-capability-search",
|
|
611
678
|
"activity",
|
|
612
679
|
"routines",
|
|
613
680
|
"budgets",
|
|
@@ -628,6 +695,10 @@ resource "aws_lambda_function" "handler" {
|
|
|
628
695
|
# dispatch can withhold a failing/stale connection loudly.
|
|
629
696
|
"analyst-connection-reconciler",
|
|
630
697
|
"cron-stall-monitor",
|
|
698
|
+
# THINK-307: drains retry_queue rows the stall monitor enqueues. Built by
|
|
699
|
+
# scripts/build-lambdas.sh since PRD-09 but first registered here; its
|
|
700
|
+
# schedule ships DISABLED (var.retry_dispatcher_enabled default false).
|
|
701
|
+
"cron-retry-dispatcher",
|
|
631
702
|
"webhook-crm-opportunity",
|
|
632
703
|
"webhook-task-event",
|
|
633
704
|
"workspace-files",
|
|
@@ -642,13 +713,28 @@ resource "aws_lambda_function" "handler" {
|
|
|
642
713
|
"email-provider-webhook",
|
|
643
714
|
"email-readiness-probe",
|
|
644
715
|
"slack-events",
|
|
645
|
-
"slack-slash-command",
|
|
646
|
-
"slack-interactivity",
|
|
647
716
|
"slack-oauth-install",
|
|
717
|
+
"msteams-install-start",
|
|
718
|
+
"msteams-install-complete",
|
|
719
|
+
"msteams-account-link-complete",
|
|
648
720
|
"github-app",
|
|
649
721
|
"memory",
|
|
650
722
|
"memory-retain",
|
|
651
723
|
"brain-dream-state",
|
|
724
|
+
"memory-stage-worker",
|
|
725
|
+
# THINK-193 U2 (Codex P1 #3): scheduled retry drainer for the retraction
|
|
726
|
+
# saga ledger. Claims due/stale memory_retraction_attempts rows with the
|
|
727
|
+
# locked_by + lock_generation fence, processes each via the saga, sweeps
|
|
728
|
+
# exhausted rows to dead_lettered, and emits structured-log metrics.
|
|
729
|
+
# rate(5 minutes) EventBridge Scheduler + MaxRetryAttempts=0 (dedicated
|
|
730
|
+
# resources below) — the next tick IS the retry.
|
|
731
|
+
"memory-retraction-drainer",
|
|
732
|
+
# THINK-193 U3: stalled memory_stage token sweeper — re-invokes the
|
|
733
|
+
# memory-stage-worker for pending/executing tokens past their lease and
|
|
734
|
+
# redrives consumed-but-unsent results; unrecoverable parks get a
|
|
735
|
+
# terminal step event + SendTaskFailure. rate(15 minutes) schedule
|
|
736
|
+
# (dedicated resource below).
|
|
737
|
+
"memory-stage-sweeper",
|
|
652
738
|
"wiki-compile",
|
|
653
739
|
"knowledge-graph-observations-ingest",
|
|
654
740
|
"ontology-scan",
|
|
@@ -791,6 +877,14 @@ resource "aws_lambda_function" "handler" {
|
|
|
791
877
|
# POSTs one row per agent-session-start. Shared
|
|
792
878
|
# API_AUTH_SECRET bearer (runtime→API; no tenant OAuth).
|
|
793
879
|
"manifest-log",
|
|
880
|
+
# Governed capability runtime control-plane service (THINK-280 U2).
|
|
881
|
+
# NO HTTP route: the Pi container invokes it directly (RequestResponse)
|
|
882
|
+
# via lambda:InvokeFunction over the approved in-account path — public
|
|
883
|
+
# execute-api is not reliable from Pi's private VPC. Identity comes
|
|
884
|
+
# exclusively from the Ed25519-signed capability caller context (the
|
|
885
|
+
# CAPABILITY_SIGNING_PUBLIC_KEY in the shared runtime-config document
|
|
886
|
+
# verifies it); plaintext payload fields are never trusted.
|
|
887
|
+
"capability-control-service",
|
|
794
888
|
# SI-7 catalog-list read endpoint (plan §U15 pt 3/3). The runtime
|
|
795
889
|
# fetches the allowed builtin-tool slug set once per
|
|
796
890
|
# session-start + feature-flag-gated enforcement filter drops
|
|
@@ -831,9 +925,13 @@ resource "aws_lambda_function" "handler" {
|
|
|
831
925
|
]), toset(local.optional_integration_handler_names)) : toset([])
|
|
832
926
|
|
|
833
927
|
function_name = "thinkwork-${var.stage}-api-${each.key}"
|
|
834
|
-
role
|
|
835
|
-
|
|
836
|
-
|
|
928
|
+
# S2 (THINK-193 U2): memory-retraction-drainer runs under a DEDICATED role
|
|
929
|
+
# so its destructive evidence-snapshot S3 capability (version enumeration +
|
|
930
|
+
# bulk version deletion) never leaks into the 90+ handlers on the shared
|
|
931
|
+
# role. Everything else keeps the shared role.
|
|
932
|
+
role = each.key == "memory-retraction-drainer" ? aws_iam_role.memory_retraction_drainer.arn : aws_iam_role.lambda.arn
|
|
933
|
+
handler = "index.handler"
|
|
934
|
+
runtime = local.runtime
|
|
837
935
|
# Parameters and Secrets extension: container-local cache for the SSM
|
|
838
936
|
# runtime-config document + Secrets Manager reads (runtime-config.tf).
|
|
839
937
|
layers = local.api_handler_layers
|
|
@@ -859,7 +957,7 @@ resource "aws_lambda_function" "handler" {
|
|
|
859
957
|
# validates the agent, builds the AgentCore invoke payload, dispatches
|
|
860
958
|
# Event-mode, and returns. Setup is ~5s in practice; 60s gives 12×
|
|
861
959
|
# headroom for transient slowness.
|
|
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
|
|
960
|
+
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 == "memory-stage-worker" ? 900 : each.key == "memory-stage-sweeper" ? 120 : each.key == "memory-retraction-drainer" ? 300 : each.key == "canvas-refresh" ? 120 : each.key == "document-conformance-judge" ? 300 : each.key == "workflow-step-dispatch" ? 600 : each.key == "workflow-execution-callback" ? 60 : each.key == "workflow-resume" ? 60 : 30
|
|
863
961
|
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
|
|
864
962
|
|
|
865
963
|
filename = local.use_local_zips ? "${var.lambda_zips_dir}/${each.key}.zip" : null
|
|
@@ -904,6 +1002,19 @@ resource "aws_lambda_function" "handler" {
|
|
|
904
1002
|
}
|
|
905
1003
|
}
|
|
906
1004
|
|
|
1005
|
+
# Analyst data-path handlers get a stable NAT egress IP when
|
|
1006
|
+
# analyst_egress_subnet_ids is set — external Postgres sources behind an IP
|
|
1007
|
+
# allowlist admit that one EIP. Disjoint from the okf-efs-refresh block
|
|
1008
|
+
# above (a function takes at most one vpc_config).
|
|
1009
|
+
dynamic "vpc_config" {
|
|
1010
|
+
for_each = contains(local.analyst_vpc_handlers, each.key) && local.analyst_vpc_enabled ? [1] : []
|
|
1011
|
+
|
|
1012
|
+
content {
|
|
1013
|
+
subnet_ids = var.analyst_egress_subnet_ids
|
|
1014
|
+
security_group_ids = var.analyst_egress_security_group_ids
|
|
1015
|
+
}
|
|
1016
|
+
}
|
|
1017
|
+
|
|
907
1018
|
dynamic "file_system_config" {
|
|
908
1019
|
for_each = each.key == "okf-efs-refresh" && local.okf_efs_vpc_enabled ? [1] : []
|
|
909
1020
|
|
|
@@ -1061,6 +1172,21 @@ resource "aws_lambda_function_event_invoke_config" "routine_approval_callback" {
|
|
|
1061
1172
|
# retain-cost path (Bedrock tokens charged in adapter.retainConversation)
|
|
1062
1173
|
# is NOT idempotent — retries multiply LLM cost. Per
|
|
1063
1174
|
# project_async_retry_idempotency_lessons.
|
|
1175
|
+
# memory-stage-worker (THINK-193 U1): Event-invoked by workflow-step-dispatch
|
|
1176
|
+
# AFTER the memory_stage task token is stored. Lambda async retries are
|
|
1177
|
+
# disabled like its memory siblings — the worker's stages are idempotent, but
|
|
1178
|
+
# an automatic re-execution would race the original's token CAS and turn a
|
|
1179
|
+
# completed stage into a spurious failure. A worker that dies without
|
|
1180
|
+
# resuming the token is bounded by the state machine's HeartbeatSeconds
|
|
1181
|
+
# (3600s): the parked step times out and the run fails visibly, and a
|
|
1182
|
+
# re-triggered run self-heals from the durable checkpoint/evidence ledger.
|
|
1183
|
+
resource "aws_lambda_function_event_invoke_config" "memory_stage_worker" {
|
|
1184
|
+
count = local.deploy_lambda_handlers ? 1 : 0
|
|
1185
|
+
function_name = aws_lambda_function.handler["memory-stage-worker"].function_name
|
|
1186
|
+
maximum_retry_attempts = 0
|
|
1187
|
+
maximum_event_age_in_seconds = 3600
|
|
1188
|
+
}
|
|
1189
|
+
|
|
1064
1190
|
resource "aws_lambda_function_event_invoke_config" "memory_retain" {
|
|
1065
1191
|
count = local.deploy_lambda_handlers ? 1 : 0
|
|
1066
1192
|
function_name = aws_lambda_function.handler["memory-retain"].function_name
|
|
@@ -1068,6 +1194,132 @@ resource "aws_lambda_function_event_invoke_config" "memory_retain" {
|
|
|
1068
1194
|
maximum_event_age_in_seconds = 3600
|
|
1069
1195
|
}
|
|
1070
1196
|
|
|
1197
|
+
# ---------------------------------------------------------------------------
|
|
1198
|
+
# THINK-193 U2 (Codex S2): dedicated IAM role for memory-retraction-drainer.
|
|
1199
|
+
#
|
|
1200
|
+
# The drainer is the ONLY principal allowed to enumerate and bulk-delete
|
|
1201
|
+
# evidence-snapshot object VERSIONS (S1: the brain-artifacts bucket is
|
|
1202
|
+
# versioned; erase completeness requires deleting every noncurrent version
|
|
1203
|
+
# and delete marker under the source prefix). Granting that on the shared
|
|
1204
|
+
# api-lambda role would let every unrelated handler destroy any tenant's
|
|
1205
|
+
# evidence — hence the sibling-role pattern (same as
|
|
1206
|
+
# compliance-anchor-watchdog). The role otherwise carries only what the
|
|
1207
|
+
# drainer actually uses: logs (managed basic policy), Secrets Manager +
|
|
1208
|
+
# SSM runtime-config reads, and conditional KMS for the encrypted bucket.
|
|
1209
|
+
# ---------------------------------------------------------------------------
|
|
1210
|
+
|
|
1211
|
+
resource "aws_iam_role" "memory_retraction_drainer" {
|
|
1212
|
+
name = "thinkwork-${var.stage}-memory-retraction-drainer-role"
|
|
1213
|
+
|
|
1214
|
+
assume_role_policy = jsonencode({
|
|
1215
|
+
Version = "2012-10-17"
|
|
1216
|
+
Statement = [{
|
|
1217
|
+
Effect = "Allow"
|
|
1218
|
+
Principal = { Service = "lambda.amazonaws.com" }
|
|
1219
|
+
Action = "sts:AssumeRole"
|
|
1220
|
+
}]
|
|
1221
|
+
})
|
|
1222
|
+
}
|
|
1223
|
+
|
|
1224
|
+
resource "aws_iam_role_policy_attachment" "memory_retraction_drainer_basic" {
|
|
1225
|
+
role = aws_iam_role.memory_retraction_drainer.name
|
|
1226
|
+
policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
|
|
1227
|
+
}
|
|
1228
|
+
|
|
1229
|
+
resource "aws_iam_role_policy" "memory_retraction_drainer" {
|
|
1230
|
+
name = "memory-retraction-drainer"
|
|
1231
|
+
role = aws_iam_role.memory_retraction_drainer.id
|
|
1232
|
+
|
|
1233
|
+
policy = jsonencode({
|
|
1234
|
+
Version = "2012-10-17"
|
|
1235
|
+
Statement = concat(
|
|
1236
|
+
[
|
|
1237
|
+
# Versioned evidence-snapshot destruction, evidence-snapshots/ only.
|
|
1238
|
+
{
|
|
1239
|
+
Effect = "Allow"
|
|
1240
|
+
Action = [
|
|
1241
|
+
"s3:DeleteObject",
|
|
1242
|
+
"s3:DeleteObjectVersion",
|
|
1243
|
+
]
|
|
1244
|
+
Resource = "${aws_s3_bucket.brain_artifacts.arn}/evidence-snapshots/*"
|
|
1245
|
+
},
|
|
1246
|
+
{
|
|
1247
|
+
Effect = "Allow"
|
|
1248
|
+
Action = [
|
|
1249
|
+
"s3:ListBucket",
|
|
1250
|
+
"s3:ListBucketVersions",
|
|
1251
|
+
]
|
|
1252
|
+
Resource = aws_s3_bucket.brain_artifacts.arn
|
|
1253
|
+
Condition = {
|
|
1254
|
+
StringLike = {
|
|
1255
|
+
"s3:prefix" = "evidence-snapshots/*"
|
|
1256
|
+
}
|
|
1257
|
+
}
|
|
1258
|
+
},
|
|
1259
|
+
# Runtime-config document + platform secrets (DATABASE_URL rides the
|
|
1260
|
+
# env during the R8 transition window; the loader prefetches the
|
|
1261
|
+
# api-auth/appsync secrets at cold start).
|
|
1262
|
+
{
|
|
1263
|
+
Effect = "Allow"
|
|
1264
|
+
Action = ["ssm:GetParameter", "ssm:GetParameters"]
|
|
1265
|
+
Resource = "arn:aws:ssm:${var.region}:${var.account_id}:parameter/thinkwork/${var.stage}/*"
|
|
1266
|
+
},
|
|
1267
|
+
{
|
|
1268
|
+
Effect = "Allow"
|
|
1269
|
+
Action = ["secretsmanager:GetSecretValue"]
|
|
1270
|
+
Resource = "arn:aws:secretsmanager:${var.region}:${var.account_id}:secret:thinkwork/*"
|
|
1271
|
+
},
|
|
1272
|
+
],
|
|
1273
|
+
var.brain_artifacts_kms_key_arn != "" ? [
|
|
1274
|
+
{
|
|
1275
|
+
Effect = "Allow"
|
|
1276
|
+
Action = [
|
|
1277
|
+
"kms:Decrypt",
|
|
1278
|
+
"kms:GenerateDataKey",
|
|
1279
|
+
]
|
|
1280
|
+
Resource = var.brain_artifacts_kms_key_arn
|
|
1281
|
+
},
|
|
1282
|
+
] : [],
|
|
1283
|
+
)
|
|
1284
|
+
})
|
|
1285
|
+
}
|
|
1286
|
+
|
|
1287
|
+
# memory-retraction-drainer (THINK-193 U2, Codex P1 #3): the retraction
|
|
1288
|
+
# saga's product-owned retry path. Lambda async retries are disabled — every
|
|
1289
|
+
# transition on memory_retraction_attempts is a fenced CAS, so a duplicate
|
|
1290
|
+
# invocation is harmless but pointless; the rate(5 minutes) schedule below
|
|
1291
|
+
# is the retry. Attempts exceeding max_attempts are swept to dead_lettered
|
|
1292
|
+
# by the drainer itself instead of retrying forever.
|
|
1293
|
+
resource "aws_lambda_function_event_invoke_config" "memory_retraction_drainer" {
|
|
1294
|
+
count = local.deploy_lambda_handlers ? 1 : 0
|
|
1295
|
+
function_name = aws_lambda_function.handler["memory-retraction-drainer"].function_name
|
|
1296
|
+
maximum_retry_attempts = 0
|
|
1297
|
+
maximum_event_age_in_seconds = 3600
|
|
1298
|
+
}
|
|
1299
|
+
|
|
1300
|
+
resource "aws_scheduler_schedule" "memory_retraction_drainer" {
|
|
1301
|
+
count = local.deploy_lambda_handlers ? 1 : 0
|
|
1302
|
+
|
|
1303
|
+
name = "thinkwork-${var.stage}-memory-retraction-drainer"
|
|
1304
|
+
group_name = "default"
|
|
1305
|
+
schedule_expression = "rate(5 minutes)"
|
|
1306
|
+
state = "ENABLED"
|
|
1307
|
+
|
|
1308
|
+
flexible_time_window {
|
|
1309
|
+
mode = "OFF"
|
|
1310
|
+
}
|
|
1311
|
+
|
|
1312
|
+
target {
|
|
1313
|
+
arn = aws_lambda_function.handler["memory-retraction-drainer"].arn
|
|
1314
|
+
role_arn = aws_iam_role.scheduler.arn
|
|
1315
|
+
input = jsonencode({ limit = 25 })
|
|
1316
|
+
|
|
1317
|
+
retry_policy {
|
|
1318
|
+
maximum_retry_attempts = 0
|
|
1319
|
+
}
|
|
1320
|
+
}
|
|
1321
|
+
}
|
|
1322
|
+
|
|
1071
1323
|
# Product-owned retry path for memory-retain. Lambda async retries remain
|
|
1072
1324
|
# disabled above; this scheduled drain claims due rows from
|
|
1073
1325
|
# memory_retain_attempts and replays bounded retry payloads idempotently.
|
|
@@ -1311,6 +1563,11 @@ locals {
|
|
|
1311
1563
|
"ANY /mcp/user-memory" = "mcp-user-memory"
|
|
1312
1564
|
"ANY /mcp/context-engine" = "mcp-context-engine"
|
|
1313
1565
|
"ANY /mcp/open-engine" = "mcp-open-engine"
|
|
1566
|
+
# THINK-280 U8: scoped external capability search facade. The handler is
|
|
1567
|
+
# inert unless CAPABILITY_EXTERNAL_SEARCH_ENABLED (gated on
|
|
1568
|
+
# enable_capability_broker) is on — routing it while disabled returns an
|
|
1569
|
+
# empty, no-data projection.
|
|
1570
|
+
"ANY /mcp/capabilities" = "mcp-capability-search"
|
|
1314
1571
|
|
|
1315
1572
|
# Brain v0 service-auth writeback.
|
|
1316
1573
|
"POST /api/brain/agent-write" = "brain-agent-write"
|
|
@@ -1419,11 +1676,18 @@ locals {
|
|
|
1419
1676
|
# Slack workspace app ingress. These unauthenticated public endpoints
|
|
1420
1677
|
# verify Slack signatures in handler code before any tenant work happens.
|
|
1421
1678
|
"POST /slack/events" = "slack-events"
|
|
1422
|
-
"POST /slack/slash-command" = "slack-slash-command"
|
|
1423
|
-
"POST /slack/interactivity" = "slack-interactivity"
|
|
1424
1679
|
"GET /slack/oauth/install" = "slack-oauth-install"
|
|
1425
1680
|
"POST /slack/oauth/install" = "slack-oauth-install"
|
|
1426
1681
|
|
|
1682
|
+
# Microsoft Teams install + account-link ingress. Like the Slack block
|
|
1683
|
+
# above, these routes have no gateway authorizer: install/start and
|
|
1684
|
+
# account-link/complete verify the Cognito JWT in-handler, and
|
|
1685
|
+
# install/complete (the Microsoft admin-consent redirect) verifies the
|
|
1686
|
+
# HMAC-signed install state in-handler before any tenant work happens.
|
|
1687
|
+
"POST /msteams/install/start" = "msteams-install-start"
|
|
1688
|
+
"GET /msteams/install/complete" = "msteams-install-complete"
|
|
1689
|
+
"POST /msteams/account-link/complete" = "msteams-account-link-complete"
|
|
1690
|
+
|
|
1427
1691
|
# Memory
|
|
1428
1692
|
"ANY /api/memory/{proxy+}" = "memory"
|
|
1429
1693
|
|
|
@@ -1740,6 +2004,25 @@ resource "aws_scheduler_schedule" "requester_memory_dreaming" {
|
|
|
1740
2004
|
# the audit log.
|
|
1741
2005
|
# ---------------------------------------------------------------------------
|
|
1742
2006
|
|
|
2007
|
+
# THINK-193 U3: memory_stage stall recovery — every 15 minutes, bounded batch.
|
|
2008
|
+
resource "aws_scheduler_schedule" "memory_stage_sweeper" {
|
|
2009
|
+
count = local.deploy_lambda_handlers ? 1 : 0
|
|
2010
|
+
|
|
2011
|
+
name = "thinkwork-${var.stage}-memory-stage-sweeper"
|
|
2012
|
+
group_name = "default"
|
|
2013
|
+
schedule_expression = "rate(15 minutes)"
|
|
2014
|
+
state = "ENABLED"
|
|
2015
|
+
|
|
2016
|
+
flexible_time_window {
|
|
2017
|
+
mode = "OFF"
|
|
2018
|
+
}
|
|
2019
|
+
|
|
2020
|
+
target {
|
|
2021
|
+
arn = aws_lambda_function.handler["memory-stage-sweeper"].arn
|
|
2022
|
+
role_arn = aws_iam_role.scheduler.arn
|
|
2023
|
+
}
|
|
2024
|
+
}
|
|
2025
|
+
|
|
1743
2026
|
resource "aws_scheduler_schedule" "mcp_approval_sweeper" {
|
|
1744
2027
|
count = local.deploy_lambda_handlers ? 1 : 0
|
|
1745
2028
|
|
|
@@ -2199,6 +2482,47 @@ resource "aws_scheduler_schedule" "stall_monitor" {
|
|
|
2199
2482
|
}
|
|
2200
2483
|
}
|
|
2201
2484
|
|
|
2485
|
+
# ---------------------------------------------------------------------------
|
|
2486
|
+
# Retry dispatcher — drains retry_queue rows the stall monitor enqueues and
|
|
2487
|
+
# re-runs genuinely stalled turns (THINK-307). First-ever scheduling of this
|
|
2488
|
+
# handler; state is var-driven and defaults DISABLED — never enable on a
|
|
2489
|
+
# stage before THINK-305/308/309 are live there (parent plan deploy ordering).
|
|
2490
|
+
# The 1-minute rate is fixed by design: the queue's own scheduled_at does the
|
|
2491
|
+
# pacing. Scheduler retries stay at 0 — the next 1-minute tick IS the retry.
|
|
2492
|
+
# ---------------------------------------------------------------------------
|
|
2493
|
+
|
|
2494
|
+
# Lambda async retries are disabled (mirrors memory-retraction-drainer): the
|
|
2495
|
+
# claim is a CAS UPDATE so a duplicate invocation only picks up new rows, and
|
|
2496
|
+
# the next 1-minute tick is the retry.
|
|
2497
|
+
resource "aws_lambda_function_event_invoke_config" "retry_dispatcher" {
|
|
2498
|
+
count = local.deploy_lambda_handlers ? 1 : 0
|
|
2499
|
+
function_name = aws_lambda_function.handler["cron-retry-dispatcher"].function_name
|
|
2500
|
+
maximum_retry_attempts = 0
|
|
2501
|
+
maximum_event_age_in_seconds = 3600
|
|
2502
|
+
}
|
|
2503
|
+
|
|
2504
|
+
resource "aws_scheduler_schedule" "retry_dispatcher" {
|
|
2505
|
+
count = local.deploy_lambda_handlers ? 1 : 0
|
|
2506
|
+
|
|
2507
|
+
name = "thinkwork-${var.stage}-retry-dispatcher"
|
|
2508
|
+
group_name = "default"
|
|
2509
|
+
schedule_expression = "rate(1 minutes)"
|
|
2510
|
+
state = var.retry_dispatcher_enabled ? "ENABLED" : "DISABLED"
|
|
2511
|
+
|
|
2512
|
+
flexible_time_window {
|
|
2513
|
+
mode = "OFF"
|
|
2514
|
+
}
|
|
2515
|
+
|
|
2516
|
+
target {
|
|
2517
|
+
arn = aws_lambda_function.handler["cron-retry-dispatcher"].arn
|
|
2518
|
+
role_arn = aws_iam_role.scheduler.arn
|
|
2519
|
+
|
|
2520
|
+
retry_policy {
|
|
2521
|
+
maximum_retry_attempts = 0
|
|
2522
|
+
}
|
|
2523
|
+
}
|
|
2524
|
+
}
|
|
2525
|
+
|
|
2202
2526
|
|
|
2203
2527
|
# ---------------------------------------------------------------------------
|
|
2204
2528
|
# Compounding Memory — nightly hygiene + export
|
|
@@ -2447,6 +2771,27 @@ resource "aws_s3_bucket_lifecycle_configuration" "brain_artifacts" {
|
|
|
2447
2771
|
}
|
|
2448
2772
|
}
|
|
2449
2773
|
|
|
2774
|
+
# THINK-193 U1 (Codex F6): normalized evidence snapshots are short-lived
|
|
2775
|
+
# working copies — the durable record is the evidence row (hash + ref) and
|
|
2776
|
+
# the Hindsight projection. Expire content after 30 days; the app mirrors
|
|
2777
|
+
# this via memory_evidence_items.snapshot_expires_at.
|
|
2778
|
+
rule {
|
|
2779
|
+
id = "expire-evidence-snapshots"
|
|
2780
|
+
status = "Enabled"
|
|
2781
|
+
|
|
2782
|
+
filter {
|
|
2783
|
+
prefix = "evidence-snapshots/"
|
|
2784
|
+
}
|
|
2785
|
+
|
|
2786
|
+
expiration {
|
|
2787
|
+
days = 30
|
|
2788
|
+
}
|
|
2789
|
+
|
|
2790
|
+
noncurrent_version_expiration {
|
|
2791
|
+
noncurrent_days = 30
|
|
2792
|
+
}
|
|
2793
|
+
}
|
|
2794
|
+
|
|
2450
2795
|
rule {
|
|
2451
2796
|
id = "exports-expiration"
|
|
2452
2797
|
status = "Enabled"
|