thinkwork-cli 0.13.1 → 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-4DZ266J5.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-Y2WHJECR.js → chunk-Z2F6RJFR.js} +1 -39
- package/dist/cli.js +43080 -13150
- 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 +6 -0
- package/dist/drizzle/0230_analyst_rls.sql +9 -0
- 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_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 +223 -66
- package/dist/terraform/examples/greenfield/terraform.tfvars.example +15 -1
- 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 +237 -8
- package/dist/terraform/modules/app/agentcore-harness/outputs.tf +63 -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 +72 -1
- 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/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/deployment-control-plane/runner.py +966 -27
- package/dist/terraform/modules/app/deployment-control-plane/test_runner_bundle.py +581 -22
- 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/handlers.tf +298 -74
- package/dist/terraform/modules/app/lambda-api/iam-grouped.tf +99 -54
- package/dist/terraform/modules/app/lambda-api/main.tf +24 -0
- package/dist/terraform/modules/app/lambda-api/mcp-oauth.tf +181 -4
- 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 +109 -16
- package/dist/terraform/modules/foundation/cognito/main.tf +294 -72
- package/dist/terraform/modules/foundation/cognito/outputs.tf +42 -0
- package/dist/terraform/modules/foundation/cognito/variables.tf +114 -4
- package/dist/terraform/modules/thinkwork/main.tf +269 -46
- package/dist/terraform/modules/thinkwork/outputs.tf +136 -8
- package/dist/terraform/modules/thinkwork/variables.tf +124 -17
- package/dist/terraform/schema.graphql +69 -36
- package/dist/workspace-defaults/files/USER.md +1 -0
- package/package.json +3 -2
- package/dist/drizzle/0261_thread_turns_origin_turn_index.sql +0 -11
- 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
|
@@ -0,0 +1,543 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
for required in AWS_REGION GATEWAY_NAME GATEWAY_ROLE_ARN GATEWAY_DISCOVERY_URL \
|
|
5
|
+
GATEWAY_AUDIENCE TARGET_NAME TARGET_BASE_URL OAUTH_CREDENTIAL_PROVIDER_ARN \
|
|
6
|
+
OAUTH_RETURN_URL POLICY_ENGINE_NAME POLICY_NAME PROOF_OWNER_ALLOWLIST; do
|
|
7
|
+
[[ -n "${!required:-}" ]] || { printf '%s is required\n' "$required" >&2; exit 1; }
|
|
8
|
+
done
|
|
9
|
+
|
|
10
|
+
tmp_dir="$(mktemp -d)"
|
|
11
|
+
trap 'rm -rf "$tmp_dir"' EXIT
|
|
12
|
+
|
|
13
|
+
# API Gateway routes and Lambdas are reconciled in a sibling Terraform module.
|
|
14
|
+
# The URL string alone does not create an apply-time dependency on those route
|
|
15
|
+
# instances, so wait for the public discovery document before asking AgentCore
|
|
16
|
+
# to validate CUSTOM_JWT. This keeps parallel applies deterministic.
|
|
17
|
+
discovery_ready=false
|
|
18
|
+
for _ in $(seq 1 60); do
|
|
19
|
+
if curl --fail --silent --show-error --max-time 5 \
|
|
20
|
+
"$GATEWAY_DISCOVERY_URL" \
|
|
21
|
+
| jq -e --arg issuer "${GATEWAY_DISCOVERY_URL%/.well-known/openid-configuration}" \
|
|
22
|
+
'.issuer == $issuer and (.jwks_uri | type == "string")' >/dev/null; then
|
|
23
|
+
discovery_ready=true
|
|
24
|
+
break
|
|
25
|
+
fi
|
|
26
|
+
sleep 5
|
|
27
|
+
done
|
|
28
|
+
[[ "$discovery_ready" == "true" ]] || {
|
|
29
|
+
printf 'Gateway discovery document did not become ready within five minutes\n' >&2
|
|
30
|
+
exit 1
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
list_id_by_name() {
|
|
34
|
+
local command="$1" collection="$2" id_key="$3" name="$4"
|
|
35
|
+
aws bedrock-agentcore-control "$command" --region "$AWS_REGION" --output json \
|
|
36
|
+
| jq -r --arg collection "$collection" --arg id_key "$id_key" --arg name "$name" \
|
|
37
|
+
'(.[$collection] // .items // [])[] | select(.name == $name) | .[$id_key]' \
|
|
38
|
+
| head -n 1
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
wait_status() {
|
|
42
|
+
local command="$1" id_flag="$2" id="$3" success="$4"
|
|
43
|
+
local status="" attempts=0
|
|
44
|
+
while (( attempts < 90 )); do
|
|
45
|
+
status="$(aws bedrock-agentcore-control "$command" --region "$AWS_REGION" \
|
|
46
|
+
"$id_flag" "$id" --query status --output text 2>/dev/null || true)"
|
|
47
|
+
[[ "$status" == "$success" ]] && return 0
|
|
48
|
+
case "$status" in
|
|
49
|
+
FAILED|CREATE_FAILED|UPDATE_UNSUCCESSFUL|SYNCHRONIZE_UNSUCCESSFUL)
|
|
50
|
+
printf '%s %s entered terminal status %s\n' "$command" "$id" "$status" >&2
|
|
51
|
+
return 1
|
|
52
|
+
;;
|
|
53
|
+
esac
|
|
54
|
+
sleep 2
|
|
55
|
+
attempts=$((attempts + 1))
|
|
56
|
+
done
|
|
57
|
+
printf '%s %s did not reach %s (last=%s)\n' "$command" "$id" "$success" "$status" >&2
|
|
58
|
+
return 1
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
wait_policy_status() {
|
|
62
|
+
local engine_id="$1" policy_id="$2" status="" attempts=0
|
|
63
|
+
while (( attempts < 90 )); do
|
|
64
|
+
status="$(aws bedrock-agentcore-control get-policy --region "$AWS_REGION" \
|
|
65
|
+
--policy-engine-id "$engine_id" --policy-id "$policy_id" \
|
|
66
|
+
--query status --output text 2>/dev/null || true)"
|
|
67
|
+
[[ "$status" == "ACTIVE" ]] && return 0
|
|
68
|
+
case "$status" in
|
|
69
|
+
CREATE_FAILED|UPDATE_FAILED|FAILED)
|
|
70
|
+
printf 'policy %s entered terminal status %s\n' "$policy_id" "$status" >&2
|
|
71
|
+
return 1
|
|
72
|
+
;;
|
|
73
|
+
esac
|
|
74
|
+
sleep 2
|
|
75
|
+
attempts=$((attempts + 1))
|
|
76
|
+
done
|
|
77
|
+
printf 'policy %s did not reach ACTIVE (last=%s)\n' "$policy_id" "$status" >&2
|
|
78
|
+
return 1
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
policy_engine_id="$(list_id_by_name list-policy-engines policyEngines policyEngineId "$POLICY_ENGINE_NAME")"
|
|
82
|
+
if [[ -z "$policy_engine_id" ]]; then
|
|
83
|
+
policy_engine_id="$(aws bedrock-agentcore-control create-policy-engine \
|
|
84
|
+
--region "$AWS_REGION" \
|
|
85
|
+
--name "$POLICY_ENGINE_NAME" \
|
|
86
|
+
--description "THINK-316 exact-user Gateway proof policy" \
|
|
87
|
+
--tags '{"purpose":"think-316-proof","managed-by":"terraform"}' \
|
|
88
|
+
--query policyEngineId --output text)"
|
|
89
|
+
fi
|
|
90
|
+
wait_status get-policy-engine --policy-engine-id "$policy_engine_id" ACTIVE
|
|
91
|
+
policy_engine_arn="$(aws bedrock-agentcore-control get-policy-engine \
|
|
92
|
+
--region "$AWS_REGION" --policy-engine-id "$policy_engine_id" \
|
|
93
|
+
--query policyEngineArn --output text)"
|
|
94
|
+
|
|
95
|
+
jq -n \
|
|
96
|
+
--arg name "$GATEWAY_NAME" \
|
|
97
|
+
--arg roleArn "$GATEWAY_ROLE_ARN" \
|
|
98
|
+
--arg discoveryUrl "$GATEWAY_DISCOVERY_URL" \
|
|
99
|
+
--arg audience "$GATEWAY_AUDIENCE" \
|
|
100
|
+
--arg policyArn "$policy_engine_arn" \
|
|
101
|
+
'{
|
|
102
|
+
name: $name,
|
|
103
|
+
description: "THINK-316 exact-user multiplayer proof Gateway",
|
|
104
|
+
exceptionLevel: "DEBUG",
|
|
105
|
+
roleArn: $roleArn,
|
|
106
|
+
protocolType: "MCP",
|
|
107
|
+
protocolConfiguration: {mcp: {
|
|
108
|
+
supportedVersions: ["2025-03-26", "2025-11-25"],
|
|
109
|
+
sessionConfiguration: {sessionTimeoutInSeconds: 900},
|
|
110
|
+
streamingConfiguration: {enableResponseStreaming: true}
|
|
111
|
+
}},
|
|
112
|
+
authorizerType: "CUSTOM_JWT",
|
|
113
|
+
authorizerConfiguration: {customJWTAuthorizer: {
|
|
114
|
+
discoveryUrl: $discoveryUrl,
|
|
115
|
+
allowedAudience: [$audience],
|
|
116
|
+
allowedScopes: ["gateway:invoke"]
|
|
117
|
+
}},
|
|
118
|
+
policyEngineConfiguration: {arn: $policyArn, mode: "ENFORCE"}
|
|
119
|
+
}' >"$tmp_dir/gateway.json"
|
|
120
|
+
|
|
121
|
+
gateway_id="$(list_id_by_name list-gateways items gatewayId "$GATEWAY_NAME")"
|
|
122
|
+
if [[ -z "$gateway_id" ]]; then
|
|
123
|
+
gateway_id="$(aws bedrock-agentcore-control create-gateway \
|
|
124
|
+
--region "$AWS_REGION" --cli-input-json "file://$tmp_dir/gateway.json" \
|
|
125
|
+
--query gatewayId --output text)"
|
|
126
|
+
else
|
|
127
|
+
jq --arg id "$gateway_id" '. + {gatewayIdentifier: $id}' \
|
|
128
|
+
"$tmp_dir/gateway.json" >"$tmp_dir/gateway-update.json"
|
|
129
|
+
aws bedrock-agentcore-control update-gateway --region "$AWS_REGION" \
|
|
130
|
+
--cli-input-json "file://$tmp_dir/gateway-update.json" >/dev/null
|
|
131
|
+
fi
|
|
132
|
+
wait_status get-gateway --gateway-identifier "$gateway_id" READY
|
|
133
|
+
gateway_arn="$(aws bedrock-agentcore-control get-gateway --region "$AWS_REGION" \
|
|
134
|
+
--gateway-identifier "$gateway_id" --query gatewayArn --output text)"
|
|
135
|
+
|
|
136
|
+
# Gateway creates a service-managed workload identity named after its concrete
|
|
137
|
+
# gateway id. OAuth 3LO fails internally unless the selected return URL is also
|
|
138
|
+
# allowlisted on that managed identity; target configuration alone is not
|
|
139
|
+
# sufficient.
|
|
140
|
+
aws bedrock-agentcore-control update-workload-identity \
|
|
141
|
+
--region "$AWS_REGION" \
|
|
142
|
+
--name "$gateway_id" \
|
|
143
|
+
--allowed-resource-oauth2-return-urls "$OAUTH_RETURN_URL" >/dev/null
|
|
144
|
+
|
|
145
|
+
openapi_payload="$(jq -nc --arg server "$TARGET_BASE_URL" '{
|
|
146
|
+
openapi: "3.0.3",
|
|
147
|
+
info: {title: "ThinkWork identity boundary proof", version: "1.0.0"},
|
|
148
|
+
servers: [{url: $server}],
|
|
149
|
+
paths: {
|
|
150
|
+
"/agentcore-proof/target/owner": {get: {
|
|
151
|
+
operationId: "owner_probe",
|
|
152
|
+
summary: "Return a structurally sanitized owner fixture",
|
|
153
|
+
parameters: [{
|
|
154
|
+
name: "requested_owner", in: "query", required: true,
|
|
155
|
+
schema: {type: "string"}
|
|
156
|
+
}],
|
|
157
|
+
responses: {"200": {description: "Sanitized owner projection"}}
|
|
158
|
+
}},
|
|
159
|
+
"/agentcore-proof/target/mixed": {get: {
|
|
160
|
+
operationId: "mixed_disclosure",
|
|
161
|
+
summary: "Return an allowlisted task field and a withholding decision",
|
|
162
|
+
parameters: [{
|
|
163
|
+
name: "requested_owner", in: "query", required: true,
|
|
164
|
+
schema: {type: "string"}
|
|
165
|
+
}],
|
|
166
|
+
responses: {"200": {description: "Sanitized mixed-sensitivity projection"}}
|
|
167
|
+
}},
|
|
168
|
+
"/agentcore/capabilities/mcp/tools/list": {post: {
|
|
169
|
+
operationId: "list_connector_tools",
|
|
170
|
+
summary: "List the current participant authorized tools for one ThinkWork connector",
|
|
171
|
+
requestBody: {required: true, content: {"application/json": {schema: {
|
|
172
|
+
type: "object", additionalProperties: false, required: ["connector", "query"],
|
|
173
|
+
properties: {
|
|
174
|
+
connector: {type: "string", description: "Connector name from the trusted turn context"},
|
|
175
|
+
query: {type: "string", description: "The connector task, used to return only relevant direct tools"}
|
|
176
|
+
}
|
|
177
|
+
}}}},
|
|
178
|
+
responses: {"200": {description: "Authorized connector tool definitions"}}
|
|
179
|
+
}},
|
|
180
|
+
"/agentcore/capabilities/mcp/tools/call": {post: {
|
|
181
|
+
operationId: "call_connector_tool",
|
|
182
|
+
summary: "Call one currently authorized ThinkWork connector tool as the exact turn participant",
|
|
183
|
+
requestBody: {required: true, content: {"application/json": {schema: {
|
|
184
|
+
type: "object", additionalProperties: false,
|
|
185
|
+
required: ["connector", "query", "tool", "arguments"],
|
|
186
|
+
properties: {
|
|
187
|
+
connector: {type: "string", description: "Connector name from the trusted turn context"},
|
|
188
|
+
query: {type: "string", description: "The same user task passed to list_connector_tools"},
|
|
189
|
+
tool: {type: "string", description: "Tool name returned by list_connector_tools"},
|
|
190
|
+
arguments: {type: "object", additionalProperties: true}
|
|
191
|
+
}
|
|
192
|
+
}}}},
|
|
193
|
+
responses: {"200": {description: "Connector tool result"}}
|
|
194
|
+
}},
|
|
195
|
+
"/agentcore/capabilities/sandbox/execute": {post: {
|
|
196
|
+
operationId: "execute_code",
|
|
197
|
+
summary: "Execute one bounded Python program in a short-lived internal-only sandbox",
|
|
198
|
+
requestBody: {required: true, content: {"application/json": {schema: {
|
|
199
|
+
type: "object", additionalProperties: false,
|
|
200
|
+
required: ["language", "code"],
|
|
201
|
+
properties: {
|
|
202
|
+
language: {type: "string", enum: ["python"]},
|
|
203
|
+
code: {type: "string", maxLength: 16384},
|
|
204
|
+
output_files: {
|
|
205
|
+
type: "array", maxItems: 5,
|
|
206
|
+
description: "Optional absolute files under /tmp/thinkwork/ to return as text",
|
|
207
|
+
items: {type: "string", pattern: "^/tmp/thinkwork/[A-Za-z0-9][A-Za-z0-9._/-]{0,180}$"}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}}}},
|
|
211
|
+
responses: {"200": {description: "Sanitized code result and declared files"}}
|
|
212
|
+
}},
|
|
213
|
+
"/agentcore/capabilities/web/search": {post: {
|
|
214
|
+
operationId: "web_search",
|
|
215
|
+
summary: "Search the current web through the tenant-configured governed provider",
|
|
216
|
+
requestBody: {required: true, content: {"application/json": {schema: {
|
|
217
|
+
type: "object", additionalProperties: false,
|
|
218
|
+
required: ["query"],
|
|
219
|
+
properties: {
|
|
220
|
+
query: {type: "string", minLength: 1, maxLength: 2000},
|
|
221
|
+
limit: {type: "integer", minimum: 1, maximum: 10, default: 5}
|
|
222
|
+
}
|
|
223
|
+
}}}},
|
|
224
|
+
responses: {"200": {description: "Sanitized current web search results"}}
|
|
225
|
+
}},
|
|
226
|
+
"/agentcore/capabilities/web/extract": {post: {
|
|
227
|
+
operationId: "web_extract",
|
|
228
|
+
summary: "Extract one known HTTPS page through the tenant-configured governed provider",
|
|
229
|
+
requestBody: {required: true, content: {"application/json": {schema: {
|
|
230
|
+
type: "object", additionalProperties: false,
|
|
231
|
+
required: ["url"],
|
|
232
|
+
properties: {
|
|
233
|
+
url: {type: "string", format: "uri", maxLength: 2048, pattern: "^https://"}
|
|
234
|
+
}
|
|
235
|
+
}}}},
|
|
236
|
+
responses: {"200": {description: "Sanitized bounded page content"}}
|
|
237
|
+
}},
|
|
238
|
+
"/agentcore/capabilities/brain/query": {post: {
|
|
239
|
+
operationId: "query_brain",
|
|
240
|
+
summary: "Query permissioned ThinkWork Brain context as the exact turn participant",
|
|
241
|
+
requestBody: {required: true, content: {"application/json": {schema: {
|
|
242
|
+
type: "object", additionalProperties: false,
|
|
243
|
+
required: ["query"],
|
|
244
|
+
properties: {
|
|
245
|
+
query: {type: "string", minLength: 1, maxLength: 2000},
|
|
246
|
+
mode: {type: "string", enum: ["results", "answer"], default: "results"},
|
|
247
|
+
limit: {type: "integer", minimum: 1, maximum: 10, default: 8}
|
|
248
|
+
}
|
|
249
|
+
}}}},
|
|
250
|
+
responses: {"200": {description: "Sanitized permissioned Brain context"}}
|
|
251
|
+
}},
|
|
252
|
+
"/agentcore/capabilities/workspace/skills/list": {post: {
|
|
253
|
+
operationId: "list_workspace_skills",
|
|
254
|
+
summary: "List the exact participant current authorized ThinkWork workspace skills",
|
|
255
|
+
requestBody: {required: true, content: {"application/json": {schema: {
|
|
256
|
+
type: "object", additionalProperties: false,
|
|
257
|
+
properties: {}
|
|
258
|
+
}}}},
|
|
259
|
+
responses: {"200": {description: "Current canonical authorized skill index"}}
|
|
260
|
+
}},
|
|
261
|
+
"/agentcore/capabilities/workspace/skills/load": {post: {
|
|
262
|
+
operationId: "load_workspace_skill",
|
|
263
|
+
summary: "Load one currently authorized ThinkWork SKILL.md as the exact turn participant",
|
|
264
|
+
requestBody: {required: true, content: {"application/json": {schema: {
|
|
265
|
+
type: "object", additionalProperties: false,
|
|
266
|
+
required: ["skill"],
|
|
267
|
+
properties: {
|
|
268
|
+
skill: {type: "string", pattern: "^[a-z0-9](?:[a-z0-9-]{0,62}[a-z0-9])?$"}
|
|
269
|
+
}
|
|
270
|
+
}}}},
|
|
271
|
+
responses: {
|
|
272
|
+
"200": {description: "Bounded authorized skill body"},
|
|
273
|
+
"403": {description: "Skill is not currently authorized"}
|
|
274
|
+
}
|
|
275
|
+
}},
|
|
276
|
+
"/agentcore/capabilities/message/attachments/list": {post: {
|
|
277
|
+
operationId: "list_message_attachments",
|
|
278
|
+
summary: "List files attached to the exact canonical triggering message",
|
|
279
|
+
requestBody: {required: true, content: {"application/json": {schema: {
|
|
280
|
+
type: "object", additionalProperties: false,
|
|
281
|
+
properties: {}
|
|
282
|
+
}}}},
|
|
283
|
+
responses: {"200": {description: "Sanitized canonical attachment metadata"}}
|
|
284
|
+
}},
|
|
285
|
+
"/agentcore/capabilities/message/attachments/read": {post: {
|
|
286
|
+
operationId: "read_message_attachment",
|
|
287
|
+
summary: "Read a bounded text chunk from one file on the exact triggering message",
|
|
288
|
+
requestBody: {required: true, content: {"application/json": {schema: {
|
|
289
|
+
type: "object", additionalProperties: false,
|
|
290
|
+
required: ["attachment_id"],
|
|
291
|
+
properties: {
|
|
292
|
+
attachment_id: {type: "string", format: "uuid"},
|
|
293
|
+
offset: {type: "integer", minimum: 0, default: 0},
|
|
294
|
+
max_chars: {type: "integer", minimum: 1, maximum: 65536, default: 32768}
|
|
295
|
+
}
|
|
296
|
+
}}}},
|
|
297
|
+
responses: {
|
|
298
|
+
"200": {description: "Bounded extracted text and continuation offset"},
|
|
299
|
+
"403": {description: "Attachment is not on the canonical triggering message"},
|
|
300
|
+
"422": {description: "Attachment format has no safe text projection"}
|
|
301
|
+
}
|
|
302
|
+
}},
|
|
303
|
+
"/agentcore/capabilities/user/questions/ask": {post: {
|
|
304
|
+
operationId: "ask_user_question",
|
|
305
|
+
summary: "Pause the exact participant turn for one governed structured question batch",
|
|
306
|
+
requestBody: {required: true, content: {"application/json": {schema: {
|
|
307
|
+
type: "object", additionalProperties: false,
|
|
308
|
+
required: ["questions"],
|
|
309
|
+
properties: {
|
|
310
|
+
questions: {
|
|
311
|
+
type: "array", minItems: 1, maxItems: 4,
|
|
312
|
+
items: {
|
|
313
|
+
type: "object", additionalProperties: false,
|
|
314
|
+
required: ["question", "header", "options"],
|
|
315
|
+
properties: {
|
|
316
|
+
question: {type: "string", minLength: 1, maxLength: 500},
|
|
317
|
+
header: {type: "string", minLength: 1, maxLength: 12},
|
|
318
|
+
options: {
|
|
319
|
+
type: "array", minItems: 2, maxItems: 4,
|
|
320
|
+
items: {
|
|
321
|
+
type: "object", additionalProperties: false,
|
|
322
|
+
required: ["label", "description"],
|
|
323
|
+
properties: {
|
|
324
|
+
label: {type: "string", minLength: 1, maxLength: 60},
|
|
325
|
+
description: {type: "string", minLength: 1, maxLength: 300}
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
},
|
|
329
|
+
multiSelect: {type: "boolean", default: false}
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
},
|
|
333
|
+
delegation_context: {type: "object", additionalProperties: true}
|
|
334
|
+
}
|
|
335
|
+
}}}},
|
|
336
|
+
responses: {
|
|
337
|
+
"200": {description: "Question batch posted or an existing pending batch retained"},
|
|
338
|
+
"403": {description: "Question capability denied for this exact participant"}
|
|
339
|
+
}
|
|
340
|
+
}},
|
|
341
|
+
"/agentcore/capabilities/email/send": {post: {
|
|
342
|
+
operationId: "send_email",
|
|
343
|
+
summary: "Send or request approval for one idempotent policy-governed email",
|
|
344
|
+
requestBody: {required: true, content: {"application/json": {schema: {
|
|
345
|
+
type: "object", additionalProperties: false,
|
|
346
|
+
required: ["to", "subject", "content"],
|
|
347
|
+
properties: {
|
|
348
|
+
to: {type: "array", minItems: 1, maxItems: 5, items: {type: "string", format: "email", maxLength: 320}},
|
|
349
|
+
subject: {type: "string", minLength: 1, maxLength: 500},
|
|
350
|
+
content: {type: "string", minLength: 1, maxLength: 60000, description: "Complete email message body"}
|
|
351
|
+
}
|
|
352
|
+
}}}},
|
|
353
|
+
responses: {
|
|
354
|
+
"200": {description: "Email sent or replayed safely"},
|
|
355
|
+
"202": {description: "First-send human review requested"}
|
|
356
|
+
}
|
|
357
|
+
}}
|
|
358
|
+
}
|
|
359
|
+
}')"
|
|
360
|
+
|
|
361
|
+
jq -n \
|
|
362
|
+
--arg name "$TARGET_NAME" \
|
|
363
|
+
--arg schema "$openapi_payload" \
|
|
364
|
+
--arg providerArn "$OAUTH_CREDENTIAL_PROVIDER_ARN" \
|
|
365
|
+
--arg returnUrl "$OAUTH_RETURN_URL" \
|
|
366
|
+
'{
|
|
367
|
+
name: $name,
|
|
368
|
+
description: "THINK-316 OAuth owner-isolation target",
|
|
369
|
+
targetConfiguration: {mcp: {openApiSchema: {inlinePayload: $schema}}},
|
|
370
|
+
credentialProviderConfigurations: [{
|
|
371
|
+
credentialProviderType: "OAUTH",
|
|
372
|
+
credentialProvider: {oauthCredentialProvider: {
|
|
373
|
+
providerArn: $providerArn,
|
|
374
|
+
scopes: ["owner.read"],
|
|
375
|
+
grantType: "TOKEN_EXCHANGE"
|
|
376
|
+
}}
|
|
377
|
+
}]
|
|
378
|
+
}' >"$tmp_dir/target.json"
|
|
379
|
+
|
|
380
|
+
target_id="$(aws bedrock-agentcore-control list-gateway-targets \
|
|
381
|
+
--region "$AWS_REGION" --gateway-identifier "$gateway_id" --output json \
|
|
382
|
+
| jq -r --arg name "$TARGET_NAME" '(.items // .targets // [])[] | select(.name == $name) | .targetId' \
|
|
383
|
+
| head -n 1)"
|
|
384
|
+
if [[ -z "$target_id" ]]; then
|
|
385
|
+
target_id="$(jq --arg gateway "$gateway_id" '. + {gatewayIdentifier: $gateway}' \
|
|
386
|
+
"$tmp_dir/target.json" >"$tmp_dir/target-create.json" && \
|
|
387
|
+
aws bedrock-agentcore-control create-gateway-target --region "$AWS_REGION" \
|
|
388
|
+
--cli-input-json "file://$tmp_dir/target-create.json" --query targetId --output text)"
|
|
389
|
+
else
|
|
390
|
+
jq --arg gateway "$gateway_id" --arg target "$target_id" \
|
|
391
|
+
'. + {gatewayIdentifier: $gateway, targetId: $target}' \
|
|
392
|
+
"$tmp_dir/target.json" >"$tmp_dir/target-update.json"
|
|
393
|
+
aws bedrock-agentcore-control update-gateway-target --region "$AWS_REGION" \
|
|
394
|
+
--cli-input-json "file://$tmp_dir/target-update.json" >/dev/null
|
|
395
|
+
fi
|
|
396
|
+
|
|
397
|
+
target_status=""
|
|
398
|
+
for _ in $(seq 1 90); do
|
|
399
|
+
target_status="$(aws bedrock-agentcore-control get-gateway-target \
|
|
400
|
+
--region "$AWS_REGION" --gateway-identifier "$gateway_id" --target-id "$target_id" \
|
|
401
|
+
--query status --output text 2>/dev/null || true)"
|
|
402
|
+
[[ "$target_status" == "READY" || "$target_status" == "CREATE_PENDING_AUTH" || "$target_status" == "UPDATE_PENDING_AUTH" ]] && break
|
|
403
|
+
[[ "$target_status" == "FAILED" || "$target_status" == "UPDATE_UNSUCCESSFUL" ]] && {
|
|
404
|
+
printf 'target %s entered terminal status %s\n' "$target_id" "$target_status" >&2; exit 1;
|
|
405
|
+
}
|
|
406
|
+
sleep 2
|
|
407
|
+
done
|
|
408
|
+
[[ "$target_status" == "READY" || "$target_status" == "CREATE_PENDING_AUTH" || "$target_status" == "UPDATE_PENDING_AUTH" ]] || {
|
|
409
|
+
printf 'target %s never reached a usable authorization state (last=%s)\n' "$target_id" "$target_status" >&2; exit 1;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
# The Harness config grants one Gateway namespace, so a missing OpenAPI
|
|
413
|
+
# operation is otherwise silent: the model simply never sees that tool. Keep
|
|
414
|
+
# the reconciler from reporting success when Terraform's expected contract and
|
|
415
|
+
# AgentCore's live target schema have drifted apart.
|
|
416
|
+
expected_operations=(
|
|
417
|
+
owner_probe mixed_disclosure list_connector_tools call_connector_tool
|
|
418
|
+
execute_code web_search web_extract query_brain list_workspace_skills
|
|
419
|
+
load_workspace_skill list_message_attachments read_message_attachment
|
|
420
|
+
ask_user_question send_email
|
|
421
|
+
)
|
|
422
|
+
live_schema="$(aws bedrock-agentcore-control get-gateway-target \
|
|
423
|
+
--region "$AWS_REGION" --gateway-identifier "$gateway_id" --target-id "$target_id" \
|
|
424
|
+
--query 'targetConfiguration.mcp.openApiSchema.inlinePayload' --output text)"
|
|
425
|
+
for operation_id in "${expected_operations[@]}"; do
|
|
426
|
+
jq -e --arg operation_id "$operation_id" \
|
|
427
|
+
'[.paths[][] | .operationId] | index($operation_id) != null' \
|
|
428
|
+
<<<"$live_schema" >/dev/null || {
|
|
429
|
+
printf 'Gateway target %s is missing required operationId %s after reconciliation\n' \
|
|
430
|
+
"$target_id" "$operation_id" >&2
|
|
431
|
+
exit 1
|
|
432
|
+
}
|
|
433
|
+
done
|
|
434
|
+
|
|
435
|
+
# Explicit OAuthUser principal branches make the owner match mechanically
|
|
436
|
+
# reviewable and let Cedar reject cross-owner requests before AgentCore resolves
|
|
437
|
+
# a target credential. AgentCore maps JWT `sub` to the principal entity id (not
|
|
438
|
+
# a tag) and accepts one Cedar statement per policy definition. Connector and
|
|
439
|
+
# tool assignments are mutable ThinkWork state, so Cedar provides authenticated
|
|
440
|
+
# tenant admission while the target re-authorizes the live turn, connector, and
|
|
441
|
+
# tool assignment before resolving credentials or invoking the provider.
|
|
442
|
+
IFS=',' read -r -a proof_owners <<<"$PROOF_OWNER_ALLOWLIST"
|
|
443
|
+
owner_conditions=""
|
|
444
|
+
first_owner=""
|
|
445
|
+
for raw_owner in "${proof_owners[@]}"; do
|
|
446
|
+
owner="$(tr '[:upper:]' '[:lower:]' <<<"$raw_owner" | xargs)"
|
|
447
|
+
[[ "$owner" =~ ^[a-z0-9-]{1,128}$ ]] || {
|
|
448
|
+
printf 'invalid proof owner subject\n' >&2
|
|
449
|
+
exit 1
|
|
450
|
+
}
|
|
451
|
+
branch="(principal == AgentCore::OAuthUser::\"${owner}\" && context.input.requested_owner == \"${owner}\")"
|
|
452
|
+
[[ -z "$owner_conditions" ]] || owner_conditions+=$' ||\n '
|
|
453
|
+
owner_conditions+="$branch"
|
|
454
|
+
[[ -n "$first_owner" ]] || first_owner="$owner"
|
|
455
|
+
done
|
|
456
|
+
[[ "${#proof_owners[@]}" -ge 2 ]] || {
|
|
457
|
+
printf 'at least two proof owners are required\n' >&2
|
|
458
|
+
exit 1
|
|
459
|
+
}
|
|
460
|
+
cedar_statement="$(cat <<CEDAR
|
|
461
|
+
permit(
|
|
462
|
+
principal,
|
|
463
|
+
action in [
|
|
464
|
+
AgentCore::Action::"${TARGET_NAME}___owner_probe",
|
|
465
|
+
AgentCore::Action::"${TARGET_NAME}___mixed_disclosure",
|
|
466
|
+
AgentCore::Action::"${TARGET_NAME}___list_connector_tools",
|
|
467
|
+
AgentCore::Action::"${TARGET_NAME}___call_connector_tool",
|
|
468
|
+
AgentCore::Action::"${TARGET_NAME}___execute_code",
|
|
469
|
+
AgentCore::Action::"${TARGET_NAME}___web_search",
|
|
470
|
+
AgentCore::Action::"${TARGET_NAME}___web_extract",
|
|
471
|
+
AgentCore::Action::"${TARGET_NAME}___query_brain",
|
|
472
|
+
AgentCore::Action::"${TARGET_NAME}___list_workspace_skills",
|
|
473
|
+
AgentCore::Action::"${TARGET_NAME}___load_workspace_skill",
|
|
474
|
+
AgentCore::Action::"${TARGET_NAME}___list_message_attachments",
|
|
475
|
+
AgentCore::Action::"${TARGET_NAME}___read_message_attachment",
|
|
476
|
+
AgentCore::Action::"${TARGET_NAME}___ask_user_question",
|
|
477
|
+
AgentCore::Action::"${TARGET_NAME}___send_email"
|
|
478
|
+
],
|
|
479
|
+
resource == AgentCore::Gateway::"${gateway_arn}"
|
|
480
|
+
)
|
|
481
|
+
when {
|
|
482
|
+
principal.hasTag("tenant_id") &&
|
|
483
|
+
principal.hasTag("purpose") &&
|
|
484
|
+
principal.getTag("purpose") == "gateway_operation" &&
|
|
485
|
+
(
|
|
486
|
+
(
|
|
487
|
+
action == AgentCore::Action::"${TARGET_NAME}___owner_probe" &&
|
|
488
|
+
(${owner_conditions})
|
|
489
|
+
) ||
|
|
490
|
+
(
|
|
491
|
+
action == AgentCore::Action::"${TARGET_NAME}___mixed_disclosure" &&
|
|
492
|
+
principal == AgentCore::OAuthUser::"${first_owner}" &&
|
|
493
|
+
context.input.requested_owner == "${first_owner}"
|
|
494
|
+
) ||
|
|
495
|
+
(
|
|
496
|
+
(
|
|
497
|
+
action == AgentCore::Action::"${TARGET_NAME}___list_connector_tools" ||
|
|
498
|
+
action == AgentCore::Action::"${TARGET_NAME}___call_connector_tool" ||
|
|
499
|
+
action == AgentCore::Action::"${TARGET_NAME}___execute_code" ||
|
|
500
|
+
action == AgentCore::Action::"${TARGET_NAME}___web_search" ||
|
|
501
|
+
action == AgentCore::Action::"${TARGET_NAME}___web_extract" ||
|
|
502
|
+
action == AgentCore::Action::"${TARGET_NAME}___query_brain" ||
|
|
503
|
+
action == AgentCore::Action::"${TARGET_NAME}___list_workspace_skills" ||
|
|
504
|
+
action == AgentCore::Action::"${TARGET_NAME}___load_workspace_skill" ||
|
|
505
|
+
action == AgentCore::Action::"${TARGET_NAME}___list_message_attachments" ||
|
|
506
|
+
action == AgentCore::Action::"${TARGET_NAME}___read_message_attachment" ||
|
|
507
|
+
action == AgentCore::Action::"${TARGET_NAME}___ask_user_question" ||
|
|
508
|
+
action == AgentCore::Action::"${TARGET_NAME}___send_email"
|
|
509
|
+
)
|
|
510
|
+
)
|
|
511
|
+
)
|
|
512
|
+
};
|
|
513
|
+
CEDAR
|
|
514
|
+
)"
|
|
515
|
+
|
|
516
|
+
jq -n --arg name "$POLICY_NAME" --arg engine "$policy_engine_id" \
|
|
517
|
+
--arg statement "$cedar_statement" '{
|
|
518
|
+
name: $name,
|
|
519
|
+
description: "THINK-316 exact-user admission; target owns dynamic capability authorization",
|
|
520
|
+
definition: {cedar: {statement: $statement}},
|
|
521
|
+
validationMode: "FAIL_ON_ANY_FINDINGS",
|
|
522
|
+
policyEngineId: $engine
|
|
523
|
+
}' >"$tmp_dir/policy.json"
|
|
524
|
+
|
|
525
|
+
policy_id="$(aws bedrock-agentcore-control list-policies --region "$AWS_REGION" \
|
|
526
|
+
--policy-engine-id "$policy_engine_id" --output json \
|
|
527
|
+
| jq -r --arg name "$POLICY_NAME" '(.policies // .items // [])[] | select(.name == $name) | .policyId' \
|
|
528
|
+
| head -n 1)"
|
|
529
|
+
if [[ -z "$policy_id" ]]; then
|
|
530
|
+
policy_id="$(aws bedrock-agentcore-control create-policy --region "$AWS_REGION" \
|
|
531
|
+
--cli-input-json "file://$tmp_dir/policy.json" --query policyId --output text)"
|
|
532
|
+
else
|
|
533
|
+
jq --arg id "$policy_id" '{
|
|
534
|
+
policyEngineId, policyId: $id, description: {optionalValue: .description},
|
|
535
|
+
definition, validationMode
|
|
536
|
+
}' "$tmp_dir/policy.json" >"$tmp_dir/policy-update.json"
|
|
537
|
+
aws bedrock-agentcore-control update-policy --region "$AWS_REGION" \
|
|
538
|
+
--cli-input-json "file://$tmp_dir/policy-update.json" >/dev/null
|
|
539
|
+
fi
|
|
540
|
+
wait_policy_status "$policy_engine_id" "$policy_id"
|
|
541
|
+
|
|
542
|
+
printf 'AgentCore Gateway proof resources reconciled: gateway=%s target=%s engine=%s policy=%s\n' \
|
|
543
|
+
"$gateway_id" "$target_id" "$policy_engine_id" "$policy_id"
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
variable "enabled" {
|
|
2
|
+
description = "Reconcile the non-production THINK-316 Gateway proof resources."
|
|
3
|
+
type = bool
|
|
4
|
+
default = false
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
variable "stage" {
|
|
8
|
+
description = "Deployment stage."
|
|
9
|
+
type = string
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
variable "region" {
|
|
13
|
+
description = "AWS region."
|
|
14
|
+
type = string
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
variable "account_id" {
|
|
18
|
+
description = "AWS account id."
|
|
19
|
+
type = string
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
variable "discovery_url" {
|
|
23
|
+
description = "CUSTOM_JWT OIDC discovery URL for the purpose-bound Gateway assertion issuer."
|
|
24
|
+
type = string
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
variable "gateway_audience" {
|
|
28
|
+
description = "Exact audience accepted by this proof Gateway."
|
|
29
|
+
type = string
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
variable "target_base_url" {
|
|
33
|
+
description = "Owned HTTPS API base URL hosting the controlled proof target."
|
|
34
|
+
type = string
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
variable "oauth_credential_provider_arn" {
|
|
38
|
+
description = "Exact AgentCore Identity OAuth provider ARN used for the target."
|
|
39
|
+
type = string
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
variable "oauth_credential_secret_arn" {
|
|
43
|
+
description = "Exact AgentCore-managed secret backing the OAuth provider."
|
|
44
|
+
type = string
|
|
45
|
+
sensitive = true
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
variable "oauth_return_url" {
|
|
49
|
+
description = "Application callback URL allowed for the 3LO user-federation flow."
|
|
50
|
+
type = string
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
variable "proof_owner_allowlist" {
|
|
54
|
+
description = "Comma-separated exact OAuthUser subjects admitted by the proof Cedar policy."
|
|
55
|
+
type = string
|
|
56
|
+
default = ""
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
variable "observability_retention_days" {
|
|
60
|
+
description = "Retention for AgentCore Gateway application logs delivered to CloudWatch."
|
|
61
|
+
type = number
|
|
62
|
+
default = 90
|
|
63
|
+
|
|
64
|
+
validation {
|
|
65
|
+
condition = contains([
|
|
66
|
+
1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1096, 1827, 2192, 2557, 2922, 3288, 3653,
|
|
67
|
+
], var.observability_retention_days)
|
|
68
|
+
error_message = "observability_retention_days must be a CloudWatch Logs-supported retention period."
|
|
69
|
+
}
|
|
70
|
+
}
|