thinkwork-cli 0.13.2 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -14
- package/dist/{api-client-JYZXYQJR.js → api-client-4P4JZOBX.js} +1 -1
- package/dist/{chunk-Z2F6RJFR.js → chunk-4OMDWYZQ.js} +4 -5
- package/dist/{chunk-ILZKG5WV.js → chunk-AD2NIWB5.js} +434 -69
- package/dist/chunk-MWQ7RO76.js +137 -0
- package/dist/{chunk-DVPBI5HM.js → chunk-OLUQ4U2Z.js} +26 -26
- package/dist/{chunk-QOERT44A.js → chunk-YQCYD6NE.js} +57 -44
- package/dist/cli.js +4400 -16431
- package/dist/commands/enterprise/templates/deploy-repo/scripts/apply-release.mjs +0 -1
- package/dist/commands/enterprise/templates/deploy-repo/scripts/smoke.mjs +0 -1
- package/dist/commands/enterprise/templates/deploy-repo/terraform/main.tf +0 -14
- package/dist/{dist-es-CRV46D5B.js → dist-es-2OTNTL4N.js} +4 -4
- package/dist/{dist-es-ENBUC3JP.js → dist-es-2XVAH4BQ.js} +2 -2
- package/dist/{dist-es-DCY4IC3Y.js → dist-es-3DPDUJAH.js} +2 -2
- package/dist/{dist-es-G7PTG75M.js → dist-es-BNZTBBVC.js} +1 -1
- package/dist/{dist-es-GKDBE7E6.js → dist-es-CD2RBDAC.js} +1 -1
- package/dist/{dist-es-R7FGL2IB.js → dist-es-I4FW57PS.js} +1 -1
- package/dist/{dist-es-USORBXZ5.js → dist-es-KVFWJNDY.js} +4 -4
- package/dist/{dist-es-HY3535OI.js → dist-es-PS73DWNL.js} +2 -2
- package/dist/{dist-es-LDE437AM.js → dist-es-S3NZQFGT.js} +1 -1
- package/dist/{dist-es-G54LBMRN.js → dist-es-SGCA4P32.js} +1 -1
- package/dist/{dist-es-Q57SZXZ7.js → dist-es-WBM6J4RA.js} +2 -2
- package/dist/{dist-es-P26FWFLT.js → dist-es-ZGVADYIF.js} +8 -8
- package/dist/drizzle/0227_analyst_reader_role.sql +17 -26
- package/dist/drizzle/0230_analyst_rls.sql +28 -45
- package/dist/drizzle/0261_native_auth_control_plane.sql +7 -3
- package/dist/drizzle/0270_tool_execution_ledger.sql +115 -0
- package/dist/drizzle/0271_ontology_twin_declarations.sql +47 -0
- package/dist/drizzle/0272_identity_graph_projection_cursor.sql +23 -0
- package/dist/drizzle/0273_twin_materialization_suggestions.sql +29 -0
- package/dist/drizzle/0274_tenant_mcp_twin_keys.sql +59 -0
- package/dist/drizzle/0275_identity_bulk_rebuild_fence.sql +30 -0
- package/dist/drizzle/0276_tool_execution_ledger_allow_cascade_delete.sql +18 -0
- package/dist/drizzle/0277_knowledge_base_sources.sql +107 -0
- package/dist/drizzle/0278_kb_page_transcription.sql +55 -0
- package/dist/drizzle/0279_mcp_servers_off_plugin_provenance.sql +93 -0
- package/dist/drizzle/0280_work_item_external_refs_drop_plane_provider.sql +46 -0
- package/dist/drizzle/0281_tenant_mcp_twin_keys_expiry_suffix.sql +9 -0
- package/dist/drizzle/0282_tenant_mcp_twin_keys_grants.sql +24 -0
- package/dist/drizzle/0283_agents_agentcore_runtime_dispatch.sql +13 -0
- package/dist/drizzle/0284_user_brain_claims.sql +69 -0
- package/dist/drizzle/0285_tenant_mcp_twin_keys_trusted_subsystem.sql +30 -0
- package/dist/drizzle/0286_brain_analytics_key.sql +26 -0
- package/dist/drizzle/0287_brain_subject.sql +25 -0
- package/dist/drizzle/0288_multi_lane_identities.sql +25 -0
- package/dist/{loadSso-DJVB7BXE.js → loadSso-ETCXTR4I.js} +2 -2
- package/dist/{loadSso-JAMNA3WY.js → loadSso-UBD7KUHE.js} +2 -2
- package/dist/plugins/README.md +2 -2
- package/dist/plugins/catalog/package.json +0 -3
- package/dist/plugins/catalog/src/__tests__/build-catalog.test.ts +6 -3
- package/dist/plugins/catalog/src/__tests__/catalog.test.ts +21 -21
- package/dist/plugins/catalog/src/__tests__/contracts.test.ts +102 -25
- package/dist/plugins/catalog/src/__tests__/plugin-package.test.ts +7 -6
- package/dist/plugins/catalog/src/__tests__/plugin-registry.test.ts +0 -15
- package/dist/plugins/catalog/src/contracts.ts +15 -0
- package/dist/plugins/catalog/src/registry/generated-first-party.ts +0 -18
- package/dist/plugins/n8n/test/integrated-app-contract.test.ts +1 -1
- package/dist/plugins/twenty/package.json +2 -1
- package/dist/plugins/twenty/scripts/LAMBDA_DEPLOY.md +114 -0
- package/dist/plugins/twenty/scripts/build-lambda.sh +29 -0
- package/dist/plugins/twenty/scripts/configure-product-views.ts +195 -0
- package/dist/plugins/twenty/scripts/lambda-handler.ts +49 -0
- package/dist/plugins/twenty/scripts/lib/__tests__/load-attachments.test.ts +38 -0
- package/dist/plugins/twenty/scripts/lib/__tests__/load-records.test.ts +145 -2
- package/dist/plugins/twenty/scripts/lib/__tests__/mappers.test.ts +397 -151
- package/dist/plugins/twenty/scripts/lib/__tests__/members-ensure.test.ts +28 -129
- package/dist/plugins/twenty/scripts/lib/__tests__/provision-members-db.test.ts +10 -0
- package/dist/plugins/twenty/scripts/lib/__tests__/schema-ensure.test.ts +13 -8
- package/dist/plugins/twenty/scripts/lib/lastmile-reader.ts +222 -2
- package/dist/plugins/twenty/scripts/lib/load-attachments.ts +29 -0
- package/dist/plugins/twenty/scripts/lib/load-records.ts +160 -43
- package/dist/plugins/twenty/scripts/lib/mappers.ts +368 -152
- package/dist/plugins/twenty/scripts/lib/members-ensure.ts +43 -268
- package/dist/plugins/twenty/scripts/lib/provision-members-db.ts +57 -0
- package/dist/plugins/twenty/scripts/lib/schema-ensure.ts +136 -31
- package/dist/plugins/twenty/scripts/migrate-lastmile.ts +254 -152
- package/dist/plugins/twenty/scripts/provision-twenty-members.ts +44 -1
- package/dist/plugins/twenty/scripts/purge-lastmile-import.ts +178 -0
- package/dist/plugins/twenty/scripts/restructure-products.ts +312 -0
- package/dist/plugins/twenty/scripts/retag-stage-values.ts +362 -0
- package/dist/plugins/twenty/test/manifest.test.ts +2 -4
- package/dist/scripts/post-deploy.sh +79 -1
- package/dist/{signin-UGDWTGS4.js → signin-5QZNRSOO.js} +2 -2
- package/dist/{sso-oidc-Q4VXANXY.js → sso-oidc-XK673P54.js} +2 -2
- package/dist/{sts-CWLSE3GH.js → sts-OXI2UALF.js} +6 -134
- package/dist/{sts-DNZLNVOV.js → sts-SQW4NBK3.js} +6 -134
- package/dist/terraform/examples/greenfield/main.tf +233 -175
- package/dist/terraform/examples/greenfield/terraform.tfvars.example +12 -8
- package/dist/terraform/modules/app/agentcore-admin/main.tf +47 -0
- package/dist/terraform/modules/app/agentcore-code-interpreter/README.md +39 -47
- package/dist/terraform/modules/app/agentcore-code-interpreter/main.tf +13 -66
- package/dist/terraform/modules/app/agentcore-identity/main.tf +106 -26
- package/dist/terraform/modules/app/agentcore-identity/outputs.tf +6 -6
- package/dist/terraform/modules/app/agentcore-identity/scripts/bootstrap_twenty_oauth_client.sh +216 -99
- package/dist/terraform/modules/app/agentcore-identity/scripts/delete_identity.sh +6 -9
- package/dist/terraform/modules/app/agentcore-identity/scripts/delete_workload_identity.sh +19 -0
- package/dist/terraform/modules/app/agentcore-identity/scripts/ensure_workload_identity.sh +29 -0
- package/dist/terraform/modules/app/agentcore-identity/scripts/read_identity.sh +22 -7
- package/dist/terraform/modules/app/agentcore-identity/scripts/reconcile_twenty_identity.sh +17 -46
- package/dist/terraform/modules/app/agentcore-identity/scripts/reconcile_twenty_provider.mjs +65 -3
- package/dist/terraform/modules/app/agentcore-identity/tests/tainted-marker/after.tf +15 -0
- package/dist/terraform/modules/app/agentcore-identity/tests/tainted-marker/before.tf +7 -0
- package/dist/terraform/modules/app/agentcore-identity/tests/tainted-marker/identity-after.tf +8 -0
- package/dist/terraform/modules/app/agentcore-identity/tests/tainted-marker/identity-before.tf +9 -0
- package/dist/terraform/modules/app/agentcore-identity/tests/tainted-marker/thinkwork-after.tf +3 -0
- package/dist/terraform/modules/app/agentcore-identity/tests/tainted-marker/thinkwork-before.tf +3 -0
- package/dist/terraform/modules/app/agentcore-identity/variables.tf +6 -0
- package/dist/terraform/modules/app/agentcore-memory/README.md +46 -9
- package/dist/terraform/modules/app/agentcore-memory/main.tf +27 -10
- package/dist/terraform/modules/app/agentcore-memory/scripts/create_or_find_memory.sh +156 -24
- package/dist/terraform/modules/app/agentcore-pi/README.md +1 -3
- package/dist/terraform/modules/app/agentcore-pi/main.tf +42 -52
- package/dist/terraform/modules/app/agentcore-pi/outputs.tf +3 -3
- package/dist/terraform/modules/app/agentcore-pi/scripts/reconcile_pi_runtime.mjs +175 -0
- package/dist/terraform/modules/app/agentcore-pi/variables.tf +35 -28
- package/dist/terraform/modules/app/agentcore-platform/main.tf +68 -0
- package/dist/terraform/modules/app/agentcore-runtime/main.tf +4 -20
- package/dist/terraform/modules/app/capability-broker/main.tf +2 -2
- package/dist/terraform/modules/app/capability-broker/variables.tf +11 -0
- package/dist/terraform/modules/app/deployment-control-plane/README.md +264 -0
- package/dist/terraform/modules/app/deployment-control-plane/buildspec.yml +4 -1
- package/dist/terraform/modules/app/deployment-control-plane/main.tf +94 -0
- package/dist/terraform/modules/app/deployment-control-plane/outputs.tf +5 -0
- package/dist/terraform/modules/app/deployment-control-plane/runner.py +2641 -124
- package/dist/terraform/modules/app/deployment-control-plane/test_runner_bundle.py +2034 -154
- package/dist/terraform/modules/app/deployment-control-plane/variables.tf +33 -0
- package/dist/terraform/modules/app/lambda-api/auth-state.tf +72 -0
- package/dist/terraform/modules/app/lambda-api/chat-latency-observability.tf +466 -0
- package/dist/terraform/modules/app/lambda-api/dispatch-dlq.tf +55 -0
- package/dist/terraform/modules/app/lambda-api/handlers.tf +411 -723
- package/dist/terraform/modules/app/lambda-api/iam-grouped.tf +262 -198
- package/dist/terraform/modules/app/lambda-api/main.tf +51 -13
- package/dist/terraform/modules/app/lambda-api/mcp-oauth.tf +4 -181
- package/dist/terraform/modules/app/lambda-api/memory-alarms.tf +3 -28
- package/dist/terraform/modules/app/lambda-api/oauth-secrets.tf +1 -2
- package/dist/terraform/modules/app/lambda-api/outputs.tf +17 -45
- package/dist/terraform/modules/app/lambda-api/turn-assertion.tf +45 -0
- package/dist/terraform/modules/app/lambda-api/variables.tf +219 -126
- package/dist/{plugins/n8n/terraform → terraform/modules/app}/n8n/README.md +1 -1
- package/dist/{plugins/n8n/terraform → terraform/modules/app}/n8n/main.tf +18 -18
- package/dist/terraform/modules/app/sandbox-log-scrubber/README.md +11 -10
- package/dist/terraform/modules/app/sandbox-log-scrubber/main.tf +5 -5
- package/dist/terraform/modules/app/static-site/main.tf +1 -1
- package/dist/terraform/modules/app/www-dns/main.tf +9 -27
- package/dist/terraform/modules/app/www-dns/variables.tf +4 -10
- package/dist/terraform/modules/data/aurora-postgres/README.md +34 -0
- package/dist/terraform/modules/data/aurora-postgres/alarms.tf +82 -0
- package/dist/terraform/modules/data/aurora-postgres/main.tf +27 -57
- package/dist/terraform/modules/data/aurora-postgres/outputs.tf +0 -9
- package/dist/terraform/modules/data/aurora-postgres/variables.tf +41 -0
- package/dist/terraform/modules/data/s3-buckets/main.tf +5 -6
- package/dist/terraform/modules/foundation/cognito/main.tf +81 -8
- package/dist/terraform/modules/foundation/cognito/outputs.tf +5 -0
- package/dist/terraform/modules/foundation/cognito/variables.tf +24 -12
- package/dist/terraform/modules/thinkwork/README.md +5 -1
- package/dist/terraform/modules/thinkwork/main.tf +376 -374
- package/dist/terraform/modules/thinkwork/outputs.tf +12 -158
- package/dist/terraform/modules/thinkwork/variables.tf +246 -89
- package/dist/workspace-defaults/files/INSTRUCTIONS.md +9 -11
- package/dist/workspace-defaults/files/MEMORY_GUIDE.md +38 -35
- package/dist/workspace-defaults/files/ROUTER.md +1 -1
- package/dist/workspace-defaults/files/TOOLS.md +9 -39
- package/dist/workspace-defaults/files/agents/analyst/INSTRUCTIONS.md +6 -3
- package/dist/workspace-defaults/files/catalog-skills/brain-brief-builder/SKILL.md +165 -0
- package/dist/workspace-defaults/files/catalog-skills/n8n-workflow-operator/SKILL.md +75 -0
- package/dist/workspace-defaults/files/catalog-skills/n8n-workflow-operator/references/mcp-tooling.md +40 -0
- package/dist/workspace-defaults/files/catalog-skills/n8n-workflow-operator/references/validation-and-handoff.md +40 -0
- package/dist/workspace-defaults/files/catalog-skills/n8n-workflow-operator/references/workflow-authoring.md +46 -0
- package/dist/workspace-defaults/files/skills/artifact-builder/references/crm-dashboard.md +1 -1
- package/dist/workspace-defaults/files/skills/document-composer/SKILL.md +22 -3
- package/package.json +1 -1
- package/dist/drizzle/0261_managed_harness_multiplayer.sql +0 -313
- package/dist/drizzle/0262_parallel_harness_threads.sql +0 -9
- package/dist/drizzle/0264_harness_tool_execution_ledger.sql +0 -113
- package/dist/plugins/company-data/README.md +0 -49
- package/dist/plugins/company-data/package.json +0 -21
- package/dist/plugins/company-data/src/index.ts +0 -30
- package/dist/plugins/company-data/src/manifest.ts +0 -26
- package/dist/plugins/company-data/test/manifest.test.ts +0 -116
- package/dist/plugins/company-data/tsconfig.json +0 -8
- package/dist/plugins/company-etl/README.md +0 -46
- package/dist/plugins/company-etl/package.json +0 -21
- package/dist/plugins/company-etl/src/index.ts +0 -29
- package/dist/plugins/company-etl/src/manifest.ts +0 -26
- package/dist/plugins/company-etl/test/manifest.test.ts +0 -108
- package/dist/plugins/company-etl/tsconfig.json +0 -8
- package/dist/plugins/lastmile/README.md +0 -50
- package/dist/plugins/lastmile/package.json +0 -23
- package/dist/plugins/lastmile/smoke/lastmile-plugin-smoke.mjs +0 -661
- package/dist/plugins/lastmile/src/api/tasks-adapter.ts +0 -572
- package/dist/plugins/lastmile/src/discovery.fixture.ts +0 -64
- package/dist/plugins/lastmile/src/index.ts +0 -46
- package/dist/plugins/lastmile/src/manifest.ts +0 -139
- package/dist/plugins/lastmile/test/api/tasks-adapter.test.ts +0 -266
- package/dist/plugins/lastmile/test/discovery.test.ts +0 -88
- package/dist/plugins/lastmile/tsconfig.json +0 -8
- package/dist/plugins/n8n/smoke/n8n-managed-app-smoke.mjs +0 -409
- package/dist/plugins/twenty/smoke/twenty-managed-app-smoke.mjs +0 -359
- package/dist/terraform/modules/app/agentcore-code-interpreter/Dockerfile.sandbox-base +0 -61
- package/dist/terraform/modules/app/agentcore-code-interpreter/sandbox/sitecustomize.py +0 -227
- package/dist/terraform/modules/app/agentcore-code-interpreter/sandbox/test_sitecustomize.py +0 -277
- package/dist/terraform/modules/app/agentcore-code-interpreter/scripts/build_and_push_sandbox_base.sh +0 -70
- package/dist/terraform/modules/app/agentcore-gateway/main.tf +0 -305
- package/dist/terraform/modules/app/agentcore-gateway/outputs.tf +0 -44
- package/dist/terraform/modules/app/agentcore-gateway/scripts/delete_gateway.sh +0 -93
- package/dist/terraform/modules/app/agentcore-gateway/scripts/read_gateway.sh +0 -33
- package/dist/terraform/modules/app/agentcore-gateway/scripts/reconcile_gateway.sh +0 -543
- package/dist/terraform/modules/app/agentcore-gateway/variables.tf +0 -70
- package/dist/terraform/modules/app/agentcore-harness/main.tf +0 -330
- package/dist/terraform/modules/app/agentcore-harness/outputs.tf +0 -72
- package/dist/terraform/modules/app/agentcore-harness/scripts/delete_harness.sh +0 -5
- package/dist/terraform/modules/app/agentcore-harness/scripts/harness-lifecycle.mjs +0 -430
- package/dist/terraform/modules/app/agentcore-harness/scripts/harness-readback.mjs +0 -180
- package/dist/terraform/modules/app/agentcore-harness/scripts/harness-tool-contract.mjs +0 -193
- package/dist/terraform/modules/app/agentcore-harness/scripts/prune_harness.sh +0 -5
- package/dist/terraform/modules/app/agentcore-harness/scripts/read_harness.sh +0 -5
- package/dist/terraform/modules/app/agentcore-harness/scripts/reconcile_harness.sh +0 -5
- package/dist/terraform/modules/app/agentcore-harness/variables.tf +0 -96
- package/dist/terraform/modules/app/hindsight-memory/README.md +0 -89
- package/dist/terraform/modules/app/hindsight-memory/main.tf +0 -411
- package/dist/terraform/modules/app/lambda-api/agentcore-harness-alarms.tf +0 -88
- package/dist/terraform/modules/app/lambda-api/agentcore-identity-alarms.tf +0 -91
- package/dist/terraform/modules/data/bedrock-knowledge-base/main.tf +0 -102
- /package/dist/{plugins/n8n/terraform → terraform/modules/app}/n8n/outputs.tf +0 -0
- /package/dist/{plugins/n8n/terraform → terraform/modules/app}/n8n/scripts/sync-database.py +0 -0
- /package/dist/{plugins/n8n/terraform → terraform/modules/app}/n8n/scripts/test_sync_database.py +0 -0
- /package/dist/{plugins/n8n/terraform → terraform/modules/app}/n8n/variables.tf +0 -0
- /package/dist/{plugins/twenty/terraform → terraform/modules/app}/twenty/README.md +0 -0
- /package/dist/{plugins/twenty/terraform → terraform/modules/app}/twenty/main.tf +0 -0
- /package/dist/{plugins/twenty/terraform → terraform/modules/app}/twenty/outputs.tf +0 -0
- /package/dist/{plugins/twenty/terraform → terraform/modules/app}/twenty/variables.tf +0 -0
|
@@ -6,25 +6,25 @@
|
|
|
6
6
|
# 10,240-byte aggregate hard cap for inline policies (#2378 failed the dev
|
|
7
7
|
# apply with LimitExceeded; #2379 is this consolidation). Every grant that was
|
|
8
8
|
# inline on this role — plus the one-off standalone managed policies that had
|
|
9
|
-
# accreted as cap workarounds — now lives in
|
|
9
|
+
# accreted as cap workarounds — now lives in five grouped
|
|
10
10
|
# customer-managed policies:
|
|
11
11
|
#
|
|
12
12
|
# thinkwork-<stage>-api-data-plane — RDS Data API, Secrets Manager, S3,
|
|
13
13
|
# DynamoDB, Cognito, SSM reads, KMS,
|
|
14
14
|
# SQS (here for size balance, see
|
|
15
15
|
# the locals note)
|
|
16
|
-
# thinkwork-<stage>-api-orchestration —
|
|
17
|
-
#
|
|
18
|
-
# thinkwork-<stage>-api-ai — Bedrock invoke,
|
|
16
|
+
# thinkwork-<stage>-api-orchestration — Scheduler, Step Functions, SES
|
|
17
|
+
# thinkwork-<stage>-api-invocation — internal lambda:InvokeFunction
|
|
18
|
+
# thinkwork-<stage>-api-ai — Bedrock invoke,
|
|
19
19
|
# AgentCore memory/eval/code-interp
|
|
20
20
|
# thinkwork-<stage>-api-observability — CloudWatch Logs reads, ECS/ALB
|
|
21
21
|
# health reads
|
|
22
22
|
#
|
|
23
|
-
# STANDING RULE: new grants for aws_iam_role.lambda go into one of these
|
|
23
|
+
# STANDING RULE: new grants for aws_iam_role.lambda go into one of these five
|
|
24
24
|
# grouped policies — never a new inline aws_iam_role_policy and never a new
|
|
25
25
|
# standalone managed-policy attachment. (Managed-policy attachments have a
|
|
26
26
|
# default quota of 10 per role; the steady state here is
|
|
27
|
-
# AWSLambdaBasicExecutionRole + these
|
|
27
|
+
# AWSLambdaBasicExecutionRole + these five, plus the conditional AWS-managed
|
|
28
28
|
# VPC-access policy when OKF EFS wiring is enabled.)
|
|
29
29
|
#
|
|
30
30
|
# Each managed policy document caps at 6,144 characters (JSON minus
|
|
@@ -59,16 +59,6 @@ locals {
|
|
|
59
59
|
Action = ["secretsmanager:GetSecretValue"]
|
|
60
60
|
Resource = var.graphql_db_secret_arn
|
|
61
61
|
},
|
|
62
|
-
# THINK-239 — analystInternalClusters enumerates the environment's own
|
|
63
|
-
# RDS clusters (filtered to thinkwork-<stage>-* in code) so operators can
|
|
64
|
-
# register a database with zero credential entry. Describe-only; the
|
|
65
|
-
# admin credential read is covered by graphql_db_secret_arn above.
|
|
66
|
-
{
|
|
67
|
-
Sid = "AnalystInternalClustersDescribe"
|
|
68
|
-
Effect = "Allow"
|
|
69
|
-
Action = ["rds:DescribeDBClusters"]
|
|
70
|
-
Resource = "*"
|
|
71
|
-
},
|
|
72
62
|
{
|
|
73
63
|
Effect = "Allow"
|
|
74
64
|
Action = [
|
|
@@ -76,14 +66,6 @@ locals {
|
|
|
76
66
|
"secretsmanager:UpdateSecret",
|
|
77
67
|
"secretsmanager:DeleteSecret",
|
|
78
68
|
"secretsmanager:GetSecretValue",
|
|
79
|
-
# THINK-230 — provisionAnalystConnector writes the broker credential
|
|
80
|
-
# secret value (thinkwork/<stage>/analyst/broker-credential, under
|
|
81
|
-
# this thinkwork/* prefix) via ensureAnalystBrokerSecret's
|
|
82
|
-
# PutSecretValue. GetSecretValue above already covers the read; this
|
|
83
|
-
# role already holds Create/Update/Delete on the same prefix, so
|
|
84
|
-
# PutSecretValue grants no capability beyond the existing delete +
|
|
85
|
-
# recreate. Kept on the existing statement to stay under the 6,144
|
|
86
|
-
# rendered-char managed-policy cap.
|
|
87
69
|
"secretsmanager:PutSecretValue"
|
|
88
70
|
]
|
|
89
71
|
Resource = "arn:aws:secretsmanager:${var.region}:${var.account_id}:secret:thinkwork/*"
|
|
@@ -119,13 +101,6 @@ locals {
|
|
|
119
101
|
"${var.bucket_arn}/*",
|
|
120
102
|
]
|
|
121
103
|
},
|
|
122
|
-
# (was inline policy "wiki-exports-s3" in handlers.tf) — wiki-export
|
|
123
|
-
# writes markdown vault bundles to the per-stage wiki-exports bucket.
|
|
124
|
-
{
|
|
125
|
-
Effect = "Allow"
|
|
126
|
-
Action = ["s3:PutObject", "s3:AbortMultipartUpload"]
|
|
127
|
-
Resource = "${aws_s3_bucket.wiki_exports.arn}/*"
|
|
128
|
-
},
|
|
129
104
|
# Canonical ThinkWork Brain artifacts: durable source artifacts,
|
|
130
105
|
# ingestion manifests, migration snapshots, vault projections, and
|
|
131
106
|
# exports, and OKF Wiki Navigator bundles/current manifests.
|
|
@@ -324,17 +299,25 @@ locals {
|
|
|
324
299
|
Resource = var.plugin_catalog_github_token_secret_arn
|
|
325
300
|
},
|
|
326
301
|
] : [],
|
|
327
|
-
#
|
|
328
|
-
#
|
|
329
|
-
#
|
|
330
|
-
#
|
|
331
|
-
|
|
332
|
-
# narrow Resource IS the control surface.
|
|
333
|
-
var.analyst_db_cluster_resource_id != "" ? [
|
|
302
|
+
# Company Brain machine lane (THINK-628): MCP config build mints Cognito
|
|
303
|
+
# client-credentials bearers from this one secret instead of reading a
|
|
304
|
+
# stored tkt_ token. Read-only, one exact ARN, count-gated: an account
|
|
305
|
+
# that never sets the var plans to zero changes.
|
|
306
|
+
var.brain_m2m_platform_agent_secret_arn != "" ? [
|
|
334
307
|
{
|
|
335
308
|
Effect = "Allow"
|
|
336
|
-
Action = ["
|
|
337
|
-
Resource =
|
|
309
|
+
Action = ["secretsmanager:GetSecretValue"]
|
|
310
|
+
Resource = var.brain_m2m_platform_agent_secret_arn
|
|
311
|
+
},
|
|
312
|
+
] : [],
|
|
313
|
+
# Brain ops-api agent identity (THINK-781): flagThreadToBrain mints a
|
|
314
|
+
# bearer from this secret to POST /flags. Same posture as the machine
|
|
315
|
+
# lane above — read-only, one exact ARN, count-gated.
|
|
316
|
+
var.brain_ops_m2m_secret_arn != "" ? [
|
|
317
|
+
{
|
|
318
|
+
Effect = "Allow"
|
|
319
|
+
Action = ["secretsmanager:GetSecretValue"]
|
|
320
|
+
Resource = var.brain_ops_m2m_secret_arn
|
|
338
321
|
},
|
|
339
322
|
] : [],
|
|
340
323
|
# (was standalone managed policy "lambda_deployment_evidence_read")
|
|
@@ -397,33 +380,33 @@ locals {
|
|
|
397
380
|
)
|
|
398
381
|
},
|
|
399
382
|
] : [],
|
|
400
|
-
|
|
383
|
+
# THINK-585 U6: the dispatcher's on-failure destination (Lambda sends
|
|
384
|
+
# with the function's execution role) + the redrive consumer's ESM
|
|
385
|
+
# polling, both on the agentcore-dispatch DLQ.
|
|
386
|
+
local.deploy_lambda_handlers ? [
|
|
401
387
|
{
|
|
402
388
|
Effect = "Allow"
|
|
403
389
|
Action = [
|
|
404
|
-
"
|
|
405
|
-
"
|
|
390
|
+
"sqs:SendMessage",
|
|
391
|
+
"sqs:ReceiveMessage",
|
|
392
|
+
"sqs:DeleteMessage",
|
|
393
|
+
"sqs:GetQueueAttributes",
|
|
394
|
+
"sqs:ChangeMessageVisibility",
|
|
406
395
|
]
|
|
407
|
-
Resource =
|
|
408
|
-
Condition = {
|
|
409
|
-
StringEquals = {
|
|
410
|
-
"kms:ViaService" = "s3.${var.region}.amazonaws.com"
|
|
411
|
-
}
|
|
412
|
-
}
|
|
396
|
+
Resource = [for q in aws_sqs_queue.agentcore_dispatch_dlq : q.arn]
|
|
413
397
|
},
|
|
414
398
|
] : [],
|
|
415
|
-
var.
|
|
399
|
+
var.brain_artifacts_kms_key_arn != "" ? [
|
|
416
400
|
{
|
|
417
|
-
Sid = "OkfEfsHydratorMountWrite"
|
|
418
401
|
Effect = "Allow"
|
|
419
402
|
Action = [
|
|
420
|
-
"
|
|
421
|
-
"
|
|
403
|
+
"kms:Decrypt",
|
|
404
|
+
"kms:GenerateDataKey",
|
|
422
405
|
]
|
|
423
|
-
Resource = var.
|
|
406
|
+
Resource = var.brain_artifacts_kms_key_arn
|
|
424
407
|
Condition = {
|
|
425
408
|
StringEquals = {
|
|
426
|
-
"
|
|
409
|
+
"kms:ViaService" = "s3.${var.region}.amazonaws.com"
|
|
427
410
|
}
|
|
428
411
|
}
|
|
429
412
|
},
|
|
@@ -444,13 +427,36 @@ locals {
|
|
|
444
427
|
Resource = var.capability_broker_session_table_arn
|
|
445
428
|
},
|
|
446
429
|
] : [],
|
|
430
|
+
# THINK-643 — auth-subscription-ticket mints tickets and bumps the connect
|
|
431
|
+
# counter; appsync-subscription-authorizer reads and conditionally consumes
|
|
432
|
+
# them. Both run on this shared role. Empty (→ no grant) while
|
|
433
|
+
# auth_state_store is "postgres", so the grant appears with the table.
|
|
434
|
+
#
|
|
435
|
+
# THINK-644 adds the `webhooks` handler (idempotency receipts) as a third
|
|
436
|
+
# consumer. It needs no separate statement: every handler in the
|
|
437
|
+
# aws_lambda_function.api for_each runs on aws_iam_role.lambda — the sole
|
|
438
|
+
# exception is memory-retraction-drainer, which does not touch this table.
|
|
439
|
+
# A future consumer on a sibling role would need its own grant.
|
|
440
|
+
local.auth_state_enabled ? [
|
|
441
|
+
{
|
|
442
|
+
Effect = "Allow"
|
|
443
|
+
Action = [
|
|
444
|
+
"dynamodb:GetItem",
|
|
445
|
+
"dynamodb:PutItem",
|
|
446
|
+
"dynamodb:UpdateItem",
|
|
447
|
+
"dynamodb:DeleteItem",
|
|
448
|
+
"dynamodb:Query",
|
|
449
|
+
]
|
|
450
|
+
Resource = aws_dynamodb_table.auth_state[0].arn
|
|
451
|
+
},
|
|
452
|
+
] : [],
|
|
447
453
|
)
|
|
448
454
|
|
|
449
455
|
# ---------------------------------------------------------------------------
|
|
450
456
|
# Group 2: orchestration — cross-function invokes, Scheduler, Step
|
|
451
457
|
# Functions, SQS, SES.
|
|
452
458
|
# ---------------------------------------------------------------------------
|
|
453
|
-
|
|
459
|
+
api_orchestration_candidate_statements = concat(
|
|
454
460
|
[
|
|
455
461
|
# (was inline policy "ses-send")
|
|
456
462
|
# SES send permissions for the email-send handler. Scoped to any
|
|
@@ -500,39 +506,30 @@ locals {
|
|
|
500
506
|
# (was inline policy "api-cross-function-invoke")
|
|
501
507
|
# Allow API handler Lambdas to invoke each other directly. sendMessage
|
|
502
508
|
# dispatches to chat-agent-invoke for instant chat response; the memory
|
|
503
|
-
# resolvers reach
|
|
504
|
-
# admin-driven operations. The
|
|
509
|
+
# resolvers reach job-schedule-manager for
|
|
510
|
+
# admin-driven operations. The Pi-invoke statement below covers
|
|
505
511
|
# the Pi runtime Lambda only — this one covers internal api-to-api
|
|
506
512
|
# calls. ARNs are constructed deterministically from the handler naming
|
|
507
513
|
# pattern so we don't create a dependency cycle with the handler
|
|
508
514
|
# resource.
|
|
509
515
|
{
|
|
516
|
+
Sid = "ApiCrossFunctionInvoke"
|
|
510
517
|
Effect = "Allow"
|
|
511
518
|
Action = ["lambda:InvokeFunction"]
|
|
512
519
|
Resource = [
|
|
513
520
|
"arn:aws:lambda:${var.region}:${var.account_id}:function:thinkwork-${var.stage}-api-chat-agent-invoke",
|
|
514
|
-
|
|
521
|
+
# THINK-583 U3: invokers address the `live` alias (provisioned
|
|
522
|
+
# concurrency only serves alias-qualified invokes); the alias ARN
|
|
523
|
+
# is a distinct IAM resource from the unqualified function ARN.
|
|
524
|
+
"arn:aws:lambda:${var.region}:${var.account_id}:function:thinkwork-${var.stage}-api-chat-agent-invoke:live",
|
|
515
525
|
"arn:aws:lambda:${var.region}:${var.account_id}:function:thinkwork-${var.stage}-api-job-schedule-manager",
|
|
516
526
|
# eval-runner: graphql-http's startEvalRun mutation Event-invokes
|
|
517
527
|
# this asynchronously after inserting the eval_runs row.
|
|
518
528
|
"arn:aws:lambda:${var.region}:${var.account_id}:function:thinkwork-${var.stage}-api-eval-runner",
|
|
519
|
-
#
|
|
520
|
-
#
|
|
521
|
-
#
|
|
522
|
-
"arn:aws:lambda:${var.region}:${var.account_id}:function:thinkwork-${var.stage}-api-
|
|
523
|
-
# knowledge-graph-observations-ingest: graphql-http's
|
|
524
|
-
# startKnowledgeGraphObservationsIngest mutation invokes this with
|
|
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.)
|
|
532
|
-
"arn:aws:lambda:${var.region}:${var.account_id}:function:thinkwork-${var.stage}-api-knowledge-graph-observations-ingest",
|
|
533
|
-
# wiki-bootstrap-import: bootstrapJournalImport admin mutation
|
|
534
|
-
# Event-invokes this for the long-running ingest path.
|
|
535
|
-
"arn:aws:lambda:${var.region}:${var.account_id}:function:thinkwork-${var.stage}-api-wiki-bootstrap-import",
|
|
529
|
+
# identity-graph-projector (Company Brain U5): identity mutations
|
|
530
|
+
# Event-invoke this as a post-commit nudge; the rebuild command is
|
|
531
|
+
# a RequestResponse invoke. Cursor makes missed nudges harmless.
|
|
532
|
+
"arn:aws:lambda:${var.region}:${var.account_id}:function:thinkwork-${var.stage}-api-identity-graph-projector",
|
|
536
533
|
# harness-runner: chat-agent-invoke Event-invokes this for chat
|
|
537
534
|
# turns routed to the AWS AgentCore runtime (THINK-311 trial).
|
|
538
535
|
"arn:aws:lambda:${var.region}:${var.account_id}:function:thinkwork-${var.stage}-api-harness-runner",
|
|
@@ -544,19 +541,10 @@ locals {
|
|
|
544
541
|
# signer re-derives the actor/tenant/thread tuple from the running
|
|
545
542
|
# turn and alone holds KMS Sign; the shared runner role never does.
|
|
546
543
|
"arn:aws:lambda:${var.region}:${var.account_id}:function:thinkwork-${var.stage}-api-turn-assertion-mint",
|
|
547
|
-
#
|
|
548
|
-
# after inserting a durable
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
# after inserting a durable reprocess job row.
|
|
552
|
-
"arn:aws:lambda:${var.region}:${var.account_id}:function:thinkwork-${var.stage}-api-ontology-reprocess",
|
|
553
|
-
# okf-materialize / okf-efs-refresh: the OKF distribution chain
|
|
554
|
-
# (THINK-200). wiki-compile Event-invokes okf-materialize after a
|
|
555
|
-
# successful compile; okf-materialize Event-invokes okf-efs-refresh
|
|
556
|
-
# after publishing bundles, keeping the Pi wiki navigator's EFS
|
|
557
|
-
# view current without manual invocation.
|
|
558
|
-
"arn:aws:lambda:${var.region}:${var.account_id}:function:thinkwork-${var.stage}-api-okf-materialize",
|
|
559
|
-
"arn:aws:lambda:${var.region}:${var.account_id}:function:thinkwork-${var.stage}-api-okf-efs-refresh",
|
|
544
|
+
# identity-match (THINK-321 U7): startIdentityMatchJob Event-invokes
|
|
545
|
+
# this after inserting a durable match job row; identity-match also
|
|
546
|
+
# self-invokes for the continuation chain (same shared role).
|
|
547
|
+
"arn:aws:lambda:${var.region}:${var.account_id}:function:thinkwork-${var.stage}-api-identity-match",
|
|
560
548
|
# routine-resume: routine-approval-bridge (Phase B U8) invokes
|
|
561
549
|
# this with RequestResponse after a HITL decideInboxItem
|
|
562
550
|
# decision. Calls SendTaskSuccess/SendTaskFailure on the SFN
|
|
@@ -568,7 +556,9 @@ locals {
|
|
|
568
556
|
"arn:aws:lambda:${var.region}:${var.account_id}:function:thinkwork-${var.stage}-api-workspace-files-efs",
|
|
569
557
|
# workspace-renderer: chat-agent-invoke invokes this synchronously
|
|
570
558
|
# before AgentCore so Pi can opt into the rendered
|
|
571
|
-
# per-(agent, Space, user) workspace prefix.
|
|
559
|
+
# per-(agent, Space, user) workspace prefix. THINK-583 U3: the
|
|
560
|
+
# `:live` alias ARN is covered by the dedicated workspace-renderer
|
|
561
|
+
# statement below (`...workspace-renderer:*`).
|
|
572
562
|
"arn:aws:lambda:${var.region}:${var.account_id}:function:thinkwork-${var.stage}-api-workspace-renderer",
|
|
573
563
|
# skill-trust-runner: graphql-http's publishSkillDraft mutation
|
|
574
564
|
# invokes this with RequestResponse so SkillSpector completion is a
|
|
@@ -614,6 +604,9 @@ locals {
|
|
|
614
604
|
Resource = [
|
|
615
605
|
"arn:aws:lambda:${var.region}:${var.account_id}:function:thinkwork-${var.stage}-api-workspace-renderer",
|
|
616
606
|
"arn:aws:lambda:${var.region}:${var.account_id}:function:thinkwork-${var.stage}-api-workspace-renderer:*",
|
|
607
|
+
# THINK-585 U6: chat-agent-invoke Event-invokes the runtime
|
|
608
|
+
# dispatcher at the flag-on dispatch seam.
|
|
609
|
+
"arn:aws:lambda:${var.region}:${var.account_id}:function:thinkwork-${var.stage}-api-agentcore-runtime-dispatch",
|
|
617
610
|
]
|
|
618
611
|
},
|
|
619
612
|
# (was standalone managed policy "thread_idle_memory_learning_invoke")
|
|
@@ -781,11 +774,35 @@ locals {
|
|
|
781
774
|
] : [],
|
|
782
775
|
)
|
|
783
776
|
|
|
777
|
+
# Internal Lambda invocation is intentionally partitioned from the remaining
|
|
778
|
+
# orchestration grants. The generated resource list grows with API features
|
|
779
|
+
# and can otherwise push the shared orchestration managed policy beyond
|
|
780
|
+
# IAM's hard 6,144-character document limit. Both partitions remain attached
|
|
781
|
+
# to the same shared Lambda role and are covered by the size assertion below.
|
|
782
|
+
api_orchestration_statements = [
|
|
783
|
+
for statement in local.api_orchestration_candidate_statements : statement
|
|
784
|
+
if !contains(try(statement.Action, []), "lambda:InvokeFunction")
|
|
785
|
+
]
|
|
786
|
+
api_invocation_statements = [
|
|
787
|
+
for statement in local.api_orchestration_candidate_statements : statement
|
|
788
|
+
if contains(try(statement.Action, []), "lambda:InvokeFunction")
|
|
789
|
+
]
|
|
790
|
+
|
|
784
791
|
# ---------------------------------------------------------------------------
|
|
785
|
-
# Group 3: AI — Bedrock model invocation,
|
|
792
|
+
# Group 3: AI — Bedrock model invocation, AgentCore
|
|
786
793
|
# memory / evaluations / code interpreter.
|
|
787
794
|
# ---------------------------------------------------------------------------
|
|
788
795
|
api_ai_statements = concat([
|
|
796
|
+
# Signed-turn identity (THINK-324 C18): dispatch Lambdas mint with
|
|
797
|
+
# kms:Sign; verifiers fetch the public key once per container with
|
|
798
|
+
# kms:GetPublicKey. Scoped to the turn-assertion keys only; the role is
|
|
799
|
+
# shared, so which handler may mint is code-enforced.
|
|
800
|
+
{
|
|
801
|
+
Sid = "TurnAssertionSigning"
|
|
802
|
+
Effect = "Allow"
|
|
803
|
+
Action = ["kms:Sign", "kms:GetPublicKey"]
|
|
804
|
+
Resource = local.turn_assertion_key_arns
|
|
805
|
+
},
|
|
789
806
|
# (was inline policy "bedrock-invoke")
|
|
790
807
|
# Cross-region inference profiles (us.anthropic.claude-*) require
|
|
791
808
|
# `bedrock:InvokeModel` on the *inference-profile* ARN AND on the
|
|
@@ -801,62 +818,17 @@ locals {
|
|
|
801
818
|
"arn:aws:bedrock:*:${var.account_id}:inference-profile/*",
|
|
802
819
|
]
|
|
803
820
|
},
|
|
804
|
-
# (was standalone managed policy "lambda_bedrock_knowledge_base")
|
|
805
|
-
# The knowledge-base-manager Lambda provisions and manages Bedrock
|
|
806
|
-
# Knowledge Bases (control plane: create/sync/rechunk/delete), and
|
|
807
|
-
# graphql-http's testKnowledgeBaseRetrieval query calls Retrieve. Without
|
|
808
|
-
# these the manager fails with "not authorized to perform:
|
|
809
|
-
# bedrock:CreateKnowledgeBase" and every KB is stuck in `failed`.
|
|
810
|
-
# CreateKnowledgeBase / CreateDataSource also take a roleArn that Bedrock
|
|
811
|
-
# assumes, so the caller needs iam:PassRole on the KB service role.
|
|
812
|
-
{
|
|
813
|
-
Effect = "Allow"
|
|
814
|
-
Action = [
|
|
815
|
-
"bedrock:CreateKnowledgeBase",
|
|
816
|
-
"bedrock:GetKnowledgeBase",
|
|
817
|
-
"bedrock:UpdateKnowledgeBase",
|
|
818
|
-
"bedrock:DeleteKnowledgeBase",
|
|
819
|
-
"bedrock:ListKnowledgeBases",
|
|
820
|
-
"bedrock:CreateDataSource",
|
|
821
|
-
"bedrock:GetDataSource",
|
|
822
|
-
"bedrock:UpdateDataSource",
|
|
823
|
-
"bedrock:DeleteDataSource",
|
|
824
|
-
"bedrock:ListDataSources",
|
|
825
|
-
"bedrock:StartIngestionJob",
|
|
826
|
-
"bedrock:GetIngestionJob",
|
|
827
|
-
"bedrock:ListIngestionJobs",
|
|
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",
|
|
841
|
-
]
|
|
842
|
-
# CreateKnowledgeBase/CreateDataSource have no resource ARN at create
|
|
843
|
-
# time and don't support resource-level scoping, so a knowledge-base/*
|
|
844
|
-
# ARN makes the grant not match. Control-plane "*" for this internal
|
|
845
|
-
# manager Lambda; PassRole below stays scoped to the KB service role.
|
|
846
|
-
Resource = "*"
|
|
847
|
-
},
|
|
848
|
-
{
|
|
849
|
-
Effect = "Allow"
|
|
850
|
-
Action = ["iam:PassRole"]
|
|
851
|
-
Resource = var.kb_service_role_arn != "" ? var.kb_service_role_arn : "*"
|
|
852
|
-
},
|
|
853
821
|
# (was inline policy "agentcore-memory-rw")
|
|
854
|
-
# AgentCore Memory
|
|
855
|
-
# memoryRecords / memorySearch call
|
|
856
|
-
# records across the tenant's agents
|
|
822
|
+
# AgentCore Memory access for the GraphQL memory resolvers and the
|
|
823
|
+
# memory-retain handler. memoryRecords / memorySearch call
|
|
824
|
+
# ListMemoryRecordsCommand to fetch records across the tenant's agents;
|
|
825
|
+
# memory-retain calls CreateEventCommand to land the turn in the managed
|
|
826
|
+
# memory (before the agentcore engine flip that write went to Hindsight
|
|
827
|
+
# over HTTP, so no IAM action existed for it).
|
|
857
828
|
{
|
|
858
829
|
Effect = "Allow"
|
|
859
830
|
Action = [
|
|
831
|
+
"bedrock-agentcore:CreateEvent",
|
|
860
832
|
"bedrock-agentcore:ListMemoryRecords",
|
|
861
833
|
"bedrock-agentcore:RetrieveMemoryRecords",
|
|
862
834
|
"bedrock-agentcore:GetMemoryRecord",
|
|
@@ -907,29 +879,15 @@ locals {
|
|
|
907
879
|
Resource = "*"
|
|
908
880
|
},
|
|
909
881
|
],
|
|
910
|
-
# THINK-
|
|
911
|
-
#
|
|
912
|
-
#
|
|
913
|
-
#
|
|
914
|
-
#
|
|
915
|
-
#
|
|
916
|
-
|
|
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
|
-
},
|
|
882
|
+
# THINK-324 — the managed-harness invoke grant is retired. The AgentCore
|
|
883
|
+
# Identity chain below survives UNCONDITIONALLY: the live Twenty
|
|
884
|
+
# connector's per-user 3LO (handlers/skills.ts via
|
|
885
|
+
# lib/agentcore-identity/agentcore-user-oauth.ts) mints workload tokens
|
|
886
|
+
# against the shared workload identity and reads the twenty-crm
|
|
887
|
+
# credential provider from the token vault.
|
|
888
|
+
[
|
|
928
889
|
{
|
|
929
|
-
|
|
930
|
-
# chain as Harness Gateway outbound auth: turn JWT -> workload token
|
|
931
|
-
# -> OBO Gateway token. No provider client secret enters Lambda.
|
|
932
|
-
Sid = "AgentCoreHarnessGatewayIdentity"
|
|
890
|
+
Sid = "AgentCoreTwentyIdentity"
|
|
933
891
|
Effect = "Allow"
|
|
934
892
|
Action = [
|
|
935
893
|
"bedrock-agentcore:GetWorkloadAccessTokenForJWT",
|
|
@@ -941,21 +899,18 @@ locals {
|
|
|
941
899
|
"arn:aws:bedrock-agentcore:${var.region}:${var.account_id}:workload-identity-directory/default",
|
|
942
900
|
"arn:aws:bedrock-agentcore:${var.region}:${var.account_id}:workload-identity-directory/default/workload-identity/thinkwork-${var.stage}-multiplayer-proof",
|
|
943
901
|
"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
902
|
"arn:aws:bedrock-agentcore:${var.region}:${var.account_id}:token-vault/default/oauth2credentialprovider/thinkwork-${var.stage}-twenty-crm",
|
|
946
903
|
]
|
|
947
904
|
},
|
|
948
|
-
]
|
|
905
|
+
],
|
|
949
906
|
)
|
|
950
907
|
|
|
951
908
|
# ---------------------------------------------------------------------------
|
|
952
909
|
# Group 4: observability — CloudWatch Logs reads, ECS/ALB health reads.
|
|
953
910
|
# ---------------------------------------------------------------------------
|
|
954
|
-
# Handler-gated SQS grants
|
|
955
|
-
#
|
|
956
|
-
#
|
|
957
|
-
# 6,018 before it). Queue plumbing is operational surface; observability
|
|
958
|
-
# has ~5k headroom. Same statements, different envelope.
|
|
911
|
+
# Handler-gated SQS grants live HERE rather than in the data-plane group:
|
|
912
|
+
# data-plane sits near IAM's 6,144-char rendered cap. Queue plumbing is
|
|
913
|
+
# operational surface; observability has ~5k headroom.
|
|
959
914
|
api_observability_sqs_statements = concat(
|
|
960
915
|
# SQS grants live here rather than in the orchestration group purely for
|
|
961
916
|
# size balance: with every conditional on, orchestration's rendered JSON
|
|
@@ -963,26 +918,12 @@ locals {
|
|
|
963
918
|
# Handler-gated SQS grants. Each statement was a count-gated inline
|
|
964
919
|
# policy whose queue exists only when local.deploy_lambda_handlers.
|
|
965
920
|
local.deploy_lambda_handlers ? [
|
|
966
|
-
#
|
|
967
|
-
{
|
|
968
|
-
Sid = "WikiCompileDlqSend"
|
|
969
|
-
Effect = "Allow"
|
|
970
|
-
Action = ["sqs:SendMessage"]
|
|
971
|
-
Resource = aws_sqs_queue.wiki_compile_dlq[0].arn
|
|
972
|
-
},
|
|
973
|
-
# (was inline policy "thinkwork-${stage}-ontology-scan-dlq-send")
|
|
974
|
-
{
|
|
975
|
-
Sid = "OntologyScanDlqSend"
|
|
976
|
-
Effect = "Allow"
|
|
977
|
-
Action = ["sqs:SendMessage"]
|
|
978
|
-
Resource = aws_sqs_queue.ontology_scan_dlq[0].arn
|
|
979
|
-
},
|
|
980
|
-
# (was inline policy "thinkwork-${stage}-ontology-reprocess-dlq-send")
|
|
921
|
+
# THINK-321 U7 identity-match async-failure DLQ.
|
|
981
922
|
{
|
|
982
|
-
Sid = "
|
|
923
|
+
Sid = "IdentityMatchDlqSend"
|
|
983
924
|
Effect = "Allow"
|
|
984
925
|
Action = ["sqs:SendMessage"]
|
|
985
|
-
Resource = aws_sqs_queue.
|
|
926
|
+
Resource = aws_sqs_queue.identity_match_dlq[0].arn
|
|
986
927
|
},
|
|
987
928
|
# (was inline policy "compliance-drainer-dlq-send")
|
|
988
929
|
{
|
|
@@ -991,13 +932,6 @@ locals {
|
|
|
991
932
|
Action = ["sqs:SendMessage"]
|
|
992
933
|
Resource = aws_sqs_queue.compliance_drainer_dlq[0].arn
|
|
993
934
|
},
|
|
994
|
-
# THINK-229 U5 — analyst-connection-reconciler async on_failure DLQ.
|
|
995
|
-
{
|
|
996
|
-
Sid = "AnalystConnectionReconcilerDlqSend"
|
|
997
|
-
Effect = "Allow"
|
|
998
|
-
Action = ["sqs:SendMessage"]
|
|
999
|
-
Resource = aws_sqs_queue.analyst_connection_reconciler_dlq[0].arn
|
|
1000
|
-
},
|
|
1001
935
|
# (was inline policy "compliance-exports-send")
|
|
1002
936
|
# graphql-http needs sqs:SendMessage on the exports queue to dispatch
|
|
1003
937
|
# jobIds from the createComplianceExport mutation. Attached to the
|
|
@@ -1039,6 +973,72 @@ locals {
|
|
|
1039
973
|
Resource = aws_sqs_queue.eval_fanout_dlq[0].arn
|
|
1040
974
|
},
|
|
1041
975
|
] : [],
|
|
976
|
+
# Company Brain twin (plan 2026-07-21-001 U5): Neptune data access for
|
|
977
|
+
# the identity-graph-projector (and the wiki-compile soft-layer writer)
|
|
978
|
+
# on the SHARED role. The twin-query read Lambda and its dedicated
|
|
979
|
+
# read-only role retired to the platform service (THINK-339 U15) — no
|
|
980
|
+
# caller-supplied query path remains product-side.
|
|
981
|
+
# Lives in the ai envelope for size balance (data-plane sits ~430 chars
|
|
982
|
+
# under IAM's 6,144 cap). Grouped — not inline — so the no-terraform
|
|
983
|
+
# targeted deploy path (which applies exactly these grouped policies)
|
|
984
|
+
# self-heals the grant; the original inline resource never survived a
|
|
985
|
+
# superseded full apply. Data actions are condition-pinned to openCypher,
|
|
986
|
+
# mirroring the etl-side policies.
|
|
987
|
+
# (Two segments, not one: the data statement carries a Condition the
|
|
988
|
+
# status statement can't — mixed shapes in one conditional tuple fail
|
|
989
|
+
# Terraform's type unification.)
|
|
990
|
+
var.neptune_cluster_resource_id == "" ? [] : [
|
|
991
|
+
{
|
|
992
|
+
Sid = "TwinNeptuneData"
|
|
993
|
+
Effect = "Allow"
|
|
994
|
+
Action = [
|
|
995
|
+
"neptune-db:ReadDataViaQuery",
|
|
996
|
+
"neptune-db:WriteDataViaQuery",
|
|
997
|
+
"neptune-db:DeleteDataViaQuery",
|
|
998
|
+
]
|
|
999
|
+
Resource = "arn:aws:neptune-db:${var.region}:${var.account_id}:${var.neptune_cluster_resource_id}/*"
|
|
1000
|
+
Condition = {
|
|
1001
|
+
StringEquals = { "neptune-db:QueryLanguage" = "OpenCypher" }
|
|
1002
|
+
}
|
|
1003
|
+
},
|
|
1004
|
+
],
|
|
1005
|
+
var.neptune_cluster_resource_id == "" ? [] : [
|
|
1006
|
+
{
|
|
1007
|
+
Sid = "TwinEngineStatus"
|
|
1008
|
+
Effect = "Allow"
|
|
1009
|
+
Action = ["neptune-db:GetEngineStatus", "neptune-db:GetGraphSummary"]
|
|
1010
|
+
Resource = "arn:aws:neptune-db:${var.region}:${var.account_id}:${var.neptune_cluster_resource_id}/*"
|
|
1011
|
+
},
|
|
1012
|
+
],
|
|
1013
|
+
# Bulk-rebuild lane (THINK-331 U4): the projector stages openCypher CSVs
|
|
1014
|
+
# under the tenant-scoped thinkwork-identity/ prefix of the etl-platform
|
|
1015
|
+
# load bucket (Put for upload, Delete for the terminal-state cleanup)
|
|
1016
|
+
# and drives the loader job API. The CSVs are streamed as S3 multipart
|
|
1017
|
+
# uploads for large tenants (THINK-409): CreateMultipartUpload /
|
|
1018
|
+
# UploadPart / CompleteMultipartUpload all authorize as s3:PutObject, and
|
|
1019
|
+
# the failure path's AbortMultipartUpload is the action below — no
|
|
1020
|
+
# s3:ListMultipartUploadParts needed, the stager tracks its own parts
|
|
1021
|
+
# (this policy is near IAM's 6,144-char cap; see below). A NEW statement
|
|
1022
|
+
# group — the existing
|
|
1023
|
+
# TwinNeptuneData statement is condition-pinned to QueryLanguage=
|
|
1024
|
+
# OpenCypher, which the loader actions don't satisfy. Gated on the
|
|
1025
|
+
# bulk-loader variables so stages without the twin stack ship inert
|
|
1026
|
+
# (KTD-9). No iam:PassRole needed: the loader role is assumed by the
|
|
1027
|
+
# Neptune service via its cluster association, not passed by this role.
|
|
1028
|
+
var.neptune_load_bucket == "" || var.neptune_loader_role_arn == "" || var.neptune_cluster_resource_id == "" ? [] : [
|
|
1029
|
+
{
|
|
1030
|
+
Sid = "TwinBulkLoaderStage"
|
|
1031
|
+
Effect = "Allow"
|
|
1032
|
+
Action = ["s3:PutObject", "s3:AbortMultipartUpload", "s3:DeleteObject"]
|
|
1033
|
+
Resource = "arn:aws:s3:::${var.neptune_load_bucket}/thinkwork-identity/*"
|
|
1034
|
+
},
|
|
1035
|
+
{
|
|
1036
|
+
Sid = "TwinBulkLoaderJobs"
|
|
1037
|
+
Effect = "Allow"
|
|
1038
|
+
Action = ["neptune-db:StartLoaderJob", "neptune-db:GetLoaderJobStatus", "neptune-db:CancelLoaderJob"]
|
|
1039
|
+
Resource = "arn:aws:neptune-db:${var.region}:${var.account_id}:${var.neptune_cluster_resource_id}/*"
|
|
1040
|
+
},
|
|
1041
|
+
],
|
|
1042
1042
|
)
|
|
1043
1043
|
|
|
1044
1044
|
api_observability_statements = concat(local.api_observability_sqs_statements, [
|
|
@@ -1122,6 +1122,10 @@ locals {
|
|
|
1122
1122
|
Version = "2012-10-17"
|
|
1123
1123
|
Statement = local.api_orchestration_statements
|
|
1124
1124
|
})
|
|
1125
|
+
invocation = jsonencode({
|
|
1126
|
+
Version = "2012-10-17"
|
|
1127
|
+
Statement = local.api_invocation_statements
|
|
1128
|
+
})
|
|
1125
1129
|
ai = jsonencode({
|
|
1126
1130
|
Version = "2012-10-17"
|
|
1127
1131
|
Statement = local.api_ai_statements
|
|
@@ -1147,6 +1151,13 @@ resource "aws_iam_policy" "api_data_plane" {
|
|
|
1147
1151
|
description = "Grouped data-plane grants (RDS Data API, Secrets Manager, S3, DynamoDB, Cognito, SSM, KMS-via-SSM, SQS) for the shared api Lambda role"
|
|
1148
1152
|
|
|
1149
1153
|
policy = local.api_grouped_policy_documents.data_plane
|
|
1154
|
+
|
|
1155
|
+
lifecycle {
|
|
1156
|
+
precondition {
|
|
1157
|
+
condition = length(local.api_grouped_policy_documents.data_plane) <= 6144
|
|
1158
|
+
error_message = "The grouped API data-plane managed-policy document exceeds AWS IAM's 6,144-character limit."
|
|
1159
|
+
}
|
|
1160
|
+
}
|
|
1150
1161
|
}
|
|
1151
1162
|
|
|
1152
1163
|
resource "aws_iam_role_policy_attachment" "api_data_plane" {
|
|
@@ -1156,9 +1167,27 @@ resource "aws_iam_role_policy_attachment" "api_data_plane" {
|
|
|
1156
1167
|
|
|
1157
1168
|
resource "aws_iam_policy" "api_orchestration" {
|
|
1158
1169
|
name = "thinkwork-${var.stage}-api-orchestration"
|
|
1159
|
-
description = "Grouped orchestration grants (
|
|
1170
|
+
description = "Grouped orchestration grants (EventBridge Scheduler, Step Functions, SES) for the shared api Lambda role"
|
|
1160
1171
|
|
|
1161
1172
|
policy = local.api_grouped_policy_documents.orchestration
|
|
1173
|
+
|
|
1174
|
+
# Attach the replacement invoke grant before removing it from this policy.
|
|
1175
|
+
# This preserves Lambda-to-Lambda access if an apply stops between updates.
|
|
1176
|
+
depends_on = [aws_iam_role_policy_attachment.api_invocation]
|
|
1177
|
+
|
|
1178
|
+
lifecycle {
|
|
1179
|
+
# Existing environments may retain the historical description that also
|
|
1180
|
+
# mentioned Lambda invocation. Description changes replace IAM managed
|
|
1181
|
+
# policies, which would destroy the old orchestration grant before the new
|
|
1182
|
+
# invocation attachment is ready. Keep the policy identity stable so the
|
|
1183
|
+
# depends_on edge above orders an in-place document update after attach.
|
|
1184
|
+
ignore_changes = [description]
|
|
1185
|
+
|
|
1186
|
+
precondition {
|
|
1187
|
+
condition = length(local.api_grouped_policy_documents.orchestration) <= 6144
|
|
1188
|
+
error_message = "The grouped API orchestration managed-policy document exceeds AWS IAM's 6,144-character limit."
|
|
1189
|
+
}
|
|
1190
|
+
}
|
|
1162
1191
|
}
|
|
1163
1192
|
|
|
1164
1193
|
resource "aws_iam_role_policy_attachment" "api_orchestration" {
|
|
@@ -1166,11 +1195,37 @@ resource "aws_iam_role_policy_attachment" "api_orchestration" {
|
|
|
1166
1195
|
policy_arn = aws_iam_policy.api_orchestration.arn
|
|
1167
1196
|
}
|
|
1168
1197
|
|
|
1198
|
+
resource "aws_iam_policy" "api_invocation" {
|
|
1199
|
+
name = "thinkwork-${var.stage}-api-invocation"
|
|
1200
|
+
description = "Internal Lambda invocation grants for the shared api Lambda role"
|
|
1201
|
+
|
|
1202
|
+
policy = local.api_grouped_policy_documents.invocation
|
|
1203
|
+
|
|
1204
|
+
lifecycle {
|
|
1205
|
+
precondition {
|
|
1206
|
+
condition = length(local.api_grouped_policy_documents.invocation) <= 6144
|
|
1207
|
+
error_message = "The grouped API invocation managed-policy document exceeds AWS IAM's 6,144-character limit."
|
|
1208
|
+
}
|
|
1209
|
+
}
|
|
1210
|
+
}
|
|
1211
|
+
|
|
1212
|
+
resource "aws_iam_role_policy_attachment" "api_invocation" {
|
|
1213
|
+
role = aws_iam_role.lambda.name
|
|
1214
|
+
policy_arn = aws_iam_policy.api_invocation.arn
|
|
1215
|
+
}
|
|
1216
|
+
|
|
1169
1217
|
resource "aws_iam_policy" "api_ai" {
|
|
1170
1218
|
name = "thinkwork-${var.stage}-api-ai"
|
|
1171
|
-
description = "Grouped AI grants (Bedrock invoke,
|
|
1219
|
+
description = "Grouped AI grants (Bedrock invoke, AgentCore memory/eval/code-interpreter) for the shared api Lambda role"
|
|
1172
1220
|
|
|
1173
1221
|
policy = local.api_grouped_policy_documents.ai
|
|
1222
|
+
|
|
1223
|
+
lifecycle {
|
|
1224
|
+
precondition {
|
|
1225
|
+
condition = length(local.api_grouped_policy_documents.ai) <= 6144
|
|
1226
|
+
error_message = "The grouped API AI managed-policy document exceeds AWS IAM's 6,144-character limit."
|
|
1227
|
+
}
|
|
1228
|
+
}
|
|
1174
1229
|
}
|
|
1175
1230
|
|
|
1176
1231
|
resource "aws_iam_role_policy_attachment" "api_ai" {
|
|
@@ -1183,6 +1238,13 @@ resource "aws_iam_policy" "api_observability" {
|
|
|
1183
1238
|
description = "Grouped observability grants (CloudWatch Logs reads, ECS/ALB health reads) for the shared api Lambda role"
|
|
1184
1239
|
|
|
1185
1240
|
policy = local.api_grouped_policy_documents.observability
|
|
1241
|
+
|
|
1242
|
+
lifecycle {
|
|
1243
|
+
precondition {
|
|
1244
|
+
condition = length(local.api_grouped_policy_documents.observability) <= 6144
|
|
1245
|
+
error_message = "The grouped API observability managed-policy document exceeds AWS IAM's 6,144-character limit."
|
|
1246
|
+
}
|
|
1247
|
+
}
|
|
1186
1248
|
}
|
|
1187
1249
|
|
|
1188
1250
|
resource "aws_iam_role_policy_attachment" "api_observability" {
|
|
@@ -1221,3 +1283,5 @@ moved {
|
|
|
1221
1283
|
from = aws_iam_role_policy_attachment.lambda_bedrock_knowledge_base
|
|
1222
1284
|
to = aws_iam_role_policy_attachment.api_ai
|
|
1223
1285
|
}
|
|
1286
|
+
|
|
1287
|
+
|