thinkwork-cli 0.13.1 → 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-4DZ266J5.js → api-client-4P4JZOBX.js} +3 -1
- package/dist/bowser-6Z6JFAIR.js +2822 -0
- package/dist/{chunk-Y2WHJECR.js → chunk-4OMDWYZQ.js} +5 -44
- package/dist/chunk-AD2NIWB5.js +6516 -0
- package/dist/chunk-DV3MRBR5.js +43 -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-KMIJ5KGT.js +128 -0
- package/dist/chunk-MWQ7RO76.js +137 -0
- package/dist/chunk-OCPHU34C.js +996 -0
- package/dist/chunk-OLUQ4U2Z.js +1728 -0
- package/dist/chunk-XYM7PE2A.js +2264 -0
- package/dist/chunk-YQCYD6NE.js +3299 -0
- package/dist/cli.js +49156 -31257
- 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-2OTNTL4N.js +315 -0
- package/dist/dist-es-2XVAH4BQ.js +14726 -0
- package/dist/dist-es-3DPDUJAH.js +2000 -0
- package/dist/dist-es-BNZTBBVC.js +176 -0
- package/dist/dist-es-CD2RBDAC.js +88 -0
- package/dist/dist-es-I4FW57PS.js +88 -0
- package/dist/dist-es-KL7Y5NB2.js +377 -0
- package/dist/dist-es-KVFWJNDY.js +318 -0
- package/dist/dist-es-PS73DWNL.js +70 -0
- package/dist/dist-es-S3NZQFGT.js +170 -0
- package/dist/dist-es-SGCA4P32.js +48 -0
- package/dist/dist-es-WBM6J4RA.js +70 -0
- package/dist/dist-es-ZGVADYIF.js +485 -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 +17 -20
- package/dist/drizzle/0230_analyst_rls.sql +28 -36
- package/dist/drizzle/0250_kg_schema_extraction.sql +27 -0
- package/dist/drizzle/0251_brain_stragglers.sql +21 -0
- package/dist/drizzle/0253_drop_brain_substrate.sql +2 -0
- package/dist/drizzle/0257_agents_runtime_allow_harness.sql +24 -0
- package/dist/drizzle/0261_native_auth_control_plane.sql +332 -0
- package/dist/drizzle/0262_auth_subscription_tickets.sql +59 -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/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/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/event-streams-7JNLJEEL.js +894 -0
- package/dist/event-streams-KDF5RWR6.js +1515 -0
- package/dist/loadSso-ETCXTR4I.js +576 -0
- package/dist/loadSso-UBD7KUHE.js +583 -0
- package/dist/plugins/README.md +2 -2
- package/dist/plugins/catalog/package.json +1 -5
- package/dist/plugins/catalog/src/__tests__/build-catalog.test.ts +6 -4
- package/dist/plugins/catalog/src/__tests__/catalog.test.ts +21 -21
- package/dist/plugins/catalog/src/__tests__/contracts.test.ts +102 -94
- package/dist/plugins/catalog/src/__tests__/plugin-package.test.ts +7 -8
- package/dist/plugins/catalog/src/__tests__/plugin-registry.test.ts +0 -20
- package/dist/plugins/catalog/src/contracts.ts +17 -179
- package/dist/plugins/catalog/src/registry/generated-first-party.ts +0 -24
- 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-5QZNRSOO.js +821 -0
- package/dist/sso-oidc-XK673P54.js +837 -0
- package/dist/sts-OXI2UALF.js +1113 -0
- package/dist/sts-SQW4NBK3.js +1117 -0
- package/dist/terraform/examples/greenfield/main.tf +391 -176
- package/dist/terraform/examples/greenfield/terraform.tfvars.example +26 -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 +253 -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 +239 -0
- package/dist/terraform/modules/app/agentcore-identity/scripts/delete_identity.sh +22 -0
- package/dist/terraform/modules/app/agentcore-identity/scripts/delete_twenty_identity.sh +16 -0
- 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 +55 -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 +45 -0
- package/dist/terraform/modules/app/agentcore-identity/scripts/reconcile_twenty_provider.mjs +123 -0
- 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 +60 -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/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 +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 +3689 -233
- package/dist/terraform/modules/app/deployment-control-plane/test_runner_bundle.py +2579 -140
- 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 +531 -619
- package/dist/terraform/modules/app/lambda-api/iam-grouped.tf +350 -241
- package/dist/terraform/modules/app/lambda-api/main.tf +75 -13
- 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 -10
- package/dist/terraform/modules/app/lambda-api/runtime-config.tf +3 -21
- package/dist/terraform/modules/app/lambda-api/turn-assertion.tf +45 -0
- package/dist/terraform/modules/app/lambda-api/variables.tf +307 -121
- 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 +367 -72
- package/dist/terraform/modules/foundation/cognito/outputs.tf +47 -0
- package/dist/terraform/modules/foundation/cognito/variables.tf +131 -9
- package/dist/terraform/modules/thinkwork/README.md +5 -1
- package/dist/terraform/modules/thinkwork/main.tf +459 -234
- package/dist/terraform/modules/thinkwork/outputs.tf +44 -62
- package/dist/terraform/modules/thinkwork/variables.tf +353 -89
- package/dist/terraform/schema.graphql +69 -36
- 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/USER.md +1 -0
- 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 +3 -2
- package/dist/drizzle/0261_thread_turns_origin_turn_index.sql +0 -11
- 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/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/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-harness/main.tf +0 -101
- package/dist/terraform/modules/app/agentcore-harness/outputs.tf +0 -9
- package/dist/terraform/modules/app/agentcore-harness/variables.tf +0 -25
- 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/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
|
@@ -13,12 +13,9 @@ account_id = "123456789012" # your AWS account ID
|
|
|
13
13
|
database_engine = "rds-postgres"
|
|
14
14
|
|
|
15
15
|
# Memory:
|
|
16
|
-
#
|
|
17
|
-
#
|
|
18
|
-
#
|
|
19
|
-
# AgentCore-only deployments.
|
|
20
|
-
# enable_hindsight = false
|
|
21
|
-
# memory_engine = "agentcore"
|
|
16
|
+
# Bedrock AgentCore managed memory is the only engine. The legacy
|
|
17
|
+
# `enable_hindsight` / `memory_engine` inputs are deprecated no-ops that are
|
|
18
|
+
# still accepted so old tfvars keep applying.
|
|
22
19
|
|
|
23
20
|
# Managed applications:
|
|
24
21
|
# Twenty CRM is optional. First enable should set both booleans true after
|
|
@@ -72,10 +69,24 @@ db_password = "CHANGE_ME_strong_password_here"
|
|
|
72
69
|
# Google OAuth (optional — leave empty to skip Google social login)
|
|
73
70
|
# google_oauth_client_id = ""
|
|
74
71
|
# google_oauth_client_secret = ""
|
|
72
|
+
# microsoft_oauth_client_id = ""
|
|
73
|
+
# microsoft_oauth_client_secret = "" # Supply securely; never commit a real value.
|
|
74
|
+
# microsoft_oauth_tenant = "" # Entra directory GUID, or common/organizations/consumers (Cognito-supported aliases).
|
|
75
|
+
|
|
76
|
+
# Tenant-specific Entra IdPs are reconciled by `thinkwork enterprise
|
|
77
|
+
# identity-provider`; Terraform receives safe provider metadata only.
|
|
78
|
+
# tenant_entra_connections = [{
|
|
79
|
+
# connection_key = "microsoft:tenant:00000000-0000-4000-8000-000000000000"
|
|
80
|
+
# tenant_id = "00000000-0000-4000-8000-000000000000"
|
|
81
|
+
# provider_name = "Entra_0000000000004000_ab12cd34"
|
|
82
|
+
# display_name = "Example organization"
|
|
83
|
+
# }]
|
|
75
84
|
|
|
76
85
|
# Cognito trigger Lambdas (optional — leave empty if not using custom auth logic)
|
|
77
86
|
# pre_signup_lambda_zip = "./lambdas/cognito-pre-signup.zip"
|
|
78
|
-
#
|
|
87
|
+
# auth_retirement_phase = "retired" # greenfield default; existing upgrades explicitly use coexistence -> cutover -> retired
|
|
88
|
+
# auth_migration_recovery_deadline = "2026-08-01T00:00:00Z" # required when auth_retirement_phase = "coexistence"
|
|
89
|
+
# cognito_custom_auth_lambda_zip = "./lambdas/cognito-custom-auth.zip" # rollback only
|
|
79
90
|
|
|
80
91
|
# Lambda artifacts:
|
|
81
92
|
# - Source checkout deploys can set lambda_zips_dir after `pnpm build:lambdas`.
|
|
@@ -101,7 +112,6 @@ db_password = "CHANGE_ME_strong_password_here"
|
|
|
101
112
|
# --name /thinkwork/<stage>/google-places/api-key --value <KEY>
|
|
102
113
|
# (terraform's lifecycle.ignore_changes on the value keeps your manual
|
|
103
114
|
# value from being overwritten on future applies.)
|
|
104
|
-
# google_places_api_key = ""
|
|
105
115
|
|
|
106
116
|
# Public website (apps/www) custom domain.
|
|
107
117
|
# Leave www_domain empty to skip the custom domain and serve on the raw
|
|
@@ -123,3 +133,11 @@ db_password = "CHANGE_ME_strong_password_here"
|
|
|
123
133
|
# ses_inbound_domain = "agents.thinkwork.ai"
|
|
124
134
|
# ses_parent_domain = "thinkwork.ai"
|
|
125
135
|
# tenant_slugs = ["dev"]
|
|
136
|
+
|
|
137
|
+
# Company Brain platform-agent machine lane (optional, THINK-628/THINK-710).
|
|
138
|
+
# Secrets Manager ARN of etl-platform/brain-mcp/m2m/platform-agent in this
|
|
139
|
+
# account. When set, the shared API Lambda role gets read on it so MCP config
|
|
140
|
+
# build can mint short-lived Cognito bearers for the Brain connector instead
|
|
141
|
+
# of using a stored tkt_ key. Leave empty until the lane's manifest entry is
|
|
142
|
+
# published (see the Brain repo's brain-mcp-m2m-migration runbook).
|
|
143
|
+
# brain_m2m_platform_agent_secret_arn = "arn:aws:secretsmanager:us-east-1:<account-id>:secret:etl-platform/brain-mcp/m2m/platform-agent-XXXXXX"
|
|
@@ -100,6 +100,28 @@ variable "graphql_db_secret_arn" {
|
|
|
100
100
|
type = string
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
+
# ---- VPC placement (THINK-1082) ------------------------------------------------
|
|
104
|
+
# The handler opens DATABASE_URL against Aurora's public endpoint today. When
|
|
105
|
+
# in_vpc is on it attaches to the private subnets behind the api-lambda
|
|
106
|
+
# security group (which the database SG admits) so the public rule can close.
|
|
107
|
+
variable "in_vpc" {
|
|
108
|
+
description = "Attach the admin Lambda to the VPC (vpc_subnet_ids + vpc_security_group_ids); NAT-routed subnets required. Default off = no change."
|
|
109
|
+
type = bool
|
|
110
|
+
default = false
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
variable "vpc_subnet_ids" {
|
|
114
|
+
description = "Private (NAT-routed) subnet IDs for the admin Lambda when in_vpc is true."
|
|
115
|
+
type = list(string)
|
|
116
|
+
default = []
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
variable "vpc_security_group_ids" {
|
|
120
|
+
description = "Security groups for the admin Lambda when in_vpc is true."
|
|
121
|
+
type = list(string)
|
|
122
|
+
default = []
|
|
123
|
+
}
|
|
124
|
+
|
|
103
125
|
# ---- Capability-private interpreter VPC placement (THINK-280 U4) ---------------
|
|
104
126
|
# Empty when the capability broker is disabled → handler skips capability-private
|
|
105
127
|
# provisioning. Sourced from the broker outputs via the code-interpreter module.
|
|
@@ -174,6 +196,14 @@ resource "aws_secretsmanager_secret_version" "admin_token" {
|
|
|
174
196
|
# AWS SDK calls (see packages/lambda/agentcore-admin.ts).
|
|
175
197
|
################################################################################
|
|
176
198
|
|
|
199
|
+
# THINK-1082: ENI grant for the in_vpc lane; never created when off.
|
|
200
|
+
resource "aws_iam_role_policy_attachment" "admin_vpc_access" {
|
|
201
|
+
count = local.deploy && var.in_vpc ? 1 : 0
|
|
202
|
+
|
|
203
|
+
role = aws_iam_role.admin[0].name
|
|
204
|
+
policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole"
|
|
205
|
+
}
|
|
206
|
+
|
|
177
207
|
resource "aws_iam_role" "admin" {
|
|
178
208
|
count = local.deploy ? 1 : 0
|
|
179
209
|
name = "thinkwork-${var.stage}-agentcore-admin"
|
|
@@ -333,6 +363,23 @@ resource "aws_lambda_function" "admin" {
|
|
|
333
363
|
}
|
|
334
364
|
}
|
|
335
365
|
|
|
366
|
+
# THINK-1082: network-only VPC attachment; absent when in_vpc is off.
|
|
367
|
+
dynamic "vpc_config" {
|
|
368
|
+
for_each = var.in_vpc ? [1] : []
|
|
369
|
+
|
|
370
|
+
content {
|
|
371
|
+
subnet_ids = var.vpc_subnet_ids
|
|
372
|
+
security_group_ids = var.vpc_security_group_ids
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
lifecycle {
|
|
377
|
+
precondition {
|
|
378
|
+
condition = !var.in_vpc || (length(var.vpc_subnet_ids) > 0 && length(var.vpc_security_group_ids) > 0)
|
|
379
|
+
error_message = "in_vpc requires non-empty vpc_subnet_ids and vpc_security_group_ids."
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
|
|
336
383
|
tags = {
|
|
337
384
|
Name = local.function_name
|
|
338
385
|
Stage = var.stage
|
|
@@ -1,53 +1,45 @@
|
|
|
1
|
-
# `agentcore-code-interpreter` — stage-level
|
|
1
|
+
# `agentcore-code-interpreter` — stage-level sandbox substrate
|
|
2
2
|
|
|
3
|
-
Stage-scoped
|
|
3
|
+
Stage-scoped substrate for the AgentCore Code Interpreter sandbox. **Per-tenant
|
|
4
4
|
Code Interpreter instances are created at runtime** by the `agentcore-admin`
|
|
5
5
|
Lambda (see `docs/adrs/per-tenant-aws-resource-fanout.md`) — this module
|
|
6
|
-
stops at the
|
|
7
|
-
|
|
8
|
-
## What it
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
- `
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
6
|
+
stops at the stage-level pieces everything else depends on.
|
|
7
|
+
|
|
8
|
+
## What it provides
|
|
9
|
+
|
|
10
|
+
The module creates no AWS resources today; it is a typed catalog + policy-template
|
|
11
|
+
surface consumed by the provisioning Lambda and by downstream modules:
|
|
12
|
+
|
|
13
|
+
- `environment_ids` + `environments` — the environment catalog (`default-public`,
|
|
14
|
+
`internal-only`, `capability-private`) with network modes.
|
|
15
|
+
- `tenant_role_trust_policy_template` / `tenant_role_inline_policy_template` —
|
|
16
|
+
JSON templates the provisioning Lambda substitutes `{tenant_id}` into at
|
|
17
|
+
`CreateRole` time (plan Unit 5).
|
|
18
|
+
- `capability_private_role_inline_policy_template` — logs-only policy for the
|
|
19
|
+
THINK-280 U4 capability-private interpreter role.
|
|
20
|
+
- `capability_private_subnet_ids` / `capability_private_security_group_ids` —
|
|
21
|
+
pass-through of the broker's no-NAT VPC placement (empty when the broker is
|
|
22
|
+
disabled); wired into the `agentcore-admin` module.
|
|
23
|
+
|
|
24
|
+
## No custom sandbox image (THINK-617)
|
|
25
|
+
|
|
26
|
+
This module used to own an ECR repo (`thinkwork-{stage}-sandbox-base`), a
|
|
27
|
+
`Dockerfile.sandbox-base` (Python 3.12 + pinned libs + a `sitecustomize.py`
|
|
28
|
+
stdio scrubber) and a CI build script. **AgentCore Code Interpreter cannot use
|
|
29
|
+
a custom image** — `CreateCodeInterpreterRequest` has no image/container
|
|
30
|
+
parameter (verified against `@aws-sdk/client-bedrock-agentcore-control`
|
|
31
|
+
3.1103.0), and `agentcore-admin` has only ever created interpreters on the
|
|
32
|
+
AWS-managed image.
|
|
33
|
+
|
|
34
|
+
The practical need (openpyxl et al. in the sandbox) is covered by the runtime's
|
|
35
|
+
on-demand install preamble — `ON_DEMAND_LIBRARIES` in
|
|
36
|
+
`packages/agentcore-pi/agent-container/src/runtime/tools/execute-code.ts`.
|
|
37
|
+
|
|
38
|
+
Consequence for log scrubbing: the value-based in-image redactor never ran in
|
|
39
|
+
production. The `sandbox-log-scrubber` CloudWatch subscription filter
|
|
40
|
+
(pattern-based, known OAuth token shapes) is the only scrubbing layer.
|
|
31
41
|
|
|
32
42
|
## What this module does **not** do
|
|
33
43
|
|
|
34
|
-
- Create per-tenant Code Interpreter instances — that's
|
|
35
|
-
- Build or push
|
|
36
|
-
- Grant the provisioning Lambda IAM permissions on the new resources — that's added in Unit 5 when the Lambda resource lands.
|
|
37
|
-
|
|
38
|
-
## Bumping the image
|
|
39
|
-
|
|
40
|
-
1. Edit `Dockerfile.sandbox-base` (pin a new pandas / add a lib / etc.).
|
|
41
|
-
2. Edit `terraform/modules/app/agentcore-code-interpreter/sandbox/sitecustomize.py` if the R13 invariant or its coverage gaps shift.
|
|
42
|
-
3. PR. CI runs `pytest` on the scrubber plus a build-then-startup-assertion smoke test.
|
|
43
|
-
4. After merge, `build_and_push_sandbox_base.sh` tags with the merge-commit SHA.
|
|
44
|
-
|
|
45
|
-
## Named residual
|
|
46
|
-
|
|
47
|
-
The R13 invariant this module's scrubber enforces is **honestly scoped** to
|
|
48
|
-
Python-stdio-mediated writes + known-shape CloudWatch patterns. See the
|
|
49
|
-
brainstorm and the `sitecustomize.py` module docstring for the full list of
|
|
50
|
-
stdio-bypass classes (os.write, subprocess env dumps, C-extension direct
|
|
51
|
-
writes, multiprocessing workers, adversarial split-writes) that the Unit 12
|
|
52
|
-
pattern backstop catches partially and the v2 in-process credential proxy
|
|
53
|
-
addresses structurally.
|
|
44
|
+
- Create per-tenant Code Interpreter instances — that's the `agentcore-admin` Lambda.
|
|
45
|
+
- Build or push any container image.
|
|
@@ -1,23 +1,25 @@
|
|
|
1
1
|
################################################################################
|
|
2
2
|
# AgentCore Code Interpreter — App Module (stage-level)
|
|
3
3
|
#
|
|
4
|
-
# Stage-scoped
|
|
5
|
-
# *
|
|
6
|
-
#
|
|
7
|
-
#
|
|
8
|
-
#
|
|
9
|
-
# CreateCodeInterpreter for each tenant on demand.
|
|
4
|
+
# Stage-scoped substrate for the AgentCore Code Interpreter sandbox:
|
|
5
|
+
# * The environment catalog (network modes) the runtime selects from.
|
|
6
|
+
# * IAM policy templates + capability-private VPC placement the per-tenant
|
|
7
|
+
# provisioning Lambda (Unit 5) consumes to CreateCodeInterpreter for each
|
|
8
|
+
# tenant on demand.
|
|
10
9
|
#
|
|
11
10
|
# **Per-tenant resources live elsewhere.** AgentCore Code Interpreter
|
|
12
11
|
# instances are created per-tenant by the ``agentcore-admin`` Lambda at
|
|
13
12
|
# tenant-create time — see docs/adrs/per-tenant-aws-resource-fanout.md.
|
|
14
13
|
# This module stops at the stage-level substrate.
|
|
15
14
|
#
|
|
16
|
-
# **
|
|
17
|
-
#
|
|
18
|
-
#
|
|
19
|
-
#
|
|
20
|
-
#
|
|
15
|
+
# **No custom image (THINK-617).** This module used to own an ECR repo for a
|
|
16
|
+
# "blessed" sandbox base image (Python 3.12 + pinned libs + a sitecustomize.py
|
|
17
|
+
# stdio scrubber). AgentCore Code Interpreter has no way to attach one:
|
|
18
|
+
# CreateCodeInterpreterRequest carries no image/container parameter. Sandboxes
|
|
19
|
+
# always run the AWS-managed image; libraries that image may lack are installed
|
|
20
|
+
# on demand by the runtime's execute_code preamble (ON_DEMAND_LIBRARIES in
|
|
21
|
+
# packages/agentcore-pi/.../tools/execute-code.ts). The image substrate was
|
|
22
|
+
# retired — git history and THINK-617 preserve it.
|
|
21
23
|
################################################################################
|
|
22
24
|
|
|
23
25
|
terraform {
|
|
@@ -44,12 +46,6 @@ variable "account_id" {
|
|
|
44
46
|
type = string
|
|
45
47
|
}
|
|
46
48
|
|
|
47
|
-
variable "image_retention_count" {
|
|
48
|
-
description = "Keep the last N image tags in ECR; older ones are lifecycle-expired."
|
|
49
|
-
type = number
|
|
50
|
-
default = 10
|
|
51
|
-
}
|
|
52
|
-
|
|
53
49
|
# THINK-280 U4 — VPC placement for the capability-private interpreter. Sourced
|
|
54
50
|
# (when the capability broker is enabled) from the broker module's no-NAT
|
|
55
51
|
# interpreter subnets + dedicated egress-only SG. Empty by default: the
|
|
@@ -91,45 +87,6 @@ locals {
|
|
|
91
87
|
}
|
|
92
88
|
}
|
|
93
89
|
|
|
94
|
-
################################################################################
|
|
95
|
-
# ECR repository — stage-level base image
|
|
96
|
-
################################################################################
|
|
97
|
-
|
|
98
|
-
resource "aws_ecr_repository" "sandbox_base" {
|
|
99
|
-
name = "thinkwork-${var.stage}-sandbox-base"
|
|
100
|
-
image_tag_mutability = "IMMUTABLE"
|
|
101
|
-
force_delete = true
|
|
102
|
-
|
|
103
|
-
image_scanning_configuration {
|
|
104
|
-
scan_on_push = true
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
tags = {
|
|
108
|
-
Name = "thinkwork-${var.stage}-sandbox-base"
|
|
109
|
-
Stage = var.stage
|
|
110
|
-
Purpose = "agentcore-code-interpreter-base-image"
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
resource "aws_ecr_lifecycle_policy" "sandbox_base" {
|
|
115
|
-
repository = aws_ecr_repository.sandbox_base.name
|
|
116
|
-
|
|
117
|
-
policy = jsonencode({
|
|
118
|
-
rules = [{
|
|
119
|
-
rulePriority = 1
|
|
120
|
-
description = "Keep last ${var.image_retention_count} images"
|
|
121
|
-
selection = {
|
|
122
|
-
tagStatus = "any"
|
|
123
|
-
countType = "imageCountMoreThan"
|
|
124
|
-
countNumber = var.image_retention_count
|
|
125
|
-
}
|
|
126
|
-
action = {
|
|
127
|
-
type = "expire"
|
|
128
|
-
}
|
|
129
|
-
}]
|
|
130
|
-
})
|
|
131
|
-
}
|
|
132
|
-
|
|
133
90
|
################################################################################
|
|
134
91
|
# IAM policy document — per-tenant trust template
|
|
135
92
|
#
|
|
@@ -207,16 +164,6 @@ locals {
|
|
|
207
164
|
# Outputs
|
|
208
165
|
################################################################################
|
|
209
166
|
|
|
210
|
-
output "ecr_repository_name" {
|
|
211
|
-
description = "Name of the sandbox base image ECR repo."
|
|
212
|
-
value = aws_ecr_repository.sandbox_base.name
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
output "ecr_repository_url" {
|
|
216
|
-
description = "Full URL of the sandbox base image ECR repo."
|
|
217
|
-
value = aws_ecr_repository.sandbox_base.repository_url
|
|
218
|
-
}
|
|
219
|
-
|
|
220
167
|
output "environment_ids" {
|
|
221
168
|
description = "Enum of valid sandbox environment identifiers."
|
|
222
169
|
value = keys(local.environments)
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
################################################################################
|
|
2
|
+
|
|
3
|
+
terraform {
|
|
4
|
+
required_providers {
|
|
5
|
+
aws = {
|
|
6
|
+
source = "hashicorp/aws"
|
|
7
|
+
version = ">= 5.0"
|
|
8
|
+
}
|
|
9
|
+
external = {
|
|
10
|
+
source = "hashicorp/external"
|
|
11
|
+
version = ">= 2.3.0"
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
# THINK-316 U1 — AgentCore Identity proof substrate
|
|
16
|
+
#
|
|
17
|
+
# The AWS provider does not yet model Workload Identity or OAuth2 credential
|
|
18
|
+
# providers. A terraform_data lifecycle wrapper reconciles them with the
|
|
19
|
+
# current AWS CLI and owns destroy cleanup. The client secret is passed only in
|
|
20
|
+
# the local-exec environment and never printed by the scripts.
|
|
21
|
+
################################################################################
|
|
22
|
+
|
|
23
|
+
locals {
|
|
24
|
+
# THINK-324: the workload identity is SHARED — live Twenty 3LO
|
|
25
|
+
# (lib/harness/agentcore-user-oauth.ts via AGENTCORE_IDENTITY_WORKLOAD_NAME)
|
|
26
|
+
# rides the same workload identity the proof plane created. It must exist
|
|
27
|
+
# whenever either half is enabled, and its deletion is owned by the Twenty
|
|
28
|
+
# cleanup owner (not the proof lifecycle) so retiring the proof plane never
|
|
29
|
+
# invalidates per-user Twenty grants.
|
|
30
|
+
identity_enabled = var.enabled || var.twenty_enabled
|
|
31
|
+
workload_identity_name = "thinkwork-${var.stage}-multiplayer-proof"
|
|
32
|
+
credential_provider_name = "thinkwork-${var.stage}-proof-oauth"
|
|
33
|
+
twenty_credential_provider_name = "thinkwork-${var.stage}-twenty-crm"
|
|
34
|
+
oauth_issuer = trimsuffix(var.oauth_issuer, "/")
|
|
35
|
+
# THINK-324: with the proof plane retired the issuer is empty; a bare
|
|
36
|
+
# "/complete" fails UpdateWorkloadIdentity's URL-pattern validation, so the
|
|
37
|
+
# proof return URL only joins the allowlist when an issuer is configured.
|
|
38
|
+
oauth_return_url = local.oauth_issuer != "" ? "${local.oauth_issuer}/complete" : ""
|
|
39
|
+
allowed_oauth_return_urls = distinct(concat(compact([local.oauth_return_url]), var.user_federation_return_urls))
|
|
40
|
+
configuration_hash = nonsensitive(sha256(jsonencode({
|
|
41
|
+
issuer = local.oauth_issuer
|
|
42
|
+
client_id = var.oauth_client_id
|
|
43
|
+
secret_digest = sha256(var.oauth_client_secret)
|
|
44
|
+
return_url = local.oauth_return_url
|
|
45
|
+
})))
|
|
46
|
+
twenty_configuration_hash = nonsensitive(sha256(jsonencode({
|
|
47
|
+
allowed_oauth_return_urls = local.allowed_oauth_return_urls
|
|
48
|
+
twenty_credential_provider_name = local.twenty_credential_provider_name
|
|
49
|
+
twenty_oauth_issuer = var.twenty_oauth_issuer
|
|
50
|
+
twenty_oauth_resource = var.twenty_oauth_resource
|
|
51
|
+
twenty_client_secret_arn = try(aws_secretsmanager_secret.twenty_oauth_client[0].arn, "")
|
|
52
|
+
bootstrap_script_sha256 = filesha256("${path.module}/scripts/bootstrap_twenty_oauth_client.sh")
|
|
53
|
+
provider_reconciler_sha256 = filesha256("${path.module}/scripts/reconcile_twenty_provider.mjs")
|
|
54
|
+
identity_reconciler_sha256 = filesha256("${path.module}/scripts/reconcile_twenty_identity.sh")
|
|
55
|
+
})))
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
# The DCR client secret is written by the reconciler, not Terraform, so its
|
|
59
|
+
# value never enters Terraform state. AgentCore Identity reads the JSON key
|
|
60
|
+
# directly and remains the sole custodian of each user's downstream grant.
|
|
61
|
+
resource "aws_secretsmanager_secret" "twenty_oauth_client" {
|
|
62
|
+
count = var.twenty_enabled ? 1 : 0
|
|
63
|
+
|
|
64
|
+
name = "thinkwork/${var.stage}/agentcore-identity/twenty-crm-oauth-client"
|
|
65
|
+
description = "Confidential Twenty OAuth client used only by AgentCore Identity Token Vault"
|
|
66
|
+
recovery_window_in_days = 7
|
|
67
|
+
|
|
68
|
+
tags = {
|
|
69
|
+
"managed-by" = "terraform"
|
|
70
|
+
"thinkwork:stage" = var.stage
|
|
71
|
+
"thinkwork:purpose" = "agentcore-identity-user-federation"
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
resource "aws_secretsmanager_secret_policy" "twenty_oauth_client" {
|
|
76
|
+
count = var.twenty_enabled ? 1 : 0
|
|
77
|
+
secret_arn = aws_secretsmanager_secret.twenty_oauth_client[0].arn
|
|
78
|
+
policy = jsonencode({
|
|
79
|
+
Version = "2012-10-17"
|
|
80
|
+
Statement = [{
|
|
81
|
+
Sid = "AgentCoreIdentityRead"
|
|
82
|
+
Effect = "Allow"
|
|
83
|
+
Principal = { Service = "bedrock-agentcore.amazonaws.com" }
|
|
84
|
+
Action = "secretsmanager:GetSecretValue"
|
|
85
|
+
Resource = aws_secretsmanager_secret.twenty_oauth_client[0].arn
|
|
86
|
+
Condition = {
|
|
87
|
+
StringEquals = { "aws:SourceAccount" = var.account_id }
|
|
88
|
+
}
|
|
89
|
+
}]
|
|
90
|
+
})
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
resource "terraform_data" "identity_lifecycle" {
|
|
94
|
+
count = var.enabled ? 1 : 0
|
|
95
|
+
|
|
96
|
+
input = {
|
|
97
|
+
region = var.region
|
|
98
|
+
workload_identity_name = local.workload_identity_name
|
|
99
|
+
credential_provider_name = local.credential_provider_name
|
|
100
|
+
}
|
|
101
|
+
triggers_replace = [local.configuration_hash]
|
|
102
|
+
|
|
103
|
+
provisioner "local-exec" {
|
|
104
|
+
command = "bash ${path.module}/scripts/reconcile_identity.sh"
|
|
105
|
+
environment = {
|
|
106
|
+
AWS_REGION = var.region
|
|
107
|
+
WORKLOAD_IDENTITY_NAME = local.workload_identity_name
|
|
108
|
+
CREDENTIAL_PROVIDER_NAME = local.credential_provider_name
|
|
109
|
+
OAUTH_ISSUER = local.oauth_issuer
|
|
110
|
+
OAUTH_CLIENT_ID = var.oauth_client_id
|
|
111
|
+
OAUTH_CLIENT_SECRET = var.oauth_client_secret
|
|
112
|
+
OAUTH_RETURN_URL = local.oauth_return_url
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
provisioner "local-exec" {
|
|
117
|
+
when = destroy
|
|
118
|
+
command = "bash ${path.module}/scripts/delete_identity.sh"
|
|
119
|
+
environment = {
|
|
120
|
+
AWS_REGION = self.input.region
|
|
121
|
+
WORKLOAD_IDENTITY_NAME = self.input.workload_identity_name
|
|
122
|
+
CREDENTIAL_PROVIDER_NAME = self.input.credential_provider_name
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
# THINK-324 — Twenty-side workload-identity guarantee. When the proof plane
|
|
128
|
+
# is retired (enabled = false) the identity_lifecycle resource above no longer
|
|
129
|
+
# runs, but live Twenty 3LO still needs the shared workload identity. This
|
|
130
|
+
# ensure step is create-if-missing only (it never rewrites the return-url
|
|
131
|
+
# allowlist — twenty_identity_reconciliation owns that) and has NO destroy
|
|
132
|
+
# action; deletion is owned by workload_identity_cleanup_owner below.
|
|
133
|
+
resource "terraform_data" "workload_identity_ensure" {
|
|
134
|
+
count = var.twenty_enabled ? 1 : 0
|
|
135
|
+
|
|
136
|
+
input = {
|
|
137
|
+
region = var.region
|
|
138
|
+
workload_identity_name = local.workload_identity_name
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
provisioner "local-exec" {
|
|
142
|
+
command = "bash ${path.module}/scripts/ensure_workload_identity.sh"
|
|
143
|
+
environment = {
|
|
144
|
+
AWS_REGION = var.region
|
|
145
|
+
WORKLOAD_IDENTITY_NAME = local.workload_identity_name
|
|
146
|
+
OAUTH_RETURN_URLS_JSON = jsonencode(local.allowed_oauth_return_urls)
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
# THINK-324 — the shared workload identity's deletion moved here from the
|
|
152
|
+
# proof lifecycle (delete_identity.sh no longer touches it): it is deleted
|
|
153
|
+
# only when the Twenty identity half itself is removed, never when the proof
|
|
154
|
+
# plane is retired. Note: on a hypothetical proof-only stage (enabled = true,
|
|
155
|
+
# twenty_enabled = false) the workload identity is leaked on teardown rather
|
|
156
|
+
# than risking a destructive replace of identity_lifecycle here; no such
|
|
157
|
+
# stage exists (dev, the only proof stage, runs Twenty).
|
|
158
|
+
resource "terraform_data" "workload_identity_cleanup_owner" {
|
|
159
|
+
count = var.twenty_enabled ? 1 : 0
|
|
160
|
+
|
|
161
|
+
input = {
|
|
162
|
+
region = var.region
|
|
163
|
+
workload_identity_name = local.workload_identity_name
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
provisioner "local-exec" {
|
|
167
|
+
when = destroy
|
|
168
|
+
command = "bash ${path.module}/scripts/delete_workload_identity.sh"
|
|
169
|
+
environment = {
|
|
170
|
+
AWS_REGION = self.input.region
|
|
171
|
+
WORKLOAD_IDENTITY_NAME = self.input.workload_identity_name
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
# Stable cleanup ownership is deliberately separate from reconciliation.
|
|
177
|
+
# Script-only changes must never replace a resource whose destroy provisioner
|
|
178
|
+
# deletes the external provider and invalidates its service-issued callback.
|
|
179
|
+
resource "terraform_data" "twenty_identity_cleanup_owner" {
|
|
180
|
+
count = var.twenty_enabled ? 1 : 0
|
|
181
|
+
|
|
182
|
+
input = {
|
|
183
|
+
region = var.region
|
|
184
|
+
twenty_credential_provider_name = local.twenty_credential_provider_name
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
provisioner "local-exec" {
|
|
188
|
+
when = destroy
|
|
189
|
+
command = "bash ${path.module}/scripts/delete_twenty_identity.sh"
|
|
190
|
+
environment = {
|
|
191
|
+
AWS_REGION = self.input.region
|
|
192
|
+
TWENTY_CREDENTIAL_PROVIDER_NAME = self.input.twenty_credential_provider_name
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
# Additive user-federation reconciliation. Code/configuration revisions replace
|
|
198
|
+
# only this terraform_data record; it has no destroy action and always updates
|
|
199
|
+
# the provider in place. The stable owner above deletes only when the module is
|
|
200
|
+
# truly disabled or removed.
|
|
201
|
+
resource "terraform_data" "twenty_identity_reconciliation" {
|
|
202
|
+
count = var.twenty_enabled ? 1 : 0
|
|
203
|
+
|
|
204
|
+
input = {
|
|
205
|
+
region = var.region
|
|
206
|
+
workload_identity_name = local.workload_identity_name
|
|
207
|
+
twenty_credential_provider_name = local.twenty_credential_provider_name
|
|
208
|
+
}
|
|
209
|
+
triggers_replace = [local.twenty_configuration_hash]
|
|
210
|
+
|
|
211
|
+
provisioner "local-exec" {
|
|
212
|
+
command = "bash ${path.module}/scripts/reconcile_twenty_identity.sh"
|
|
213
|
+
environment = {
|
|
214
|
+
AWS_REGION = var.region
|
|
215
|
+
WORKLOAD_IDENTITY_NAME = local.workload_identity_name
|
|
216
|
+
OAUTH_RETURN_URLS_JSON = jsonencode(local.allowed_oauth_return_urls)
|
|
217
|
+
TWENTY_CREDENTIAL_PROVIDER_NAME = local.twenty_credential_provider_name
|
|
218
|
+
TWENTY_CLIENT_SECRET_ARN = aws_secretsmanager_secret.twenty_oauth_client[0].arn
|
|
219
|
+
TWENTY_OAUTH_ISSUER = trimsuffix(var.twenty_oauth_issuer, "/")
|
|
220
|
+
TWENTY_OAUTH_RESOURCE = var.twenty_oauth_resource
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
depends_on = [
|
|
225
|
+
terraform_data.identity_lifecycle,
|
|
226
|
+
terraform_data.workload_identity_ensure,
|
|
227
|
+
terraform_data.twenty_identity_cleanup_owner,
|
|
228
|
+
aws_secretsmanager_secret_policy.twenty_oauth_client,
|
|
229
|
+
]
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
# Read back the service-generated ARNs only after apply-time reconciliation.
|
|
233
|
+
# Gateway IAM can therefore scope vault and secret access exactly rather than
|
|
234
|
+
# granting a token-vault or Secrets Manager wildcard.
|
|
235
|
+
data "external" "identity_state" {
|
|
236
|
+
count = local.identity_enabled ? 1 : 0
|
|
237
|
+
depends_on = [
|
|
238
|
+
terraform_data.identity_lifecycle,
|
|
239
|
+
terraform_data.workload_identity_ensure,
|
|
240
|
+
terraform_data.twenty_identity_reconciliation,
|
|
241
|
+
]
|
|
242
|
+
program = ["bash", "${path.module}/scripts/read_identity.sh"]
|
|
243
|
+
|
|
244
|
+
query = {
|
|
245
|
+
region = var.region
|
|
246
|
+
workload_identity_name = local.workload_identity_name
|
|
247
|
+
# Empty names tell the reader to skip that half (THINK-324: the proof
|
|
248
|
+
# provider is absent once the proof plane is retired; the Twenty provider
|
|
249
|
+
# is absent on proof-only stages).
|
|
250
|
+
credential_provider_name = var.enabled ? local.credential_provider_name : ""
|
|
251
|
+
twenty_credential_provider_name = var.twenty_enabled ? local.twenty_credential_provider_name : ""
|
|
252
|
+
}
|
|
253
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
output "workload_identity_name" {
|
|
2
|
+
description = "Name used for GetWorkloadAccessTokenForJWT. Empty when disabled."
|
|
3
|
+
value = local.identity_enabled ? local.workload_identity_name : ""
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
output "credential_provider_name" {
|
|
7
|
+
description = "AgentCore Identity OAuth2 credential-provider name. Empty when disabled."
|
|
8
|
+
value = var.enabled ? local.credential_provider_name : ""
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
output "oauth_return_url" {
|
|
12
|
+
description = "Allowed user-federation return URL. Empty when disabled."
|
|
13
|
+
value = var.enabled ? local.oauth_return_url : ""
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
output "twenty_credential_provider_name" {
|
|
17
|
+
description = "AgentCore Identity provider name for per-user Twenty grants."
|
|
18
|
+
value = var.twenty_enabled ? local.twenty_credential_provider_name : ""
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
output "twenty_credential_provider_arn" {
|
|
22
|
+
description = "AgentCore Identity provider ARN for per-user Twenty grants."
|
|
23
|
+
value = var.twenty_enabled ? data.external.identity_state[0].result.twenty_credential_provider_arn : ""
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
output "twenty_oauth_callback_url" {
|
|
27
|
+
description = "Service-generated callback URL registered with Twenty OAuth."
|
|
28
|
+
value = var.twenty_enabled ? data.external.identity_state[0].result.twenty_oauth_callback_url : ""
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
output "twenty_client_secret_arn" {
|
|
32
|
+
description = "External Secrets Manager client record consumed by AgentCore Identity."
|
|
33
|
+
value = var.twenty_enabled ? aws_secretsmanager_secret.twenty_oauth_client[0].arn : ""
|
|
34
|
+
sensitive = true
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
output "workload_identity_arn" {
|
|
38
|
+
description = "Service-generated workload identity ARN. Empty when disabled."
|
|
39
|
+
value = local.identity_enabled ? data.external.identity_state[0].result.workload_identity_arn : ""
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
output "credential_provider_arn" {
|
|
43
|
+
description = "Service-generated OAuth2 credential-provider ARN. Empty when disabled."
|
|
44
|
+
value = var.enabled ? data.external.identity_state[0].result.credential_provider_arn : ""
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
output "credential_secret_arn" {
|
|
48
|
+
description = "AgentCore-managed Secrets Manager ARN backing the provider. Empty when disabled."
|
|
49
|
+
value = var.enabled ? data.external.identity_state[0].result.credential_secret_arn : ""
|
|
50
|
+
sensitive = true
|
|
51
|
+
}
|