thinkwork-cli 0.13.0 → 0.13.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{api-client-JUBCQQDF.js → api-client-JYZXYQJR.js} +3 -1
- package/dist/bowser-6Z6JFAIR.js +2822 -0
- package/dist/chunk-DV3MRBR5.js +43 -0
- package/dist/chunk-DVPBI5HM.js +1728 -0
- package/dist/chunk-EI5ZX7CN.js +522 -0
- package/dist/chunk-EUJ7X6YD.js +126 -0
- package/dist/chunk-GG5WKBOX.js +436 -0
- package/dist/chunk-I64EZSU5.js +358 -0
- package/dist/chunk-ILZKG5WV.js +6151 -0
- package/dist/chunk-KMIJ5KGT.js +128 -0
- package/dist/chunk-OCPHU34C.js +996 -0
- package/dist/chunk-QOERT44A.js +3286 -0
- package/dist/chunk-XYM7PE2A.js +2264 -0
- package/dist/{chunk-STY44FQO.js → chunk-Z2F6RJFR.js} +12 -18
- package/dist/cli.js +72564 -18884
- package/dist/dist-es-CRV46D5B.js +315 -0
- package/dist/dist-es-DCY4IC3Y.js +2000 -0
- package/dist/dist-es-ENBUC3JP.js +14726 -0
- package/dist/dist-es-G54LBMRN.js +48 -0
- package/dist/dist-es-G7PTG75M.js +176 -0
- package/dist/dist-es-GKDBE7E6.js +88 -0
- package/dist/dist-es-HY3535OI.js +70 -0
- package/dist/dist-es-KL7Y5NB2.js +377 -0
- package/dist/dist-es-LDE437AM.js +170 -0
- package/dist/dist-es-P26FWFLT.js +485 -0
- package/dist/dist-es-Q57SZXZ7.js +70 -0
- package/dist/dist-es-R7FGL2IB.js +88 -0
- package/dist/dist-es-USORBXZ5.js +318 -0
- package/dist/dist-es-ZKC2QKD2.js +377 -0
- package/dist/drizzle/0076_scheduled_jobs_marco_backfill.sql +2 -1
- package/dist/drizzle/0079_seed_tenant_customize_catalog.sql +1 -0
- package/dist/drizzle/0090_brain_schema_extraction.sql +10 -0
- package/dist/drizzle/0132_drop_computer_tables.sql +3 -0
- package/dist/drizzle/0160_compliance_event_types_plugins.sql +2 -0
- package/dist/drizzle/0214_think137_drop_judge_evidence_roi.sql +1 -0
- package/dist/drizzle/0216_drop_agent_loop_versions_goal_worker_policy.sql +1 -0
- package/dist/drizzle/0227_analyst_reader_role.sql +106 -38
- package/dist/drizzle/0230_analyst_rls.sql +192 -66
- package/dist/drizzle/0232_memory_source_thin_ledger.sql +176 -0
- package/dist/drizzle/0232_message_source_event_id.sql +9 -0
- package/dist/drizzle/0233_msteams_install_and_links.sql +151 -0
- package/dist/drizzle/0233_workflow_memory_stage_tokens.sql +20 -0
- package/dist/drizzle/0234_memory_claim_lifecycle.sql +160 -0
- package/dist/drizzle/0235_workflow_token_execution_claim.sql +34 -0
- package/dist/drizzle/0236_memory_retraction_fencing.sql +50 -0
- package/dist/drizzle/0237_memory_claims_active_value_uidx.sql +172 -0
- package/dist/drizzle/0238_memory_erase_generation_fence.sql +97 -0
- package/dist/drizzle/0239_canonical_entity_identity.sql +257 -0
- package/dist/drizzle/0240_memory_personal_scope.sql +45 -0
- package/dist/drizzle/0241_knowledge_base_document_manifest.sql +67 -0
- package/dist/drizzle/0242_search_queries.sql +28 -0
- package/dist/drizzle/0243_section_sources_thread_refs.sql +12 -0
- package/dist/drizzle/0244_system_automations_and_memory_stage_overrides.sql +45 -0
- package/dist/drizzle/0245_wiki_page_render.sql +21 -0
- package/dist/drizzle/0246_automation_workflow_ownership.sql +30 -0
- package/dist/drizzle/0247_capability_runtime.sql +402 -0
- package/dist/drizzle/0248_capability_private_interpreter.sql +13 -0
- package/dist/drizzle/0249_capability_headless_execution_evidence.sql +40 -0
- package/dist/drizzle/0250_kg_schema_extraction.sql +576 -0
- package/dist/drizzle/0251_agents_json_render_ui.sql +25 -0
- package/dist/drizzle/0251_brain_stragglers.sql +263 -0
- package/dist/drizzle/0252_drop_kg_and_straggler_compat_views.sql +100 -0
- package/dist/drizzle/0253_drop_brain_substrate.sql +93 -0
- package/dist/drizzle/0254_capability_autonomous_admission.sql +29 -0
- package/dist/drizzle/0255_capability_autonomous_approval_mode.sql +16 -0
- package/dist/drizzle/0256_agent_profile_manifest_authority.sql +18 -0
- package/dist/drizzle/0257_agents_runtime_allow_harness.sql +24 -0
- package/dist/drizzle/0257_capability_approvals.sql +53 -0
- package/dist/drizzle/0258_pending_tool_approvals.sql +84 -0
- package/dist/drizzle/0259_tenant_capability_registry_trust.sql +19 -0
- package/dist/drizzle/0260_scheduled_jobs_run_as_user.sql +20 -0
- package/dist/drizzle/0261_managed_harness_multiplayer.sql +313 -0
- package/dist/drizzle/0261_native_auth_control_plane.sql +328 -0
- package/dist/drizzle/0262_auth_subscription_tickets.sql +59 -0
- package/dist/drizzle/0262_parallel_harness_threads.sql +9 -0
- package/dist/drizzle/0263_agentcore_runtime_identifier.sql +69 -0
- package/dist/drizzle/0263_drop_workos_auth_runtime.sql +236 -0
- package/dist/drizzle/0264_auth_enrollment_attempt_limits.sql +15 -0
- package/dist/drizzle/0264_harness_tool_execution_ledger.sql +113 -0
- package/dist/drizzle/0265_eval_runs_requester_identity.sql +28 -0
- package/dist/drizzle/0265_require_fully_valid_auth_publication.sql +27 -0
- package/dist/drizzle/0266_auth_identity_recovery_grants.sql +9 -0
- package/dist/drizzle/0266_eval_profiles_runtime_type.sql +12 -0
- package/dist/drizzle/0267_ontology_candidate_rejections.sql +53 -0
- package/dist/drizzle/0268_identity_crosswalk_routing.sql +182 -0
- package/dist/drizzle/0269_ontology_system_map.sql +31 -0
- package/dist/event-streams-7JNLJEEL.js +894 -0
- package/dist/event-streams-KDF5RWR6.js +1515 -0
- package/dist/loadSso-DJVB7BXE.js +576 -0
- package/dist/loadSso-JAMNA3WY.js +583 -0
- package/dist/plugins/catalog/package.json +1 -2
- package/dist/plugins/catalog/src/__tests__/build-catalog.test.ts +0 -1
- package/dist/plugins/catalog/src/__tests__/contracts.test.ts +0 -69
- package/dist/plugins/catalog/src/__tests__/plugin-package.test.ts +0 -2
- package/dist/plugins/catalog/src/__tests__/plugin-registry.test.ts +0 -5
- package/dist/plugins/catalog/src/contracts.ts +2 -179
- package/dist/plugins/catalog/src/registry/generated-first-party.ts +0 -6
- package/dist/signin-UGDWTGS4.js +821 -0
- package/dist/sso-oidc-Q4VXANXY.js +837 -0
- package/dist/sts-CWLSE3GH.js +1241 -0
- package/dist/sts-DNZLNVOV.js +1245 -0
- package/dist/terraform/examples/greenfield/main.tf +247 -50
- package/dist/terraform/examples/greenfield/terraform.tfvars.example +15 -1
- package/dist/terraform/modules/app/agentcore-admin/main.tf +341 -0
- package/dist/terraform/modules/app/agentcore-admin/outputs.tf +20 -0
- package/dist/terraform/modules/app/agentcore-code-interpreter/main.tf +61 -0
- package/dist/terraform/modules/app/agentcore-gateway/main.tf +305 -0
- package/dist/terraform/modules/app/agentcore-gateway/outputs.tf +44 -0
- package/dist/terraform/modules/app/agentcore-gateway/scripts/delete_gateway.sh +93 -0
- package/dist/terraform/modules/app/agentcore-gateway/scripts/read_gateway.sh +33 -0
- package/dist/terraform/modules/app/agentcore-gateway/scripts/reconcile_gateway.sh +543 -0
- package/dist/terraform/modules/app/agentcore-gateway/variables.tf +70 -0
- package/dist/terraform/modules/app/agentcore-harness/main.tf +330 -0
- package/dist/terraform/modules/app/agentcore-harness/outputs.tf +72 -0
- package/dist/terraform/modules/app/agentcore-harness/scripts/delete_harness.sh +5 -0
- package/dist/terraform/modules/app/agentcore-harness/scripts/harness-lifecycle.mjs +430 -0
- package/dist/terraform/modules/app/agentcore-harness/scripts/harness-readback.mjs +180 -0
- package/dist/terraform/modules/app/agentcore-harness/scripts/harness-tool-contract.mjs +193 -0
- package/dist/terraform/modules/app/agentcore-harness/scripts/prune_harness.sh +5 -0
- package/dist/terraform/modules/app/agentcore-harness/scripts/read_harness.sh +5 -0
- package/dist/terraform/modules/app/agentcore-harness/scripts/reconcile_harness.sh +5 -0
- package/dist/terraform/modules/app/agentcore-harness/variables.tf +96 -0
- package/dist/terraform/modules/app/agentcore-identity/main.tf +173 -0
- package/dist/terraform/modules/app/agentcore-identity/outputs.tf +51 -0
- package/dist/terraform/modules/app/agentcore-identity/scripts/bootstrap_twenty_oauth_client.sh +122 -0
- package/dist/terraform/modules/app/agentcore-identity/scripts/delete_identity.sh +25 -0
- package/dist/terraform/modules/app/agentcore-identity/scripts/delete_twenty_identity.sh +16 -0
- package/dist/terraform/modules/app/agentcore-identity/scripts/read_identity.sh +40 -0
- package/dist/terraform/modules/app/agentcore-identity/scripts/reconcile_identity.sh +73 -0
- package/dist/terraform/modules/app/agentcore-identity/scripts/reconcile_twenty_identity.sh +74 -0
- package/dist/terraform/modules/app/agentcore-identity/scripts/reconcile_twenty_provider.mjs +61 -0
- package/dist/terraform/modules/app/agentcore-identity/variables.tf +54 -0
- package/dist/terraform/modules/app/agentcore-pi/main.tf +7 -0
- package/dist/terraform/modules/app/appsync-subscriptions/main.tf +127 -21
- package/dist/terraform/modules/app/appsync-subscriptions/outputs.tf +0 -6
- package/dist/terraform/modules/app/appsync-subscriptions/variables.tf +5 -0
- package/dist/terraform/modules/app/capability-broker/main.tf +393 -0
- package/dist/terraform/modules/app/capability-broker/outputs.tf +54 -0
- package/dist/terraform/modules/app/capability-broker/variables.tf +98 -0
- package/dist/terraform/modules/app/deployment-control-plane/runner.py +1011 -31
- package/dist/terraform/modules/app/deployment-control-plane/test_runner_bundle.py +655 -2
- package/dist/terraform/modules/app/lambda-api/agentcore-harness-alarms.tf +88 -0
- package/dist/terraform/modules/app/lambda-api/agentcore-identity-alarms.tf +91 -0
- package/dist/terraform/modules/app/lambda-api/capability-search-alarms.tf +60 -0
- package/dist/terraform/modules/app/lambda-api/handlers.tf +606 -37
- package/dist/terraform/modules/app/lambda-api/iam-grouped.tf +192 -21
- package/dist/terraform/modules/app/lambda-api/main.tf +35 -0
- package/dist/terraform/modules/app/lambda-api/mcp-oauth.tf +181 -4
- package/dist/terraform/modules/app/lambda-api/memory-alarms.tf +92 -0
- package/dist/terraform/modules/app/lambda-api/msteams-app-secrets.tf +46 -0
- package/dist/terraform/modules/app/lambda-api/outputs.tf +35 -0
- package/dist/terraform/modules/app/lambda-api/runtime-config.tf +3 -21
- package/dist/terraform/modules/app/lambda-api/variables.tf +188 -3
- package/dist/terraform/modules/app/workflow-interpreter-stepfunctions/alarms.tf +47 -0
- package/dist/terraform/modules/app/workflow-interpreter-stepfunctions/main.tf +43 -2
- package/dist/terraform/modules/foundation/cognito/main.tf +319 -73
- package/dist/terraform/modules/foundation/cognito/outputs.tf +42 -0
- package/dist/terraform/modules/foundation/cognito/variables.tf +124 -2
- package/dist/terraform/modules/foundation/vpc/outputs.tf +5 -0
- package/dist/terraform/modules/thinkwork/main.tf +396 -26
- package/dist/terraform/modules/thinkwork/outputs.tf +188 -5
- package/dist/terraform/modules/thinkwork/variables.tf +154 -5
- package/dist/terraform/schema.graphql +69 -36
- package/dist/workspace-defaults/files/TOOLS.md +39 -0
- package/dist/workspace-defaults/files/USER.md +1 -0
- package/dist/workspace-defaults/files/agents/analyst/INSTRUCTIONS.md +18 -0
- package/dist/workspace-defaults/files/agents/coding/INSTRUCTIONS.md +11 -0
- package/dist/workspace-defaults/files/agents/research/INSTRUCTIONS.md +12 -0
- package/dist/workspace-defaults/files/agents/reviewer/INSTRUCTIONS.md +15 -0
- package/dist/workspace-defaults/files/skills/document-composer/SKILL.md +6 -2
- package/package.json +6 -3
- package/dist/plugins/workos-auth/package.json +0 -22
- package/dist/plugins/workos-auth/src/index.ts +0 -30
- package/dist/plugins/workos-auth/src/manifest.ts +0 -40
- package/dist/plugins/workos-auth/src/provider-contract.ts +0 -39
- package/dist/plugins/workos-auth/test/manifest.test.ts +0 -94
- package/dist/plugins/workos-auth/tsconfig.json +0 -8
- /package/dist/workspace-defaults/files/{AGENTS.md → INSTRUCTIONS.md} +0 -0
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
# Capability Broker (THINK-280 U3) — action-time policy, replay-safe PoP
|
|
2
|
+
# sessions, and evidence for the governed capability runtime.
|
|
3
|
+
#
|
|
4
|
+
# SHIP-INERT: gated by var.enabled (default false). Nothing here is created
|
|
5
|
+
# until U4 flips it on after the live negative-egress proof. The Lambda code
|
|
6
|
+
# itself also fails closed — its default authorization loader denies every
|
|
7
|
+
# call — so even an accidental enable dispatches no provider operation.
|
|
8
|
+
#
|
|
9
|
+
# THINK-144: this module owns a DEDICATED execute-api interface VPC endpoint
|
|
10
|
+
# with private DNS DISABLED. It is never added to the app VPC's shared
|
|
11
|
+
# okf_wiki_interface_endpoint_services list — that list's private DNS would
|
|
12
|
+
# capture every *.execute-api call in the VPC and 403 the stack's public HTTP
|
|
13
|
+
# APIs. The session bootstrap targets this endpoint's own DNS name instead.
|
|
14
|
+
|
|
15
|
+
locals {
|
|
16
|
+
enabled = var.enabled
|
|
17
|
+
count_enabled = var.enabled ? 1 : 0
|
|
18
|
+
|
|
19
|
+
name_prefix = "thinkwork-${var.stage}-capability-broker"
|
|
20
|
+
session_table_name = "thinkwork-${var.stage}-capability-broker-sessions"
|
|
21
|
+
broker_audience = "thinkwork-${var.stage}-capability-broker"
|
|
22
|
+
use_local_zips = var.lambda_zips_dir != ""
|
|
23
|
+
use_remote_artifacts = trimspace(var.lambda_artifact_bucket) != ""
|
|
24
|
+
broker_zip_local = "${var.lambda_zips_dir}/capability-broker.zip"
|
|
25
|
+
broker_artifact_s3key = "${var.lambda_artifact_prefix}/capability-broker.zip"
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
# --- Replay-safe session state (DynamoDB, conditional writes + TTL) ----------
|
|
29
|
+
|
|
30
|
+
resource "aws_dynamodb_table" "sessions" {
|
|
31
|
+
count = local.count_enabled
|
|
32
|
+
|
|
33
|
+
name = local.session_table_name
|
|
34
|
+
billing_mode = "PAY_PER_REQUEST"
|
|
35
|
+
hash_key = "pk"
|
|
36
|
+
range_key = "sk"
|
|
37
|
+
|
|
38
|
+
attribute {
|
|
39
|
+
name = "pk"
|
|
40
|
+
type = "S"
|
|
41
|
+
}
|
|
42
|
+
attribute {
|
|
43
|
+
name = "sk"
|
|
44
|
+
type = "S"
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
# Session + nonce records self-expire at session TTL (≤15 min). Epoch seconds.
|
|
48
|
+
ttl {
|
|
49
|
+
attribute_name = "ttl"
|
|
50
|
+
enabled = true
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
point_in_time_recovery {
|
|
54
|
+
enabled = true
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
tags = {
|
|
58
|
+
Name = local.session_table_name
|
|
59
|
+
Purpose = "capability-broker-sessions"
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
# --- Broker Lambda execution role -------------------------------------------
|
|
64
|
+
|
|
65
|
+
data "aws_iam_policy_document" "broker_assume" {
|
|
66
|
+
statement {
|
|
67
|
+
actions = ["sts:AssumeRole"]
|
|
68
|
+
principals {
|
|
69
|
+
type = "Service"
|
|
70
|
+
identifiers = ["lambda.amazonaws.com"]
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
resource "aws_iam_role" "broker" {
|
|
76
|
+
count = local.count_enabled
|
|
77
|
+
name = "${local.name_prefix}-role"
|
|
78
|
+
assume_role_policy = data.aws_iam_policy_document.broker_assume.json
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
data "aws_iam_policy_document" "broker_policy" {
|
|
82
|
+
count = local.count_enabled
|
|
83
|
+
|
|
84
|
+
# Session state: conditional reads/writes only, scoped to the one table.
|
|
85
|
+
statement {
|
|
86
|
+
sid = "SessionState"
|
|
87
|
+
actions = [
|
|
88
|
+
"dynamodb:GetItem",
|
|
89
|
+
"dynamodb:PutItem",
|
|
90
|
+
"dynamodb:UpdateItem",
|
|
91
|
+
"dynamodb:DeleteItem",
|
|
92
|
+
"dynamodb:Query",
|
|
93
|
+
]
|
|
94
|
+
resources = [aws_dynamodb_table.sessions[0].arn]
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
# Evidence: append capability_broker_calls rows via the RDS Data API on the
|
|
98
|
+
# existing Aurora cluster (same credential-rotation surface as graphql-http).
|
|
99
|
+
dynamic "statement" {
|
|
100
|
+
for_each = var.db_cluster_arn != "" ? [1] : []
|
|
101
|
+
content {
|
|
102
|
+
sid = "EvidenceDataApi"
|
|
103
|
+
actions = ["rds-data:ExecuteStatement", "rds-data:BatchExecuteStatement"]
|
|
104
|
+
resources = [var.db_cluster_arn]
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
dynamic "statement" {
|
|
109
|
+
for_each = var.db_secret_arn != "" ? [1] : []
|
|
110
|
+
content {
|
|
111
|
+
sid = "EvidenceDbSecret"
|
|
112
|
+
actions = ["secretsmanager:GetSecretValue"]
|
|
113
|
+
resources = [var.db_secret_arn]
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
# VPC ENI management for the in-VPC Lambda.
|
|
118
|
+
statement {
|
|
119
|
+
sid = "VpcEni"
|
|
120
|
+
actions = [
|
|
121
|
+
"ec2:CreateNetworkInterface",
|
|
122
|
+
"ec2:DescribeNetworkInterfaces",
|
|
123
|
+
"ec2:DeleteNetworkInterface",
|
|
124
|
+
"ec2:AssignPrivateIpAddresses",
|
|
125
|
+
"ec2:UnassignPrivateIpAddresses",
|
|
126
|
+
]
|
|
127
|
+
resources = ["*"]
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
statement {
|
|
131
|
+
sid = "Logs"
|
|
132
|
+
actions = ["logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents"]
|
|
133
|
+
resources = ["arn:aws:logs:${var.region}:${var.account_id}:log-group:/aws/lambda/${local.name_prefix}*"]
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
statement {
|
|
137
|
+
sid = "Xray"
|
|
138
|
+
actions = ["xray:PutTraceSegments", "xray:PutTelemetryRecords"]
|
|
139
|
+
resources = ["*"]
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
resource "aws_iam_role_policy" "broker" {
|
|
144
|
+
count = local.count_enabled
|
|
145
|
+
name = "${local.name_prefix}-policy"
|
|
146
|
+
role = aws_iam_role.broker[0].id
|
|
147
|
+
policy = data.aws_iam_policy_document.broker_policy[0].json
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
# --- Broker Lambda security group (egress only) ------------------------------
|
|
151
|
+
|
|
152
|
+
resource "aws_security_group" "broker_lambda" {
|
|
153
|
+
count = local.count_enabled
|
|
154
|
+
name = "${local.name_prefix}-lambda"
|
|
155
|
+
description = "Capability broker Lambda egress"
|
|
156
|
+
vpc_id = var.vpc_id
|
|
157
|
+
|
|
158
|
+
egress {
|
|
159
|
+
from_port = 0
|
|
160
|
+
to_port = 0
|
|
161
|
+
protocol = "-1"
|
|
162
|
+
cidr_blocks = ["0.0.0.0/0"]
|
|
163
|
+
description = "Egress to Aurora Data API, DynamoDB, Secrets Manager, provider endpoints"
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
tags = { Name = "${local.name_prefix}-lambda" }
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
resource "aws_cloudwatch_log_group" "broker" {
|
|
170
|
+
count = local.count_enabled
|
|
171
|
+
name = "/aws/lambda/${local.name_prefix}"
|
|
172
|
+
retention_in_days = var.log_retention_days
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
resource "aws_lambda_function" "broker" {
|
|
176
|
+
count = local.count_enabled
|
|
177
|
+
function_name = local.name_prefix
|
|
178
|
+
role = aws_iam_role.broker[0].arn
|
|
179
|
+
runtime = var.lambda_runtime
|
|
180
|
+
handler = "index.handler"
|
|
181
|
+
timeout = 30
|
|
182
|
+
memory_size = 512
|
|
183
|
+
|
|
184
|
+
filename = local.use_local_zips ? local.broker_zip_local : null
|
|
185
|
+
source_code_hash = local.use_local_zips ? filebase64sha256(local.broker_zip_local) : null
|
|
186
|
+
s3_bucket = local.use_remote_artifacts ? var.lambda_artifact_bucket : null
|
|
187
|
+
s3_key = local.use_remote_artifacts ? local.broker_artifact_s3key : null
|
|
188
|
+
|
|
189
|
+
vpc_config {
|
|
190
|
+
subnet_ids = var.subnet_ids
|
|
191
|
+
security_group_ids = [aws_security_group.broker_lambda[0].id]
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
environment {
|
|
195
|
+
variables = {
|
|
196
|
+
CAPABILITY_BROKER_SESSION_TABLE = aws_dynamodb_table.sessions[0].name
|
|
197
|
+
CAPABILITY_BROKER_AUDIENCE = local.broker_audience
|
|
198
|
+
# getDb() (@thinkwork/database-pg) MUST get DATABASE_URL, not just
|
|
199
|
+
# DATABASE_SECRET_ARN: the secret-only path returns an async Proxy whose
|
|
200
|
+
# `db.select()` resolves to a Promise, which breaks Drizzle's fluent
|
|
201
|
+
# `.select().from().where()` chaining (`.from is not a function`) — the
|
|
202
|
+
# cause of the loader's `authorization reload failed`. DATABASE_URL takes
|
|
203
|
+
# the synchronous pool path, matching every api handler's common_env.
|
|
204
|
+
DATABASE_URL = "postgresql://${var.db_username}:${urlencode(var.db_password)}@${var.db_cluster_endpoint}:5432/${var.database_name}?sslmode=no-verify"
|
|
205
|
+
DATABASE_SECRET_ARN = var.db_secret_arn
|
|
206
|
+
DATABASE_HOST = var.db_cluster_endpoint
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
tracing_config {
|
|
211
|
+
mode = "Active"
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
depends_on = [aws_cloudwatch_log_group.broker]
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
# --- Private REST API Gateway fronting the broker ----------------------------
|
|
218
|
+
#
|
|
219
|
+
# PRIVATE endpoint: reachable ONLY through the dedicated execute-api VPCE below.
|
|
220
|
+
# The resource policy denies anything not arriving via that endpoint.
|
|
221
|
+
|
|
222
|
+
resource "aws_api_gateway_rest_api" "broker" {
|
|
223
|
+
count = local.count_enabled
|
|
224
|
+
name = local.name_prefix
|
|
225
|
+
|
|
226
|
+
endpoint_configuration {
|
|
227
|
+
types = ["PRIVATE"]
|
|
228
|
+
vpc_endpoint_ids = [aws_vpc_endpoint.broker_execute_api[0].id]
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
# Only traffic arriving through our own VPCE is allowed; everything else 403s.
|
|
232
|
+
policy = jsonencode({
|
|
233
|
+
Version = "2012-10-17"
|
|
234
|
+
Statement = [
|
|
235
|
+
{
|
|
236
|
+
Effect = "Deny"
|
|
237
|
+
Principal = "*"
|
|
238
|
+
Action = "execute-api:Invoke"
|
|
239
|
+
Resource = "arn:aws:execute-api:${var.region}:${var.account_id}:*/*/*/*"
|
|
240
|
+
Condition = {
|
|
241
|
+
StringNotEquals = { "aws:SourceVpce" = aws_vpc_endpoint.broker_execute_api[0].id }
|
|
242
|
+
}
|
|
243
|
+
},
|
|
244
|
+
{
|
|
245
|
+
Effect = "Allow"
|
|
246
|
+
Principal = "*"
|
|
247
|
+
Action = "execute-api:Invoke"
|
|
248
|
+
Resource = "arn:aws:execute-api:${var.region}:${var.account_id}:*/*/*/*"
|
|
249
|
+
},
|
|
250
|
+
]
|
|
251
|
+
})
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
resource "aws_api_gateway_resource" "broker_proxy" {
|
|
255
|
+
count = local.count_enabled
|
|
256
|
+
rest_api_id = aws_api_gateway_rest_api.broker[0].id
|
|
257
|
+
parent_id = aws_api_gateway_rest_api.broker[0].root_resource_id
|
|
258
|
+
path_part = "{proxy+}"
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
resource "aws_api_gateway_method" "broker_any" {
|
|
262
|
+
count = local.count_enabled
|
|
263
|
+
rest_api_id = aws_api_gateway_rest_api.broker[0].id
|
|
264
|
+
resource_id = aws_api_gateway_resource.broker_proxy[0].id
|
|
265
|
+
http_method = "ANY"
|
|
266
|
+
authorization = "NONE"
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
resource "aws_api_gateway_integration" "broker" {
|
|
270
|
+
count = local.count_enabled
|
|
271
|
+
rest_api_id = aws_api_gateway_rest_api.broker[0].id
|
|
272
|
+
resource_id = aws_api_gateway_resource.broker_proxy[0].id
|
|
273
|
+
http_method = aws_api_gateway_method.broker_any[0].http_method
|
|
274
|
+
integration_http_method = "POST"
|
|
275
|
+
type = "AWS_PROXY"
|
|
276
|
+
uri = aws_lambda_function.broker[0].invoke_arn
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
resource "aws_lambda_permission" "broker_apigw" {
|
|
280
|
+
count = local.count_enabled
|
|
281
|
+
statement_id = "AllowBrokerPrivateApiInvoke"
|
|
282
|
+
action = "lambda:InvokeFunction"
|
|
283
|
+
function_name = aws_lambda_function.broker[0].function_name
|
|
284
|
+
principal = "apigateway.amazonaws.com"
|
|
285
|
+
source_arn = "${aws_api_gateway_rest_api.broker[0].execution_arn}/*/*/*"
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
resource "aws_api_gateway_deployment" "broker" {
|
|
289
|
+
count = local.count_enabled
|
|
290
|
+
rest_api_id = aws_api_gateway_rest_api.broker[0].id
|
|
291
|
+
|
|
292
|
+
triggers = {
|
|
293
|
+
redeploy = sha1(jsonencode([
|
|
294
|
+
aws_api_gateway_resource.broker_proxy[0].id,
|
|
295
|
+
aws_api_gateway_method.broker_any[0].id,
|
|
296
|
+
aws_api_gateway_integration.broker[0].id,
|
|
297
|
+
aws_api_gateway_rest_api.broker[0].policy,
|
|
298
|
+
]))
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
lifecycle {
|
|
302
|
+
create_before_destroy = true
|
|
303
|
+
}
|
|
304
|
+
depends_on = [aws_api_gateway_integration.broker]
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
resource "aws_api_gateway_stage" "broker" {
|
|
308
|
+
count = local.count_enabled
|
|
309
|
+
rest_api_id = aws_api_gateway_rest_api.broker[0].id
|
|
310
|
+
deployment_id = aws_api_gateway_deployment.broker[0].id
|
|
311
|
+
stage_name = var.stage
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
# --- Dedicated execute-api VPC endpoint (PRIVATE DNS DISABLED — THINK-144) ----
|
|
315
|
+
|
|
316
|
+
resource "aws_security_group" "broker_vpce" {
|
|
317
|
+
count = local.count_enabled
|
|
318
|
+
name = "${local.name_prefix}-vpce"
|
|
319
|
+
description = "Capability broker execute-api VPCE (broker Lambda + capability-private interpreter subnet only)"
|
|
320
|
+
vpc_id = var.vpc_id
|
|
321
|
+
|
|
322
|
+
ingress {
|
|
323
|
+
from_port = 443
|
|
324
|
+
to_port = 443
|
|
325
|
+
protocol = "tcp"
|
|
326
|
+
cidr_blocks = [var.vpc_cidr_block]
|
|
327
|
+
description = "HTTPS from in-VPC PoP callers (broker Lambda self-calls + U4 capability-private interpreter)"
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
tags = { Name = "${local.name_prefix}-vpce" }
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
resource "aws_vpc_endpoint" "broker_execute_api" {
|
|
334
|
+
count = local.count_enabled
|
|
335
|
+
|
|
336
|
+
vpc_id = var.vpc_id
|
|
337
|
+
service_name = "com.amazonaws.${var.region}.execute-api"
|
|
338
|
+
vpc_endpoint_type = "Interface"
|
|
339
|
+
subnet_ids = var.subnet_ids
|
|
340
|
+
security_group_ids = [aws_security_group.broker_vpce[0].id]
|
|
341
|
+
|
|
342
|
+
# CRITICAL (THINK-144): private DNS OFF. Callers target the endpoint-specific
|
|
343
|
+
# DNS name (surfaced as an output), never the regional execute-api domain, so
|
|
344
|
+
# this endpoint cannot capture the stack's public HTTP API traffic.
|
|
345
|
+
private_dns_enabled = false
|
|
346
|
+
|
|
347
|
+
tags = {
|
|
348
|
+
Name = "${local.name_prefix}-execute-api-vpce"
|
|
349
|
+
Purpose = "capability-broker-private-ingress"
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
# --- Capability-private interpreter SG (no NAT; broker VPCE only) — U4 --------
|
|
354
|
+
#
|
|
355
|
+
# The U4 capability-private VPC-mode Code Interpreter attaches to var.subnet_ids
|
|
356
|
+
# (the no-NAT private egress subnets) under THIS security group. Its ONLY egress
|
|
357
|
+
# is 443 to the broker execute-api VPCE SG plus DNS to the VPC resolver — there
|
|
358
|
+
# is no NAT and no 0.0.0.0/0 route, so direct GitHub / Secrets Manager / internet
|
|
359
|
+
# access does not exist (AE5 negative-egress boundary). The broker_vpce ingress
|
|
360
|
+
# above already admits 443 from the VPC CIDR, which covers these subnets.
|
|
361
|
+
resource "aws_security_group" "capability_private_interpreter" {
|
|
362
|
+
count = local.count_enabled
|
|
363
|
+
name = "${local.name_prefix}-cappriv-interpreter"
|
|
364
|
+
description = "Capability-private Code Interpreter egress: broker execute-api VPCE + DNS only"
|
|
365
|
+
vpc_id = var.vpc_id
|
|
366
|
+
|
|
367
|
+
# execute-api VPCE only (reach the private broker API).
|
|
368
|
+
egress {
|
|
369
|
+
from_port = 443
|
|
370
|
+
to_port = 443
|
|
371
|
+
protocol = "tcp"
|
|
372
|
+
security_groups = [aws_security_group.broker_vpce[0].id]
|
|
373
|
+
description = "HTTPS to the broker execute-api VPCE"
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
# DNS to the in-VPC resolver so the endpoint-specific VPCE hostname resolves.
|
|
377
|
+
egress {
|
|
378
|
+
from_port = 53
|
|
379
|
+
to_port = 53
|
|
380
|
+
protocol = "udp"
|
|
381
|
+
cidr_blocks = [var.vpc_cidr_block]
|
|
382
|
+
description = "DNS (UDP) to the VPC resolver"
|
|
383
|
+
}
|
|
384
|
+
egress {
|
|
385
|
+
from_port = 53
|
|
386
|
+
to_port = 53
|
|
387
|
+
protocol = "tcp"
|
|
388
|
+
cidr_blocks = [var.vpc_cidr_block]
|
|
389
|
+
description = "DNS (TCP) to the VPC resolver"
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
tags = { Name = "${local.name_prefix}-cappriv-interpreter" }
|
|
393
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Consumed by the API-side broker-session opener to build the sandbox
|
|
2
|
+
# SessionBootstrap. All null when the module is disabled (ship-inert).
|
|
3
|
+
|
|
4
|
+
output "enabled" {
|
|
5
|
+
value = local.enabled
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
output "session_table_name" {
|
|
9
|
+
description = "DynamoDB session table (CAPABILITY_BROKER_SESSION_TABLE)."
|
|
10
|
+
value = local.enabled ? aws_dynamodb_table.sessions[0].name : ""
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
output "session_table_arn" {
|
|
14
|
+
description = "ARN of the broker session table — granted to the lambda-api role so routine-exec-git can mint/advance PoP sessions. Empty when disabled."
|
|
15
|
+
value = local.enabled ? aws_dynamodb_table.sessions[0].arn : ""
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
output "broker_audience" {
|
|
19
|
+
description = "Audience the PoP session signatures are bound to (CAPABILITY_BROKER_AUDIENCE)."
|
|
20
|
+
value = local.enabled ? local.broker_audience : ""
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
output "private_api_id" {
|
|
24
|
+
description = "Private REST API id the sandbox targets through the VPCE (CAPABILITY_BROKER_API_ID)."
|
|
25
|
+
value = local.enabled ? aws_api_gateway_rest_api.broker[0].id : ""
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
output "execute_api_vpce_id" {
|
|
29
|
+
value = local.enabled ? aws_vpc_endpoint.broker_execute_api[0].id : ""
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
output "execute_api_vpce_dns_name" {
|
|
33
|
+
description = "Endpoint-specific execute-api DNS name (private DNS is OFF). The session bootstrap uses this exact host — CAPABILITY_BROKER_VPCE_DNS."
|
|
34
|
+
value = local.enabled ? tolist(aws_vpc_endpoint.broker_execute_api[0].dns_entry)[0].dns_name : ""
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
output "broker_function_name" {
|
|
38
|
+
value = local.enabled ? aws_lambda_function.broker[0].function_name : ""
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
# --- U4: capability-private interpreter VPC placement ------------------------
|
|
42
|
+
# Consumed by the agentcore-admin Lambda (CAPABILITY_PRIVATE_SUBNET_IDS /
|
|
43
|
+
# CAPABILITY_PRIVATE_SECURITY_GROUP_IDS). Empty lists when disabled so the
|
|
44
|
+
# Lambda skips capability-private provisioning entirely.
|
|
45
|
+
|
|
46
|
+
output "capability_private_interpreter_subnet_ids" {
|
|
47
|
+
description = "No-NAT subnets the capability-private interpreter attaches to (same egress subnets as the broker)."
|
|
48
|
+
value = local.enabled ? var.subnet_ids : []
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
output "capability_private_interpreter_security_group_id" {
|
|
52
|
+
description = "Egress-only SG (broker execute-api VPCE + DNS only) for the capability-private interpreter. Empty when disabled."
|
|
53
|
+
value = local.enabled ? aws_security_group.capability_private_interpreter[0].id : ""
|
|
54
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
variable "enabled" {
|
|
2
|
+
description = "Master switch. When false the module creates nothing (ship-inert: U3 lands the broker code + this module gated off; U4 flips it on after the negative-egress proof)."
|
|
3
|
+
type = bool
|
|
4
|
+
default = false
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
variable "stage" {
|
|
8
|
+
type = string
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
variable "account_id" {
|
|
12
|
+
type = string
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
variable "region" {
|
|
16
|
+
type = string
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
# --- VPC placement (broker Lambda egress subnets + the dedicated VPCE) -------
|
|
20
|
+
|
|
21
|
+
variable "vpc_id" {
|
|
22
|
+
type = string
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
variable "vpc_cidr_block" {
|
|
26
|
+
type = string
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
variable "subnet_ids" {
|
|
30
|
+
description = "Private egress subnets the broker Lambda and its dedicated execute-api VPC endpoint attach to."
|
|
31
|
+
type = list(string)
|
|
32
|
+
default = []
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
# --- Evidence datastore (Aurora, RDS Data API — same cluster as graphql-http)-
|
|
36
|
+
|
|
37
|
+
variable "db_cluster_arn" {
|
|
38
|
+
type = string
|
|
39
|
+
default = ""
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
variable "db_secret_arn" {
|
|
43
|
+
type = string
|
|
44
|
+
default = ""
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
variable "db_cluster_endpoint" {
|
|
48
|
+
description = "Aurora writer endpoint hostname — DATABASE_HOST for getDb() (evidence store + authorization loader)."
|
|
49
|
+
type = string
|
|
50
|
+
default = ""
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
variable "db_username" {
|
|
54
|
+
description = "Aurora master username for the broker's DATABASE_URL."
|
|
55
|
+
type = string
|
|
56
|
+
default = "thinkwork_admin"
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
variable "db_password" {
|
|
60
|
+
description = "Aurora master password for the broker's DATABASE_URL (synchronous getDb() path)."
|
|
61
|
+
type = string
|
|
62
|
+
default = ""
|
|
63
|
+
sensitive = true
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
variable "database_name" {
|
|
67
|
+
description = "Aurora database name for the broker's DATABASE_URL."
|
|
68
|
+
type = string
|
|
69
|
+
default = "thinkwork"
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
# --- Lambda artifact source (mirrors lambda-api's dual local/remote pattern) -
|
|
73
|
+
|
|
74
|
+
variable "lambda_zips_dir" {
|
|
75
|
+
description = "Local path holding dist/lambdas/*.zip for local deploys. Empty when using remote S3 artifacts."
|
|
76
|
+
type = string
|
|
77
|
+
default = ""
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
variable "lambda_artifact_bucket" {
|
|
81
|
+
type = string
|
|
82
|
+
default = ""
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
variable "lambda_artifact_prefix" {
|
|
86
|
+
type = string
|
|
87
|
+
default = ""
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
variable "lambda_runtime" {
|
|
91
|
+
type = string
|
|
92
|
+
default = "nodejs22.x"
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
variable "log_retention_days" {
|
|
96
|
+
type = number
|
|
97
|
+
default = 30
|
|
98
|
+
}
|