thinkwork-cli 0.12.17 → 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
|
@@ -146,6 +146,31 @@ locals {
|
|
|
146
146
|
Action = ["s3:ListBucket"]
|
|
147
147
|
Resource = aws_s3_bucket.brain_artifacts.arn
|
|
148
148
|
},
|
|
149
|
+
# THINK-193 U2 (Codex S2 + round-6 P1): bulk/prefix destruction of
|
|
150
|
+
# evidence snapshots lives EXCLUSIVELY on the memory-retraction-drainer's
|
|
151
|
+
# dedicated role (handlers.tf). The SHARED role gets only the narrow
|
|
152
|
+
# erase-fence COMPENSATION capability: a stage worker that loses the
|
|
153
|
+
# fence mid-PutObject must delete the EXACT object version it just
|
|
154
|
+
# wrote (VersionId from its own PutObject response) and verify the key
|
|
155
|
+
# is gone. Without ListBucketVersions-driven enumeration + bulk delete
|
|
156
|
+
# this cannot destroy anything the caller did not itself write —
|
|
157
|
+
# version ids are unguessable. ListBucketVersions is granted read-only
|
|
158
|
+
# for the verification step, prefix-conditioned.
|
|
159
|
+
{
|
|
160
|
+
Effect = "Allow"
|
|
161
|
+
Action = ["s3:DeleteObjectVersion"]
|
|
162
|
+
Resource = "${aws_s3_bucket.brain_artifacts.arn}/evidence-snapshots/*"
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
Effect = "Allow"
|
|
166
|
+
Action = ["s3:ListBucketVersions"]
|
|
167
|
+
Resource = aws_s3_bucket.brain_artifacts.arn
|
|
168
|
+
Condition = {
|
|
169
|
+
StringLike = {
|
|
170
|
+
"s3:prefix" = "evidence-snapshots/*"
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
},
|
|
149
174
|
# (was inline policy "cognito-access")
|
|
150
175
|
{
|
|
151
176
|
Effect = "Allow"
|
|
@@ -394,6 +419,22 @@ locals {
|
|
|
394
419
|
}
|
|
395
420
|
},
|
|
396
421
|
] : [],
|
|
422
|
+
# THINK-280 — the headless capability executor (routine-exec-git) mints and
|
|
423
|
+
# advances the broker PoP session by conditional reads/writes on the broker's
|
|
424
|
+
# DynamoDB session table. Empty (→ no grant) when the broker is disabled.
|
|
425
|
+
var.capability_broker_session_table_arn != "" ? [
|
|
426
|
+
{
|
|
427
|
+
Effect = "Allow"
|
|
428
|
+
Action = [
|
|
429
|
+
"dynamodb:GetItem",
|
|
430
|
+
"dynamodb:PutItem",
|
|
431
|
+
"dynamodb:UpdateItem",
|
|
432
|
+
"dynamodb:DeleteItem",
|
|
433
|
+
"dynamodb:Query",
|
|
434
|
+
]
|
|
435
|
+
Resource = var.capability_broker_session_table_arn
|
|
436
|
+
},
|
|
437
|
+
] : [],
|
|
397
438
|
)
|
|
398
439
|
|
|
399
440
|
# ---------------------------------------------------------------------------
|
|
@@ -472,9 +513,13 @@ locals {
|
|
|
472
513
|
"arn:aws:lambda:${var.region}:${var.account_id}:function:thinkwork-${var.stage}-api-wiki-compile",
|
|
473
514
|
# knowledge-graph-observations-ingest: graphql-http's
|
|
474
515
|
# startKnowledgeGraphObservationsIngest mutation invokes this with
|
|
475
|
-
# RequestResponse
|
|
476
|
-
#
|
|
477
|
-
#
|
|
516
|
+
# RequestResponse, and memory-stage-worker's graph stage (THINK-193
|
|
517
|
+
# U4 stitch) RequestResponse-invokes it with a targeted bankIds
|
|
518
|
+
# payload — the Bedrock classifier/extraction model config lives on
|
|
519
|
+
# the ingest Lambda's own env, so the worker never runs the ingest
|
|
520
|
+
# in-process. (The worker's self-invoke drain is retired — AWS
|
|
521
|
+
# recursive-loop detection terminated those chains; backlog drains
|
|
522
|
+
# in-process now.)
|
|
478
523
|
"arn:aws:lambda:${var.region}:${var.account_id}:function:thinkwork-${var.stage}-api-knowledge-graph-observations-ingest",
|
|
479
524
|
# wiki-bootstrap-import: bootstrapJournalImport admin mutation
|
|
480
525
|
# Event-invokes this for the long-running ingest path.
|
|
@@ -518,6 +563,11 @@ locals {
|
|
|
518
563
|
# step RequestResponse-invokes its workflow-delivery mode to email
|
|
519
564
|
# the maintained report to the operator-configured recipient list.
|
|
520
565
|
"arn:aws:lambda:${var.region}:${var.account_id}:function:thinkwork-${var.stage}-api-artifact-deliver",
|
|
566
|
+
# memory-stage-worker (external-memory-compounding U1):
|
|
567
|
+
# workflow-step-dispatch's memory_stage step Event-invokes it after
|
|
568
|
+
# parking on the task token; the worker resumes the token via
|
|
569
|
+
# SendTaskSuccess when the pipeline stage ends.
|
|
570
|
+
"arn:aws:lambda:${var.region}:${var.account_id}:function:thinkwork-${var.stage}-api-memory-stage-worker",
|
|
521
571
|
# job-trigger self-target (plan 2026-07-03-004 U5, KTD-3): the
|
|
522
572
|
# manual GraphQL trigger Event-invokes job-trigger with the
|
|
523
573
|
# agent_loop_continue_dispatch event so routine actions never run
|
|
@@ -528,6 +578,12 @@ locals {
|
|
|
528
578
|
# triggers), and job-trigger's canvas_refresh branch RequestResponse-
|
|
529
579
|
# invokes it (scheduled trigger). Both run on this shared role.
|
|
530
580
|
"arn:aws:lambda:${var.region}:${var.account_id}:function:thinkwork-${var.stage}-api-canvas-refresh",
|
|
581
|
+
# agentcore-admin (THINK-280): graphql-http's createTenant
|
|
582
|
+
# RequestResponse-invokes it to provision per-tenant sandbox
|
|
583
|
+
# resources; routine-exec-git (same shared role) reaches it for the
|
|
584
|
+
# capability-private provisioning path. Deployed by the dedicated
|
|
585
|
+
# agentcore-admin module with its own least-privilege role.
|
|
586
|
+
"arn:aws:lambda:${var.region}:${var.account_id}:function:thinkwork-${var.stage}-api-agentcore-admin",
|
|
531
587
|
]
|
|
532
588
|
},
|
|
533
589
|
# (was standalone managed policy "workspace_renderer_invoke")
|
|
@@ -709,7 +765,7 @@ locals {
|
|
|
709
765
|
# Group 3: AI — Bedrock model invocation, Knowledge Bases, AgentCore
|
|
710
766
|
# memory / evaluations / code interpreter.
|
|
711
767
|
# ---------------------------------------------------------------------------
|
|
712
|
-
api_ai_statements = [
|
|
768
|
+
api_ai_statements = concat([
|
|
713
769
|
# (was inline policy "bedrock-invoke")
|
|
714
770
|
# Cross-region inference profiles (us.anthropic.claude-*) require
|
|
715
771
|
# `bedrock:InvokeModel` on the *inference-profile* ARN AND on the
|
|
@@ -750,6 +806,18 @@ locals {
|
|
|
750
806
|
"bedrock:GetIngestionJob",
|
|
751
807
|
"bedrock:ListIngestionJobs",
|
|
752
808
|
"bedrock:Retrieve",
|
|
809
|
+
# THINK-193 U7: knowledge-base-manager reconciles the per-document
|
|
810
|
+
# manifest after successful syncs (List/Get) and gates deletion
|
|
811
|
+
# settlement on Get + the scoped Retrieve above. Ingest/Delete cover
|
|
812
|
+
# the explicit direct-delete path for S3 RETAIN'd documents — the
|
|
813
|
+
# manager never races them with StartIngestionJob. The workspace-
|
|
814
|
+
# bucket S3 read the memory-stage-worker needs for document text is
|
|
815
|
+
# already granted by the shared role's workspace "s3-access"
|
|
816
|
+
# statement (data-plane group).
|
|
817
|
+
"bedrock:ListKnowledgeBaseDocuments",
|
|
818
|
+
"bedrock:GetKnowledgeBaseDocuments",
|
|
819
|
+
"bedrock:IngestKnowledgeBaseDocuments",
|
|
820
|
+
"bedrock:DeleteKnowledgeBaseDocuments",
|
|
753
821
|
]
|
|
754
822
|
# CreateKnowledgeBase/CreateDataSource have no resource ARN at create
|
|
755
823
|
# time and don't support resource-level scoping, so a knowledge-base/*
|
|
@@ -818,7 +886,65 @@ locals {
|
|
|
818
886
|
]
|
|
819
887
|
Resource = "*"
|
|
820
888
|
},
|
|
821
|
-
|
|
889
|
+
],
|
|
890
|
+
# THINK-311 U4 — AgentCore Harness trial invoker grants, present only when
|
|
891
|
+
# the agentcore-harness module is enabled (empty role ARN = module off).
|
|
892
|
+
# Ship-inert: no handler calls Harness until U5's harness-runner lands.
|
|
893
|
+
#
|
|
894
|
+
# CRITICAL: never grant `bedrock-agentcore:InvokeAgentRuntimeCommand`
|
|
895
|
+
# anywhere — it bypasses Harness allowedTools enforcement. Invocation goes
|
|
896
|
+
# through InvokeHarness / InvokeAgentRuntime only.
|
|
897
|
+
var.agentcore_harness_execution_role_arn != "" ? [
|
|
898
|
+
{
|
|
899
|
+
# Data plane — invoke a Harness (and its runtime endpoints) directly.
|
|
900
|
+
Sid = "AgentCoreHarnessInvoke"
|
|
901
|
+
Effect = "Allow"
|
|
902
|
+
Action = [
|
|
903
|
+
"bedrock-agentcore:InvokeHarness",
|
|
904
|
+
"bedrock-agentcore:InvokeAgentRuntime",
|
|
905
|
+
]
|
|
906
|
+
Resource = "arn:aws:bedrock-agentcore:${var.region}:${var.account_id}:harness/*"
|
|
907
|
+
},
|
|
908
|
+
{
|
|
909
|
+
# Control plane — CreateHarness has no resource ARN at create time
|
|
910
|
+
# (same non-scopable shape as bedrock:CreateKnowledgeBase above), so
|
|
911
|
+
# this statement is "*"; PassRole below stays scoped to the single
|
|
912
|
+
# Harness execution role.
|
|
913
|
+
Sid = "AgentCoreHarnessControl"
|
|
914
|
+
Effect = "Allow"
|
|
915
|
+
Action = [
|
|
916
|
+
"bedrock-agentcore:CreateHarness",
|
|
917
|
+
"bedrock-agentcore:GetHarness",
|
|
918
|
+
"bedrock-agentcore:UpdateHarness",
|
|
919
|
+
"bedrock-agentcore:DeleteHarness",
|
|
920
|
+
"bedrock-agentcore:CreateHarnessEndpoint",
|
|
921
|
+
"bedrock-agentcore:GetHarnessEndpoint",
|
|
922
|
+
"bedrock-agentcore:ListHarnessEndpoints",
|
|
923
|
+
"bedrock-agentcore:ListHarnesses",
|
|
924
|
+
"bedrock-agentcore:ListHarnessVersions",
|
|
925
|
+
]
|
|
926
|
+
Resource = "*"
|
|
927
|
+
},
|
|
928
|
+
] : [],
|
|
929
|
+
# (Separate conditional from the two statements above only because the
|
|
930
|
+
# Condition attribute gives this object a different Terraform type —
|
|
931
|
+
# same gate, same feature.)
|
|
932
|
+
var.agentcore_harness_execution_role_arn != "" ? [
|
|
933
|
+
{
|
|
934
|
+
# CreateHarness takes executionRoleArn; the caller must be able to
|
|
935
|
+
# pass exactly that role, and only to the bedrock-agentcore service.
|
|
936
|
+
Sid = "AgentCoreHarnessPassExecutionRole"
|
|
937
|
+
Effect = "Allow"
|
|
938
|
+
Action = ["iam:PassRole"]
|
|
939
|
+
Resource = var.agentcore_harness_execution_role_arn
|
|
940
|
+
Condition = {
|
|
941
|
+
StringEquals = {
|
|
942
|
+
"iam:PassedToService" = "bedrock-agentcore.amazonaws.com"
|
|
943
|
+
}
|
|
944
|
+
}
|
|
945
|
+
},
|
|
946
|
+
] : [],
|
|
947
|
+
)
|
|
822
948
|
|
|
823
949
|
# ---------------------------------------------------------------------------
|
|
824
950
|
# Group 4: observability — CloudWatch Logs reads, ECS/ALB health reads.
|
|
@@ -20,6 +20,17 @@ data "aws_caller_identity" "current" {}
|
|
|
20
20
|
|
|
21
21
|
locals {
|
|
22
22
|
okf_efs_vpc_enabled = length(var.okf_efs_subnet_ids) > 0 && length(var.okf_efs_security_group_ids) > 0
|
|
23
|
+
# Handlers that open direct Postgres connections to registered analyst data
|
|
24
|
+
# sources. VPC-attaching them (analyst_egress_subnet_ids) gives their egress
|
|
25
|
+
# the NAT gateway's stable EIP, which external databases behind an IP
|
|
26
|
+
# allowlist can admit — a non-VPC Lambda egresses from the shared AWS pool
|
|
27
|
+
# and can never satisfy such an allowlist.
|
|
28
|
+
analyst_vpc_enabled = length(var.analyst_egress_subnet_ids) > 0 && length(var.analyst_egress_security_group_ids) > 0
|
|
29
|
+
analyst_vpc_handlers = toset([
|
|
30
|
+
"graphql-http",
|
|
31
|
+
"analyst-query-broker",
|
|
32
|
+
"analyst-connection-reconciler",
|
|
33
|
+
])
|
|
23
34
|
# Constructed rather than read from aws_apigatewayv2_stage.default.invoke_url
|
|
24
35
|
# (the two are identical for an HTTP API's $default stage). Reading it off
|
|
25
36
|
# the stage made every Lambda's env depend on the stage, which forbids the
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# THINK-193 U8 — external-memory compounding observability.
|
|
2
|
+
#
|
|
3
|
+
# Alarms here fire from metrics that EXIST without any log-group management:
|
|
4
|
+
# - AWS/Lambda Errors for the memory-stage worker and the retraction drainer
|
|
5
|
+
# (handler crashes, including ones that never reach a log line);
|
|
6
|
+
# - the wiki-compile DLQ depth (the only memory-path Lambda with an
|
|
7
|
+
# on_failure destination).
|
|
8
|
+
#
|
|
9
|
+
# DELIBERATELY NOT HERE — log-metric filters over the drainer's structured
|
|
10
|
+
# summary line and the worker's "status=failed" line. They require the
|
|
11
|
+
# /aws/lambda/<function> log groups, which only exist after a function's first
|
|
12
|
+
# invocation: PutMetricFilter failed with ResourceNotFoundException on customer
|
|
13
|
+
# stages taking a fresh release (dev passed only because its groups already
|
|
14
|
+
# existed). Managing the groups in Terraform instead needs a coordinated state
|
|
15
|
+
# import on every stage that already has the implicit group, so it is a
|
|
16
|
+
# follow-up. Until then, drainer errors / dead-letters and stage failures are
|
|
17
|
+
# observable through the structured logs and
|
|
18
|
+
# packages/api/scripts/external-memory-readiness.ts (which reports due,
|
|
19
|
+
# failed, and dead-lettered attempts directly from the ledger).
|
|
20
|
+
#
|
|
21
|
+
# Also runbook-only (no metric exists): source checkpoint age, graph-to-wiki
|
|
22
|
+
# lag, evidence lag, deferred identity count/age.
|
|
23
|
+
#
|
|
24
|
+
# alarm_actions are empty: the only SNS topic in this module
|
|
25
|
+
# (aws_sns_topic.cost_alerts) is the cost-alert channel — wiring memory alarms
|
|
26
|
+
# into it would misroute pages. Operators subscribe a topic when the rollout
|
|
27
|
+
# needs paging.
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
resource "aws_cloudwatch_metric_alarm" "memory_stage_worker_lambda_errors" {
|
|
31
|
+
count = local.deploy_lambda_handlers ? 1 : 0
|
|
32
|
+
|
|
33
|
+
alarm_name = "thinkwork-${var.stage}-memory-stage-worker-lambda-errors"
|
|
34
|
+
alarm_description = "memory-stage-worker Lambda crashed (unhandled error, retries pinned to 0, no failure destination) — the parked workflow run will need a redrive."
|
|
35
|
+
namespace = "AWS/Lambda"
|
|
36
|
+
metric_name = "Errors"
|
|
37
|
+
statistic = "Sum"
|
|
38
|
+
period = 300
|
|
39
|
+
evaluation_periods = 1
|
|
40
|
+
threshold = 1
|
|
41
|
+
comparison_operator = "GreaterThanOrEqualToThreshold"
|
|
42
|
+
treat_missing_data = "notBreaching"
|
|
43
|
+
alarm_actions = []
|
|
44
|
+
|
|
45
|
+
dimensions = {
|
|
46
|
+
FunctionName = aws_lambda_function.handler["memory-stage-worker"].function_name
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
resource "aws_cloudwatch_metric_alarm" "memory_retraction_drainer_lambda_errors" {
|
|
51
|
+
count = local.deploy_lambda_handlers ? 1 : 0
|
|
52
|
+
|
|
53
|
+
alarm_name = "thinkwork-${var.stage}-memory-retraction-drainer-lambda-errors"
|
|
54
|
+
alarm_description = "memory-retraction-drainer Lambda crashed before emitting its summary line — due retraction work is stalled until the next scheduled tick succeeds."
|
|
55
|
+
namespace = "AWS/Lambda"
|
|
56
|
+
metric_name = "Errors"
|
|
57
|
+
statistic = "Sum"
|
|
58
|
+
period = 300
|
|
59
|
+
evaluation_periods = 1
|
|
60
|
+
threshold = 1
|
|
61
|
+
comparison_operator = "GreaterThanOrEqualToThreshold"
|
|
62
|
+
treat_missing_data = "notBreaching"
|
|
63
|
+
alarm_actions = []
|
|
64
|
+
|
|
65
|
+
dimensions = {
|
|
66
|
+
FunctionName = aws_lambda_function.handler["memory-retraction-drainer"].function_name
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
# ---------------------------------------------------------------------------
|
|
71
|
+
# wiki-compile DLQ depth (graph → wiki handoff failures)
|
|
72
|
+
# ---------------------------------------------------------------------------
|
|
73
|
+
|
|
74
|
+
resource "aws_cloudwatch_metric_alarm" "wiki_compile_dlq_depth" {
|
|
75
|
+
count = local.deploy_lambda_handlers ? 1 : 0
|
|
76
|
+
|
|
77
|
+
alarm_name = "thinkwork-${var.stage}-wiki-compile-dlq-depth"
|
|
78
|
+
alarm_description = "wiki-compile DLQ has messages — a compile invocation crashed before the job ledger recorded an outcome; canonical pages are stale until replayed."
|
|
79
|
+
namespace = "AWS/SQS"
|
|
80
|
+
metric_name = "ApproximateNumberOfMessagesVisible"
|
|
81
|
+
statistic = "Maximum"
|
|
82
|
+
period = 60
|
|
83
|
+
evaluation_periods = 1
|
|
84
|
+
threshold = 1
|
|
85
|
+
comparison_operator = "GreaterThanOrEqualToThreshold"
|
|
86
|
+
treat_missing_data = "notBreaching"
|
|
87
|
+
alarm_actions = []
|
|
88
|
+
|
|
89
|
+
dimensions = {
|
|
90
|
+
QueueName = aws_sqs_queue.wiki_compile_dlq[0].name
|
|
91
|
+
}
|
|
92
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
################################################################################
|
|
2
|
+
# Microsoft Teams app credentials
|
|
3
|
+
#
|
|
4
|
+
# Stored in Secrets Manager as a JSON blob with two fields:
|
|
5
|
+
#
|
|
6
|
+
# {
|
|
7
|
+
# "app_id": "Teams (Entra) app registration / bot app id",
|
|
8
|
+
# "client_secret": "Entra app client secret"
|
|
9
|
+
# }
|
|
10
|
+
#
|
|
11
|
+
# The Teams install + account-link handlers receive only this secret ARN in
|
|
12
|
+
# Lambda configuration. The client_secret doubles as the HMAC signing key for
|
|
13
|
+
# install state and account-link tokens — transport-only material that must
|
|
14
|
+
# never appear in logs or responses. The shared Lambda role already has
|
|
15
|
+
# access to the `thinkwork/*` prefix, so no additional IAM attachment is
|
|
16
|
+
# needed (same as the Slack app credentials secret).
|
|
17
|
+
#
|
|
18
|
+
# Operators populate the real value out-of-band. Terraform creates an initial
|
|
19
|
+
# empty version so Lambdas fail with a clear missing-field error before setup,
|
|
20
|
+
# and lifecycle.ignore_changes prevents later applies from overwriting rotated
|
|
21
|
+
# credentials.
|
|
22
|
+
################################################################################
|
|
23
|
+
|
|
24
|
+
resource "aws_secretsmanager_secret" "msteams_app_credentials" {
|
|
25
|
+
count = var.enable_msteams_app ? 1 : 0
|
|
26
|
+
name = "thinkwork/${var.stage}/msteams/app"
|
|
27
|
+
description = "Microsoft Teams app credentials (app_id, client_secret). Populate via Secrets Manager; never via tfvars."
|
|
28
|
+
tags = {
|
|
29
|
+
Name = "thinkwork-${var.stage}-msteams-app"
|
|
30
|
+
Stage = var.stage
|
|
31
|
+
Provider = "msteams"
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
resource "aws_secretsmanager_secret_version" "msteams_app_credentials_initial" {
|
|
36
|
+
count = var.enable_msteams_app ? 1 : 0
|
|
37
|
+
secret_id = aws_secretsmanager_secret.msteams_app_credentials[0].id
|
|
38
|
+
secret_string = jsonencode({
|
|
39
|
+
app_id = ""
|
|
40
|
+
client_secret = ""
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
lifecycle {
|
|
44
|
+
ignore_changes = [secret_string]
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -146,6 +146,12 @@ variable "kb_service_role_arn" {
|
|
|
146
146
|
type = string
|
|
147
147
|
}
|
|
148
148
|
|
|
149
|
+
variable "agentcore_harness_execution_role_arn" {
|
|
150
|
+
description = "AgentCore Harness execution role ARN (THINK-311 U4). Empty string (harness module disabled) omits the Harness invoker grants from the grouped ai policy."
|
|
151
|
+
type = string
|
|
152
|
+
default = ""
|
|
153
|
+
}
|
|
154
|
+
|
|
149
155
|
variable "certificate_arn" {
|
|
150
156
|
description = "ACM certificate ARN for custom API domain"
|
|
151
157
|
type = string
|
|
@@ -238,6 +244,18 @@ variable "brain_dream_state_schedule_expression" {
|
|
|
238
244
|
default = "cron(0 5 * * ? *)"
|
|
239
245
|
}
|
|
240
246
|
|
|
247
|
+
variable "retry_dispatcher_enabled" {
|
|
248
|
+
description = "Enable the recurring retry-dispatcher schedule (THINK-307). Never enable on a stage before THINK-305, THINK-308, and THINK-309 are live there (parent plan deploy ordering); manual invokes work regardless."
|
|
249
|
+
type = bool
|
|
250
|
+
default = false
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
variable "stall_threshold_minutes" {
|
|
254
|
+
description = "Minutes of turn inactivity before the stall monitor marks a running turn timed_out; the retry dispatcher reads the same knob as its origin-freshness guard (THINK-306/THINK-307 — one knob, two consumers)."
|
|
255
|
+
type = number
|
|
256
|
+
default = 5
|
|
257
|
+
}
|
|
258
|
+
|
|
241
259
|
variable "extension_proxy_signing_secret" {
|
|
242
260
|
description = "Shared HMAC secret used by the generic Admin extension proxy to sign actor context for extension backends."
|
|
243
261
|
type = string
|
|
@@ -273,6 +291,18 @@ variable "memory_engine" {
|
|
|
273
291
|
}
|
|
274
292
|
}
|
|
275
293
|
|
|
294
|
+
variable "analyst_egress_subnet_ids" {
|
|
295
|
+
description = "Private (NAT-routed) subnet IDs for VPC-attaching the analyst data-path handlers (graphql-http, analyst-query-broker, analyst-connection-reconciler) so external Postgres sources can allowlist the stack's stable NAT egress IP. Leave empty to keep the handlers outside any VPC."
|
|
296
|
+
type = list(string)
|
|
297
|
+
default = []
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
variable "analyst_egress_security_group_ids" {
|
|
301
|
+
description = "Security group IDs for the VPC-attached analyst data-path handlers. Leave empty to keep the handlers outside any VPC."
|
|
302
|
+
type = list(string)
|
|
303
|
+
default = []
|
|
304
|
+
}
|
|
305
|
+
|
|
276
306
|
variable "okf_efs_subnet_ids" {
|
|
277
307
|
description = "Subnet IDs for the OKF EFS hydrator Lambda VPC attachment. Leave empty to deploy the hydrator without an EFS mount."
|
|
278
308
|
type = list(string)
|
|
@@ -435,6 +465,12 @@ variable "enable_slack_workspace_app" {
|
|
|
435
465
|
default = true
|
|
436
466
|
}
|
|
437
467
|
|
|
468
|
+
variable "enable_msteams_app" {
|
|
469
|
+
description = "Provision Microsoft Teams app Lambdas, API routes, and credentials placeholder secret."
|
|
470
|
+
type = bool
|
|
471
|
+
default = false
|
|
472
|
+
}
|
|
473
|
+
|
|
438
474
|
variable "appsync_realtime_url" {
|
|
439
475
|
description = "AppSync realtime/WebSocket endpoint URL"
|
|
440
476
|
type = string
|
|
@@ -790,6 +826,12 @@ variable "analyst_policy_source" {
|
|
|
790
826
|
}
|
|
791
827
|
}
|
|
792
828
|
|
|
829
|
+
variable "capability_self_extension_tenants" {
|
|
830
|
+
description = "Governed autonomy opt-in: comma/space-separated tenant ids allowed to autonomously self-extend capabilities (self_admit_connection / self_approve_routine). Empty (default) = NO tenant enabled; self-extension ships inert and fail-closed. Read via getConfig() in capability-control-service."
|
|
831
|
+
type = string
|
|
832
|
+
default = ""
|
|
833
|
+
}
|
|
834
|
+
|
|
793
835
|
variable "analyst_db_cluster_resource_id" {
|
|
794
836
|
description = "Immutable RDS cluster resource ID (cluster-XXXX / db-XXXX) for the stage database (THINK-229 U1). Wired from `module.database.cluster_resource_id`. Keys the broker's `rds-db:connect` IAM grant — the rds-db ARN format requires the resource ID, not the cluster ARN — and gates the IAM connect env on the broker Lambda: when empty, the broker stays on the password path."
|
|
795
837
|
type = string
|
|
@@ -801,3 +843,53 @@ variable "artifact_delivery_from_email" {
|
|
|
801
843
|
type = string
|
|
802
844
|
default = ""
|
|
803
845
|
}
|
|
846
|
+
|
|
847
|
+
variable "enable_capability_broker" {
|
|
848
|
+
description = "THINK-280 U8 rollout gate (default off). When true, the governed capability runtime's external MCP search facade (/mcp/capabilities) and the Inspector governed-runtime operation layer are enabled for the stage. The external-search leg is the LAST rollout stage (shadow → internal search → private broker dogfood → promotion/tracer → external search): keep this false until the earlier stages are proven for the stage. When false every U8 surface is inert and returns no data — the handler and route still deploy, but read nothing."
|
|
849
|
+
type = bool
|
|
850
|
+
default = false
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
# THINK-280 — sandbox provisioning + capability broker wiring. -----------------
|
|
854
|
+
variable "agentcore_admin_lambda_arn" {
|
|
855
|
+
description = "ARN of the agentcore-admin Lambda (AGENTCORE_ADMIN_LAMBDA_ARN on graphql-http). createTenant RequestResponse-invokes it. Empty when the Lambda is not deployed."
|
|
856
|
+
type = string
|
|
857
|
+
default = ""
|
|
858
|
+
}
|
|
859
|
+
|
|
860
|
+
variable "agentcore_admin_token" {
|
|
861
|
+
description = "Bearer token graphql-http presents when invoking agentcore-admin (AGENTCORE_ADMIN_TOKEN). Must match the token the admin Lambda validates. Empty when not deployed."
|
|
862
|
+
type = string
|
|
863
|
+
sensitive = true
|
|
864
|
+
default = ""
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
variable "capability_broker_session_table" {
|
|
868
|
+
description = "DynamoDB broker session table name (CAPABILITY_BROKER_SESSION_TABLE). Empty when the broker is disabled."
|
|
869
|
+
type = string
|
|
870
|
+
default = ""
|
|
871
|
+
}
|
|
872
|
+
|
|
873
|
+
variable "capability_broker_session_table_arn" {
|
|
874
|
+
description = "ARN of the broker session table — grants routine-exec-git DynamoDB access to mint/advance PoP sessions. Empty when the broker is disabled (no grant)."
|
|
875
|
+
type = string
|
|
876
|
+
default = ""
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
variable "capability_broker_audience" {
|
|
880
|
+
description = "Capability broker PoP audience (CAPABILITY_BROKER_AUDIENCE). Empty when the broker is disabled."
|
|
881
|
+
type = string
|
|
882
|
+
default = ""
|
|
883
|
+
}
|
|
884
|
+
|
|
885
|
+
variable "capability_broker_api_id" {
|
|
886
|
+
description = "Capability broker private REST API id (CAPABILITY_BROKER_API_ID). Empty when the broker is disabled."
|
|
887
|
+
type = string
|
|
888
|
+
default = ""
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
variable "capability_broker_vpce_dns" {
|
|
892
|
+
description = "Capability broker execute-api VPCE DNS name (CAPABILITY_BROKER_VPCE_DNS). Empty when the broker is disabled."
|
|
893
|
+
type = string
|
|
894
|
+
default = ""
|
|
895
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# THINK-193 U8 — workflow-interpreter execution failure alarms.
|
|
2
|
+
#
|
|
3
|
+
# Terminal FAILED/TIMED_OUT/ABORTED executions are projected onto the run
|
|
4
|
+
# row by workflow-execution-callback (DB, not a parseable log line), so the
|
|
5
|
+
# reliable infrastructure signal is the Step Functions service metrics on
|
|
6
|
+
# the interpreter state machine itself. Memory workflows (personal +
|
|
7
|
+
# shared) execute through this machine — an execution failure here is the
|
|
8
|
+
# "workflow-interpreter execution failures" rollout gate signal.
|
|
9
|
+
#
|
|
10
|
+
# alarm_actions are empty: no paging SNS topic exists in this module.
|
|
11
|
+
# Operators subscribe one when the rollout needs paging.
|
|
12
|
+
|
|
13
|
+
resource "aws_cloudwatch_metric_alarm" "interpreter_executions_failed" {
|
|
14
|
+
alarm_name = "thinkwork-${var.stage}-workflow-interpreter-executions-failed"
|
|
15
|
+
alarm_description = "Workflow-interpreter Step Functions executions FAILED — check the run's timeline (workflow_step_failed events) and the execution history."
|
|
16
|
+
namespace = "AWS/States"
|
|
17
|
+
metric_name = "ExecutionsFailed"
|
|
18
|
+
statistic = "Sum"
|
|
19
|
+
period = 300
|
|
20
|
+
evaluation_periods = 1
|
|
21
|
+
threshold = 1
|
|
22
|
+
comparison_operator = "GreaterThanOrEqualToThreshold"
|
|
23
|
+
treat_missing_data = "notBreaching"
|
|
24
|
+
alarm_actions = []
|
|
25
|
+
|
|
26
|
+
dimensions = {
|
|
27
|
+
StateMachineArn = aws_sfn_state_machine.interpreter.arn
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
resource "aws_cloudwatch_metric_alarm" "interpreter_executions_timed_out" {
|
|
32
|
+
alarm_name = "thinkwork-${var.stage}-workflow-interpreter-executions-timed-out"
|
|
33
|
+
alarm_description = "Workflow-interpreter Step Functions executions TIMED_OUT — a parked task token (approval / memory stage) was never resolved within the execution timeout."
|
|
34
|
+
namespace = "AWS/States"
|
|
35
|
+
metric_name = "ExecutionsTimedOut"
|
|
36
|
+
statistic = "Sum"
|
|
37
|
+
period = 300
|
|
38
|
+
evaluation_periods = 1
|
|
39
|
+
threshold = 1
|
|
40
|
+
comparison_operator = "GreaterThanOrEqualToThreshold"
|
|
41
|
+
treat_missing_data = "notBreaching"
|
|
42
|
+
alarm_actions = []
|
|
43
|
+
|
|
44
|
+
dimensions = {
|
|
45
|
+
StateMachineArn = aws_sfn_state_machine.interpreter.arn
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -211,8 +211,8 @@ resource "aws_iam_role_policy" "execution_states" {
|
|
|
211
211
|
#
|
|
212
212
|
# See KTD1 for the loop shape. Directives are the FROZEN protocol the
|
|
213
213
|
# step-dispatch Lambda emits: dispatch_agent, wait_until, execute_step,
|
|
214
|
-
# await_approval, continue, rollover, terminal_success,
|
|
215
|
-
# terminal_canceled.
|
|
214
|
+
# await_approval, await_memory_stage, continue, rollover, terminal_success,
|
|
215
|
+
# terminal_failure, terminal_canceled.
|
|
216
216
|
################################################################################
|
|
217
217
|
|
|
218
218
|
resource "aws_sfn_state_machine" "interpreter" {
|
|
@@ -254,6 +254,7 @@ resource "aws_sfn_state_machine" "interpreter" {
|
|
|
254
254
|
{ Variable = "$.directive", StringEquals = "wait_until", Next = "WaitState" },
|
|
255
255
|
{ Variable = "$.directive", StringEquals = "execute_step", Next = "ExecuteStep" },
|
|
256
256
|
{ Variable = "$.directive", StringEquals = "await_approval", Next = "ApprovalStep" },
|
|
257
|
+
{ Variable = "$.directive", StringEquals = "await_memory_stage", Next = "MemoryStageStep" },
|
|
257
258
|
{ Variable = "$.directive", StringEquals = "continue", Next = "LoadNextStep" },
|
|
258
259
|
{ Variable = "$.directive", StringEquals = "rollover", Next = "RolloverStart" },
|
|
259
260
|
{ Variable = "$.directive", StringEquals = "terminal_success", Next = "SucceedState" },
|
|
@@ -369,6 +370,46 @@ resource "aws_sfn_state_machine" "interpreter" {
|
|
|
369
370
|
Next = "DirectiveChoice"
|
|
370
371
|
}
|
|
371
372
|
|
|
373
|
+
# ---- Memory-stage step: park on a task token while the async memory-
|
|
374
|
+
# stage worker runs one pipeline stage; the await phase Event-invokes the
|
|
375
|
+
# worker, which resumes the token via SendTaskSuccess with a result JSON.
|
|
376
|
+
MemoryStageStep = {
|
|
377
|
+
Type = "Task"
|
|
378
|
+
Resource = "arn:aws:states:::lambda:invoke.waitForTaskToken"
|
|
379
|
+
Parameters = {
|
|
380
|
+
FunctionName = local.step_dispatch_lambda_arn
|
|
381
|
+
Payload = {
|
|
382
|
+
phase = "await_memory_stage"
|
|
383
|
+
"cursor.$" = "$.cursor"
|
|
384
|
+
"taskToken.$" = "$$.Task.Token"
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
ResultPath = "$.result"
|
|
388
|
+
TimeoutSeconds = 7200
|
|
389
|
+
HeartbeatSeconds = 3600
|
|
390
|
+
Catch = [{
|
|
391
|
+
ErrorEquals = ["States.Timeout"]
|
|
392
|
+
Next = "FailState"
|
|
393
|
+
}]
|
|
394
|
+
Next = "RecordMemoryStage"
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
RecordMemoryStage = {
|
|
398
|
+
Type = "Task"
|
|
399
|
+
Resource = "arn:aws:states:::lambda:invoke"
|
|
400
|
+
Parameters = {
|
|
401
|
+
FunctionName = local.step_dispatch_lambda_arn
|
|
402
|
+
Payload = {
|
|
403
|
+
phase = "record_memory_stage"
|
|
404
|
+
"cursor.$" = "$.cursor"
|
|
405
|
+
"result.$" = "$.result"
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
OutputPath = "$.Payload"
|
|
409
|
+
Retry = local.lambda_invoke_retry
|
|
410
|
+
Next = "DirectiveChoice"
|
|
411
|
+
}
|
|
412
|
+
|
|
372
413
|
# ---- Record the step outcome, evaluate policy, emit the next directive -
|
|
373
414
|
RecordAdvance = {
|
|
374
415
|
Type = "Task"
|
|
@@ -7,9 +7,12 @@
|
|
|
7
7
|
################################################################################
|
|
8
8
|
|
|
9
9
|
locals {
|
|
10
|
-
create
|
|
11
|
-
create_pre_signup
|
|
12
|
-
|
|
10
|
+
create = var.create_cognito
|
|
11
|
+
create_pre_signup = local.create && var.pre_signup_lambda_zip != ""
|
|
12
|
+
use_local_custom_auth_artifact = trimspace(var.custom_auth_lambda_zip) != ""
|
|
13
|
+
use_remote_custom_auth_artifact = trimspace(var.custom_auth_lambda_s3_bucket) != ""
|
|
14
|
+
custom_auth_artifact_count = (local.use_local_custom_auth_artifact ? 1 : 0) + (local.use_remote_custom_auth_artifact ? 1 : 0)
|
|
15
|
+
create_custom_auth = local.create && local.custom_auth_artifact_count == 1
|
|
13
16
|
|
|
14
17
|
user_pool_id = local.create ? aws_cognito_user_pool.main[0].id : var.existing_user_pool_id
|
|
15
18
|
user_pool_arn = local.create ? aws_cognito_user_pool.main[0].arn : var.existing_user_pool_arn
|
|
@@ -24,6 +27,22 @@ locals {
|
|
|
24
27
|
}
|
|
25
28
|
}
|
|
26
29
|
|
|
30
|
+
resource "terraform_data" "custom_auth_artifact_validation" {
|
|
31
|
+
input = local.custom_auth_artifact_count
|
|
32
|
+
|
|
33
|
+
lifecycle {
|
|
34
|
+
precondition {
|
|
35
|
+
condition = local.custom_auth_artifact_count <= 1
|
|
36
|
+
error_message = "Set only one Cognito custom-auth Lambda artifact source: custom_auth_lambda_zip or custom_auth_lambda_s3_bucket/custom_auth_lambda_s3_key."
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
precondition {
|
|
40
|
+
condition = !local.use_remote_custom_auth_artifact || trimspace(var.custom_auth_lambda_s3_key) != ""
|
|
41
|
+
error_message = "custom_auth_lambda_s3_key must be set when custom_auth_lambda_s3_bucket is set."
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
27
46
|
data "aws_caller_identity" "current" {}
|
|
28
47
|
|
|
29
48
|
################################################################################
|
|
@@ -97,7 +116,10 @@ resource "aws_lambda_permission" "cognito_pre_signup" {
|
|
|
97
116
|
|
|
98
117
|
resource "aws_iam_role" "custom_auth" {
|
|
99
118
|
count = local.create_custom_auth ? 1 : 0
|
|
100
|
-
name
|
|
119
|
+
# Release deployments use a distinct managed name so the first convergent
|
|
120
|
+
# apply does not collide with custom-auth Lambdas created during the legacy
|
|
121
|
+
# manual rollout. Local source deployments retain the original name.
|
|
122
|
+
name = local.use_remote_custom_auth_artifact ? "thinkwork-${var.stage}-cognito-custom-auth-release-role" : "thinkwork-${var.stage}-cognito-custom-auth-role"
|
|
101
123
|
|
|
102
124
|
assume_role_policy = jsonencode({
|
|
103
125
|
Version = "2012-10-17"
|
|
@@ -117,8 +139,10 @@ resource "aws_iam_role_policy_attachment" "custom_auth_basic" {
|
|
|
117
139
|
|
|
118
140
|
resource "aws_lambda_function" "custom_auth" {
|
|
119
141
|
count = local.create_custom_auth ? 1 : 0
|
|
120
|
-
function_name = "thinkwork-${var.stage}-cognito-custom-auth"
|
|
121
|
-
filename = var.custom_auth_lambda_zip
|
|
142
|
+
function_name = local.use_remote_custom_auth_artifact ? "thinkwork-${var.stage}-cognito-custom-auth-release" : "thinkwork-${var.stage}-cognito-custom-auth"
|
|
143
|
+
filename = local.use_local_custom_auth_artifact ? var.custom_auth_lambda_zip : null
|
|
144
|
+
s3_bucket = local.use_remote_custom_auth_artifact ? var.custom_auth_lambda_s3_bucket : null
|
|
145
|
+
s3_key = local.use_remote_custom_auth_artifact ? var.custom_auth_lambda_s3_key : null
|
|
122
146
|
handler = "index.handler"
|
|
123
147
|
runtime = "nodejs20.x"
|
|
124
148
|
timeout = 10
|
|
@@ -130,12 +154,12 @@ resource "aws_lambda_function" "custom_auth" {
|
|
|
130
154
|
}
|
|
131
155
|
}
|
|
132
156
|
|
|
133
|
-
source_code_hash = filebase64sha256(var.custom_auth_lambda_zip)
|
|
157
|
+
source_code_hash = local.use_local_custom_auth_artifact ? filebase64sha256(var.custom_auth_lambda_zip) : null
|
|
134
158
|
|
|
135
159
|
lifecycle {
|
|
136
160
|
precondition {
|
|
137
161
|
condition = var.api_auth_secret != ""
|
|
138
|
-
error_message = "
|
|
162
|
+
error_message = "A Cognito custom-auth Lambda artifact requires api_auth_secret so custom-auth challenges can be verified."
|
|
139
163
|
}
|
|
140
164
|
}
|
|
141
165
|
}
|