thinkwork-cli 0.13.0 → 0.13.2
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-JYZXYQJR.js} +3 -1
- package/dist/bowser-6Z6JFAIR.js +2822 -0
- package/dist/chunk-DV3MRBR5.js +43 -0
- package/dist/chunk-DVPBI5HM.js +1728 -0
- package/dist/chunk-EI5ZX7CN.js +522 -0
- package/dist/chunk-EUJ7X6YD.js +126 -0
- package/dist/chunk-GG5WKBOX.js +436 -0
- package/dist/chunk-I64EZSU5.js +358 -0
- package/dist/chunk-ILZKG5WV.js +6151 -0
- package/dist/chunk-KMIJ5KGT.js +128 -0
- package/dist/chunk-OCPHU34C.js +996 -0
- package/dist/chunk-QOERT44A.js +3286 -0
- package/dist/chunk-XYM7PE2A.js +2264 -0
- package/dist/{chunk-STY44FQO.js → chunk-Z2F6RJFR.js} +12 -18
- package/dist/cli.js +72564 -18884
- package/dist/dist-es-CRV46D5B.js +315 -0
- package/dist/dist-es-DCY4IC3Y.js +2000 -0
- package/dist/dist-es-ENBUC3JP.js +14726 -0
- package/dist/dist-es-G54LBMRN.js +48 -0
- package/dist/dist-es-G7PTG75M.js +176 -0
- package/dist/dist-es-GKDBE7E6.js +88 -0
- package/dist/dist-es-HY3535OI.js +70 -0
- package/dist/dist-es-KL7Y5NB2.js +377 -0
- package/dist/dist-es-LDE437AM.js +170 -0
- package/dist/dist-es-P26FWFLT.js +485 -0
- package/dist/dist-es-Q57SZXZ7.js +70 -0
- package/dist/dist-es-R7FGL2IB.js +88 -0
- package/dist/dist-es-USORBXZ5.js +318 -0
- package/dist/dist-es-ZKC2QKD2.js +377 -0
- package/dist/drizzle/0076_scheduled_jobs_marco_backfill.sql +2 -1
- package/dist/drizzle/0079_seed_tenant_customize_catalog.sql +1 -0
- package/dist/drizzle/0090_brain_schema_extraction.sql +10 -0
- package/dist/drizzle/0132_drop_computer_tables.sql +3 -0
- package/dist/drizzle/0160_compliance_event_types_plugins.sql +2 -0
- package/dist/drizzle/0214_think137_drop_judge_evidence_roi.sql +1 -0
- package/dist/drizzle/0216_drop_agent_loop_versions_goal_worker_policy.sql +1 -0
- package/dist/drizzle/0227_analyst_reader_role.sql +106 -38
- package/dist/drizzle/0230_analyst_rls.sql +192 -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 +576 -0
- package/dist/drizzle/0251_agents_json_render_ui.sql +25 -0
- package/dist/drizzle/0251_brain_stragglers.sql +263 -0
- package/dist/drizzle/0252_drop_kg_and_straggler_compat_views.sql +100 -0
- package/dist/drizzle/0253_drop_brain_substrate.sql +93 -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_agents_runtime_allow_harness.sql +24 -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_managed_harness_multiplayer.sql +313 -0
- package/dist/drizzle/0261_native_auth_control_plane.sql +328 -0
- package/dist/drizzle/0262_auth_subscription_tickets.sql +59 -0
- package/dist/drizzle/0262_parallel_harness_threads.sql +9 -0
- package/dist/drizzle/0263_agentcore_runtime_identifier.sql +69 -0
- package/dist/drizzle/0263_drop_workos_auth_runtime.sql +236 -0
- package/dist/drizzle/0264_auth_enrollment_attempt_limits.sql +15 -0
- package/dist/drizzle/0264_harness_tool_execution_ledger.sql +113 -0
- package/dist/drizzle/0265_eval_runs_requester_identity.sql +28 -0
- package/dist/drizzle/0265_require_fully_valid_auth_publication.sql +27 -0
- package/dist/drizzle/0266_auth_identity_recovery_grants.sql +9 -0
- package/dist/drizzle/0266_eval_profiles_runtime_type.sql +12 -0
- package/dist/drizzle/0267_ontology_candidate_rejections.sql +53 -0
- package/dist/drizzle/0268_identity_crosswalk_routing.sql +182 -0
- package/dist/drizzle/0269_ontology_system_map.sql +31 -0
- package/dist/event-streams-7JNLJEEL.js +894 -0
- package/dist/event-streams-KDF5RWR6.js +1515 -0
- package/dist/loadSso-DJVB7BXE.js +576 -0
- package/dist/loadSso-JAMNA3WY.js +583 -0
- package/dist/plugins/catalog/package.json +1 -2
- package/dist/plugins/catalog/src/__tests__/build-catalog.test.ts +0 -1
- package/dist/plugins/catalog/src/__tests__/contracts.test.ts +0 -69
- package/dist/plugins/catalog/src/__tests__/plugin-package.test.ts +0 -2
- package/dist/plugins/catalog/src/__tests__/plugin-registry.test.ts +0 -5
- package/dist/plugins/catalog/src/contracts.ts +2 -179
- package/dist/plugins/catalog/src/registry/generated-first-party.ts +0 -6
- package/dist/signin-UGDWTGS4.js +821 -0
- package/dist/sso-oidc-Q4VXANXY.js +837 -0
- package/dist/sts-CWLSE3GH.js +1241 -0
- package/dist/sts-DNZLNVOV.js +1245 -0
- package/dist/terraform/examples/greenfield/main.tf +247 -50
- package/dist/terraform/examples/greenfield/terraform.tfvars.example +15 -1
- 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-gateway/main.tf +305 -0
- package/dist/terraform/modules/app/agentcore-gateway/outputs.tf +44 -0
- package/dist/terraform/modules/app/agentcore-gateway/scripts/delete_gateway.sh +93 -0
- package/dist/terraform/modules/app/agentcore-gateway/scripts/read_gateway.sh +33 -0
- package/dist/terraform/modules/app/agentcore-gateway/scripts/reconcile_gateway.sh +543 -0
- package/dist/terraform/modules/app/agentcore-gateway/variables.tf +70 -0
- package/dist/terraform/modules/app/agentcore-harness/main.tf +330 -0
- package/dist/terraform/modules/app/agentcore-harness/outputs.tf +72 -0
- package/dist/terraform/modules/app/agentcore-harness/scripts/delete_harness.sh +5 -0
- package/dist/terraform/modules/app/agentcore-harness/scripts/harness-lifecycle.mjs +430 -0
- package/dist/terraform/modules/app/agentcore-harness/scripts/harness-readback.mjs +180 -0
- package/dist/terraform/modules/app/agentcore-harness/scripts/harness-tool-contract.mjs +193 -0
- package/dist/terraform/modules/app/agentcore-harness/scripts/prune_harness.sh +5 -0
- package/dist/terraform/modules/app/agentcore-harness/scripts/read_harness.sh +5 -0
- package/dist/terraform/modules/app/agentcore-harness/scripts/reconcile_harness.sh +5 -0
- package/dist/terraform/modules/app/agentcore-harness/variables.tf +96 -0
- package/dist/terraform/modules/app/agentcore-identity/main.tf +173 -0
- package/dist/terraform/modules/app/agentcore-identity/outputs.tf +51 -0
- package/dist/terraform/modules/app/agentcore-identity/scripts/bootstrap_twenty_oauth_client.sh +122 -0
- package/dist/terraform/modules/app/agentcore-identity/scripts/delete_identity.sh +25 -0
- package/dist/terraform/modules/app/agentcore-identity/scripts/delete_twenty_identity.sh +16 -0
- package/dist/terraform/modules/app/agentcore-identity/scripts/read_identity.sh +40 -0
- package/dist/terraform/modules/app/agentcore-identity/scripts/reconcile_identity.sh +73 -0
- package/dist/terraform/modules/app/agentcore-identity/scripts/reconcile_twenty_identity.sh +74 -0
- package/dist/terraform/modules/app/agentcore-identity/scripts/reconcile_twenty_provider.mjs +61 -0
- package/dist/terraform/modules/app/agentcore-identity/variables.tf +54 -0
- package/dist/terraform/modules/app/agentcore-pi/main.tf +7 -0
- package/dist/terraform/modules/app/appsync-subscriptions/main.tf +127 -21
- package/dist/terraform/modules/app/appsync-subscriptions/outputs.tf +0 -6
- package/dist/terraform/modules/app/appsync-subscriptions/variables.tf +5 -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 +1011 -31
- package/dist/terraform/modules/app/deployment-control-plane/test_runner_bundle.py +655 -2
- package/dist/terraform/modules/app/lambda-api/agentcore-harness-alarms.tf +88 -0
- package/dist/terraform/modules/app/lambda-api/agentcore-identity-alarms.tf +91 -0
- package/dist/terraform/modules/app/lambda-api/capability-search-alarms.tf +60 -0
- package/dist/terraform/modules/app/lambda-api/handlers.tf +606 -37
- package/dist/terraform/modules/app/lambda-api/iam-grouped.tf +192 -21
- package/dist/terraform/modules/app/lambda-api/main.tf +35 -0
- package/dist/terraform/modules/app/lambda-api/mcp-oauth.tf +181 -4
- 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/outputs.tf +35 -0
- package/dist/terraform/modules/app/lambda-api/runtime-config.tf +3 -21
- package/dist/terraform/modules/app/lambda-api/variables.tf +188 -3
- 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 +319 -73
- package/dist/terraform/modules/foundation/cognito/outputs.tf +42 -0
- package/dist/terraform/modules/foundation/cognito/variables.tf +124 -2
- package/dist/terraform/modules/foundation/vpc/outputs.tf +5 -0
- package/dist/terraform/modules/thinkwork/main.tf +396 -26
- package/dist/terraform/modules/thinkwork/outputs.tf +188 -5
- package/dist/terraform/modules/thinkwork/variables.tf +154 -5
- package/dist/terraform/schema.graphql +69 -36
- package/dist/workspace-defaults/files/TOOLS.md +39 -0
- package/dist/workspace-defaults/files/USER.md +1 -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 +6 -3
- package/dist/plugins/workos-auth/package.json +0 -22
- package/dist/plugins/workos-auth/src/index.ts +0 -30
- package/dist/plugins/workos-auth/src/manifest.ts +0 -40
- package/dist/plugins/workos-auth/src/provider-contract.ts +0 -39
- package/dist/plugins/workos-auth/test/manifest.test.ts +0 -94
- package/dist/plugins/workos-auth/tsconfig.json +0 -8
- /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"
|
|
@@ -156,6 +181,8 @@ locals {
|
|
|
156
181
|
"cognito-idp:AdminRespondToAuthChallenge",
|
|
157
182
|
"cognito-idp:AdminSetUserPassword",
|
|
158
183
|
"cognito-idp:AdminUpdateUserAttributes",
|
|
184
|
+
"cognito-idp:DescribeIdentityProvider",
|
|
185
|
+
"cognito-idp:DescribeUserPoolClient",
|
|
159
186
|
"cognito-idp:ListUsers",
|
|
160
187
|
]
|
|
161
188
|
Resource = var.user_pool_arn
|
|
@@ -321,6 +348,7 @@ locals {
|
|
|
321
348
|
# refresh path cannot replace the old manual AWS CLI step.
|
|
322
349
|
var.deployment_evidence_bucket != "" ? [
|
|
323
350
|
{
|
|
351
|
+
Sid = "DeploymentEvidenceBucket"
|
|
324
352
|
Effect = "Allow"
|
|
325
353
|
Action = [
|
|
326
354
|
"s3:GetObject",
|
|
@@ -332,6 +360,12 @@ locals {
|
|
|
332
360
|
"arn:aws:s3:::${var.deployment_evidence_bucket}/*",
|
|
333
361
|
]
|
|
334
362
|
},
|
|
363
|
+
{
|
|
364
|
+
Sid = "AgentCoreHarnessGatewayOauthSecret"
|
|
365
|
+
Effect = "Allow"
|
|
366
|
+
Action = ["secretsmanager:GetSecretValue"]
|
|
367
|
+
Resource = ["arn:aws:secretsmanager:${var.region}:${var.account_id}:secret:bedrock-agentcore-identity!default/oauth2/thinkwork-${var.stage}-proof-oauth-*"]
|
|
368
|
+
},
|
|
335
369
|
] : [],
|
|
336
370
|
var.billing_export_bucket_name != "" ? [
|
|
337
371
|
{
|
|
@@ -394,6 +428,22 @@ locals {
|
|
|
394
428
|
}
|
|
395
429
|
},
|
|
396
430
|
] : [],
|
|
431
|
+
# THINK-280 — the headless capability executor (routine-exec-git) mints and
|
|
432
|
+
# advances the broker PoP session by conditional reads/writes on the broker's
|
|
433
|
+
# DynamoDB session table. Empty (→ no grant) when the broker is disabled.
|
|
434
|
+
var.capability_broker_session_table_arn != "" ? [
|
|
435
|
+
{
|
|
436
|
+
Effect = "Allow"
|
|
437
|
+
Action = [
|
|
438
|
+
"dynamodb:GetItem",
|
|
439
|
+
"dynamodb:PutItem",
|
|
440
|
+
"dynamodb:UpdateItem",
|
|
441
|
+
"dynamodb:DeleteItem",
|
|
442
|
+
"dynamodb:Query",
|
|
443
|
+
]
|
|
444
|
+
Resource = var.capability_broker_session_table_arn
|
|
445
|
+
},
|
|
446
|
+
] : [],
|
|
397
447
|
)
|
|
398
448
|
|
|
399
449
|
# ---------------------------------------------------------------------------
|
|
@@ -472,13 +522,28 @@ locals {
|
|
|
472
522
|
"arn:aws:lambda:${var.region}:${var.account_id}:function:thinkwork-${var.stage}-api-wiki-compile",
|
|
473
523
|
# knowledge-graph-observations-ingest: graphql-http's
|
|
474
524
|
# startKnowledgeGraphObservationsIngest mutation invokes this with
|
|
475
|
-
# RequestResponse
|
|
476
|
-
#
|
|
477
|
-
#
|
|
525
|
+
# RequestResponse, and memory-stage-worker's graph stage (THINK-193
|
|
526
|
+
# U4 stitch) RequestResponse-invokes it with a targeted bankIds
|
|
527
|
+
# payload — the Bedrock classifier/extraction model config lives on
|
|
528
|
+
# the ingest Lambda's own env, so the worker never runs the ingest
|
|
529
|
+
# in-process. (The worker's self-invoke drain is retired — AWS
|
|
530
|
+
# recursive-loop detection terminated those chains; backlog drains
|
|
531
|
+
# in-process now.)
|
|
478
532
|
"arn:aws:lambda:${var.region}:${var.account_id}:function:thinkwork-${var.stage}-api-knowledge-graph-observations-ingest",
|
|
479
533
|
# wiki-bootstrap-import: bootstrapJournalImport admin mutation
|
|
480
534
|
# Event-invokes this for the long-running ingest path.
|
|
481
535
|
"arn:aws:lambda:${var.region}:${var.account_id}:function:thinkwork-${var.stage}-api-wiki-bootstrap-import",
|
|
536
|
+
# harness-runner: chat-agent-invoke Event-invokes this for chat
|
|
537
|
+
# turns routed to the AWS AgentCore runtime (THINK-311 trial).
|
|
538
|
+
"arn:aws:lambda:${var.region}:${var.account_id}:function:thinkwork-${var.stage}-api-harness-runner",
|
|
539
|
+
# harness-runner queues the same canonical post-turn memory pipeline
|
|
540
|
+
# as Pi after a completed AgentCore turn. The retain ledger makes the
|
|
541
|
+
# Event invoke idempotent on the thread-turn source key.
|
|
542
|
+
"arn:aws:lambda:${var.region}:${var.account_id}:function:thinkwork-${var.stage}-api-memory-retain",
|
|
543
|
+
# harness-runner RequestResponse-invokes this dedicated signer. The
|
|
544
|
+
# signer re-derives the actor/tenant/thread tuple from the running
|
|
545
|
+
# turn and alone holds KMS Sign; the shared runner role never does.
|
|
546
|
+
"arn:aws:lambda:${var.region}:${var.account_id}:function:thinkwork-${var.stage}-api-turn-assertion-mint",
|
|
482
547
|
# ontology-scan: startOntologySuggestionScan Event-invokes this
|
|
483
548
|
# after inserting a durable scan job row.
|
|
484
549
|
"arn:aws:lambda:${var.region}:${var.account_id}:function:thinkwork-${var.stage}-api-ontology-scan",
|
|
@@ -518,6 +583,11 @@ locals {
|
|
|
518
583
|
# step RequestResponse-invokes its workflow-delivery mode to email
|
|
519
584
|
# the maintained report to the operator-configured recipient list.
|
|
520
585
|
"arn:aws:lambda:${var.region}:${var.account_id}:function:thinkwork-${var.stage}-api-artifact-deliver",
|
|
586
|
+
# memory-stage-worker (external-memory-compounding U1):
|
|
587
|
+
# workflow-step-dispatch's memory_stage step Event-invokes it after
|
|
588
|
+
# parking on the task token; the worker resumes the token via
|
|
589
|
+
# SendTaskSuccess when the pipeline stage ends.
|
|
590
|
+
"arn:aws:lambda:${var.region}:${var.account_id}:function:thinkwork-${var.stage}-api-memory-stage-worker",
|
|
521
591
|
# job-trigger self-target (plan 2026-07-03-004 U5, KTD-3): the
|
|
522
592
|
# manual GraphQL trigger Event-invokes job-trigger with the
|
|
523
593
|
# agent_loop_continue_dispatch event so routine actions never run
|
|
@@ -528,6 +598,12 @@ locals {
|
|
|
528
598
|
# triggers), and job-trigger's canvas_refresh branch RequestResponse-
|
|
529
599
|
# invokes it (scheduled trigger). Both run on this shared role.
|
|
530
600
|
"arn:aws:lambda:${var.region}:${var.account_id}:function:thinkwork-${var.stage}-api-canvas-refresh",
|
|
601
|
+
# agentcore-admin (THINK-280): graphql-http's createTenant
|
|
602
|
+
# RequestResponse-invokes it to provision per-tenant sandbox
|
|
603
|
+
# resources; routine-exec-git (same shared role) reaches it for the
|
|
604
|
+
# capability-private provisioning path. Deployed by the dedicated
|
|
605
|
+
# agentcore-admin module with its own least-privilege role.
|
|
606
|
+
"arn:aws:lambda:${var.region}:${var.account_id}:function:thinkwork-${var.stage}-api-agentcore-admin",
|
|
531
607
|
]
|
|
532
608
|
},
|
|
533
609
|
# (was standalone managed policy "workspace_renderer_invoke")
|
|
@@ -709,7 +785,7 @@ locals {
|
|
|
709
785
|
# Group 3: AI — Bedrock model invocation, Knowledge Bases, AgentCore
|
|
710
786
|
# memory / evaluations / code interpreter.
|
|
711
787
|
# ---------------------------------------------------------------------------
|
|
712
|
-
api_ai_statements = [
|
|
788
|
+
api_ai_statements = concat([
|
|
713
789
|
# (was inline policy "bedrock-invoke")
|
|
714
790
|
# Cross-region inference profiles (us.anthropic.claude-*) require
|
|
715
791
|
# `bedrock:InvokeModel` on the *inference-profile* ARN AND on the
|
|
@@ -750,6 +826,18 @@ locals {
|
|
|
750
826
|
"bedrock:GetIngestionJob",
|
|
751
827
|
"bedrock:ListIngestionJobs",
|
|
752
828
|
"bedrock:Retrieve",
|
|
829
|
+
# THINK-193 U7: knowledge-base-manager reconciles the per-document
|
|
830
|
+
# manifest after successful syncs (List/Get) and gates deletion
|
|
831
|
+
# settlement on Get + the scoped Retrieve above. Ingest/Delete cover
|
|
832
|
+
# the explicit direct-delete path for S3 RETAIN'd documents — the
|
|
833
|
+
# manager never races them with StartIngestionJob. The workspace-
|
|
834
|
+
# bucket S3 read the memory-stage-worker needs for document text is
|
|
835
|
+
# already granted by the shared role's workspace "s3-access"
|
|
836
|
+
# statement (data-plane group).
|
|
837
|
+
"bedrock:ListKnowledgeBaseDocuments",
|
|
838
|
+
"bedrock:GetKnowledgeBaseDocuments",
|
|
839
|
+
"bedrock:IngestKnowledgeBaseDocuments",
|
|
840
|
+
"bedrock:DeleteKnowledgeBaseDocuments",
|
|
753
841
|
]
|
|
754
842
|
# CreateKnowledgeBase/CreateDataSource have no resource ARN at create
|
|
755
843
|
# time and don't support resource-level scoping, so a knowledge-base/*
|
|
@@ -818,7 +906,47 @@ locals {
|
|
|
818
906
|
]
|
|
819
907
|
Resource = "*"
|
|
820
908
|
},
|
|
821
|
-
|
|
909
|
+
],
|
|
910
|
+
# THINK-316 U2 — request path receives data-plane invocation only.
|
|
911
|
+
# Provisioning/version/endpoint/PassRole rights belong to Terraform's
|
|
912
|
+
# dedicated Harness lifecycle and never reach a chat Lambda.
|
|
913
|
+
#
|
|
914
|
+
# CRITICAL: never grant `bedrock-agentcore:InvokeAgentRuntimeCommand`
|
|
915
|
+
# anywhere — it bypasses Harness allowedTools enforcement. Invocation goes
|
|
916
|
+
# through InvokeHarness / InvokeAgentRuntime only.
|
|
917
|
+
var.enable_agentcore_harness_invocation ? [
|
|
918
|
+
{
|
|
919
|
+
# Data plane — invoke a Harness (and its runtime endpoints) directly.
|
|
920
|
+
Sid = "AgentCoreHarnessInvoke"
|
|
921
|
+
Effect = "Allow"
|
|
922
|
+
Action = [
|
|
923
|
+
"bedrock-agentcore:InvokeHarness",
|
|
924
|
+
"bedrock-agentcore:InvokeAgentRuntime",
|
|
925
|
+
]
|
|
926
|
+
Resource = ["arn:aws:bedrock-agentcore:${var.region}:${var.account_id}:harness/*"]
|
|
927
|
+
},
|
|
928
|
+
{
|
|
929
|
+
# The deterministic report adapter uses the same AgentCore Identity
|
|
930
|
+
# chain as Harness Gateway outbound auth: turn JWT -> workload token
|
|
931
|
+
# -> OBO Gateway token. No provider client secret enters Lambda.
|
|
932
|
+
Sid = "AgentCoreHarnessGatewayIdentity"
|
|
933
|
+
Effect = "Allow"
|
|
934
|
+
Action = [
|
|
935
|
+
"bedrock-agentcore:GetWorkloadAccessTokenForJWT",
|
|
936
|
+
"bedrock-agentcore:GetWorkloadAccessTokenForUserId",
|
|
937
|
+
"bedrock-agentcore:GetResourceOauth2Token",
|
|
938
|
+
"bedrock-agentcore:CompleteResourceTokenAuth",
|
|
939
|
+
]
|
|
940
|
+
Resource = [
|
|
941
|
+
"arn:aws:bedrock-agentcore:${var.region}:${var.account_id}:workload-identity-directory/default",
|
|
942
|
+
"arn:aws:bedrock-agentcore:${var.region}:${var.account_id}:workload-identity-directory/default/workload-identity/thinkwork-${var.stage}-multiplayer-proof",
|
|
943
|
+
"arn:aws:bedrock-agentcore:${var.region}:${var.account_id}:token-vault/default",
|
|
944
|
+
"arn:aws:bedrock-agentcore:${var.region}:${var.account_id}:token-vault/default/oauth2credentialprovider/thinkwork-${var.stage}-proof-oauth",
|
|
945
|
+
"arn:aws:bedrock-agentcore:${var.region}:${var.account_id}:token-vault/default/oauth2credentialprovider/thinkwork-${var.stage}-twenty-crm",
|
|
946
|
+
]
|
|
947
|
+
},
|
|
948
|
+
] : [],
|
|
949
|
+
)
|
|
822
950
|
|
|
823
951
|
# ---------------------------------------------------------------------------
|
|
824
952
|
# Group 4: observability — CloudWatch Logs reads, ECS/ALB health reads.
|
|
@@ -914,6 +1042,33 @@ locals {
|
|
|
914
1042
|
)
|
|
915
1043
|
|
|
916
1044
|
api_observability_statements = concat(local.api_observability_sqs_statements, [
|
|
1045
|
+
# Backend notification publishing is IAM-only. Scope the shared API
|
|
1046
|
+
# execution role to the NONE-resolver mutation fields; end-user identity-
|
|
1047
|
+
# pool credentials have no AppSync grant. This statement lives in the
|
|
1048
|
+
# observability envelope for size balance: adding subscription invalidation
|
|
1049
|
+
# pushed the data-plane policy over IAM's 6,144-character hard cap.
|
|
1050
|
+
{
|
|
1051
|
+
Sid = "PublishAppSyncNotifications"
|
|
1052
|
+
Effect = "Allow"
|
|
1053
|
+
Action = ["appsync:GraphQL"]
|
|
1054
|
+
Resource = [
|
|
1055
|
+
for field in [
|
|
1056
|
+
"notifyAgentStatus",
|
|
1057
|
+
"notifyNewMessage",
|
|
1058
|
+
"notifyHeartbeatActivity",
|
|
1059
|
+
"notifyThreadActivity",
|
|
1060
|
+
"notifyThreadUpdate",
|
|
1061
|
+
"notifyInboxItemUpdate",
|
|
1062
|
+
"notifyThreadTurnUpdate",
|
|
1063
|
+
"notifyThreadTurnStep",
|
|
1064
|
+
"notifyOrgUpdate",
|
|
1065
|
+
"notifyCostRecorded",
|
|
1066
|
+
"notifyEvalRunUpdate",
|
|
1067
|
+
"notifyWorkspaceAccessRevoked",
|
|
1068
|
+
"invalidateSubscription",
|
|
1069
|
+
] : "arn:aws:appsync:${var.region}:${var.account_id}:apis/${var.appsync_api_id}/types/Mutation/fields/${field}"
|
|
1070
|
+
]
|
|
1071
|
+
},
|
|
917
1072
|
# (was inline policy "cloudwatch-logs-read")
|
|
918
1073
|
{
|
|
919
1074
|
Effect = "Allow"
|
|
@@ -957,16 +1112,41 @@ locals {
|
|
|
957
1112
|
Resource = "*"
|
|
958
1113
|
},
|
|
959
1114
|
])
|
|
1115
|
+
|
|
1116
|
+
api_grouped_policy_documents = {
|
|
1117
|
+
data_plane = jsonencode({
|
|
1118
|
+
Version = "2012-10-17"
|
|
1119
|
+
Statement = local.api_data_plane_statements
|
|
1120
|
+
})
|
|
1121
|
+
orchestration = jsonencode({
|
|
1122
|
+
Version = "2012-10-17"
|
|
1123
|
+
Statement = local.api_orchestration_statements
|
|
1124
|
+
})
|
|
1125
|
+
ai = jsonencode({
|
|
1126
|
+
Version = "2012-10-17"
|
|
1127
|
+
Statement = local.api_ai_statements
|
|
1128
|
+
})
|
|
1129
|
+
observability = jsonencode({
|
|
1130
|
+
Version = "2012-10-17"
|
|
1131
|
+
Statement = local.api_observability_statements
|
|
1132
|
+
})
|
|
1133
|
+
}
|
|
1134
|
+
}
|
|
1135
|
+
|
|
1136
|
+
check "api_grouped_managed_policy_sizes" {
|
|
1137
|
+
assert {
|
|
1138
|
+
condition = alltrue([
|
|
1139
|
+
for document in values(local.api_grouped_policy_documents) : length(document) <= 6144
|
|
1140
|
+
])
|
|
1141
|
+
error_message = "Each grouped API managed-policy document must remain within AWS IAM's 6,144-character limit."
|
|
1142
|
+
}
|
|
960
1143
|
}
|
|
961
1144
|
|
|
962
1145
|
resource "aws_iam_policy" "api_data_plane" {
|
|
963
1146
|
name = "thinkwork-${var.stage}-api-data-plane"
|
|
964
1147
|
description = "Grouped data-plane grants (RDS Data API, Secrets Manager, S3, DynamoDB, Cognito, SSM, KMS-via-SSM, SQS) for the shared api Lambda role"
|
|
965
1148
|
|
|
966
|
-
policy =
|
|
967
|
-
Version = "2012-10-17"
|
|
968
|
-
Statement = local.api_data_plane_statements
|
|
969
|
-
})
|
|
1149
|
+
policy = local.api_grouped_policy_documents.data_plane
|
|
970
1150
|
}
|
|
971
1151
|
|
|
972
1152
|
resource "aws_iam_role_policy_attachment" "api_data_plane" {
|
|
@@ -978,10 +1158,7 @@ resource "aws_iam_policy" "api_orchestration" {
|
|
|
978
1158
|
name = "thinkwork-${var.stage}-api-orchestration"
|
|
979
1159
|
description = "Grouped orchestration grants (Lambda invoke, EventBridge Scheduler, Step Functions, SES) for the shared api Lambda role"
|
|
980
1160
|
|
|
981
|
-
policy =
|
|
982
|
-
Version = "2012-10-17"
|
|
983
|
-
Statement = local.api_orchestration_statements
|
|
984
|
-
})
|
|
1161
|
+
policy = local.api_grouped_policy_documents.orchestration
|
|
985
1162
|
}
|
|
986
1163
|
|
|
987
1164
|
resource "aws_iam_role_policy_attachment" "api_orchestration" {
|
|
@@ -993,10 +1170,7 @@ resource "aws_iam_policy" "api_ai" {
|
|
|
993
1170
|
name = "thinkwork-${var.stage}-api-ai"
|
|
994
1171
|
description = "Grouped AI grants (Bedrock invoke, Knowledge Bases, AgentCore memory/eval/code-interpreter) for the shared api Lambda role"
|
|
995
1172
|
|
|
996
|
-
policy =
|
|
997
|
-
Version = "2012-10-17"
|
|
998
|
-
Statement = local.api_ai_statements
|
|
999
|
-
})
|
|
1173
|
+
policy = local.api_grouped_policy_documents.ai
|
|
1000
1174
|
}
|
|
1001
1175
|
|
|
1002
1176
|
resource "aws_iam_role_policy_attachment" "api_ai" {
|
|
@@ -1008,10 +1182,7 @@ resource "aws_iam_policy" "api_observability" {
|
|
|
1008
1182
|
name = "thinkwork-${var.stage}-api-observability"
|
|
1009
1183
|
description = "Grouped observability grants (CloudWatch Logs reads, ECS/ALB health reads) for the shared api Lambda role"
|
|
1010
1184
|
|
|
1011
|
-
policy =
|
|
1012
|
-
Version = "2012-10-17"
|
|
1013
|
-
Statement = local.api_observability_statements
|
|
1014
|
-
})
|
|
1185
|
+
policy = local.api_grouped_policy_documents.observability
|
|
1015
1186
|
}
|
|
1016
1187
|
|
|
1017
1188
|
resource "aws_iam_role_policy_attachment" "api_observability" {
|
|
@@ -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
|
|
@@ -62,6 +73,14 @@ resource "aws_apigatewayv2_stage" "default" {
|
|
|
62
73
|
throttling_burst_limit = 20
|
|
63
74
|
}
|
|
64
75
|
|
|
76
|
+
# Session revocation is authenticated and independently rate-limited in the
|
|
77
|
+
# handler per principal. This edge throttle also bounds aggregate abuse.
|
|
78
|
+
route_settings {
|
|
79
|
+
route_key = "POST /api/auth/revoke"
|
|
80
|
+
throttling_rate_limit = 5
|
|
81
|
+
throttling_burst_limit = 10
|
|
82
|
+
}
|
|
83
|
+
|
|
65
84
|
# UpdateStage 404s ("Unable to find Route by key … within the provided
|
|
66
85
|
# RouteSettings") if the stage update races the route creation — Terraform
|
|
67
86
|
# sees no reference edge between route_settings.route_key and the route
|
|
@@ -245,3 +264,19 @@ resource "aws_lambda_permission" "placeholder_apigw" {
|
|
|
245
264
|
principal = "apigateway.amazonaws.com"
|
|
246
265
|
source_arn = "${aws_apigatewayv2_api.main.execution_arn}/*/*"
|
|
247
266
|
}
|
|
267
|
+
resource "terraform_data" "auth_migration_recovery_deadline_guard" {
|
|
268
|
+
input = {
|
|
269
|
+
phase = var.auth_retirement_phase
|
|
270
|
+
deadline = var.auth_migration_recovery_deadline
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
lifecycle {
|
|
274
|
+
precondition {
|
|
275
|
+
condition = var.auth_retirement_phase != "coexistence" || (
|
|
276
|
+
trimspace(var.auth_migration_recovery_deadline) != "" &&
|
|
277
|
+
can(timecmp(var.auth_migration_recovery_deadline, var.auth_migration_recovery_deadline))
|
|
278
|
+
)
|
|
279
|
+
error_message = "auth_migration_recovery_deadline must be an RFC3339 timestamp when auth_retirement_phase is coexistence."
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
@@ -1,8 +1,185 @@
|
|
|
1
1
|
locals {
|
|
2
|
-
mcp_oauth_api_base_url
|
|
3
|
-
mcp_oauth_cognito_base_url
|
|
4
|
-
mcp_oauth_identity_providers
|
|
5
|
-
mcp_oauth_logo_path
|
|
2
|
+
mcp_oauth_api_base_url = "https://${aws_apigatewayv2_api.main.id}.execute-api.${var.region}.amazonaws.com"
|
|
3
|
+
mcp_oauth_cognito_base_url = var.cognito_auth_domain != "" ? "https://${var.cognito_auth_domain}.auth.${var.region}.amazoncognito.com" : ""
|
|
4
|
+
mcp_oauth_identity_providers = var.google_oauth_client_id != "" ? ["Google", "COGNITO"] : ["COGNITO"]
|
|
5
|
+
mcp_oauth_logo_path = "${path.module}/../../../../apps/web/public/logo.png"
|
|
6
|
+
agentcore_turn_assertion_issuer = "${local.mcp_oauth_api_base_url}/agentcore"
|
|
7
|
+
agentcore_harness_audience = "urn:thinkwork:${var.stage}:agentcore:harness"
|
|
8
|
+
agentcore_gateway_audience = "urn:thinkwork:${var.stage}:agentcore:gateway"
|
|
9
|
+
agentcore_turn_assertion_keys = {
|
|
10
|
+
for version, key in aws_kms_key.agentcore_turn_assertion : version => {
|
|
11
|
+
key_id = key.arn
|
|
12
|
+
# A version label alone is not globally unique: destroying and
|
|
13
|
+
# reprovisioning v1 creates different RSA material while downstream JWT
|
|
14
|
+
# validators may still cache the old public key under the same kid.
|
|
15
|
+
# Bind the kid to the immutable KMS key id so a reprovision is observed
|
|
16
|
+
# as a real key rotation instead of an invalid-signature outage.
|
|
17
|
+
kid = "thinkwork-${var.stage}-agentcore-turn-${version}-${substr(key.key_id, 0, 8)}"
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
agentcore_turn_assertion_active_key = try(
|
|
21
|
+
local.agentcore_turn_assertion_keys[var.agentcore_turn_assertion_active_key_version],
|
|
22
|
+
{ key_id = "", kid = "" },
|
|
23
|
+
)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
# THINK-316 U1: short-lived CUSTOM_JWT assertions are signed by KMS so private
|
|
27
|
+
# key material never enters Lambda configuration or process memory. The key
|
|
28
|
+
# policy is the capability boundary: the dedicated mint role can Sign, while
|
|
29
|
+
# the shared mcp-oauth role can only fetch the public key for JWKS publication.
|
|
30
|
+
resource "aws_iam_role" "turn_assertion_mint" {
|
|
31
|
+
count = var.enable_agentcore_multiplayer_proof ? 1 : 0
|
|
32
|
+
name = "thinkwork-${var.stage}-turn-assertion-mint-role"
|
|
33
|
+
|
|
34
|
+
assume_role_policy = jsonencode({
|
|
35
|
+
Version = "2012-10-17"
|
|
36
|
+
Statement = [{
|
|
37
|
+
Effect = "Allow"
|
|
38
|
+
Principal = { Service = "lambda.amazonaws.com" }
|
|
39
|
+
Action = "sts:AssumeRole"
|
|
40
|
+
}]
|
|
41
|
+
})
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
resource "aws_iam_role_policy_attachment" "turn_assertion_mint_basic" {
|
|
45
|
+
count = var.enable_agentcore_multiplayer_proof ? 1 : 0
|
|
46
|
+
role = aws_iam_role.turn_assertion_mint[0].name
|
|
47
|
+
policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
# The synthetic OAuth provider and boundary target are public proof surfaces
|
|
51
|
+
# but need no AWS data-plane permissions. A sibling logs-only role prevents a
|
|
52
|
+
# parser defect from inheriting the shared API role or its platform secrets.
|
|
53
|
+
resource "aws_iam_role" "agentcore_proof_boundary" {
|
|
54
|
+
count = var.enable_agentcore_multiplayer_proof ? 1 : 0
|
|
55
|
+
name = "thinkwork-${var.stage}-agentcore-proof-boundary-role"
|
|
56
|
+
|
|
57
|
+
assume_role_policy = jsonencode({
|
|
58
|
+
Version = "2012-10-17"
|
|
59
|
+
Statement = [{
|
|
60
|
+
Effect = "Allow"
|
|
61
|
+
Principal = { Service = "lambda.amazonaws.com" }
|
|
62
|
+
Action = "sts:AssumeRole"
|
|
63
|
+
}]
|
|
64
|
+
})
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
resource "aws_iam_role_policy_attachment" "agentcore_proof_boundary_basic" {
|
|
68
|
+
count = var.enable_agentcore_multiplayer_proof ? 1 : 0
|
|
69
|
+
role = aws_iam_role.agentcore_proof_boundary[0].name
|
|
70
|
+
policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
# The token-exchange provider is the only proof boundary allowed to mint the
|
|
74
|
+
# derived Gateway assertion. Keep that capability off the public target role.
|
|
75
|
+
resource "aws_iam_role" "agentcore_proof_provider" {
|
|
76
|
+
count = var.enable_agentcore_multiplayer_proof ? 1 : 0
|
|
77
|
+
name = "thinkwork-${var.stage}-agentcore-proof-provider-role"
|
|
78
|
+
|
|
79
|
+
assume_role_policy = jsonencode({
|
|
80
|
+
Version = "2012-10-17"
|
|
81
|
+
Statement = [{
|
|
82
|
+
Effect = "Allow"
|
|
83
|
+
Principal = { Service = "lambda.amazonaws.com" }
|
|
84
|
+
Action = "sts:AssumeRole"
|
|
85
|
+
}]
|
|
86
|
+
})
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
resource "aws_iam_role_policy_attachment" "agentcore_proof_provider_basic" {
|
|
90
|
+
count = var.enable_agentcore_multiplayer_proof ? 1 : 0
|
|
91
|
+
role = aws_iam_role.agentcore_proof_provider[0].name
|
|
92
|
+
policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
resource "aws_iam_role_policy" "agentcore_proof_provider_kms" {
|
|
96
|
+
count = var.enable_agentcore_multiplayer_proof ? 1 : 0
|
|
97
|
+
name = "thinkwork-${var.stage}-agentcore-proof-provider-key"
|
|
98
|
+
role = aws_iam_role.agentcore_proof_provider[0].id
|
|
99
|
+
|
|
100
|
+
policy = jsonencode({
|
|
101
|
+
Version = "2012-10-17"
|
|
102
|
+
Statement = [{
|
|
103
|
+
Effect = "Allow"
|
|
104
|
+
Action = ["kms:Sign"]
|
|
105
|
+
Resource = [local.agentcore_turn_assertion_active_key.key_id]
|
|
106
|
+
Condition = {
|
|
107
|
+
StringEquals = {
|
|
108
|
+
"kms:SigningAlgorithm" = "RSASSA_PKCS1_V1_5_SHA_256"
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}]
|
|
112
|
+
})
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
resource "aws_kms_key" "agentcore_turn_assertion" {
|
|
116
|
+
for_each = var.enable_agentcore_multiplayer_proof ? toset(var.agentcore_turn_assertion_key_versions) : toset([])
|
|
117
|
+
|
|
118
|
+
description = "ThinkWork ${var.stage} AgentCore per-turn assertion signing ${each.key}"
|
|
119
|
+
key_usage = "SIGN_VERIFY"
|
|
120
|
+
customer_master_key_spec = "RSA_2048"
|
|
121
|
+
deletion_window_in_days = 7
|
|
122
|
+
|
|
123
|
+
policy = jsonencode({
|
|
124
|
+
Version = "2012-10-17"
|
|
125
|
+
Statement = [
|
|
126
|
+
{
|
|
127
|
+
Sid = "AccountAdministration"
|
|
128
|
+
Effect = "Allow"
|
|
129
|
+
Principal = { AWS = "arn:aws:iam::${var.account_id}:root" }
|
|
130
|
+
Action = "kms:*"
|
|
131
|
+
Resource = "*"
|
|
132
|
+
},
|
|
133
|
+
]
|
|
134
|
+
})
|
|
135
|
+
|
|
136
|
+
tags = {
|
|
137
|
+
Name = "thinkwork-${var.stage}-agentcore-turn-assertion-${each.key}"
|
|
138
|
+
KeyVersion = each.key
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
resource "aws_kms_alias" "agentcore_turn_assertion" {
|
|
143
|
+
for_each = aws_kms_key.agentcore_turn_assertion
|
|
144
|
+
name = "alias/thinkwork-${var.stage}-agentcore-turn-assertion-${each.key}"
|
|
145
|
+
target_key_id = each.value.key_id
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
# The mint role can sign with exactly the active key. The public discovery
|
|
149
|
+
# handler can read all currently published public keys, but can never sign.
|
|
150
|
+
resource "aws_iam_role_policy" "turn_assertion_mint_kms" {
|
|
151
|
+
count = var.enable_agentcore_multiplayer_proof ? 1 : 0
|
|
152
|
+
name = "thinkwork-${var.stage}-turn-assertion-active-key"
|
|
153
|
+
role = aws_iam_role.turn_assertion_mint[0].id
|
|
154
|
+
|
|
155
|
+
policy = jsonencode({
|
|
156
|
+
Version = "2012-10-17"
|
|
157
|
+
Statement = [{
|
|
158
|
+
Effect = "Allow"
|
|
159
|
+
Action = ["kms:Sign"]
|
|
160
|
+
Resource = [local.agentcore_turn_assertion_active_key.key_id]
|
|
161
|
+
Condition = {
|
|
162
|
+
StringEquals = {
|
|
163
|
+
"kms:SigningAlgorithm" = "RSASSA_PKCS1_V1_5_SHA_256"
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}]
|
|
167
|
+
})
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
resource "aws_iam_role_policy" "turn_assertion_jwks_kms" {
|
|
171
|
+
count = var.enable_agentcore_multiplayer_proof ? 1 : 0
|
|
172
|
+
name = "thinkwork-${var.stage}-turn-assertion-published-keys"
|
|
173
|
+
role = aws_iam_role.lambda.id
|
|
174
|
+
|
|
175
|
+
policy = jsonencode({
|
|
176
|
+
Version = "2012-10-17"
|
|
177
|
+
Statement = [{
|
|
178
|
+
Effect = "Allow"
|
|
179
|
+
Action = ["kms:GetPublicKey"]
|
|
180
|
+
Resource = [for key in values(local.agentcore_turn_assertion_keys) : key.key_id]
|
|
181
|
+
}]
|
|
182
|
+
})
|
|
6
183
|
}
|
|
7
184
|
|
|
8
185
|
resource "aws_dynamodb_table" "mcp_oauth_revocations" {
|
|
@@ -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
|
+
}
|