thinkwork-cli 0.9.0 → 0.9.1
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/LICENSE +202 -0
- package/README.md +2 -2
- package/dist/cli.js +1187 -315
- package/dist/terraform/examples/greenfield/main.tf +325 -19
- package/dist/terraform/examples/greenfield/terraform.tfvars.example +14 -0
- package/dist/terraform/modules/app/agentcore-code-interpreter/Dockerfile.sandbox-base +61 -0
- package/dist/terraform/modules/app/agentcore-code-interpreter/README.md +54 -0
- package/dist/terraform/modules/app/agentcore-code-interpreter/main.tf +197 -0
- package/dist/terraform/modules/app/agentcore-code-interpreter/scripts/build_and_push_sandbox_base.sh +70 -0
- package/dist/terraform/modules/app/agentcore-flue/README.md +58 -0
- package/dist/terraform/modules/app/agentcore-flue/main.tf +322 -0
- package/dist/terraform/modules/app/agentcore-flue/outputs.tf +23 -0
- package/dist/terraform/modules/app/agentcore-flue/variables.tf +91 -0
- package/dist/terraform/modules/app/agentcore-memory/scripts/create_or_find_memory.sh +0 -0
- package/dist/terraform/modules/app/agentcore-runtime/main.tf +165 -0
- package/dist/terraform/modules/app/appsync-subscriptions/main.tf +4 -0
- package/dist/terraform/modules/app/appsync-subscriptions/outputs.tf +5 -0
- package/dist/terraform/modules/app/computer-runtime/README.md +15 -0
- package/dist/terraform/modules/app/computer-runtime/main.tf +406 -0
- package/dist/terraform/modules/app/computer-runtime/outputs.tf +75 -0
- package/dist/terraform/modules/app/computer-runtime/variables.tf +66 -0
- package/dist/terraform/modules/app/hindsight-memory/main.tf +6 -0
- package/dist/terraform/modules/app/lambda-api/eval-fanout.tf +128 -0
- package/dist/terraform/modules/app/lambda-api/handlers.tf +1454 -43
- package/dist/terraform/modules/app/lambda-api/main.tf +221 -12
- package/dist/terraform/modules/app/lambda-api/mcp-oauth.tf +118 -0
- package/dist/terraform/modules/app/lambda-api/oauth-secrets.tf +49 -0
- package/dist/terraform/modules/app/lambda-api/outputs.tf +38 -0
- package/dist/terraform/modules/app/lambda-api/slack-app-secrets.tf +43 -0
- package/dist/terraform/modules/app/lambda-api/stripe-secrets.tf +53 -0
- package/dist/terraform/modules/app/lambda-api/variables.tf +349 -2
- package/dist/terraform/modules/app/lambda-api/workspace-events.tf +125 -0
- package/dist/terraform/modules/app/routines-stepfunctions/main.tf +453 -0
- package/dist/terraform/modules/app/sandbox-log-scrubber/README.md +66 -0
- package/dist/terraform/modules/app/sandbox-log-scrubber/main.tf +200 -0
- package/dist/terraform/modules/app/static-site/main.tf +146 -5
- package/dist/terraform/modules/app/www-dns/main.tf +118 -15
- package/dist/terraform/modules/app/www-dns/outputs.tf +10 -0
- package/dist/terraform/modules/app/www-dns/variables.tf +42 -0
- package/dist/terraform/modules/data/aurora-postgres/main.tf +164 -3
- package/dist/terraform/modules/data/aurora-postgres/outputs.tf +34 -0
- package/dist/terraform/modules/data/aurora-postgres/variables.tf +16 -0
- package/dist/terraform/modules/data/compliance-audit-bucket/README.md +145 -0
- package/dist/terraform/modules/data/compliance-audit-bucket/main.tf +573 -0
- package/dist/terraform/modules/data/compliance-audit-bucket/outputs.tf +43 -0
- package/dist/terraform/modules/data/compliance-audit-bucket/variables.tf +93 -0
- package/dist/terraform/modules/data/compliance-exports-bucket/main.tf +269 -0
- package/dist/terraform/modules/data/compliance-exports-bucket/outputs.tf +23 -0
- package/dist/terraform/modules/data/compliance-exports-bucket/variables.tf +50 -0
- package/dist/terraform/modules/data/s3-backups-bucket/main.tf +123 -0
- package/dist/terraform/modules/data/s3-buckets/main.tf +13 -0
- package/dist/terraform/modules/foundation/cognito/variables.tf +2 -2
- package/dist/terraform/modules/thinkwork/main.tf +439 -21
- package/dist/terraform/modules/thinkwork/outputs.tf +121 -0
- package/dist/terraform/modules/thinkwork/variables.tf +153 -2
- package/dist/terraform/schema.graphql +17 -0
- package/package.json +15 -14
|
@@ -60,6 +60,12 @@ variable "bucket_arn" {
|
|
|
60
60
|
type = string
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
+
variable "enable_workspace_orchestration" {
|
|
64
|
+
description = "Enable S3 EventBridge/SQS routing for workspace file orchestration."
|
|
65
|
+
type = bool
|
|
66
|
+
default = false
|
|
67
|
+
}
|
|
68
|
+
|
|
63
69
|
variable "user_pool_id" {
|
|
64
70
|
description = "Cognito user pool ID"
|
|
65
71
|
type = string
|
|
@@ -80,6 +86,12 @@ variable "mobile_client_id" {
|
|
|
80
86
|
type = string
|
|
81
87
|
}
|
|
82
88
|
|
|
89
|
+
variable "cognito_auth_domain" {
|
|
90
|
+
description = "Cognito hosted UI domain prefix, e.g. thinkwork-dev. Empty disables MCP OAuth login."
|
|
91
|
+
type = string
|
|
92
|
+
default = ""
|
|
93
|
+
}
|
|
94
|
+
|
|
83
95
|
variable "appsync_api_url" {
|
|
84
96
|
description = "AppSync subscriptions endpoint URL"
|
|
85
97
|
type = string
|
|
@@ -134,6 +146,19 @@ variable "api_auth_secret" {
|
|
|
134
146
|
default = ""
|
|
135
147
|
}
|
|
136
148
|
|
|
149
|
+
variable "extension_proxy_backends_json" {
|
|
150
|
+
description = "JSON map of enabled Admin extension ids to allowlisted backend base URLs. Example: {\"customer-module\":{\"baseUrl\":\"https://extension.example.com\"}}"
|
|
151
|
+
type = string
|
|
152
|
+
default = "{}"
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
variable "extension_proxy_signing_secret" {
|
|
156
|
+
description = "Shared HMAC secret used by the generic Admin extension proxy to sign actor context for extension backends."
|
|
157
|
+
type = string
|
|
158
|
+
sensitive = true
|
|
159
|
+
default = ""
|
|
160
|
+
}
|
|
161
|
+
|
|
137
162
|
variable "hindsight_endpoint" {
|
|
138
163
|
description = "Hindsight API endpoint (empty when enable_hindsight = false)"
|
|
139
164
|
type = string
|
|
@@ -162,12 +187,118 @@ variable "agentcore_function_name" {
|
|
|
162
187
|
default = ""
|
|
163
188
|
}
|
|
164
189
|
|
|
190
|
+
variable "agentcore_flue_function_name" {
|
|
191
|
+
description = "Flue AgentCore Lambda function name (for direct SDK invoke); empty until the Flue runtime is provisioned for the stage."
|
|
192
|
+
type = string
|
|
193
|
+
default = ""
|
|
194
|
+
}
|
|
195
|
+
|
|
165
196
|
variable "agentcore_function_arn" {
|
|
166
197
|
description = "AgentCore Lambda function ARN (used to grant lambda:InvokeFunction)"
|
|
167
198
|
type = string
|
|
168
199
|
default = ""
|
|
169
200
|
}
|
|
170
201
|
|
|
202
|
+
variable "agentcore_flue_function_arn" {
|
|
203
|
+
description = "Flue AgentCore Lambda function ARN (used to grant lambda:InvokeFunction)"
|
|
204
|
+
type = string
|
|
205
|
+
default = ""
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
variable "computer_runtime_cluster_name" {
|
|
209
|
+
description = "ECS cluster name for ThinkWork Computer runtime services"
|
|
210
|
+
type = string
|
|
211
|
+
default = ""
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
variable "computer_runtime_cluster_arn" {
|
|
215
|
+
description = "ECS cluster ARN for ThinkWork Computer runtime services"
|
|
216
|
+
type = string
|
|
217
|
+
default = ""
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
variable "computer_runtime_efs_file_system_id" {
|
|
221
|
+
description = "Shared EFS file system ID for Computer live workspaces"
|
|
222
|
+
type = string
|
|
223
|
+
default = ""
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
variable "computer_runtime_subnet_ids" {
|
|
227
|
+
description = "Subnets for Computer runtime ECS services"
|
|
228
|
+
type = list(string)
|
|
229
|
+
default = []
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
variable "computer_runtime_assign_public_ip" {
|
|
233
|
+
description = "ENABLED or DISABLED for Computer runtime ECS task public IP assignment"
|
|
234
|
+
type = string
|
|
235
|
+
default = "DISABLED"
|
|
236
|
+
validation {
|
|
237
|
+
condition = contains(["ENABLED", "DISABLED"], var.computer_runtime_assign_public_ip)
|
|
238
|
+
error_message = "computer_runtime_assign_public_ip must be ENABLED or DISABLED."
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
variable "computer_runtime_task_sg_id" {
|
|
243
|
+
description = "Security group for Computer runtime ECS tasks"
|
|
244
|
+
type = string
|
|
245
|
+
default = ""
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
variable "computer_runtime_execution_role_arn" {
|
|
249
|
+
description = "ECS execution role ARN for Computer runtime tasks"
|
|
250
|
+
type = string
|
|
251
|
+
default = ""
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
variable "computer_runtime_task_role_arn" {
|
|
255
|
+
description = "ECS task role ARN for Computer runtime tasks"
|
|
256
|
+
type = string
|
|
257
|
+
default = ""
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
variable "computer_runtime_log_group_name" {
|
|
261
|
+
description = "CloudWatch log group for Computer runtime tasks"
|
|
262
|
+
type = string
|
|
263
|
+
default = ""
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
variable "computer_runtime_repository_url" {
|
|
267
|
+
description = "ECR repository URL for the Computer runtime image"
|
|
268
|
+
type = string
|
|
269
|
+
default = ""
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
variable "computer_runtime_default_cpu" {
|
|
273
|
+
description = "Default Fargate CPU units for Computer runtime tasks"
|
|
274
|
+
type = number
|
|
275
|
+
default = 256
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
variable "computer_runtime_default_memory" {
|
|
279
|
+
description = "Default Fargate memory MB for Computer runtime tasks"
|
|
280
|
+
type = number
|
|
281
|
+
default = 512
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
variable "computer_runtime_manager_policy_arn" {
|
|
285
|
+
description = "IAM policy ARN granting Computer manager access to ECS/EFS runtime resources"
|
|
286
|
+
type = string
|
|
287
|
+
default = ""
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
variable "workspace_admin_efs_access_point_arn" {
|
|
291
|
+
description = "Shared EFS access point ARN consumed by the workspace-files-efs Lambda. Rooted at /tenants on the Computer runtime EFS file system so a single Lambda can resolve any (tenantId, computerId) at request time."
|
|
292
|
+
type = string
|
|
293
|
+
default = ""
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
variable "workspace_admin_lambda_sg_id" {
|
|
297
|
+
description = "Security group ID assigned to the workspace-files-efs Lambda. Allowed NFS into the Computer runtime EFS security group via a sibling ingress rule defined in the computer-runtime module."
|
|
298
|
+
type = string
|
|
299
|
+
default = ""
|
|
300
|
+
}
|
|
301
|
+
|
|
171
302
|
variable "admin_url" {
|
|
172
303
|
description = "Admin app URL (e.g. https://d3li9vbqnhv7w.cloudfront.net)"
|
|
173
304
|
type = string
|
|
@@ -180,6 +311,24 @@ variable "docs_url" {
|
|
|
180
311
|
default = ""
|
|
181
312
|
}
|
|
182
313
|
|
|
314
|
+
variable "www_url" {
|
|
315
|
+
description = "Marketing site URL (e.g. https://thinkwork.ai). Used for Stripe Checkout cancel_url and CORS origin."
|
|
316
|
+
type = string
|
|
317
|
+
default = ""
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
variable "stripe_price_ids_json" {
|
|
321
|
+
description = "JSON object mapping internal plan names to Stripe price IDs for this stage, e.g. {\"starter\":\"price_...\",\"team\":\"price_...\"}. Non-secret; per-stage. Default is an empty object so Lambdas boot even before pricing is configured."
|
|
322
|
+
type = string
|
|
323
|
+
default = "{}"
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
variable "stripe_welcome_from_email" {
|
|
327
|
+
description = "Override From: address on the Stripe post-checkout welcome email. Must be an SES-verified identity. Empty string falls back to the in-code default (hello@agents.thinkwork.ai, which uses the already-verified SES inbound domain). Set to hello@thinkwork.ai once the bare-apex sender identity is verified."
|
|
328
|
+
type = string
|
|
329
|
+
default = ""
|
|
330
|
+
}
|
|
331
|
+
|
|
183
332
|
variable "appsync_realtime_url" {
|
|
184
333
|
description = "AppSync realtime/WebSocket endpoint URL"
|
|
185
334
|
type = string
|
|
@@ -204,8 +353,206 @@ variable "job_scheduler_role_arn" {
|
|
|
204
353
|
default = ""
|
|
205
354
|
}
|
|
206
355
|
|
|
207
|
-
variable "
|
|
208
|
-
description = "
|
|
356
|
+
variable "wiki_compile_model_id" {
|
|
357
|
+
description = "Bedrock model id the wiki-compile Lambda uses for the leaf planner, aggregation planner, and section writer. Any Converse-compatible model works. Override per-env if you want to spike a different model without re-deploying code."
|
|
358
|
+
type = string
|
|
359
|
+
default = "openai.gpt-oss-120b-1:0"
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
variable "company_brain_source_agent_model_id" {
|
|
363
|
+
description = "Bedrock model id the GraphQL context-engine Company Brain source-agent runtime uses for JSON tool/action turns. Kept separate from the high-throughput wiki compiler model so source agents can use a model tuned for reliable action JSON."
|
|
364
|
+
type = string
|
|
365
|
+
default = "us.anthropic.claude-haiku-4-5-20251001-v1:0"
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
variable "wiki_aggregation_pass_enabled" {
|
|
369
|
+
description = "Feature flag for the wiki aggregation pass (parent section rollups + section promotion). Pipeline stops after leaf compile when this is off and never populates hub rollups. Stored as a string because the Lambda reads it verbatim from env; must be 'true' / '1' / 'yes' to enable."
|
|
370
|
+
type = string
|
|
371
|
+
default = "true"
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
variable "wiki_deterministic_linking_enabled" {
|
|
375
|
+
description = "Feature flag for deterministic compile-time link emission (parent-expander-driven city/journal references + entity↔entity co-mention edges). When off, the compile pipeline never calls the deterministic linkers and `links_written_deterministic` / `links_written_co_mention` stay at 0 in metrics. Stored as a string because the Lambda reads it verbatim from env; must be 'true' / '1' / 'yes' to enable."
|
|
376
|
+
type = string
|
|
377
|
+
default = "true"
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
variable "google_places_api_key" {
|
|
381
|
+
description = "Google Places API (New) key used by wiki-compile for POI → city/state/country hierarchy enrichment. Stored as a SecureString SSM parameter at /thinkwork/<stage>/google-places/api-key. Empty default creates the parameter with a placeholder value; operator populates via `aws ssm put-parameter --overwrite`. The parameter's value has lifecycle.ignore_changes set so CLI rotation sticks across terraform applies. Compile gracefully degrades when the key is absent (metadata-only place rows) — never fails compile."
|
|
382
|
+
type = string
|
|
383
|
+
default = ""
|
|
384
|
+
sensitive = true
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
# ---------------------------------------------------------------------------
|
|
388
|
+
# Per-user OAuth client credentials
|
|
389
|
+
# ---------------------------------------------------------------------------
|
|
390
|
+
|
|
391
|
+
variable "google_oauth_client_id" {
|
|
392
|
+
description = "Google Workspace OAuth 2.0 client ID (for per-user Gmail/Calendar integration). Stored in Secrets Manager via aws_secretsmanager_secret_version; fetched by Lambdas at cold-start via oauth-client-credentials.ts."
|
|
393
|
+
type = string
|
|
394
|
+
default = ""
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
variable "google_oauth_client_secret" {
|
|
398
|
+
description = "Google Workspace OAuth 2.0 client secret (for per-user Gmail/Calendar integration). Stored in Secrets Manager alongside the client_id; Lambdas fetch both values at cold-start."
|
|
399
|
+
type = string
|
|
400
|
+
default = ""
|
|
401
|
+
sensitive = true
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
variable "redirect_success_url" {
|
|
405
|
+
description = "Default OAuth-callback redirect target used when the caller doesn't supply a returnUrl. Mobile callers pass a thinkwork:// custom scheme; web (admin) falls through to this default."
|
|
406
|
+
type = string
|
|
407
|
+
default = "https://app.thinkwork.ai/settings/credentials"
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
variable "platform_operator_emails" {
|
|
411
|
+
description = "Comma-separated allowlist of emails permitted to invoke operator-gated GraphQL mutations (updateTenantPolicy, sandbox fixture setup, etc.). Compared against ctx.auth.email — pulled from the Cognito JWT for user callers and from the x-principal-email header for service-auth callers. Empty ⇒ the gate rejects every call."
|
|
412
|
+
type = string
|
|
413
|
+
default = ""
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
# ---------------------------------------------------------------------------
|
|
417
|
+
# MCP custom domain (optional) — e.g., mcp.thinkwork.ai
|
|
418
|
+
# ---------------------------------------------------------------------------
|
|
419
|
+
|
|
420
|
+
variable "mcp_custom_domain" {
|
|
421
|
+
description = "Custom domain for the MCP endpoint (e.g., 'mcp.thinkwork.ai'). Empty disables the custom-domain setup entirely. When set, an ACM cert is created; flip mcp_custom_domain_ready=true on the second apply to attach the domain + API mapping after DNS validation completes. See docs/solutions/patterns/mcp-custom-domain-setup-2026-04-23.md for the workflow."
|
|
422
|
+
type = string
|
|
423
|
+
default = ""
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
variable "mcp_custom_domain_ready" {
|
|
427
|
+
description = "Two-apply gate for the MCP custom domain. Leave false on the first apply (cert-only). After running `pnpm cf:sync-mcp` + waiting for ACM validation, flip to true and re-apply to create the API Gateway domain + mapping."
|
|
428
|
+
type = bool
|
|
429
|
+
default = false
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
# ---------------------------------------------------------------------------
|
|
433
|
+
# Routines runtime (Phase B U6) — code-interpreter id for routine-task-python
|
|
434
|
+
# ---------------------------------------------------------------------------
|
|
435
|
+
|
|
436
|
+
variable "agentcore_code_interpreter_id" {
|
|
437
|
+
description = "AgentCore Code Interpreter id used by routine-task-python (Phase B U6) for SFN `python` recipe states. Default empty — the Lambda fails closed with sandbox_misconfigured when unset, which is the correct behavior until Phase B U7 provisions a routines-dedicated interpreter. Operations sets this via tfvars once the interpreter is created."
|
|
438
|
+
type = string
|
|
439
|
+
default = ""
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
variable "routines_execution_role_arn" {
|
|
443
|
+
description = "ARN of the Step Functions execution role newly-created routine state machines run under (Phase B U7). Wired from the routines-stepfunctions module's execution_role_arn output. createRoutine passes this as RoleArn on CreateStateMachine; the lambda-api role's RoutinePassExecutionRole grant is scoped to exactly this ARN."
|
|
444
|
+
type = string
|
|
445
|
+
default = ""
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
variable "routines_log_group_arn" {
|
|
449
|
+
description = "ARN of the routines-stepfunctions CloudWatch log group (Phase B U7). Surfaced to the publish flow for future LoggingConfiguration on CreateStateMachine."
|
|
450
|
+
type = string
|
|
451
|
+
default = ""
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
# ---------------------------------------------------------------------------
|
|
455
|
+
# Phase 3 U4 — compliance-outbox-drainer Aurora credentials
|
|
456
|
+
# ---------------------------------------------------------------------------
|
|
457
|
+
|
|
458
|
+
variable "compliance_drainer_secret_arn" {
|
|
459
|
+
description = "ARN of the Secrets Manager secret holding the `compliance_drainer` Aurora role credentials (Phase 3 U2 / PR #887). Wired from `module.database.compliance_drainer_secret_arn`. The compliance-outbox-drainer Lambda resolves this at module load to connect with INSERT-only access on `compliance.audit_events`."
|
|
460
|
+
type = string
|
|
461
|
+
default = ""
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
# ---------------------------------------------------------------------------
|
|
465
|
+
# Phase 3 U7 — compliance audit-anchor bucket (S3 Object Lock)
|
|
466
|
+
# Default empty until U8a wires the anchor Lambda. The variables exist so
|
|
467
|
+
# U8a can reference them without forcing this PR to also wire a Lambda body.
|
|
468
|
+
# ---------------------------------------------------------------------------
|
|
469
|
+
|
|
470
|
+
variable "compliance_anchor_bucket_arn" {
|
|
471
|
+
description = "ARN of the WORM-protected compliance audit-anchor S3 bucket. Default empty until U8a wires the anchor Lambda."
|
|
472
|
+
type = string
|
|
473
|
+
default = ""
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
variable "compliance_anchor_bucket_name" {
|
|
477
|
+
description = "Name of the WORM-protected compliance audit-anchor S3 bucket. Default empty until U8a wires the anchor Lambda."
|
|
478
|
+
type = string
|
|
479
|
+
default = ""
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
variable "compliance_anchor_lambda_role_arn" {
|
|
483
|
+
description = "ARN of the IAM role the anchor Lambda will assume. Default empty until U8a wires the anchor Lambda."
|
|
484
|
+
type = string
|
|
485
|
+
default = ""
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
variable "compliance_anchor_lambda_role_name" {
|
|
489
|
+
description = "Name of the IAM role the anchor Lambda assumes (extracted from the role resource for inline-policy attachments like the U8a DLQ SendMessage grant)."
|
|
490
|
+
type = string
|
|
491
|
+
default = ""
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
# ---------------------------------------------------------------------------
|
|
495
|
+
# Phase 3 U8a — compliance anchor Lambda runtime config
|
|
496
|
+
# ---------------------------------------------------------------------------
|
|
497
|
+
|
|
498
|
+
variable "compliance_reader_secret_arn" {
|
|
499
|
+
description = "ARN of the Secrets Manager secret holding the `compliance_reader` Aurora role credentials. Wired from `module.database.compliance_reader_secret_arn`. The U8a anchor Lambda uses this for least-privilege SELECT on `compliance.audit_events`."
|
|
500
|
+
type = string
|
|
501
|
+
default = ""
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
variable "compliance_anchor_object_lock_retention_days" {
|
|
505
|
+
description = "Default Object Lock retention for the compliance anchor bucket, in days. Forwarded to the anchor Lambda as COMPLIANCE_ANCHOR_RETENTION_DAYS (consumed by U8b's live function; pre-plumbed in U8a). Master plan baseline: 365."
|
|
506
|
+
type = number
|
|
507
|
+
default = 365
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
# ---------------------------------------------------------------------------
|
|
511
|
+
# Phase 3 U8b — anchor Lambda live config
|
|
512
|
+
# ---------------------------------------------------------------------------
|
|
513
|
+
|
|
514
|
+
variable "compliance_anchor_kms_key_arn" {
|
|
515
|
+
description = "ARN of the customer-managed CMK used for SSE-KMS encryption of anchor objects. Forwarded to the anchor Lambda as COMPLIANCE_ANCHOR_KMS_KEY_ARN (required by `_anchor_fn_live` for the SSE-KMS PutObject)."
|
|
516
|
+
type = string
|
|
517
|
+
default = ""
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
variable "compliance_anchor_object_lock_mode" {
|
|
521
|
+
description = "Object Lock retention mode applied per-object to anchor PutObjects. GOVERNANCE in dev/staging; COMPLIANCE in prod (irreversible). Forwarded to the anchor Lambda as COMPLIANCE_ANCHOR_OBJECT_LOCK_MODE."
|
|
522
|
+
type = string
|
|
523
|
+
default = "GOVERNANCE"
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
variable "compliance_anchor_watchdog_role_arn" {
|
|
527
|
+
description = "ARN of the sibling IAM role the watchdog Lambda assumes (Phase 3 U8b). Decrypt-less: kms:DescribeKey only on the bucket CMK; s3:ListBucket prefix-scoped to anchors/."
|
|
528
|
+
type = string
|
|
529
|
+
default = ""
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
variable "compliance_anchor_watchdog_role_name" {
|
|
533
|
+
description = "Name of the sibling watchdog IAM role. Used for any future inline-policy attachments (e.g., DLQ SendMessage) without re-deriving the name from the ARN."
|
|
534
|
+
type = string
|
|
535
|
+
default = ""
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
# ---------------------------------------------------------------------------
|
|
539
|
+
# Phase 3 U11.U2 — compliance export runner Lambda
|
|
540
|
+
# ---------------------------------------------------------------------------
|
|
541
|
+
|
|
542
|
+
variable "compliance_exports_bucket_name" {
|
|
543
|
+
description = "Name of the compliance-exports S3 bucket. Forwarded to the runner Lambda as COMPLIANCE_EXPORTS_BUCKET so the U11.U3 live body knows where to write CSV/NDJSON artifacts. Default empty — the runner function still deploys but the live body throws on boot."
|
|
544
|
+
type = string
|
|
545
|
+
default = ""
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
variable "compliance_exports_runner_role_arn" {
|
|
549
|
+
description = "ARN of the IAM role the U11 export runner Lambda assumes. Wired from `module.compliance_exports.runner_role_arn`. Default empty until U11.U2 ships."
|
|
550
|
+
type = string
|
|
551
|
+
default = ""
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
variable "compliance_exports_runner_role_name" {
|
|
555
|
+
description = "Name of the IAM role the U11 export runner Lambda assumes (extracted from the role resource for inline-policy attachments — DLQ SendMessage, SQS receive)."
|
|
209
556
|
type = string
|
|
210
557
|
default = ""
|
|
211
558
|
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
locals {
|
|
2
|
+
workspace_event_enabled = var.enable_workspace_orchestration && local.use_local_zips
|
|
3
|
+
# EventBridge rejects the more precise per-folder S3 wildcard rules as too
|
|
4
|
+
# complex. Keep broad workspace/catalog families in separate rules and let the
|
|
5
|
+
# dispatcher keep the canonical allowlist in code.
|
|
6
|
+
workspace_event_patterns = {
|
|
7
|
+
workspace = [
|
|
8
|
+
"tenants/*/agents/*/workspace/*",
|
|
9
|
+
]
|
|
10
|
+
catalog_skills = [
|
|
11
|
+
"tenants/*/agents/_catalog/*/workspace/skills/*",
|
|
12
|
+
]
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
resource "aws_sqs_queue" "workspace_event_dlq" {
|
|
17
|
+
for_each = local.workspace_event_enabled ? local.workspace_event_patterns : {}
|
|
18
|
+
|
|
19
|
+
name = "thinkwork-${var.stage}-workspace-events-${each.key}-dlq"
|
|
20
|
+
message_retention_seconds = 1209600
|
|
21
|
+
sqs_managed_sse_enabled = true
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
resource "aws_sqs_queue" "workspace_event" {
|
|
25
|
+
for_each = local.workspace_event_enabled ? local.workspace_event_patterns : {}
|
|
26
|
+
|
|
27
|
+
name = "thinkwork-${var.stage}-workspace-events-${each.key}"
|
|
28
|
+
visibility_timeout_seconds = 180
|
|
29
|
+
sqs_managed_sse_enabled = true
|
|
30
|
+
|
|
31
|
+
redrive_policy = jsonencode({
|
|
32
|
+
deadLetterTargetArn = aws_sqs_queue.workspace_event_dlq[each.key].arn
|
|
33
|
+
maxReceiveCount = 1
|
|
34
|
+
})
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
resource "aws_cloudwatch_event_rule" "workspace_event" {
|
|
38
|
+
for_each = local.workspace_event_enabled ? local.workspace_event_patterns : {}
|
|
39
|
+
|
|
40
|
+
name = "thinkwork-${var.stage}-workspace-event-${each.key}"
|
|
41
|
+
description = "Workspace orchestration S3 ${each.key} object events"
|
|
42
|
+
|
|
43
|
+
event_pattern = jsonencode({
|
|
44
|
+
source = ["aws.s3"]
|
|
45
|
+
"detail-type" = ["Object Created", "Object Deleted"]
|
|
46
|
+
detail = {
|
|
47
|
+
bucket = {
|
|
48
|
+
name = [var.bucket_name]
|
|
49
|
+
}
|
|
50
|
+
object = {
|
|
51
|
+
key = [for pattern in each.value : { wildcard = pattern }]
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
})
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
resource "aws_cloudwatch_event_target" "workspace_event" {
|
|
58
|
+
for_each = local.workspace_event_enabled ? local.workspace_event_patterns : {}
|
|
59
|
+
|
|
60
|
+
rule = aws_cloudwatch_event_rule.workspace_event[each.key].name
|
|
61
|
+
arn = aws_sqs_queue.workspace_event[each.key].arn
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
resource "aws_sqs_queue_policy" "workspace_event" {
|
|
65
|
+
for_each = local.workspace_event_enabled ? local.workspace_event_patterns : {}
|
|
66
|
+
|
|
67
|
+
queue_url = aws_sqs_queue.workspace_event[each.key].id
|
|
68
|
+
policy = jsonencode({
|
|
69
|
+
Version = "2012-10-17"
|
|
70
|
+
Statement = [
|
|
71
|
+
{
|
|
72
|
+
Effect = "Allow"
|
|
73
|
+
Principal = {
|
|
74
|
+
Service = "events.amazonaws.com"
|
|
75
|
+
}
|
|
76
|
+
Action = "sqs:SendMessage"
|
|
77
|
+
Resource = aws_sqs_queue.workspace_event[each.key].arn
|
|
78
|
+
Condition = {
|
|
79
|
+
ArnEquals = {
|
|
80
|
+
"aws:SourceArn" = aws_cloudwatch_event_rule.workspace_event[each.key].arn
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
]
|
|
85
|
+
})
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
resource "aws_lambda_event_source_mapping" "workspace_event_dispatcher" {
|
|
89
|
+
for_each = local.workspace_event_enabled ? local.workspace_event_patterns : {}
|
|
90
|
+
|
|
91
|
+
event_source_arn = aws_sqs_queue.workspace_event[each.key].arn
|
|
92
|
+
function_name = aws_lambda_function.handler["workspace-event-dispatcher"].arn
|
|
93
|
+
batch_size = 10
|
|
94
|
+
function_response_types = ["ReportBatchItemFailures"]
|
|
95
|
+
|
|
96
|
+
scaling_config {
|
|
97
|
+
maximum_concurrency = 5
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
resource "aws_iam_role_policy" "lambda_workspace_events_sqs" {
|
|
102
|
+
count = local.workspace_event_enabled ? 1 : 0
|
|
103
|
+
|
|
104
|
+
name = "thinkwork-${var.stage}-lambda-workspace-events-sqs"
|
|
105
|
+
role = aws_iam_role.lambda.id
|
|
106
|
+
|
|
107
|
+
policy = jsonencode({
|
|
108
|
+
Version = "2012-10-17"
|
|
109
|
+
Statement = [
|
|
110
|
+
{
|
|
111
|
+
Effect = "Allow"
|
|
112
|
+
Action = [
|
|
113
|
+
"sqs:ReceiveMessage",
|
|
114
|
+
"sqs:DeleteMessage",
|
|
115
|
+
"sqs:GetQueueAttributes",
|
|
116
|
+
"sqs:ChangeMessageVisibility",
|
|
117
|
+
]
|
|
118
|
+
Resource = concat(
|
|
119
|
+
[for q in aws_sqs_queue.workspace_event : q.arn],
|
|
120
|
+
[for q in aws_sqs_queue.workspace_event_dlq : q.arn],
|
|
121
|
+
)
|
|
122
|
+
},
|
|
123
|
+
]
|
|
124
|
+
})
|
|
125
|
+
}
|