thinkwork-cli 0.12.12 → 0.12.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +42 -38
- package/dist/{api-client-ASJWIG3Z.js → api-client-4VT3FWOH.js} +1 -1
- package/dist/{chunk-JEHV35EU.js → chunk-H7AB42ES.js} +340 -30
- package/dist/cli.js +22123 -9219
- package/dist/commands/enterprise/templates/deploy-repo/.github/workflows/deploy.yml +17 -6
- package/dist/commands/enterprise/templates/deploy-repo/docs/runbook.md +81 -9
- package/dist/commands/enterprise/templates/deploy-repo/scripts/apply-release.mjs +183 -21
- package/dist/commands/enterprise/templates/deploy-repo/scripts/smoke.mjs +1 -2
- package/dist/commands/enterprise/templates/deploy-repo/terraform/main.tf +286 -0
- package/dist/drizzle/0000_petite_marvel_apes.sql +1188 -0
- package/dist/drizzle/0001_milky_surge.sql +103 -0
- package/dist/drizzle/0002_aberrant_mattie_franklin.sql +41 -0
- package/dist/drizzle/0003_exotic_ogun.sql +3 -0
- package/dist/drizzle/0004_glamorous_magneto.sql +2 -0
- package/dist/drizzle/0005_ancient_nocturne.sql +2 -0
- package/dist/drizzle/0006_new_colonel_america.sql +2 -0
- package/dist/drizzle/0007_unique_external_task_id.sql +31 -0
- package/dist/drizzle/0008_external_task_id_column.sql +43 -0
- package/dist/drizzle/0009_evaluations.sql +64 -0
- package/dist/drizzle/0010_eval_agent_template.sql +2 -0
- package/dist/drizzle/0011_eval_run_template.sql +2 -0
- package/dist/drizzle/0012_eval_seed_unique.sql +16 -0
- package/dist/drizzle/0013_motionless_white_queen.sql +140 -0
- package/dist/drizzle/0014_wiki_aggregation.sql +11 -0
- package/dist/drizzle/0015_pg_trgm_alias_title_indexes.sql +9 -0
- package/dist/drizzle/0016_wiki_schema_drops.sql +24 -0
- package/dist/drizzle/0017_wiki_places.sql +46 -0
- package/dist/drizzle/0018_agent_workspace_overlay.sql +26 -0
- package/dist/drizzle/0018_cool_firebird.sql +24 -0
- package/dist/drizzle/0018_skill_runs.sql +84 -0
- package/dist/drizzle/0019_condemned_dragon_man.sql +95 -0
- package/dist/drizzle/0019_webhook_skill_runs.sql +58 -0
- package/dist/drizzle/0020_crazy_the_anarchist.sql +9 -0
- package/dist/drizzle/0020_mutation_idempotency.sql +64 -0
- package/dist/drizzle/0021_crm_work_links.sql +76 -0
- package/dist/drizzle/0021_skill_runs_completion_hmac.sql +33 -0
- package/dist/drizzle/0022_add_billing_tables.sql +70 -0
- package/dist/drizzle/0022_seed_thinkwork_admin_permissions.sql +160 -0
- package/dist/drizzle/0022_stripe_billing_indexes.sql +48 -0
- package/dist/drizzle/0023_tenants_deactivation.sql +27 -0
- package/dist/drizzle/0024_tenant_mcp_admin_keys.sql +63 -0
- package/dist/drizzle/0025_v1_agent_architecture.sql +182 -0
- package/dist/drizzle/0026_thread_turns_add_kind.sql +28 -0
- package/dist/drizzle/0027_capability_catalog_and_manifests.sql +219 -0
- package/dist/drizzle/0028_aws_s3_extension.sql +26 -0
- package/dist/drizzle/0029_collapse_execution_types.sql +42 -0
- package/dist/drizzle/0030_retire_composition_primitives.sql +48 -0
- package/dist/drizzle/0031_thread_cleanup_drops.sql +131 -0
- package/dist/drizzle/0032_add_browser_automation_template_config.sql +24 -0
- package/dist/drizzle/0033_agent_operation_leases.sql +32 -0
- package/dist/drizzle/0034_agent_workspace_events.sql +116 -0
- package/dist/drizzle/0035_workspace_review_decisions.sql +19 -0
- package/dist/drizzle/0036_user_scoped_memory_wiki.sql +152 -0
- package/dist/drizzle/0037_user_profile_operating_model.sql +34 -0
- package/dist/drizzle/0042_agent_runtime_selector.sql +41 -0
- package/dist/drizzle/0043_wiki_search_tsv_tokenization.sql +48 -0
- package/dist/drizzle/0044_add_web_search_template_config.sql +7 -0
- package/dist/drizzle/0045_add_send_email_template_config.sql +7 -0
- package/dist/drizzle/0046_tenant_mcp_context_tools.sql +26 -0
- package/dist/drizzle/0047_add_context_engine_template_config.sql +7 -0
- package/dist/drizzle/0048_tenant_context_provider_settings.sql +22 -0
- package/dist/drizzle/0050_brain_v0_entity_subtype.sql +29 -0
- package/dist/drizzle/0051_brain_v0_tenant_entity_pages.sql +170 -0
- package/dist/drizzle/0052_brain_v0_external_refs.sql +41 -0
- package/dist/drizzle/0053_brain_v0_unresolved_mentions_subtype.sql +48 -0
- package/dist/drizzle/0054_wiki_compile_jobs_input.sql +28 -0
- package/dist/drizzle/0055_routines_stepfunctions_substrate.sql +202 -0
- package/dist/drizzle/0056_routine_step_events_dedup_idx.sql +25 -0
- package/dist/drizzle/0057_archive_legacy_python_routines.sql +36 -0
- package/dist/drizzle/0058_routines_visibility_and_owning_agent.sql +61 -0
- package/dist/drizzle/0061_routine_execution_asl_version_id.sql +29 -0
- package/dist/drizzle/0062_migrate_pi_to_flue.sql +110 -0
- package/dist/drizzle/0063_threads_session_data.sql +23 -0
- package/dist/drizzle/0064_tenant_credentials.sql +65 -0
- package/dist/drizzle/0067_thinkwork_computers_phase_one.sql +174 -0
- package/dist/drizzle/0068_drop_system_workflows_and_activation.sql +115 -0
- package/dist/drizzle/0069_compliance_schema.sql +364 -0
- package/dist/drizzle/0070_compliance_aurora_roles.sql +171 -0
- package/dist/drizzle/0072_threads_computer_ownership.sql +24 -0
- package/dist/drizzle/0073_compliance_tenant_anchor_state.sql +105 -0
- package/dist/drizzle/0074_compliance_event_hash_index.sql +49 -0
- package/dist/drizzle/0075_scheduled_jobs_computer_ownership.sql +27 -0
- package/dist/drizzle/0076_scheduled_jobs_marco_backfill.sql +69 -0
- package/dist/drizzle/0077_computers_primary_agent_id.sql +38 -0
- package/dist/drizzle/0078_tenant_customize_catalog.sql +46 -0
- package/dist/drizzle/0079_seed_tenant_customize_catalog.sql +53 -0
- package/dist/drizzle/0081_routines_catalog_slug.sql +42 -0
- package/dist/drizzle/0082_messages_parts_jsonb.sql +52 -0
- package/dist/drizzle/0083_computer_runbooks.sql +103 -0
- package/dist/drizzle/0084_artifacts_favorited_at.sql +32 -0
- package/dist/drizzle/0085_seed_thinkwork_computer_default_template.sql +46 -0
- package/dist/drizzle/0086_update_default_template_models.sql +19 -0
- package/dist/drizzle/0087_retire_oss_connectors.sql +77 -0
- package/dist/drizzle/0088_compliance_event_types_finance_pilot.sql +37 -0
- package/dist/drizzle/0089_remove_maniflow_eval_seeds.sql +81 -0
- package/dist/drizzle/0089_wiki_schema_extraction.sql +315 -0
- package/dist/drizzle/0090_brain_schema_extraction.sql +274 -0
- package/dist/drizzle/0091_drop_wiki_brain_compat_views.sql +118 -0
- package/dist/drizzle/0092_finish_oss_connector_retirement.sql +97 -0
- package/dist/drizzle/0093_eval_runs_scheduled_job_id.sql +23 -0
- package/dist/drizzle/0094_slack_workspace_app.sql +140 -0
- package/dist/drizzle/0095_eval_runs_computer_id.sql +22 -0
- package/dist/drizzle/0096_true_redteam_eval_seed_cleanup.sql +67 -0
- package/dist/drizzle/0097_shared_computers.sql +191 -0
- package/dist/drizzle/0098_business_ontology.sql +587 -0
- package/dist/drizzle/0099_thread_idle_learning.sql +145 -0
- package/dist/drizzle/0100_ontology_gated_brain_dynamic_subtypes.sql +7 -0
- package/dist/drizzle/0101_ontology_gated_unresolved_mentions_dynamic_subtypes.sql +7 -0
- package/dist/drizzle/0102_wiki_brain_owner_repair.sql +87 -0
- package/dist/drizzle/0103_brain_section_source_trigger_repair.sql +75 -0
- package/dist/drizzle/0104_expand_seed_ontology_for_user_memory.sql +166 -0
- package/dist/drizzle/0105_spaces_domain.sql +349 -0
- package/dist/drizzle/0106_expand_seed_ontology_for_triples.sql +173 -0
- package/dist/drizzle/0106_space_threads_participants.sql +197 -0
- package/dist/drizzle/0107_linked_task_mirror.sql +245 -0
- package/dist/drizzle/0108_message_mentions.sql +95 -0
- package/dist/drizzle/0109_space_owned_threads.sql +217 -0
- package/dist/drizzle/0110_thread_participant_read_state.sql +21 -0
- package/dist/drizzle/0111_agents_tenant_name_unique.sql +38 -0
- package/dist/drizzle/0112_recast_spaces_as_contextual_workrooms.sql +138 -0
- package/dist/drizzle/0113_agents_own_runtime_fields.sql +48 -0
- package/dist/drizzle/0114_migrate_templates_to_agents_and_spaces.sql +361 -0
- package/dist/drizzle/0115_remove_computer_eval_template_dependencies.sql +69 -0
- package/dist/drizzle/0116_backfill_thread_participants_access.sql +126 -0
- package/dist/drizzle/0117_space_access_mode.sql +40 -0
- package/dist/drizzle/0118_normalize_tenant_member_principal_type.sql +41 -0
- package/dist/drizzle/0119_space_knowledge_bases.sql +126 -0
- package/dist/drizzle/0120_space_automations.sql +58 -0
- package/dist/drizzle/0121_drop_computer_runbooks.sql +26 -0
- package/dist/drizzle/0122_space_email_triggers.sql +24 -0
- package/dist/drizzle/0123_single_platform_agent_and_overrides.sql +58 -0
- package/dist/drizzle/0124_thread_turns_finalized_at.sql +17 -0
- package/dist/drizzle/0125_drop_space_agent_assignments.sql +42 -0
- package/dist/drizzle/0126_migrate_flue_to_pi.sql +42 -0
- package/dist/drizzle/0127_runtime_type_observability.sql +28 -0
- package/dist/drizzle/0128_drop_eval_test_cases_agent_id.sql +37 -0
- package/dist/drizzle/0129_drop_code_factory_tables.sql +43 -0
- package/dist/drizzle/0129_eval_results_system_prompt.sql +30 -0
- package/dist/drizzle/0130_drop_teams_and_team_id_columns.sql +54 -0
- package/dist/drizzle/0131_drop_skill_catalog_and_tenant_skills.sql +33 -0
- package/dist/drizzle/0132_drop_computer_tables.sql +31 -0
- package/dist/drizzle/0133_drop_seed_view_tombstones.sql +79 -0
- package/dist/drizzle/0133_thread_turns_system_prompt.sql +22 -0
- package/dist/drizzle/0134_drop_dead_agent_runtime_tables.sql +53 -0
- package/dist/drizzle/0135_native_checklist_linked_tasks.sql +48 -0
- package/dist/drizzle/0136_goal_ledger.sql +55 -0
- package/dist/drizzle/0136_space_email_trigger_status.sql +66 -0
- package/dist/drizzle/0137_thread_participant_pins.sql +25 -0
- package/dist/drizzle/0138_users_cognito_sub.sql +30 -0
- package/dist/drizzle/0139_mobile_turn_client_id.sql +23 -0
- package/dist/drizzle/0140_workspace_folder_names.sql +36 -0
- package/dist/drizzle/0141_eval_runs_desktop_pi_provenance.sql +31 -0
- package/dist/drizzle/0142_pi_only_agent_runtime.sql +61 -0
- package/dist/drizzle/0143_add_web_extract_builtin_config.sql +28 -0
- package/dist/drizzle/0144_skill_catalog_index.sql +40 -0
- package/dist/drizzle/0145_knowledge_graph_thread_ingest.sql +512 -0
- package/dist/drizzle/0146_knowledge_graph_source_scope.sql +413 -0
- package/dist/drizzle/0147_knowledge_graph_scope_trigger_qualification.sql +211 -0
- package/dist/drizzle/0148_user_cost_attribution.sql +171 -0
- package/dist/drizzle/0149_managed_mcp_servers.sql +64 -0
- package/dist/drizzle/0149_user_model_approvals.sql +89 -0
- package/dist/drizzle/0150_bootstrap_first_admin_claim.sql +11 -0
- package/dist/drizzle/0151_managed_deployments.sql +91 -0
- package/dist/drizzle/0152_agent_profiles.sql +81 -0
- package/dist/drizzle/0153_message_mentions_agent_profile.sql +9 -0
- package/dist/drizzle/0154_customer_deployment_sessions.sql +61 -0
- package/dist/drizzle/0155_tenant_model_catalog.sql +152 -0
- package/dist/drizzle/0156_bootstrap_credential_leases.sql +52 -0
- package/dist/drizzle/0157_knowledge_graph_observations_source.sql +79 -0
- package/dist/drizzle/0158_pending_user_questions.sql +80 -0
- package/dist/drizzle/0158_wiki_tenant_scope.sql +38 -0
- package/dist/drizzle/0159_agent_profiles_space_local.sql +49 -0
- package/dist/drizzle/0159_application_plugins.sql +193 -0
- package/dist/drizzle/0159_eval_scoring_version.sql +46 -0
- package/dist/drizzle/0160_compliance_event_types_plugins.sql +37 -0
- package/dist/drizzle/0160_eval_datasets.sql +75 -0
- package/dist/drizzle/0160_eval_results_thread_turn.sql +35 -0
- package/dist/drizzle/0161_eval_run_pinning.sql +54 -0
- package/dist/drizzle/0161_tenant_mcp_servers_plugin_source.sql +62 -0
- package/dist/drizzle/0162_eval_result_override.sql +49 -0
- package/dist/drizzle/0163_eval_replay_tool_allowlist.sql +50 -0
- package/dist/drizzle/0164_eval_replay_tool_override_mode.sql +52 -0
- package/dist/drizzle/0165_plugin_premium_entitlements.sql +153 -0
- package/dist/drizzle/0166_company_brain_substrate_contract.sql +386 -0
- package/dist/drizzle/0167_company_brain_artifact_manifest_runtime.sql +85 -0
- package/dist/drizzle/0168_eval_skill_gate.sql +44 -0
- package/dist/drizzle/0169_release_update_jobs.sql +67 -0
- package/dist/drizzle/0170_email_channel_plugin.sql +291 -0
- package/dist/drizzle/0171_linked_task_external_providers.sql +30 -0
- package/dist/drizzle/0172_email_channel_sendgrid_provider.sql +8 -0
- package/dist/drizzle/0173_auth_provider_resources.sql +83 -0
- package/dist/drizzle/0174_workos_auth_bridges.sql +37 -0
- package/dist/drizzle/0175_workos_auth_sessions.sql +38 -0
- package/dist/drizzle/0176_n8n_agent_step_runs.sql +107 -0
- package/dist/drizzle/0177_workflow_control_plane.sql +281 -0
- package/dist/drizzle/0178_workflow_backfill_existing_routines.sql +525 -0
- package/dist/drizzle/0179_tenant_goal_budget_settings.sql +21 -0
- package/dist/drizzle/0180_skill_drafts.sql +89 -0
- package/dist/drizzle/0181_skill_draft_publish_status.sql +21 -0
- package/dist/drizzle/0182_agent_loops.sql +260 -0
- package/dist/drizzle/0183_okf_artifact_manifests.sql +52 -0
- package/dist/drizzle/0184_skill_catalog_trust_cache.sql +35 -0
- package/dist/drizzle/0185_agent_loop_space.sql +16 -0
- package/dist/drizzle/0186_tenant_mcp_runtime_metadata.sql +10 -0
- package/dist/drizzle/0187_native_work_items.sql +220 -0
- package/dist/drizzle/0188_company_etl_plugin_rename.sql +99 -0
- package/dist/drizzle/0189_trace_cost_substrate.sql +247 -0
- package/dist/drizzle/0190_billing_export_reconciliation.sql +101 -0
- package/dist/drizzle/0191_open_engine_work_item_queue.sql +66 -0
- package/dist/drizzle/0192_work_item_labels.sql +44 -0
- package/dist/drizzle/0193_work_item_documents.sql +31 -0
- package/dist/drizzle/0194_memory_retain_attempts.sql +103 -0
- package/dist/drizzle/0194_work_item_comments.sql +35 -0
- package/dist/drizzle/0195_plugin_app_overlays.sql +45 -0
- package/dist/drizzle/0196_pi_extensions.sql +118 -0
- package/dist/drizzle/0197_eval_profiles.sql +150 -0
- package/dist/drizzle/0198_eval_runs_unstable.sql +27 -0
- package/dist/drizzle/0199_eval_runs_cost_partial.sql +27 -0
- package/dist/drizzle/meta/_journal.json +160 -0
- package/dist/plugins/README.md +162 -0
- package/dist/plugins/catalog/package.json +40 -0
- package/dist/plugins/catalog/scripts/build-catalog.ts +120 -0
- package/dist/plugins/catalog/scripts/generate-plugin-registry.ts +144 -0
- package/dist/plugins/catalog/src/__tests__/build-catalog.test.ts +86 -0
- package/dist/plugins/catalog/src/__tests__/catalog.test.ts +308 -0
- package/dist/plugins/catalog/src/__tests__/contracts.test.ts +861 -0
- package/dist/plugins/catalog/src/__tests__/plugin-package.test.ts +124 -0
- package/dist/plugins/catalog/src/__tests__/plugin-registry.test.ts +120 -0
- package/dist/plugins/catalog/src/catalog.ts +434 -0
- package/dist/plugins/catalog/src/contracts.ts +1498 -0
- package/dist/plugins/catalog/src/index.ts +4 -0
- package/dist/plugins/catalog/src/plugin-package.ts +171 -0
- package/dist/plugins/catalog/src/registry/generated-first-party.ts +76 -0
- package/dist/plugins/catalog/src/registry/index.ts +1 -0
- package/dist/plugins/catalog/tsconfig.json +8 -0
- package/dist/plugins/company-brain/README.md +37 -0
- package/dist/plugins/company-brain/package.json +33 -0
- package/dist/plugins/company-brain/runtime/cognee/Dockerfile +11 -0
- package/dist/plugins/company-brain/smoke/cognee-managed-app-smoke.mjs +458 -0
- package/dist/plugins/company-brain/smoke/cognee-memory-cutover-smoke.mjs +539 -0
- package/dist/plugins/company-brain/smoke/company-brain-context-engine-smoke.mjs +312 -0
- package/dist/plugins/company-brain/smoke/company-brain-operations-smoke.mjs +449 -0
- package/dist/plugins/company-brain/smoke/company-brain-plugin-smoke.mjs +655 -0
- package/dist/plugins/company-brain/smoke/hindsight-memory-isolation-smoke.mjs +474 -0
- package/dist/plugins/company-brain/src/api/cognee-client.ts +896 -0
- package/dist/plugins/company-brain/src/api/cognee-cluster-identity.ts +49 -0
- package/dist/plugins/company-brain/src/api/cognee-memory-scope.ts +84 -0
- package/dist/plugins/company-brain/src/api/context-engine-provider.ts +888 -0
- package/dist/plugins/company-brain/src/api/migration.ts +665 -0
- package/dist/plugins/company-brain/src/deployment/cognee-managed-app.ts +396 -0
- package/dist/plugins/company-brain/src/index.ts +62 -0
- package/dist/plugins/company-brain/src/manifest.ts +112 -0
- package/dist/plugins/company-brain/terraform/cognee/README.md +263 -0
- package/dist/plugins/company-brain/terraform/cognee/main.tf +766 -0
- package/dist/plugins/company-brain/terraform/cognee/outputs.tf +144 -0
- package/dist/plugins/company-brain/terraform/cognee/variables.tf +402 -0
- package/dist/plugins/company-brain/test/api/cognee-client.test.ts +562 -0
- package/dist/plugins/company-brain/test/api/cognee-memory-scope.test.ts +74 -0
- package/dist/plugins/company-brain/test/api/context-engine-provider.test.ts +447 -0
- package/dist/plugins/company-brain/test/api/migration.test.ts +465 -0
- package/dist/plugins/company-brain/test/manifest.test.ts +95 -0
- package/dist/plugins/company-brain/tsconfig.json +8 -0
- package/dist/plugins/company-data/README.md +49 -0
- package/dist/plugins/company-data/package.json +21 -0
- package/dist/plugins/company-data/src/index.ts +30 -0
- package/dist/plugins/company-data/src/manifest.ts +26 -0
- package/dist/plugins/company-data/test/manifest.test.ts +116 -0
- package/dist/plugins/company-data/tsconfig.json +8 -0
- package/dist/plugins/company-etl/README.md +46 -0
- package/dist/plugins/company-etl/package.json +21 -0
- package/dist/plugins/company-etl/src/index.ts +29 -0
- package/dist/plugins/company-etl/src/manifest.ts +26 -0
- package/dist/plugins/company-etl/test/manifest.test.ts +108 -0
- package/dist/plugins/company-etl/tsconfig.json +8 -0
- package/dist/plugins/email-channel/README.md +41 -0
- package/dist/plugins/email-channel/package.json +22 -0
- package/dist/plugins/email-channel/src/index.ts +36 -0
- package/dist/plugins/email-channel/src/manifest.ts +44 -0
- package/dist/plugins/email-channel/src/provider-contract.ts +36 -0
- package/dist/plugins/email-channel/test/manifest.test.ts +119 -0
- package/dist/plugins/email-channel/tsconfig.json +8 -0
- package/dist/plugins/lastmile/README.md +50 -0
- package/dist/plugins/lastmile/package.json +23 -0
- package/dist/plugins/lastmile/smoke/lastmile-plugin-smoke.mjs +661 -0
- package/dist/plugins/lastmile/src/api/tasks-adapter.ts +572 -0
- package/dist/plugins/lastmile/src/discovery.fixture.ts +64 -0
- package/dist/plugins/lastmile/src/index.ts +46 -0
- package/dist/plugins/lastmile/src/manifest.ts +139 -0
- package/dist/plugins/lastmile/test/api/tasks-adapter.test.ts +266 -0
- package/dist/plugins/lastmile/test/discovery.test.ts +88 -0
- package/dist/plugins/lastmile/tsconfig.json +8 -0
- package/dist/plugins/n8n/README.md +201 -0
- package/dist/plugins/n8n/n8n-app/README.md +33 -0
- package/dist/plugins/n8n/n8n-app/package.json +23 -0
- package/dist/plugins/n8n/n8n-app/src/application-config.ts +45 -0
- package/dist/plugins/n8n/n8n-app/src/front-components/thinkwork-workflows.front-component.tsx +970 -0
- package/dist/plugins/n8n/n8n-app/src/lib/n8n-app-data.ts +190 -0
- package/dist/plugins/n8n/n8n-app/src/vite-env.d.ts +7 -0
- package/dist/plugins/n8n/n8n-app/tsconfig.json +15 -0
- package/dist/plugins/n8n/package.json +35 -0
- package/dist/plugins/n8n/runtime/Dockerfile +18 -0
- package/dist/plugins/n8n/runtime/n8n-task-runners.json +14 -0
- package/dist/plugins/n8n/runtime/n8n-task-runners.json.template +14 -0
- package/dist/plugins/n8n/runtime/package-lock.json +13 -0
- package/dist/plugins/n8n/runtime/package.json +7 -0
- package/dist/plugins/n8n/scripts/sync-thinkwork-app.mjs +268 -0
- package/dist/plugins/n8n/smoke/README.md +95 -0
- package/dist/plugins/n8n/smoke/n8n-agent-step-bridge-smoke.mjs +866 -0
- package/dist/plugins/n8n/smoke/n8n-integrated-app-smoke.mjs +262 -0
- package/dist/plugins/n8n/smoke/n8n-managed-app-smoke.mjs +409 -0
- package/dist/plugins/n8n/smoke/n8n-mcp-smoke.mjs +624 -0
- package/dist/plugins/n8n/src/deployment/image-build.ts +172 -0
- package/dist/plugins/n8n/src/deployment/managed-app.ts +429 -0
- package/dist/plugins/n8n/src/index.ts +79 -0
- package/dist/plugins/n8n/src/manifest.ts +403 -0
- package/dist/plugins/n8n/src/package-config.ts +186 -0
- package/dist/plugins/n8n/src/skills/n8n-workflow-operator/SKILL.md +76 -0
- package/dist/plugins/n8n/src/skills/n8n-workflow-operator/references/mcp-tooling.md +40 -0
- package/dist/plugins/n8n/src/skills/n8n-workflow-operator/references/validation-and-handoff.md +40 -0
- package/dist/plugins/n8n/src/skills/n8n-workflow-operator/references/workflow-authoring.md +45 -0
- package/dist/plugins/n8n/terraform/n8n/README.md +113 -0
- package/dist/plugins/n8n/terraform/n8n/main.tf +918 -0
- package/dist/plugins/n8n/terraform/n8n/outputs.tf +124 -0
- package/dist/plugins/n8n/terraform/n8n/scripts/sync-database.py +250 -0
- package/dist/plugins/n8n/terraform/n8n/scripts/test_sync_database.py +55 -0
- package/dist/plugins/n8n/terraform/n8n/variables.tf +354 -0
- package/dist/plugins/n8n/test/image-build.test.ts +118 -0
- package/dist/plugins/n8n/test/integrated-app-contract.test.ts +353 -0
- package/dist/plugins/n8n/test/manifest.test.ts +278 -0
- package/dist/plugins/n8n/test/package-config.test.ts +57 -0
- package/dist/plugins/n8n/tsconfig.json +8 -0
- package/dist/plugins/sendgrid/README.md +30 -0
- package/dist/plugins/sendgrid/package.json +22 -0
- package/dist/plugins/sendgrid/src/index.ts +36 -0
- package/dist/plugins/sendgrid/src/manifest.ts +37 -0
- package/dist/plugins/sendgrid/src/provider-contract.ts +14 -0
- package/dist/plugins/sendgrid/test/manifest.test.ts +80 -0
- package/dist/plugins/sendgrid/tsconfig.json +8 -0
- package/dist/plugins/twenty/README.md +78 -0
- package/dist/plugins/twenty/package.json +27 -0
- package/dist/plugins/twenty/scripts/__tests__/sync-thinkwork-app.test.mjs +67 -0
- package/dist/plugins/twenty/scripts/sync-thinkwork-app.mjs +185 -0
- package/dist/plugins/twenty/scripts/wire-thinkwork-workflow.mjs +658 -0
- package/dist/plugins/twenty/smoke/twenty-managed-app-smoke.mjs +359 -0
- package/dist/plugins/twenty/smoke/twenty-mcp-oauth-smoke.mjs +574 -0
- package/dist/plugins/twenty/src/api/cutover.ts +209 -0
- package/dist/plugins/twenty/src/deployment/managed-app.ts +253 -0
- package/dist/plugins/twenty/src/index.ts +55 -0
- package/dist/plugins/twenty/src/manifest.ts +259 -0
- package/dist/plugins/twenty/terraform/twenty/README.md +97 -0
- package/dist/plugins/twenty/terraform/twenty/main.tf +829 -0
- package/dist/plugins/twenty/terraform/twenty/outputs.tf +79 -0
- package/dist/plugins/twenty/terraform/twenty/variables.tf +268 -0
- package/dist/plugins/twenty/test/api/cutover.test.ts +183 -0
- package/dist/plugins/twenty/test/manifest.test.ts +463 -0
- package/dist/plugins/twenty/tsconfig.json +9 -0
- package/dist/plugins/twenty/twenty-app/.nvmrc +1 -0
- package/dist/plugins/twenty/twenty-app/README.md +148 -0
- package/dist/plugins/twenty/twenty-app/package.json +30 -0
- package/dist/plugins/twenty/twenty-app/src/application-config.ts +44 -0
- package/dist/plugins/twenty/twenty-app/src/constants/universal-identifiers.ts +18 -0
- package/dist/plugins/twenty/twenty-app/src/default-role.ts +24 -0
- package/dist/plugins/twenty/twenty-app/src/front-components/thinkwork-settings.front-component.tsx +299 -0
- package/dist/plugins/twenty/twenty-app/src/logic-functions/thinkwork-webhook.logic-function.ts +354 -0
- package/dist/plugins/twenty/twenty-app/tsconfig.json +14 -0
- package/dist/plugins/twenty/twenty-app/yarn.lock +4144 -0
- package/dist/plugins/workos-auth/package.json +22 -0
- package/dist/plugins/workos-auth/src/index.ts +30 -0
- package/dist/plugins/workos-auth/src/manifest.ts +40 -0
- package/dist/plugins/workos-auth/src/provider-contract.ts +39 -0
- package/dist/plugins/workos-auth/test/manifest.test.ts +94 -0
- package/dist/plugins/workos-auth/tsconfig.json +8 -0
- package/dist/scripts/bootstrap-workspace.sh +162 -0
- package/dist/scripts/post-deploy.sh +290 -0
- package/dist/terraform/examples/greenfield/main.tf +903 -75
- package/dist/terraform/examples/greenfield/terraform.tfvars.example +67 -8
- package/dist/terraform/modules/app/agentcore-code-interpreter/Dockerfile.sandbox-base +2 -2
- package/dist/terraform/modules/app/agentcore-code-interpreter/README.md +8 -9
- package/dist/terraform/modules/app/agentcore-code-interpreter/sandbox/sitecustomize.py +227 -0
- package/dist/terraform/modules/app/agentcore-code-interpreter/sandbox/test_sitecustomize.py +277 -0
- package/dist/terraform/modules/app/agentcore-memory/README.md +6 -6
- package/dist/terraform/modules/app/agentcore-memory/main.tf +1 -1
- package/dist/terraform/modules/app/agentcore-memory/scripts/create_or_find_memory.sh +40 -9
- package/dist/terraform/modules/app/agentcore-pi/README.md +61 -0
- package/dist/terraform/modules/app/agentcore-pi/main.tf +453 -0
- package/dist/terraform/modules/app/agentcore-pi/outputs.tf +38 -0
- package/dist/terraform/modules/app/agentcore-pi/variables.tf +145 -0
- package/dist/terraform/modules/app/agentcore-platform/main.tf +83 -0
- package/dist/terraform/modules/app/agentcore-runtime/main.tf +9 -11
- package/dist/terraform/modules/app/appsync-subscriptions/main.tf +5 -1
- package/dist/terraform/modules/app/customer-domain/main.tf +483 -0
- package/dist/terraform/modules/app/deployment-control-plane/README.md +47 -0
- package/dist/terraform/modules/app/deployment-control-plane/buildspec.yml +24 -0
- package/dist/terraform/modules/app/deployment-control-plane/main.tf +614 -0
- package/dist/terraform/modules/app/deployment-control-plane/outputs.tf +54 -0
- package/dist/terraform/modules/app/deployment-control-plane/runner.py +4720 -0
- package/dist/terraform/modules/app/deployment-control-plane/test_runner_bundle.py +3026 -0
- package/dist/terraform/modules/app/deployment-control-plane/variables.tf +96 -0
- package/dist/terraform/modules/app/hindsight-memory/README.md +25 -23
- package/dist/terraform/modules/app/hindsight-memory/main.tf +26 -2
- package/dist/terraform/modules/app/lambda-api/eval-fanout.tf +17 -50
- package/dist/terraform/modules/app/lambda-api/handlers.tf +1290 -679
- package/dist/terraform/modules/app/lambda-api/iam-grouped.tf +933 -0
- package/dist/terraform/modules/app/lambda-api/main.tf +14 -527
- package/dist/terraform/modules/app/lambda-api/mcp-oauth.tf +3 -19
- package/dist/terraform/modules/app/lambda-api/outputs.tf +50 -6
- package/dist/terraform/modules/app/lambda-api/runtime-config.tf +163 -0
- package/dist/terraform/modules/app/lambda-api/slack-app-secrets.tf +3 -1
- package/dist/terraform/modules/app/lambda-api/stripe-secrets.tf +3 -1
- package/dist/terraform/modules/app/lambda-api/variables.tf +240 -53
- package/dist/terraform/modules/app/lambda-api/workspace-events.tf +2 -25
- package/dist/terraform/modules/app/ses-email/main.tf +143 -30
- package/dist/terraform/modules/app/static-site/main.tf +4 -3
- package/dist/terraform/modules/app/www-dns/main.tf +45 -5
- package/dist/terraform/modules/app/www-dns/outputs.tf +10 -0
- package/dist/terraform/modules/app/www-dns/variables.tf +24 -0
- package/dist/terraform/modules/data/aurora-postgres/main.tf +15 -1
- package/dist/terraform/modules/data/compliance-exports-bucket/main.tf +1 -1
- package/dist/terraform/modules/data/compliance-exports-bucket/variables.tf +6 -0
- package/dist/terraform/modules/foundation/cognito/main.tf +167 -11
- package/dist/terraform/modules/foundation/cognito/outputs.tf +5 -0
- package/dist/terraform/modules/foundation/cognito/variables.tf +110 -0
- package/dist/terraform/modules/foundation/vpc/main.tf +45 -3
- package/dist/terraform/modules/foundation/vpc/outputs.tf +20 -0
- package/dist/terraform/modules/foundation/vpc/variables.tf +18 -0
- package/dist/terraform/modules/thinkwork/README.md +71 -0
- package/dist/terraform/modules/thinkwork/main.tf +1325 -174
- package/dist/terraform/modules/thinkwork/outputs.tf +457 -24
- package/dist/terraform/modules/thinkwork/variables.tf +1169 -93
- package/dist/terraform/schema.graphql +82 -9
- package/dist/workspace-defaults/files/AGENTS.md +344 -0
- package/dist/workspace-defaults/files/CONTEXT.md +8 -0
- package/dist/workspace-defaults/files/GUARDRAILS.md +51 -0
- package/dist/workspace-defaults/files/MEMORY_GUIDE.md +65 -0
- package/dist/workspace-defaults/files/ROUTER.md +24 -0
- package/dist/workspace-defaults/files/SPACE.md +62 -0
- package/dist/workspace-defaults/files/TOOLS.md +65 -0
- package/dist/workspace-defaults/files/USER.md +40 -0
- package/dist/workspace-defaults/files/mcp.json +3 -0
- package/dist/workspace-defaults/files/memory/contacts.md +13 -0
- package/dist/workspace-defaults/files/memory/lessons.md +13 -0
- package/dist/workspace-defaults/files/memory/preferences.md +12 -0
- package/dist/workspace-defaults/files/skills/.gitkeep +1 -0
- package/dist/workspace-defaults/files/skills/artifact-builder/SKILL.md +79 -0
- package/dist/workspace-defaults/files/skills/artifact-builder/references/crm-dashboard.md +166 -0
- package/dist/workspace-defaults/files/skills/automation-loop-designer/SKILL.md +120 -0
- package/dist/workspace-defaults/files/skills/skill-creator/LICENSE.txt +202 -0
- package/dist/workspace-defaults/files/skills/skill-creator/SKILL.md +485 -0
- package/dist/workspace-defaults/files/skills/skill-creator/UPSTREAM.json +124 -0
- package/dist/workspace-defaults/files/skills/skill-creator/agents/analyzer.md +274 -0
- package/dist/workspace-defaults/files/skills/skill-creator/agents/comparator.md +202 -0
- package/dist/workspace-defaults/files/skills/skill-creator/agents/grader.md +223 -0
- package/dist/workspace-defaults/files/skills/skill-creator/assets/eval_review.html +146 -0
- package/dist/workspace-defaults/files/skills/skill-creator/eval-viewer/generate_review.py +471 -0
- package/dist/workspace-defaults/files/skills/skill-creator/eval-viewer/viewer.html +1325 -0
- package/dist/workspace-defaults/files/skills/skill-creator/references/schemas.md +430 -0
- package/dist/workspace-defaults/files/skills/skill-creator/scripts/__init__.py +0 -0
- package/dist/workspace-defaults/files/skills/skill-creator/scripts/aggregate_benchmark.py +401 -0
- package/dist/workspace-defaults/files/skills/skill-creator/scripts/generate_report.py +326 -0
- package/dist/workspace-defaults/files/skills/skill-creator/scripts/improve_description.py +247 -0
- package/dist/workspace-defaults/files/skills/skill-creator/scripts/package_skill.py +136 -0
- package/dist/workspace-defaults/files/skills/skill-creator/scripts/quick_validate.py +103 -0
- package/dist/workspace-defaults/files/skills/skill-creator/scripts/run_eval.py +310 -0
- package/dist/workspace-defaults/files/skills/skill-creator/scripts/run_loop.py +328 -0
- package/dist/workspace-defaults/files/skills/skill-creator/scripts/utils.py +47 -0
- package/package.json +1 -1
- package/dist/terraform/modules/app/agentcore-flue/README.md +0 -58
- package/dist/terraform/modules/app/agentcore-flue/main.tf +0 -323
- package/dist/terraform/modules/app/agentcore-flue/outputs.tf +0 -23
- package/dist/terraform/modules/app/agentcore-flue/variables.tf +0 -97
- package/dist/terraform/modules/app/computer-runtime/README.md +0 -15
- package/dist/terraform/modules/app/computer-runtime/main.tf +0 -406
- package/dist/terraform/modules/app/computer-runtime/outputs.tf +0 -75
- package/dist/terraform/modules/app/computer-runtime/variables.tf +0 -66
|
@@ -10,16 +10,58 @@ locals {
|
|
|
10
10
|
use_local_zips = var.lambda_zips_dir != ""
|
|
11
11
|
eval_fanout_queue_url = local.deploy_lambda_handlers ? aws_sqs_queue.eval_fanout[0].url : ""
|
|
12
12
|
runtime = "nodejs20.x"
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
13
|
+
cognee_env = var.cognee_enabled ? {
|
|
14
|
+
# graphql-http is close to Lambda's 4 KB environment ceiling. Keep Cognee
|
|
15
|
+
# status in one compact value; stable names are derived in the resolver.
|
|
16
|
+
COGNEE = "${var.cognee_backend_mode}|${var.cognee_endpoint}"
|
|
17
|
+
} : {}
|
|
18
|
+
# Twenty managed-app status is DB-served (managed_applications +
|
|
19
|
+
# deployment jobs — plan 2026-06-12-001 U10); the TWENTY config key is
|
|
20
|
+
# retired. Cognee's env-var status projection above is unchanged.
|
|
21
|
+
optional_integration_handler_names = concat(
|
|
22
|
+
var.deployment_control_plane_enabled ? [] : [
|
|
23
|
+
# Host-only onboarding/deployment API. Customer foundations disable the
|
|
24
|
+
# deployment control plane, so release-based customer installs must not
|
|
25
|
+
# require this Lambda artifact or expose these routes.
|
|
26
|
+
"deployment-sessions",
|
|
27
|
+
],
|
|
28
|
+
var.enable_stripe_billing ? [] : [
|
|
29
|
+
"stripe-checkout",
|
|
30
|
+
"stripe-webhook",
|
|
31
|
+
"stripe-portal",
|
|
32
|
+
"stripe-subscription",
|
|
33
|
+
],
|
|
34
|
+
var.enable_slack_workspace_app ? [] : [
|
|
35
|
+
"oauth-authorize",
|
|
36
|
+
"oauth-callback",
|
|
37
|
+
"slack-events",
|
|
38
|
+
"slack-slash-command",
|
|
39
|
+
"slack-interactivity",
|
|
40
|
+
"slack-oauth-install",
|
|
41
|
+
],
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
# Config-class configuration shared by all API handlers. As of plan
|
|
45
|
+
# 2026-06-11-006 U6 these keys live ONLY in the SSM runtime-config
|
|
46
|
+
# document (runtime-config.tf) — they are NOT injected as Lambda env.
|
|
47
|
+
# Code reads them through @thinkwork/runtime-config's getConfig(), whose
|
|
48
|
+
# env-wins merge still honors a hand-set env var as an incident override.
|
|
49
|
+
# The reader-coverage fixture test in apps/cli fails CI if a key in this
|
|
50
|
+
# map still has a direct process.env reader. Identity values (STAGE,
|
|
51
|
+
# AWS_ACCOUNT_ID, NODE_OPTIONS) and secrets (DATABASE_URL,
|
|
52
|
+
# API_AUTH_SECRET, APPSYNC_API_KEY) stay out of this map — identity stays
|
|
53
|
+
# env forever, secrets live in Secrets Manager (R4), never in the String
|
|
54
|
+
# document.
|
|
55
|
+
config_env = merge({
|
|
56
|
+
DATABASE_SECRET_ARN = var.graphql_db_secret_arn
|
|
57
|
+
DATABASE_HOST = var.db_cluster_endpoint
|
|
58
|
+
DATABASE_NAME = var.database_name
|
|
59
|
+
# BUCKET_NAME and USER_POOL_ID were duplicate aliases of WORKSPACE_BUCKET
|
|
60
|
+
# and COGNITO_USER_POOL_ID; GRAPHQL_API_KEY duplicated APPSYNC_API_KEY;
|
|
61
|
+
# THINKWORK_API_SECRET and EMAIL_HMAC_SECRET duplicated API_AUTH_SECRET
|
|
62
|
+
# (~310 serialized bytes total). graphql-http sits at Lambda's hard 4KB
|
|
63
|
+
# env ceiling (#2375) — every reader falls back to the canonical name.
|
|
64
|
+
# Same precedent as the APP_URL/WEB_URL dedupe below.
|
|
23
65
|
COGNITO_USER_POOL_ID = var.user_pool_id
|
|
24
66
|
ADMIN_CLIENT_ID = var.admin_client_id
|
|
25
67
|
MOBILE_CLIENT_ID = var.mobile_client_id
|
|
@@ -29,12 +71,7 @@ locals {
|
|
|
29
71
|
MCP_OAUTH_REVOCATIONS_TABLE = aws_dynamodb_table.mcp_oauth_revocations.name
|
|
30
72
|
COGNITO_APP_CLIENT_IDS = "${var.admin_client_id},${var.mobile_client_id}"
|
|
31
73
|
APPSYNC_ENDPOINT = var.appsync_api_url
|
|
32
|
-
|
|
33
|
-
GRAPHQL_API_KEY = var.appsync_api_key
|
|
34
|
-
API_AUTH_SECRET = var.api_auth_secret
|
|
35
|
-
THINKWORK_API_SECRET = var.api_auth_secret
|
|
36
|
-
EMAIL_HMAC_SECRET = var.api_auth_secret
|
|
37
|
-
THINKWORK_API_URL = "https://${aws_apigatewayv2_api.main.id}.execute-api.${var.region}.amazonaws.com"
|
|
74
|
+
THINKWORK_API_URL = local.api_base_url
|
|
38
75
|
# Comma-separated allowlist of caller emails permitted to invoke
|
|
39
76
|
# operator-gated mutations (updateTenantPolicy, sandbox fixture
|
|
40
77
|
# setup, etc.). Resolved against ctx.auth.email, which is pulled
|
|
@@ -43,32 +80,32 @@ locals {
|
|
|
43
80
|
# packages/api/src/lib/cognito-auth.ts). Empty ⇒ the gate
|
|
44
81
|
# rejects every call, which is the safe default pre-rollout.
|
|
45
82
|
THINKWORK_PLATFORM_OPERATOR_EMAILS = var.platform_operator_emails
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
#
|
|
49
|
-
#
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
#
|
|
61
|
-
#
|
|
62
|
-
#
|
|
63
|
-
#
|
|
64
|
-
#
|
|
65
|
-
|
|
66
|
-
ADMIN_URL
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
83
|
+
AGENTCORE_PI_FUNCTION_NAME = var.agentcore_pi_function_name
|
|
84
|
+
# WORKSPACE_RENDERER_FUNCTION_NAME is derived from the per-stage naming
|
|
85
|
+
# convention by deriveFunctionName("workspace-renderer") — stored
|
|
86
|
+
# nowhere (R7).
|
|
87
|
+
WORKSPACE_BUCKET = var.bucket_name
|
|
88
|
+
HINDSIGHT_ENDPOINT = var.hindsight_endpoint
|
|
89
|
+
AGENTCORE_MEMORY_ID = var.agentcore_memory_id
|
|
90
|
+
MEMORY_ENGINE = var.memory_engine
|
|
91
|
+
# CHAT_AGENT_INVOKE_FN_ARN (~112 serialized bytes) was dropped for the
|
|
92
|
+
# 4KB env ceiling (#2375): getChatAgentInvokeFnArn and managed-dispatch
|
|
93
|
+
# now derive the ARN from the deterministic naming pattern
|
|
94
|
+
# (AWS_REGION + AWS_ACCOUNT_ID + STAGE) before the SSM fallback, so the
|
|
95
|
+
# silent-SSM-failure path that originally motivated the env var stays
|
|
96
|
+
# closed without spending env bytes.
|
|
97
|
+
# APP_URL/WEB_URL were duplicate aliases of ADMIN_URL (all = var.admin_url)
|
|
98
|
+
# and pushed this Lambda's env block past AWS's hard 4KB limit, failing
|
|
99
|
+
# every Terraform apply (UpdateFunctionConfiguration 400 InvalidParameter:
|
|
100
|
+
# environment variables exceeded the 4KB limit). Every reader resolves via
|
|
101
|
+
# ADMIN_URL — stripe-webhook/stripe-portal use `APP_URL || WEB_URL ||
|
|
102
|
+
# ADMIN_URL`, mcp-oauth-client's candidate list includes ADMIN_URL, and
|
|
103
|
+
# deploymentStatus reads ADMIN_URL directly — so the single canonical
|
|
104
|
+
# ADMIN_URL is sufficient. Re-add aliases only after env vars move to SSM.
|
|
105
|
+
ADMIN_URL = var.admin_url
|
|
106
|
+
DOCS_URL = var.docs_url
|
|
107
|
+
APPSYNC_REALTIME_URL = var.appsync_realtime_url
|
|
108
|
+
ECR_REPOSITORY_URL = var.ecr_repository_url
|
|
72
109
|
# Per-user OAuth wiring (Google Workspace today; Microsoft 365 follow-up).
|
|
73
110
|
# Secret ARNs are the indirection; the actual client_id/client_secret
|
|
74
111
|
# values live in Secrets Manager and are fetched by
|
|
@@ -76,56 +113,96 @@ locals {
|
|
|
76
113
|
# OAUTH_CALLBACK_URL is the URL registered with Google/Azure OAuth apps.
|
|
77
114
|
# REDIRECT_SUCCESS_URL is the fallback post-OAuth redirect when the
|
|
78
115
|
# caller doesn't pass a per-request returnUrl (mobile passes thinkwork://).
|
|
79
|
-
GOOGLE_PRODUCTIVITY_OAUTH_SECRET_ARN
|
|
80
|
-
OAUTH_CALLBACK_URL
|
|
81
|
-
REDIRECT_SUCCESS_URL
|
|
82
|
-
COMPANY_BRAIN_SOURCE_AGENT_MODEL_ID
|
|
116
|
+
GOOGLE_PRODUCTIVITY_OAUTH_SECRET_ARN = aws_secretsmanager_secret.oauth_google_productivity.arn
|
|
117
|
+
OAUTH_CALLBACK_URL = "https://${aws_apigatewayv2_api.main.id}.execute-api.${var.region}.amazonaws.com/api/oauth/callback"
|
|
118
|
+
REDIRECT_SUCCESS_URL = var.redirect_success_url
|
|
119
|
+
COMPANY_BRAIN_SOURCE_AGENT_MODEL_ID = var.company_brain_source_agent_model_id
|
|
120
|
+
COMPANY_BRAIN_BACKDOOR_INSTALL_KEY_SECRET_ARN = var.company_brain_backdoor_install_key_secret_arn
|
|
121
|
+
COMPANY_BRAIN_BACKDOOR_INSTALL_KEY_STAGES = var.company_brain_backdoor_install_key_stages
|
|
122
|
+
WWW_URL = var.www_url
|
|
123
|
+
},
|
|
83
124
|
# Stripe billing — see stripe-secrets.tf. The ARN is the indirection;
|
|
84
125
|
# the actual keys live in Secrets Manager and are fetched by
|
|
85
126
|
# packages/api/src/lib/stripe-credentials.ts at cold-start. Price IDs
|
|
86
127
|
# are non-secret per-stage config carried as a plain JSON env var so
|
|
87
128
|
# staging/prod can use different products without a secret rotation.
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
129
|
+
# The whole block is omitted when Stripe is disabled (~315 serialized
|
|
130
|
+
# bytes): the stripe-* handlers are excluded from deployment in that
|
|
131
|
+
# case and stripe-plans.ts defaults to "{}" — see #2375 (4KB env cap).
|
|
132
|
+
var.enable_stripe_billing ? {
|
|
133
|
+
STRIPE_CREDENTIALS_SECRET_ARN = aws_secretsmanager_secret.stripe_api_credentials[0].arn
|
|
134
|
+
STRIPE_PRICE_IDS_JSON = var.stripe_price_ids_json
|
|
135
|
+
STRIPE_CHECKOUT_SUCCESS_URL = "${var.admin_url}/onboarding/welcome?session_id={CHECKOUT_SESSION_ID}"
|
|
136
|
+
STRIPE_CHECKOUT_CANCEL_URL = "${var.www_url}/cloud"
|
|
137
|
+
# Override the welcome email's From: address. Defaults to
|
|
138
|
+
# hello@agents.thinkwork.ai (the already-verified SES inbound domain);
|
|
139
|
+
# set to hello@thinkwork.ai once the bare-apex identity is verified in SES.
|
|
140
|
+
STRIPE_WELCOME_FROM_EMAIL = var.stripe_welcome_from_email
|
|
141
|
+
} : {},
|
|
142
|
+
local.cognee_env,
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
# graphql-http-only config that also belongs in the runtime-config
|
|
146
|
+
# document. Kept out of config_env so the legacy env copies stay scoped
|
|
147
|
+
# to graphql-http (handler_extra_env below) instead of growing every
|
|
148
|
+
# handler's env during the R8 transition window.
|
|
149
|
+
graphql_http_config_env = {
|
|
150
|
+
ROUTINES_EXECUTION_ROLE_ARN = var.routines_execution_role_arn
|
|
151
|
+
ROUTINES_LOG_GROUP_ARN = var.routines_log_group_arn
|
|
152
|
+
# Settings > General starts release updates from the GraphQL API.
|
|
153
|
+
DEPLOYMENT_STATE_MACHINE_ARN = var.deployment_state_machine_arn
|
|
154
|
+
DEPLOYMENT_EVIDENCE_BUCKET = var.deployment_evidence_bucket
|
|
155
|
+
# Cognee user + Space memory captures use explicit add+cognify so accepted
|
|
156
|
+
# documents enter the scoped graph. GraphQL has a 30s Lambda ceiling, so
|
|
157
|
+
# indexing wait is intentionally short/best-effort; callers poll search for
|
|
158
|
+
# eventual retrieval instead of pinning the capture request.
|
|
159
|
+
COGNEE_INGEST_MODE = "add_cognify"
|
|
160
|
+
COGNEE_INDEX_TIMEOUT_MS = "8000"
|
|
161
|
+
COGNEE_INDEX_POLL_MS = "2000"
|
|
162
|
+
# THNK-37 — the GraphQL API is the runtime trust boundary for the
|
|
163
|
+
# GitHub-hosted signed plugin catalog. Browsers keep reading through
|
|
164
|
+
# GraphQL; API verifies the release asset with the trusted public key
|
|
165
|
+
# and persists only verified snapshots in the primary workspace bucket.
|
|
166
|
+
THINKWORK_PLUGIN_CATALOG_SOURCE = "github"
|
|
167
|
+
THINKWORK_PLUGIN_CATALOG_REPOSITORY = "thinkwork-ai/thinkwork"
|
|
168
|
+
THINKWORK_PLUGIN_CATALOG_RELEASE_TAG = "plugin-catalog-main"
|
|
169
|
+
THINKWORK_PLUGIN_CATALOG_ASSET_NAME = "thinkwork-plugin-catalog-main.json"
|
|
170
|
+
THINKWORK_PLUGIN_CATALOG_CACHE_TTL_SECONDS = "300"
|
|
171
|
+
THINKWORK_PLUGIN_CATALOG_USER_AGENT = "thinkwork-api/${var.stage}"
|
|
172
|
+
THINKWORK_PLUGIN_CATALOG_CACHE_BUCKET = var.bucket_name
|
|
173
|
+
THINKWORK_PLUGIN_CATALOG_CACHE_KEY = "system/plugin-catalog/github-release-cache.json"
|
|
174
|
+
THINKWORK_PLUGIN_CATALOG_GITHUB_TOKEN_SECRET_ARN = var.plugin_catalog_github_token_secret_arn
|
|
175
|
+
# Phase 3 U10 — compliance read resolvers (complianceEvents,
|
|
176
|
+
# complianceEvent, complianceEventByHash) connect to Aurora as
|
|
177
|
+
# the compliance_reader role. The existing secrets-manager grant in
|
|
178
|
+
# aws_iam_policy.api_data_plane (iam-grouped.tf) grants
|
|
179
|
+
# secretsmanager:GetSecretValue on the thinkwork/* wildcard, so no
|
|
180
|
+
# new IAM resource is needed.
|
|
181
|
+
COMPLIANCE_READER_SECRET_ARN = var.compliance_reader_secret_arn
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
# Identity env + the secrets still in their one-release transition
|
|
185
|
+
# window (R8). Config-class keys live ONLY in the SSM runtime-config
|
|
186
|
+
# document now — adding a key here is guarded by the identity-allowlist
|
|
187
|
+
# fixture test in apps/cli (R10). Follow-up release: DATABASE_URL,
|
|
188
|
+
# APPSYNC_API_KEY, and API_AUTH_SECRET drop too (readers already resolve
|
|
189
|
+
# via Secrets Manager prefetch when the env copies are absent), bringing
|
|
190
|
+
# every handler under the ≤1KB R1 target.
|
|
191
|
+
common_env = {
|
|
192
|
+
STAGE = var.stage
|
|
193
|
+
DATABASE_URL = "postgresql://${var.db_username}:${urlencode(var.db_password)}@${var.db_cluster_endpoint}:5432/${var.database_name}?sslmode=no-verify"
|
|
194
|
+
APPSYNC_API_KEY = var.appsync_api_key
|
|
195
|
+
API_AUTH_SECRET = var.api_auth_secret
|
|
196
|
+
AWS_ACCOUNT_ID = var.account_id
|
|
197
|
+
NODE_OPTIONS = "--enable-source-maps"
|
|
122
198
|
}
|
|
123
199
|
|
|
124
200
|
# Per-handler env-var overrides. ARNs are constructed from the naming
|
|
125
|
-
# pattern (same trick as
|
|
126
|
-
# introduce a self-referential dependency
|
|
201
|
+
# pattern (same trick as the api-cross-function-invoke statement in
|
|
202
|
+
# iam-grouped.tf) so we don't introduce a self-referential dependency
|
|
203
|
+
# inside the handler for_each.
|
|
127
204
|
slack_handler_env = {
|
|
128
|
-
SLACK_APP_CREDENTIALS_SECRET_ARN = aws_secretsmanager_secret.slack_app_credentials.arn
|
|
205
|
+
SLACK_APP_CREDENTIALS_SECRET_ARN = var.enable_slack_workspace_app ? aws_secretsmanager_secret.slack_app_credentials[0].arn : ""
|
|
129
206
|
}
|
|
130
207
|
|
|
131
208
|
handler_extra_env = {
|
|
@@ -133,10 +210,27 @@ locals {
|
|
|
133
210
|
EXTENSION_PROXY_BACKENDS_JSON = var.extension_proxy_backends_json
|
|
134
211
|
EXTENSION_PROXY_SIGNING_SECRET = var.extension_proxy_signing_secret
|
|
135
212
|
}
|
|
213
|
+
"trace-invocation-reconciler" = {
|
|
214
|
+
BEDROCK_INVOCATION_LOG_GROUP = local.bedrock_invocation_log_group_name
|
|
215
|
+
}
|
|
136
216
|
"job-schedule-manager" = {
|
|
137
217
|
JOB_TRIGGER_ARN = "arn:aws:lambda:${var.region}:${var.account_id}:function:thinkwork-${var.stage}-api-job-trigger"
|
|
138
218
|
JOB_TRIGGER_ROLE_ARN = var.job_scheduler_role_arn
|
|
139
219
|
}
|
|
220
|
+
"deployment-sessions" = {
|
|
221
|
+
THINKWORK_DEPLOYMENT_STATE_MACHINE_ARN = var.deployment_state_machine_arn
|
|
222
|
+
THINKWORK_DEPLOYMENT_EVIDENCE_BUCKET = var.deployment_evidence_bucket
|
|
223
|
+
THINKWORK_RELEASE_VERSION = var.deployment_release_version
|
|
224
|
+
THINKWORK_RELEASE_MANIFEST_URL = var.deployment_release_manifest_url
|
|
225
|
+
THINKWORK_RELEASE_MANIFEST_SHA256 = var.deployment_release_manifest_sha256
|
|
226
|
+
THINKWORK_BOOTSTRAP_LEASE_SECRET_PREFIX = "thinkwork/${var.stage}/deployment-bootstrap-leases"
|
|
227
|
+
THINKWORK_BOOTSTRAP_LEASE_KMS_KEY_ID = var.bootstrap_credential_lease_kms_key_id
|
|
228
|
+
}
|
|
229
|
+
"graphql-http" = {
|
|
230
|
+
THINKWORK_RELEASE_VERSION = var.deployment_release_version
|
|
231
|
+
THINKWORK_RELEASE_MANIFEST_URL = var.deployment_release_manifest_url
|
|
232
|
+
THINKWORK_RELEASE_MANIFEST_SHA256 = var.deployment_release_manifest_sha256
|
|
233
|
+
}
|
|
140
234
|
# Compounding Memory compile Lambda. Any Converse-compatible Bedrock
|
|
141
235
|
# model works; the planner + section-writer cap themselves at ~500
|
|
142
236
|
# records / 25 new pages per invocation so a 480 s timeout covers
|
|
@@ -147,6 +241,10 @@ locals {
|
|
|
147
241
|
BEDROCK_MODEL_ID = var.wiki_compile_model_id
|
|
148
242
|
WIKI_AGGREGATION_PASS_ENABLED = var.wiki_aggregation_pass_enabled
|
|
149
243
|
WIKI_DETERMINISTIC_LINKING_ENABLED = var.wiki_deterministic_linking_enabled
|
|
244
|
+
# Wiki pipeline source dispatch (plan 2026-06-09-004 U10):
|
|
245
|
+
# 'planner' (default, LLM compile) | 'graph' (deterministic
|
|
246
|
+
# graph→wiki materializer over the knowledge-graph mirror).
|
|
247
|
+
WIKI_SOURCE = var.wiki_source
|
|
150
248
|
# Name (not value) of the SecureString SSM parameter that holds the
|
|
151
249
|
# Google Places API key. wiki-compile fetches + caches on cold start.
|
|
152
250
|
# The parameter may contain a placeholder value at apply time — the
|
|
@@ -157,15 +255,15 @@ locals {
|
|
|
157
255
|
BEDROCK_MODEL_ID = var.wiki_compile_model_id
|
|
158
256
|
}
|
|
159
257
|
"wiki-export" = {
|
|
160
|
-
WIKI_EXPORT_BUCKET
|
|
258
|
+
WIKI_EXPORT_BUCKET = aws_s3_bucket.wiki_exports.bucket
|
|
259
|
+
BRAIN_ARTIFACTS_BUCKET = aws_s3_bucket.brain_artifacts.bucket
|
|
260
|
+
}
|
|
261
|
+
"okf-materialize" = {
|
|
262
|
+
BRAIN_ARTIFACTS_BUCKET = aws_s3_bucket.brain_artifacts.bucket
|
|
161
263
|
}
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
# referential dependency on the standalone Lambda resource defined at
|
|
166
|
-
# the bottom of this file.
|
|
167
|
-
"workspace-files" = {
|
|
168
|
-
WORKSPACE_FILES_EFS_FN_ARN = "arn:aws:lambda:${var.region}:${var.account_id}:function:thinkwork-${var.stage}-api-workspace-files-efs"
|
|
264
|
+
"okf-efs-refresh" = {
|
|
265
|
+
BRAIN_ARTIFACTS_BUCKET = aws_s3_bucket.brain_artifacts.bucket
|
|
266
|
+
OKF_EFS_ROOT = var.okf_efs_mount_path
|
|
169
267
|
}
|
|
170
268
|
"oauth-authorize" = local.slack_handler_env
|
|
171
269
|
"oauth-callback" = local.slack_handler_env
|
|
@@ -173,23 +271,6 @@ locals {
|
|
|
173
271
|
"slack-slash-command" = local.slack_handler_env
|
|
174
272
|
"slack-interactivity" = local.slack_handler_env
|
|
175
273
|
"slack-oauth-install" = local.slack_handler_env
|
|
176
|
-
"slack-dispatch" = local.slack_handler_env
|
|
177
|
-
# computer-terminal-start needs the cluster name to scope its
|
|
178
|
-
# ECS ListTasks / DescribeTasks / ExecuteCommand calls.
|
|
179
|
-
"computer-terminal-start" = {
|
|
180
|
-
COMPUTER_RUNTIME_CLUSTER_NAME = var.computer_runtime_cluster_name
|
|
181
|
-
}
|
|
182
|
-
# computer-manager and computer-runtime-reconciler consume ECS/EFS task
|
|
183
|
-
# config from packages/api/src/lib/computers/runtime-control.ts.
|
|
184
|
-
# Scoping the COMPUTER_RUNTIME_* variables here (instead of in
|
|
185
|
-
# local.common_env_vars) keeps the per-Lambda env-var payload under
|
|
186
|
-
# the AWS 4KB hard limit — they were previously dumped into every
|
|
187
|
-
# handler and pushed ~70 Lambdas over quota.
|
|
188
|
-
"computer-manager" = local.computer_runtime_control_env
|
|
189
|
-
"computer-runtime-reconciler" = local.computer_runtime_control_env
|
|
190
|
-
"computer-runtime" = {
|
|
191
|
-
REQUESTER_IDLE_MEMORY_LEARNING_ENABLED = tostring(var.requester_idle_memory_learning_enabled)
|
|
192
|
-
}
|
|
193
274
|
"thread-attachments-finalize" = {
|
|
194
275
|
REQUESTER_IDLE_MEMORY_LEARNING_ENABLED = tostring(var.requester_idle_memory_learning_enabled)
|
|
195
276
|
}
|
|
@@ -201,6 +282,48 @@ locals {
|
|
|
201
282
|
CONTEXT_ENGINE_MEMORY_QUERY_MODE = "reflect"
|
|
202
283
|
CONTEXT_ENGINE_MEMORY_TIMEOUT_MS = "20000"
|
|
203
284
|
}
|
|
285
|
+
# Agent graph access (plan 2026-06-09-004 U8): stage gate for the Pi
|
|
286
|
+
# knowledge_graph_search tool; the per-agent tool policy gates on top.
|
|
287
|
+
"chat-agent-invoke" = {
|
|
288
|
+
KNOWLEDGE_GRAPH_TOOL_ENABLED = tostring(var.knowledge_graph_tool_enabled)
|
|
289
|
+
}
|
|
290
|
+
"memory-retain" = {
|
|
291
|
+
HINDSIGHT_TIMEOUT_MS = "75000"
|
|
292
|
+
}
|
|
293
|
+
# Bedrock KB provisioning. Per-handler (not common_env) so these don't bloat
|
|
294
|
+
# the already-near-4KB graphql-http env. Bedrock's RDS-backed KB needs the
|
|
295
|
+
# cluster ARN + the KB service role (passed at CreateKnowledgeBase time).
|
|
296
|
+
"knowledge-base-manager" = {
|
|
297
|
+
KB_SERVICE_ROLE_ARN = var.kb_service_role_arn
|
|
298
|
+
DATABASE_CLUSTER_ARN = var.db_cluster_arn
|
|
299
|
+
}
|
|
300
|
+
"knowledge-graph-thread-ingest" = {
|
|
301
|
+
COGNEE_ENDPOINT = var.cognee_endpoint
|
|
302
|
+
COGNEE_BACKEND_MODE = var.cognee_backend_mode
|
|
303
|
+
COGNEE_INGEST_MODE = "remember"
|
|
304
|
+
BRAIN_ARTIFACTS_BUCKET = aws_s3_bucket.brain_artifacts.bucket
|
|
305
|
+
}
|
|
306
|
+
# Observations → Knowledge Graph worker (plan 2026-06-09-004 U5).
|
|
307
|
+
# add_cognify pins the incremental ingest path into the stable
|
|
308
|
+
# per-tenant dataset; the promotion-gate classifier reads
|
|
309
|
+
# OBSERVATION_CLASSIFIER_MODEL_ID (Bedrock IAM via the shared
|
|
310
|
+
# lambda_bedrock invoke policy).
|
|
311
|
+
"knowledge-graph-observations-ingest" = {
|
|
312
|
+
COGNEE_ENDPOINT = var.cognee_endpoint
|
|
313
|
+
COGNEE_BACKEND_MODE = var.cognee_backend_mode
|
|
314
|
+
COGNEE_INGEST_MODE = "add_cognify"
|
|
315
|
+
BRAIN_ARTIFACTS_BUCKET = aws_s3_bucket.brain_artifacts.bucket
|
|
316
|
+
OBSERVATION_CLASSIFIER_MODEL_ID = var.observation_classifier_model_id
|
|
317
|
+
# Per-run candidate cap: bounds classifier cost AND keeps each Cognee
|
|
318
|
+
# cognify small enough to index within budget on the single dogfood
|
|
319
|
+
# task; truncated runs self-invoke (Event) to drain the backlog across
|
|
320
|
+
# successive runs. COGNEE_INDEX_TIMEOUT_MS raised well above the default
|
|
321
|
+
# 240s (dogfood indexing of a fresh dataset is slow) but under the 900s
|
|
322
|
+
# Lambda ceiling, leaving room for graph fetch + normalize + snapshot.
|
|
323
|
+
KG_OBS_MAX_CANDIDATES_PER_RUN = var.kg_obs_max_candidates_per_run
|
|
324
|
+
COGNEE_INDEX_TIMEOUT_MS = "700000"
|
|
325
|
+
COGNEE_INDEX_POLL_MS = "7000"
|
|
326
|
+
}
|
|
204
327
|
# routine-task-python (Phase B U6) needs the AgentCore code-interpreter
|
|
205
328
|
# id + the per-stage S3 routine-output bucket. The interpreter id is
|
|
206
329
|
# provisioned by the agentcore-code-interpreter module and exposed via
|
|
@@ -215,64 +338,53 @@ locals {
|
|
|
215
338
|
# graphql-http hosts the createRoutine / publishRoutineVersion / etc.
|
|
216
339
|
# resolvers (Phase B U7) AND the routine-approval-bridge (Phase B
|
|
217
340
|
# U8) which invokes routine-resume via the AWS SDK.
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
ROUTINE_RESUME_FUNCTION_NAME = "thinkwork-${var.stage}-api-routine-resume"
|
|
226
|
-
# triggerRoutineRun seeds this into the SFN execution input so the
|
|
227
|
-
# inbox_approval recipe Task can find the callback Lambda via
|
|
228
|
-
# $$.Execution.Input.inboxApprovalFunctionName.
|
|
229
|
-
ROUTINE_APPROVAL_CALLBACK_FUNCTION_NAME = "thinkwork-${var.stage}-api-routine-approval-callback"
|
|
230
|
-
EMAIL_SEND_FUNCTION_NAME = "thinkwork-${var.stage}-api-email-send"
|
|
231
|
-
ROUTINE_TASK_PYTHON_FUNCTION_NAME = "thinkwork-${var.stage}-api-routine-task-python"
|
|
232
|
-
ADMIN_OPS_MCP_FUNCTION_NAME = "thinkwork-${var.stage}-api-admin-ops-mcp"
|
|
233
|
-
SLACK_SEND_FUNCTION_NAME = "thinkwork-${var.stage}-api-slack-send"
|
|
234
|
-
# requester idle memory learning defaults on in API code so this
|
|
235
|
-
# env-heavy Lambda can stay below AWS's 4 KB environment limit.
|
|
236
|
-
# Phase 3 U10 — compliance read resolvers (complianceEvents,
|
|
237
|
-
# complianceEvent, complianceEventByHash) connect to Aurora as
|
|
238
|
-
# the compliance_reader role. The existing lambda_secrets policy
|
|
239
|
-
# in main.tf grants secretsmanager:GetSecretValue on the
|
|
240
|
-
# thinkwork/* wildcard, so no new IAM resource is needed.
|
|
241
|
-
COMPLIANCE_READER_SECRET_ARN = var.compliance_reader_secret_arn
|
|
242
|
-
# Phase 3 U11.U2 — createComplianceExport mutation dispatches a
|
|
243
|
-
# jobId to a known-name SQS queue. We do NOT pass the queue URL
|
|
244
|
-
# as an env var here: graphql-http's env block is already at the
|
|
245
|
-
# AWS 4 KB ceiling, and adding another URL pushed the deploy over
|
|
246
|
-
# the limit. The mutation derives the URL from STAGE + AWS_REGION
|
|
247
|
-
# + AWS_ACCOUNT_ID, which the Lambda already has. The runner
|
|
248
|
-
# Lambda (separate function below) keeps an explicit
|
|
249
|
-
# COMPLIANCE_EXPORTS_QUEUE_URL because its env is small.
|
|
250
|
-
}
|
|
341
|
+
# graphql-http's former env extras now ride the SSM runtime-config
|
|
342
|
+
# document (local.graphql_http_config_env feeds the document body in
|
|
343
|
+
# runtime-config.tf). The thinkwork-<stage>-api-* function names the
|
|
344
|
+
# routines bridge/dispatch paths use are derived from STAGE at call
|
|
345
|
+
# time (runtimeFunctionName/deriveFunctionName — R7), and the
|
|
346
|
+
# compliance-export queue URL is derived from STAGE + AWS_REGION +
|
|
347
|
+
# AWS_ACCOUNT_ID, so none of them are stored anywhere.
|
|
251
348
|
# U2 eval fan-out substrate. eval-runner does not dispatch to this
|
|
252
349
|
# queue until U3; eval-worker is a throwing inert stub that redrives
|
|
253
350
|
# accidental traffic to the DLQ.
|
|
254
351
|
"eval-runner" = {
|
|
255
352
|
EVAL_FANOUT_QUEUE_URL = local.eval_fanout_queue_url
|
|
256
353
|
EVAL_DIRECT_AGENTCORE_MESSAGE_SHARDS = "20"
|
|
354
|
+
# SSM parameter name for the Pi Bedrock AgentCore Runtime ID. deploy.yml's
|
|
355
|
+
# runtime update job writes this in `update-agentcore-runtime-image.sh`;
|
|
356
|
+
# eval-runner reads it via `loadRuntimeId(runtimeType)`.
|
|
357
|
+
AGENTCORE_RUNTIME_SSM_PI = "/thinkwork/${var.stage}/agentcore/runtime-id-pi"
|
|
257
358
|
}
|
|
258
359
|
"eval-worker" = {
|
|
259
360
|
EVAL_FANOUT_QUEUE_URL = local.eval_fanout_queue_url
|
|
260
361
|
EVAL_AGENTCORE_EVALUATORS = "disabled"
|
|
362
|
+
# Mirrors the fan-out queue's redrive maxReceiveCount (same local in
|
|
363
|
+
# eval-fanout.tf — no drift possible) so the worker can detect the
|
|
364
|
+
# final SQS receive and record error/throttle instead of letting the
|
|
365
|
+
# case vanish into the DLQ without a result row.
|
|
366
|
+
EVAL_FANOUT_MAX_RECEIVE_COUNT = tostring(local.eval_fanout_max_receive_count)
|
|
367
|
+
# Enables the real Bedrock Converse llm-rubric judge (U12). Without
|
|
368
|
+
# this the worker passes no judge and non-refusal quality rubrics
|
|
369
|
+
# fall back to a heuristic that can never honestly score them — the
|
|
370
|
+
# vacuous-pass trust bug. EVAL_JUDGE_MODEL_ID matches the default in
|
|
371
|
+
# in-house.ts; the api-ai IAM policy already grants
|
|
372
|
+
# bedrock:InvokeModel(+WithResponseStream) on inference-profile/*,
|
|
373
|
+
# which authorizes Converse with this profile ID.
|
|
374
|
+
EVAL_LLM_JUDGE = "1"
|
|
375
|
+
EVAL_JUDGE_MODEL_ID = "us.anthropic.claude-haiku-4-5-20251001-v1:0"
|
|
261
376
|
}
|
|
262
|
-
#
|
|
263
|
-
#
|
|
264
|
-
#
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
ROUTINE_APPROVAL_CALLBACK_FUNCTION_NAME = "thinkwork-${var.stage}-api-routine-approval-callback"
|
|
270
|
-
EMAIL_SEND_FUNCTION_NAME = "thinkwork-${var.stage}-api-email-send"
|
|
271
|
-
ROUTINE_TASK_PYTHON_FUNCTION_NAME = "thinkwork-${var.stage}-api-routine-task-python"
|
|
272
|
-
ADMIN_OPS_MCP_FUNCTION_NAME = "thinkwork-${var.stage}-api-admin-ops-mcp"
|
|
273
|
-
SLACK_SEND_FUNCTION_NAME = "thinkwork-${var.stage}-api-slack-send"
|
|
274
|
-
THREAD_IDLE_MEMORY_LEARNING_FUNCTION_NAME = "thinkwork-${var.stage}-api-thread-idle-memory-learning"
|
|
377
|
+
# THNK-74 U4 — optional AWS billing export importer. Missing bucket/key is
|
|
378
|
+
# a healthy no-op so stages can ship the reconciler before CUR/Data Export
|
|
379
|
+
# delivery is configured out-of-band in the AWS billing account.
|
|
380
|
+
"cost-bill-reconciler" = {
|
|
381
|
+
BILLING_EXPORT_BUCKET = var.billing_export_bucket_name
|
|
382
|
+
BILLING_EXPORT_MANIFEST_KEY = var.billing_export_manifest_key
|
|
383
|
+
BILLING_RECONCILIATION_TOLERANCE_USD = tostring(var.billing_reconciliation_tolerance_usd)
|
|
275
384
|
}
|
|
385
|
+
# job-trigger's thinkwork-<stage>-api-* worker function names are
|
|
386
|
+
# derived from STAGE at call time (runtimeFunctionName — R7), and
|
|
387
|
+
# AWS_ACCOUNT_ID already rides common_env, so it needs no extras.
|
|
276
388
|
# Phase 3 U4 Compliance outbox drainer.
|
|
277
389
|
# Connects to Aurora as the compliance_drainer role (provisioned in
|
|
278
390
|
# U2). The DATABASE_SECRET_ARN-style indirection is via
|
|
@@ -284,16 +396,86 @@ locals {
|
|
|
284
396
|
}
|
|
285
397
|
}
|
|
286
398
|
|
|
399
|
+
resource "aws_lambda_function" "skill_trust_runner" {
|
|
400
|
+
# Gated on the static ecr_repository_provisioned flag: the repository URL is
|
|
401
|
+
# an apply-time-unknown attribute in a fresh account, and count cannot
|
|
402
|
+
# depend on it ("Invalid count argument" — THINK-118 harness cycle 4).
|
|
403
|
+
count = local.deploy_lambda_handlers && var.ecr_repository_provisioned ? 1 : 0
|
|
404
|
+
|
|
405
|
+
function_name = "thinkwork-${var.stage}-skill-trust-runner"
|
|
406
|
+
role = aws_iam_role.lambda.arn
|
|
407
|
+
package_type = "Image"
|
|
408
|
+
image_uri = "${var.ecr_repository_url}:skill-trust-runner-latest"
|
|
409
|
+
timeout = 60
|
|
410
|
+
memory_size = 1024
|
|
411
|
+
architectures = ["x86_64"]
|
|
412
|
+
|
|
413
|
+
environment {
|
|
414
|
+
variables = {
|
|
415
|
+
SKILLSPECTOR_LOG_LEVEL = "WARNING"
|
|
416
|
+
SKILLSPECTOR_TIMEOUT_SECONDS = "45"
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
tags = {
|
|
421
|
+
Name = "thinkwork-${var.stage}-skill-trust-runner"
|
|
422
|
+
Handler = "skill-trust-runner"
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
|
|
287
426
|
# ---------------------------------------------------------------------------
|
|
288
427
|
# Helper: creates Lambda functions from a local zip directory or release S3 keys
|
|
289
428
|
# ---------------------------------------------------------------------------
|
|
290
429
|
|
|
291
430
|
resource "aws_lambda_function" "handler" {
|
|
292
|
-
for_each = local.deploy_lambda_handlers ? toset([
|
|
431
|
+
for_each = local.deploy_lambda_handlers ? setsubtract(toset([
|
|
293
432
|
"graphql-http",
|
|
294
433
|
"chat-agent-invoke",
|
|
434
|
+
# Mobile agent harness: cloud Bedrock Converse proxy + completed-turn
|
|
435
|
+
# persistence. Routes for these live in local.api_routes; the function
|
|
436
|
+
# names must also be listed here (this set is the for_each source for
|
|
437
|
+
# aws_lambda_function.handler, NOT derived from api_routes).
|
|
438
|
+
"model-converse",
|
|
439
|
+
"record-turn",
|
|
440
|
+
"mobile-turn-session",
|
|
441
|
+
# Mobile local Pi built-in tools. These are ThinkWork platform tools, not
|
|
442
|
+
# MCP connector tools.
|
|
443
|
+
"mobile-tools",
|
|
444
|
+
# Agent-visible task status mutation tool. Service and first-party callers
|
|
445
|
+
# land here so linked_tasks remains database-authoritative.
|
|
446
|
+
"task-status-tool",
|
|
447
|
+
# Mobile agent harness MCP proxy. tools/list + tools/call routes live in
|
|
448
|
+
# local.api_routes; the function name must also be listed here (this set
|
|
449
|
+
# is the for_each source for aws_lambda_function.handler).
|
|
450
|
+
"mcp-proxy",
|
|
451
|
+
# Client Engagement app API. Calls Twenty REST API directly server-side;
|
|
452
|
+
# it is not backed by ThinkWork GraphQL or the agent MCP runtime.
|
|
453
|
+
"twenty-client-engagement",
|
|
454
|
+
# Desktop-local Pi tombstone endpoints. Kept temporarily so old packaged
|
|
455
|
+
# desktop clients receive a stable 410 while all supported Pi execution
|
|
456
|
+
# routes through managed AgentCore.
|
|
457
|
+
"desktop-runtime-session",
|
|
458
|
+
"desktop-workspace-prewarm",
|
|
459
|
+
"managed-delegation",
|
|
460
|
+
"desktop-eval-runs",
|
|
461
|
+
# chat-agent-finalize — POST /api/threads/{threadId}/finalize. The
|
|
462
|
+
# AgentCore runtime POSTs here at end-of-turn so the post-AgentCore
|
|
463
|
+
# bookkeeping (cost recording, message insert, AppSync notify,
|
|
464
|
+
# computer-task completion, memory retain dispatch) can run without
|
|
465
|
+
# chat-agent-invoke holding a Lambda open for the full turn duration.
|
|
466
|
+
# Bearer API_AUTH_SECRET. Idempotent on thread_turns.finalized_at
|
|
467
|
+
# (migration 0123). Plan: 2026-05-22-006.
|
|
468
|
+
"chat-agent-finalize",
|
|
469
|
+
# chat-agent-activity — POST /api/threads/{threadId}/activity. The Pi
|
|
470
|
+
# runtime POSTs here mid-turn so live agent activity (tool/skill/phase
|
|
471
|
+
# steps, coalesced text deltas) streams to the Spaces thread via
|
|
472
|
+
# thread_turn_events + the onThreadTurnStep AppSync subscription.
|
|
473
|
+
# Bearer API_AUTH_SECRET, best-effort (never fails the turn).
|
|
474
|
+
# Plan: 2026-06-03-001.
|
|
475
|
+
"chat-agent-activity",
|
|
295
476
|
"wakeup-processor",
|
|
296
477
|
"workspace-event-dispatcher",
|
|
478
|
+
"workspace-renderer",
|
|
297
479
|
"agents",
|
|
298
480
|
"agent-actions",
|
|
299
481
|
"messages",
|
|
@@ -304,10 +486,11 @@ resource "aws_lambda_function" "handler" {
|
|
|
304
486
|
"stripe-webhook",
|
|
305
487
|
"stripe-portal",
|
|
306
488
|
"stripe-subscription",
|
|
489
|
+
"deployment-sessions",
|
|
307
490
|
"auth-me",
|
|
491
|
+
"public-auth-options",
|
|
492
|
+
"workos-auth",
|
|
308
493
|
"extension-proxy",
|
|
309
|
-
"teams",
|
|
310
|
-
"team-members",
|
|
311
494
|
"tenants",
|
|
312
495
|
"users",
|
|
313
496
|
"invites",
|
|
@@ -315,6 +498,7 @@ resource "aws_lambda_function" "handler" {
|
|
|
315
498
|
"mcp-oauth",
|
|
316
499
|
"mcp-user-memory",
|
|
317
500
|
"mcp-context-engine",
|
|
501
|
+
"mcp-open-engine",
|
|
318
502
|
"activity",
|
|
319
503
|
"routines",
|
|
320
504
|
"budgets",
|
|
@@ -326,6 +510,8 @@ resource "aws_lambda_function" "handler" {
|
|
|
326
510
|
"job-trigger",
|
|
327
511
|
"routine-task-weather-email",
|
|
328
512
|
"webhooks",
|
|
513
|
+
"n8n-agent-step-bridge",
|
|
514
|
+
"n8n-agent-step-expirer",
|
|
329
515
|
"webhooks-admin",
|
|
330
516
|
"webhook-deliveries-cleanup",
|
|
331
517
|
"skill-runs-reconciler",
|
|
@@ -333,45 +519,48 @@ resource "aws_lambda_function" "handler" {
|
|
|
333
519
|
"webhook-crm-opportunity",
|
|
334
520
|
"webhook-task-event",
|
|
335
521
|
"workspace-files",
|
|
522
|
+
# Workspace source fetch authorization (dynamic workspace plan
|
|
523
|
+
# 2026-06-12-002 U4). Bearer API_AUTH_SECRET + x-tenant-id; the runtime
|
|
524
|
+
# fetch tool authorizes here, then downloads the returned S3 keys itself.
|
|
525
|
+
"workspace-fetch-source",
|
|
336
526
|
"knowledge-base-manager",
|
|
337
527
|
"knowledge-base-files",
|
|
338
528
|
"email-send",
|
|
339
529
|
"email-inbound",
|
|
530
|
+
"email-provider-webhook",
|
|
531
|
+
"email-readiness-probe",
|
|
340
532
|
"slack-events",
|
|
341
533
|
"slack-slash-command",
|
|
342
534
|
"slack-interactivity",
|
|
343
535
|
"slack-oauth-install",
|
|
344
|
-
"slack-dispatch",
|
|
345
536
|
"github-app",
|
|
346
|
-
"github-repos",
|
|
347
537
|
"memory",
|
|
348
538
|
"memory-retain",
|
|
349
539
|
"wiki-compile",
|
|
540
|
+
"knowledge-graph-thread-ingest",
|
|
541
|
+
"knowledge-graph-observations-ingest",
|
|
350
542
|
"ontology-scan",
|
|
351
543
|
"ontology-reprocess",
|
|
352
544
|
"wiki-lint",
|
|
353
545
|
"wiki-export",
|
|
546
|
+
"okf-materialize",
|
|
547
|
+
"okf-efs-refresh",
|
|
354
548
|
"wiki-bootstrap-import",
|
|
355
549
|
"artifact-deliver",
|
|
356
550
|
"recipe-refresh",
|
|
357
551
|
"agent-skills-list",
|
|
358
552
|
"bootstrap-workspaces",
|
|
359
|
-
"migrate-agents-to-computers",
|
|
360
|
-
"computer-runtime",
|
|
361
|
-
"computer-manager",
|
|
362
|
-
"computer-runtime-reconciler",
|
|
363
|
-
# Admin Terminal tab — POST /api/computers/{computerId}/terminal/start.
|
|
364
|
-
# Returns the SSM Session Manager session envelope (sessionId,
|
|
365
|
-
# streamUrl, tokenValue) so the browser can open a direct WebSocket
|
|
366
|
-
# to ssmmessages. Plan:
|
|
367
|
-
# docs/plans/2026-05-13-004-feat-computer-terminal-ecs-exec-plan.md.
|
|
368
|
-
"computer-terminal-start",
|
|
369
|
-
"code-factory",
|
|
370
553
|
"eval-runner",
|
|
371
554
|
"eval-worker",
|
|
372
555
|
"eval-runs-reconciler",
|
|
556
|
+
# THNK-74 U4 — imports AWS Data Exports/CUR bill evidence and reconciles
|
|
557
|
+
# aggregate spend against ThinkWork accounting rows.
|
|
558
|
+
"cost-bill-reconciler",
|
|
559
|
+
# THNK-74 U3 — reconciles runtime-reported model usage against Bedrock
|
|
560
|
+
# model invocation logs and appends invocation-scope trace ledger facts.
|
|
561
|
+
"trace-invocation-reconciler",
|
|
373
562
|
# AgentCore Code Sandbox narrow REST endpoints (plan Unit 10 + Unit 11).
|
|
374
|
-
# Both are service-endpoint shape: the
|
|
563
|
+
# Both are service-endpoint shape: the runtime POSTs with
|
|
375
564
|
# Bearer API_AUTH_SECRET. No GraphQL resolver involvement, no extra IAM.
|
|
376
565
|
"sandbox-quota-check",
|
|
377
566
|
"sandbox-invocation-log",
|
|
@@ -411,12 +600,12 @@ resource "aws_lambda_function" "handler" {
|
|
|
411
600
|
"routine-execution-callback",
|
|
412
601
|
# Skill-run dispatcher runtime-config fetch (plan
|
|
413
602
|
# docs/plans/2026-04-24-008-feat-skill-run-dispatcher-plan.md §U1). The
|
|
414
|
-
#
|
|
415
|
-
#
|
|
416
|
-
#
|
|
603
|
+
# runtime skill dispatch calls this with Bearer API_AUTH_SECRET to pull
|
|
604
|
+
# the agent's template + skills + MCP + KBs before building the headless
|
|
605
|
+
# agent turn.
|
|
417
606
|
"agents-runtime-config",
|
|
418
607
|
# Admin-Ops MCP — JSON-RPC endpoint at POST /mcp/admin, exposes the
|
|
419
|
-
# @thinkwork/admin-ops package as MCP tools for
|
|
608
|
+
# @thinkwork/admin-ops package as MCP tools for managed agents.
|
|
420
609
|
"admin-ops-mcp",
|
|
421
610
|
# MCP admin key management — per-tenant Bearer tokens for admin-ops.
|
|
422
611
|
# Admin-ops-mcp authenticates incoming tokens by sha256-hash lookup
|
|
@@ -425,7 +614,8 @@ resource "aws_lambda_function" "handler" {
|
|
|
425
614
|
# One-shot tenant provisioning: mints a tkm_ key + stores in Secrets
|
|
426
615
|
# Manager at thinkwork/<stage>/mcp/<tenantId>/admin-ops + upserts
|
|
427
616
|
# tenant_mcp_servers. SM IAM is already granted on thinkwork/* by
|
|
428
|
-
#
|
|
617
|
+
# the secrets-manager grant in aws_iam_policy.api_data_plane
|
|
618
|
+
# (iam-grouped.tf; Create/Update/Get).
|
|
429
619
|
"mcp-admin-provision",
|
|
430
620
|
# Plugin-installed MCP server admin approval (plan §U11, SI-5). Cognito
|
|
431
621
|
# JWT admin caller → approve/reject. Approve computes url_hash =
|
|
@@ -435,10 +625,6 @@ resource "aws_lambda_function" "handler" {
|
|
|
435
625
|
# Daily sweeper: auto-rejects MCP servers pending > 30 days. Triggered
|
|
436
626
|
# by EventBridge schedule (mcp-approval-sweeper-daily).
|
|
437
627
|
"mcp-approval-sweeper",
|
|
438
|
-
# Plugin upload REST handler (plan §U10). Four routes:
|
|
439
|
-
# POST /api/plugins/presign + /upload, GET /api/plugins (+ /:uploadId).
|
|
440
|
-
# Cognito JWT; admin-role gated. Needs WORKSPACE_BUCKET env for S3.
|
|
441
|
-
"plugin-upload",
|
|
442
628
|
# Finance pilot U2 — thread-attachment upload (presign + finalize).
|
|
443
629
|
# presign issues a 5-min PUT URL the end-user client uses to push
|
|
444
630
|
# Excel/CSV bytes directly to S3; finalize sniffs magic bytes, scans
|
|
@@ -458,20 +644,17 @@ resource "aws_lambda_function" "handler" {
|
|
|
458
644
|
# or GitHub ref and the handler normalizes vendor folder layouts into
|
|
459
645
|
# the agent workspace.
|
|
460
646
|
"folder-bundle-import",
|
|
461
|
-
#
|
|
462
|
-
#
|
|
463
|
-
"plugin-staging-sweeper",
|
|
464
|
-
# Resolved Capability Manifest write endpoint (plan §U15). Strands
|
|
465
|
-
# container POSTs one row per agent-session-start. Shared
|
|
647
|
+
# Resolved Capability Manifest write endpoint (plan §U15). The runtime
|
|
648
|
+
# POSTs one row per agent-session-start. Shared
|
|
466
649
|
# API_AUTH_SECRET bearer (runtime→API; no tenant OAuth).
|
|
467
650
|
"manifest-log",
|
|
468
|
-
# SI-7 catalog-list read endpoint (plan §U15 pt 3/3).
|
|
469
|
-
#
|
|
651
|
+
# SI-7 catalog-list read endpoint (plan §U15 pt 3/3). The runtime
|
|
652
|
+
# fetches the allowed builtin-tool slug set once per
|
|
470
653
|
# session-start + feature-flag-gated enforcement filter drops
|
|
471
654
|
# catalog-missing tools before Agent(tools=...). Shared
|
|
472
655
|
# API_AUTH_SECRET bearer.
|
|
473
656
|
"capability-catalog-list",
|
|
474
|
-
# Brain v0 narrow write endpoint.
|
|
657
|
+
# Brain v0 narrow write endpoint. Runtime callers use
|
|
475
658
|
# Bearer API_AUTH_SECRET; GraphQL remains user/admin-facing only.
|
|
476
659
|
"brain-agent-write",
|
|
477
660
|
# Phase 3 U4 of the Compliance audit-event log
|
|
@@ -482,10 +665,9 @@ resource "aws_lambda_function" "handler" {
|
|
|
482
665
|
# U2). EventBridge rate(1 minute) schedule + DLQ + MaxRetryAttempts=0
|
|
483
666
|
# (defined in dedicated resources below).
|
|
484
667
|
"compliance-outbox-drainer",
|
|
485
|
-
# Phase 3 U6 of the Compliance audit-event log
|
|
486
|
-
# (docs/plans/2026-05-07-007-feat-compliance-u6-strands-emit-path-plan.md).
|
|
668
|
+
# Phase 3 U6 of the Compliance audit-event log: runtime REST emit path.
|
|
487
669
|
# Cross-runtime emit endpoint POST /api/compliance/events — Bearer
|
|
488
|
-
# API_AUTH_SECRET,
|
|
670
|
+
# API_AUTH_SECRET, runtime clients post here with a
|
|
489
671
|
# client-supplied UUIDv7 event_id for idempotency. Connects to
|
|
490
672
|
# Aurora via the master DATABASE_SECRET_ARN like every other narrow
|
|
491
673
|
# handler (compliance_writer role is reserved for future hardening).
|
|
@@ -498,12 +680,24 @@ resource "aws_lambda_function" "handler" {
|
|
|
498
680
|
# 60+ unrelated handlers. Pre-merge step: `terraform state mv`
|
|
499
681
|
# the existing handler["compliance-anchor-watchdog"] address to the
|
|
500
682
|
# new standalone resource (see U8b plan operator-step section).
|
|
501
|
-
]) : toset([])
|
|
683
|
+
]), toset(local.optional_integration_handler_names)) : toset([])
|
|
502
684
|
|
|
503
685
|
function_name = "thinkwork-${var.stage}-api-${each.key}"
|
|
504
686
|
role = aws_iam_role.lambda.arn
|
|
505
687
|
handler = "index.handler"
|
|
506
688
|
runtime = local.runtime
|
|
689
|
+
# Parameters and Secrets extension: container-local cache for the SSM
|
|
690
|
+
# runtime-config document + Secrets Manager reads (runtime-config.tf).
|
|
691
|
+
layers = local.api_handler_layers
|
|
692
|
+
|
|
693
|
+
# The runtime-config document must exist before any function loses its
|
|
694
|
+
# env copies, or a mid-apply cold start could cache an empty document
|
|
695
|
+
# for a TTL window. Same reasoning for the platform secrets.
|
|
696
|
+
depends_on = [
|
|
697
|
+
aws_ssm_parameter.runtime_config,
|
|
698
|
+
aws_secretsmanager_secret_version.api_auth,
|
|
699
|
+
aws_secretsmanager_secret_version.appsync_api_key,
|
|
700
|
+
]
|
|
507
701
|
# eval-runner walks every test case sequentially, invoking an agent +
|
|
508
702
|
# waiting up to 2 min for spans to propagate per test, so a 10-test run
|
|
509
703
|
# can easily exceed the 30 s default. 900 s covers ~5-15 min sweeps.
|
|
@@ -513,8 +707,12 @@ resource "aws_lambda_function" "handler" {
|
|
|
513
707
|
# routine-task-python wraps a 300s sandbox session and needs headroom
|
|
514
708
|
# for the Start/Invoke/Stop/S3-offload round trip; 360s leaves ~60s
|
|
515
709
|
# for AWS-call setup and offload after the sandbox's own ceiling.
|
|
516
|
-
|
|
517
|
-
|
|
710
|
+
# chat-agent-invoke is now the SETUP phase only (plan 2026-05-22-006 U3):
|
|
711
|
+
# validates the agent, builds the AgentCore invoke payload, dispatches
|
|
712
|
+
# Event-mode, and returns. Setup is ~5s in practice; 60s gives 12×
|
|
713
|
+
# headroom for transient slowness.
|
|
714
|
+
timeout = each.key == "wakeup-processor" ? 300 : each.key == "chat-agent-invoke" ? 60 : each.key == "chat-agent-finalize" ? 60 : each.key == "workspace-event-dispatcher" ? 60 : each.key == "eval-runner" ? 900 : each.key == "eval-worker" ? 240 : each.key == "wiki-compile" ? 480 : each.key == "knowledge-graph-thread-ingest" ? 300 : each.key == "knowledge-graph-observations-ingest" ? 480 : each.key == "requester-memory-dreaming" ? 300 : each.key == "ontology-scan" ? 300 : each.key == "ontology-reprocess" ? 300 : each.key == "wiki-lint" ? 300 : each.key == "wiki-export" ? 600 : each.key == "okf-materialize" ? 600 : each.key == "okf-efs-refresh" ? 600 : each.key == "wiki-bootstrap-import" ? 900 : each.key == "folder-bundle-import" ? 300 : each.key == "routine-task-python" ? 360 : each.key == "model-converse" ? 60 : each.key == "memory-retain" ? 90 : 30
|
|
715
|
+
memory_size = each.key == "graphql-http" ? 512 : each.key == "wakeup-processor" ? 512 : each.key == "workspace-event-dispatcher" ? 512 : each.key == "eval-runner" ? 512 : each.key == "eval-worker" ? 512 : each.key == "wiki-compile" ? 1024 : each.key == "knowledge-graph-thread-ingest" ? 1024 : each.key == "knowledge-graph-observations-ingest" ? 1024 : each.key == "requester-memory-dreaming" ? 512 : each.key == "ontology-scan" ? 512 : each.key == "wiki-export" ? 1024 : each.key == "okf-materialize" ? 1024 : each.key == "okf-efs-refresh" ? 1024 : each.key == "wiki-bootstrap-import" ? 1024 : each.key == "folder-bundle-import" ? 1024 : 256
|
|
518
716
|
|
|
519
717
|
filename = local.use_local_zips ? "${var.lambda_zips_dir}/${each.key}.zip" : null
|
|
520
718
|
source_code_hash = local.use_local_zips ? filebase64sha256("${var.lambda_zips_dir}/${each.key}.zip") : null
|
|
@@ -530,12 +728,45 @@ resource "aws_lambda_function" "handler" {
|
|
|
530
728
|
|
|
531
729
|
environment {
|
|
532
730
|
variables = merge(
|
|
533
|
-
|
|
731
|
+
local.common_env,
|
|
534
732
|
{ FUNCTION_NAME = each.key },
|
|
535
733
|
lookup(local.handler_extra_env, each.key, {}),
|
|
536
734
|
)
|
|
537
735
|
}
|
|
538
736
|
|
|
737
|
+
dynamic "vpc_config" {
|
|
738
|
+
for_each = (
|
|
739
|
+
(
|
|
740
|
+
contains(["knowledge-graph-thread-ingest", "knowledge-graph-observations-ingest"], each.key) ||
|
|
741
|
+
(each.key == "graphql-http" && var.memory_engine == "cognee")
|
|
742
|
+
) && local.cognee_worker_vpc_enabled
|
|
743
|
+
) ? [1] : each.key == "okf-efs-refresh" && local.okf_efs_vpc_enabled ? [1] : []
|
|
744
|
+
|
|
745
|
+
content {
|
|
746
|
+
subnet_ids = each.key == "okf-efs-refresh" ? var.okf_efs_subnet_ids : var.cognee_worker_subnet_ids
|
|
747
|
+
security_group_ids = each.key == "okf-efs-refresh" ? var.okf_efs_security_group_ids : var.cognee_worker_security_group_ids
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
dynamic "file_system_config" {
|
|
752
|
+
for_each = each.key == "okf-efs-refresh" && local.okf_efs_vpc_enabled ? [1] : []
|
|
753
|
+
|
|
754
|
+
content {
|
|
755
|
+
arn = var.okf_efs_refresh_access_point_arn
|
|
756
|
+
local_mount_path = var.okf_efs_mount_path
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
lifecycle {
|
|
761
|
+
precondition {
|
|
762
|
+
condition = each.key != "okf-efs-refresh" || var.okf_efs_refresh_access_point_arn == "" || (
|
|
763
|
+
length(var.okf_efs_mount_target_ids) == length(var.okf_efs_subnet_ids) &&
|
|
764
|
+
alltrue([for id in var.okf_efs_mount_target_ids : id != ""])
|
|
765
|
+
)
|
|
766
|
+
error_message = "okf-efs-refresh requires an available EFS mount target dependency for every configured subnet."
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
|
|
539
770
|
tags = {
|
|
540
771
|
Name = "thinkwork-${var.stage}-api-${each.key}"
|
|
541
772
|
Handler = each.key
|
|
@@ -568,19 +799,22 @@ resource "aws_sqs_queue" "wiki_compile_dlq" {
|
|
|
568
799
|
}
|
|
569
800
|
}
|
|
570
801
|
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
802
|
+
# chat-agent-invoke retry-0 (plan 2026-05-22-006 U3). After the
|
|
803
|
+
# direct-callback finalize refactor, chat-agent-invoke is Event-mode-
|
|
804
|
+
# dispatched by the GraphQL resolver and itself dispatches AgentCore
|
|
805
|
+
# Event-mode. There is no synchronous wait anymore — the Lambda returns
|
|
806
|
+
# in ~5s. Retries pinned to 0 so the 2-default-retry storm that produced
|
|
807
|
+
# 5-min stall cascades cannot recur. Setup failures (agent lookup,
|
|
808
|
+
# runtime config resolve, throttling) surface exactly once via the
|
|
809
|
+
# inline error-message-insert path. No DLQ destination: the shared
|
|
810
|
+
# Lambda execution role's inline policy budget is already at the
|
|
811
|
+
# 10240-byte AWS hard cap, and operator replay of a setup failure is
|
|
812
|
+
# rarely useful (the user has already retried by re-sending the message).
|
|
813
|
+
resource "aws_lambda_function_event_invoke_config" "chat_agent_invoke" {
|
|
814
|
+
count = local.deploy_lambda_handlers ? 1 : 0
|
|
815
|
+
function_name = aws_lambda_function.handler["chat-agent-invoke"].function_name
|
|
816
|
+
maximum_retry_attempts = 0
|
|
817
|
+
maximum_event_age_in_seconds = 3600
|
|
584
818
|
}
|
|
585
819
|
|
|
586
820
|
resource "aws_lambda_function_event_invoke_config" "wiki_compile" {
|
|
@@ -609,21 +843,6 @@ resource "aws_sqs_queue" "ontology_scan_dlq" {
|
|
|
609
843
|
}
|
|
610
844
|
}
|
|
611
845
|
|
|
612
|
-
resource "aws_iam_role_policy" "ontology_scan_dlq_send" {
|
|
613
|
-
count = local.deploy_lambda_handlers ? 1 : 0
|
|
614
|
-
name = "thinkwork-${var.stage}-ontology-scan-dlq-send"
|
|
615
|
-
role = aws_iam_role.lambda.id
|
|
616
|
-
|
|
617
|
-
policy = jsonencode({
|
|
618
|
-
Version = "2012-10-17"
|
|
619
|
-
Statement = [{
|
|
620
|
-
Effect = "Allow"
|
|
621
|
-
Action = ["sqs:SendMessage"]
|
|
622
|
-
Resource = aws_sqs_queue.ontology_scan_dlq[0].arn
|
|
623
|
-
}]
|
|
624
|
-
})
|
|
625
|
-
}
|
|
626
|
-
|
|
627
846
|
resource "aws_lambda_function_event_invoke_config" "ontology_scan" {
|
|
628
847
|
count = local.deploy_lambda_handlers ? 1 : 0
|
|
629
848
|
function_name = aws_lambda_function.handler["ontology-scan"].function_name
|
|
@@ -649,21 +868,6 @@ resource "aws_sqs_queue" "ontology_reprocess_dlq" {
|
|
|
649
868
|
}
|
|
650
869
|
}
|
|
651
870
|
|
|
652
|
-
resource "aws_iam_role_policy" "ontology_reprocess_dlq_send" {
|
|
653
|
-
count = local.deploy_lambda_handlers ? 1 : 0
|
|
654
|
-
name = "thinkwork-${var.stage}-ontology-reprocess-dlq-send"
|
|
655
|
-
role = aws_iam_role.lambda.id
|
|
656
|
-
|
|
657
|
-
policy = jsonencode({
|
|
658
|
-
Version = "2012-10-17"
|
|
659
|
-
Statement = [{
|
|
660
|
-
Effect = "Allow"
|
|
661
|
-
Action = ["sqs:SendMessage"]
|
|
662
|
-
Resource = aws_sqs_queue.ontology_reprocess_dlq[0].arn
|
|
663
|
-
}]
|
|
664
|
-
})
|
|
665
|
-
}
|
|
666
|
-
|
|
667
871
|
resource "aws_lambda_function_event_invoke_config" "ontology_reprocess" {
|
|
668
872
|
count = local.deploy_lambda_handlers ? 1 : 0
|
|
669
873
|
function_name = aws_lambda_function.handler["ontology-reprocess"].function_name
|
|
@@ -692,7 +896,7 @@ resource "aws_lambda_function_event_invoke_config" "routine_approval_callback" {
|
|
|
692
896
|
maximum_event_age_in_seconds = 3600
|
|
693
897
|
}
|
|
694
898
|
|
|
695
|
-
# Per-turn auto-retain: the runtime
|
|
899
|
+
# Per-turn auto-retain: the runtime Event-invokes
|
|
696
900
|
# memory-retain after every chat turn. AWS Lambda's default async-retry
|
|
697
901
|
# policy is 2 attempts; without overriding it, a transient failure on the
|
|
698
902
|
# canonical-transcript fetch or adapter write retries the entire writeback
|
|
@@ -708,6 +912,32 @@ resource "aws_lambda_function_event_invoke_config" "memory_retain" {
|
|
|
708
912
|
maximum_event_age_in_seconds = 3600
|
|
709
913
|
}
|
|
710
914
|
|
|
915
|
+
# Product-owned retry path for memory-retain. Lambda async retries remain
|
|
916
|
+
# disabled above; this scheduled drain claims due rows from
|
|
917
|
+
# memory_retain_attempts and replays bounded retry payloads idempotently.
|
|
918
|
+
resource "aws_scheduler_schedule" "memory_retain_retry_drainer" {
|
|
919
|
+
count = local.deploy_lambda_handlers ? 1 : 0
|
|
920
|
+
|
|
921
|
+
name = "thinkwork-${var.stage}-memory-retain-retry-drainer"
|
|
922
|
+
group_name = "default"
|
|
923
|
+
schedule_expression = "rate(1 minutes)"
|
|
924
|
+
state = "ENABLED"
|
|
925
|
+
|
|
926
|
+
flexible_time_window {
|
|
927
|
+
mode = "OFF"
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
target {
|
|
931
|
+
arn = aws_lambda_function.handler["memory-retain"].arn
|
|
932
|
+
role_arn = aws_iam_role.scheduler.arn
|
|
933
|
+
input = jsonencode({ kind = "drain_due", limit = 25 })
|
|
934
|
+
|
|
935
|
+
retry_policy {
|
|
936
|
+
maximum_retry_attempts = 0
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
|
|
711
941
|
# ---------------------------------------------------------------------------
|
|
712
942
|
# Phase 3 U4: compliance-outbox-drainer DLQ + async retry config
|
|
713
943
|
#
|
|
@@ -728,21 +958,6 @@ resource "aws_sqs_queue" "compliance_drainer_dlq" {
|
|
|
728
958
|
}
|
|
729
959
|
}
|
|
730
960
|
|
|
731
|
-
resource "aws_iam_role_policy" "compliance_drainer_dlq_send" {
|
|
732
|
-
count = local.deploy_lambda_handlers ? 1 : 0
|
|
733
|
-
name = "compliance-drainer-dlq-send"
|
|
734
|
-
role = aws_iam_role.lambda.id
|
|
735
|
-
|
|
736
|
-
policy = jsonencode({
|
|
737
|
-
Version = "2012-10-17"
|
|
738
|
-
Statement = [{
|
|
739
|
-
Effect = "Allow"
|
|
740
|
-
Action = ["sqs:SendMessage"]
|
|
741
|
-
Resource = aws_sqs_queue.compliance_drainer_dlq[0].arn
|
|
742
|
-
}]
|
|
743
|
-
})
|
|
744
|
-
}
|
|
745
|
-
|
|
746
961
|
resource "aws_lambda_function_event_invoke_config" "compliance_outbox_drainer" {
|
|
747
962
|
count = local.deploy_lambda_handlers ? 1 : 0
|
|
748
963
|
function_name = aws_lambda_function.handler["compliance-outbox-drainer"].function_name
|
|
@@ -785,280 +1000,358 @@ resource "aws_scheduler_schedule" "compliance_outbox_drainer" {
|
|
|
785
1000
|
locals {
|
|
786
1001
|
# Map of route_key → handler name for API Gateway
|
|
787
1002
|
api_routes = local.deploy_lambda_handlers ? {
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1003
|
+
for route_key, handler_name in {
|
|
1004
|
+
# GraphQL — the main API entry point
|
|
1005
|
+
"POST /graphql" = "graphql-http"
|
|
1006
|
+
"GET /graphql" = "graphql-http"
|
|
1007
|
+
|
|
1008
|
+
# Health check (keep placeholder alive too)
|
|
1009
|
+
# "GET /health" is handled by placeholder
|
|
1010
|
+
|
|
1011
|
+
# Public login capabilities. Unauthenticated by design; the handler
|
|
1012
|
+
# resolves tenant-scoped OAuth options only from trusted API Gateway
|
|
1013
|
+
# domain metadata and fails closed for unknown/shared hosts.
|
|
1014
|
+
"GET /api/auth/options" = "public-auth-options"
|
|
1015
|
+
"OPTIONS /api/auth/options" = "public-auth-options"
|
|
1016
|
+
"GET /api/auth/workos/authorize" = "workos-auth"
|
|
1017
|
+
"OPTIONS /api/auth/workos/authorize" = "workos-auth"
|
|
1018
|
+
"GET /api/auth/workos/callback" = "workos-auth"
|
|
1019
|
+
"OPTIONS /api/auth/workos/callback" = "workos-auth"
|
|
1020
|
+
"POST /api/auth/workos/bridge" = "workos-auth"
|
|
1021
|
+
"OPTIONS /api/auth/workos/bridge" = "workos-auth"
|
|
1022
|
+
"POST /api/auth/workos/logout" = "workos-auth"
|
|
1023
|
+
"OPTIONS /api/auth/workos/logout" = "workos-auth"
|
|
1024
|
+
|
|
1025
|
+
# Agents
|
|
1026
|
+
"ANY /api/agents/{proxy+}" = "agents"
|
|
1027
|
+
"ANY /api/agents" = "agents"
|
|
1028
|
+
|
|
1029
|
+
# Agent actions (start/stop/heartbeat/budget)
|
|
1030
|
+
"ANY /api/agent-actions/{proxy+}" = "agent-actions"
|
|
1031
|
+
|
|
1032
|
+
# Desktop-local Pi tombstones. Specific routes before broad REST handlers;
|
|
1033
|
+
# OPTIONS is handled inside the Lambda before auth.
|
|
1034
|
+
"POST /api/desktop/runtime-session" = "desktop-runtime-session"
|
|
1035
|
+
"OPTIONS /api/desktop/runtime-session" = "desktop-runtime-session"
|
|
1036
|
+
"POST /api/desktop/workspace-prewarm" = "desktop-workspace-prewarm"
|
|
1037
|
+
"OPTIONS /api/desktop/workspace-prewarm" = "desktop-workspace-prewarm"
|
|
1038
|
+
"POST /api/desktop/managed-delegation" = "managed-delegation"
|
|
1039
|
+
"OPTIONS /api/desktop/managed-delegation" = "managed-delegation"
|
|
1040
|
+
"POST /api/desktop/eval-runs" = "desktop-eval-runs"
|
|
1041
|
+
"OPTIONS /api/desktop/eval-runs" = "desktop-eval-runs"
|
|
1042
|
+
"POST /api/desktop/eval-runs/{runId}/sessions" = "desktop-eval-runs"
|
|
1043
|
+
"OPTIONS /api/desktop/eval-runs/{runId}/sessions" = "desktop-eval-runs"
|
|
1044
|
+
"POST /api/desktop/eval-runs/{runId}/results" = "desktop-eval-runs"
|
|
1045
|
+
"OPTIONS /api/desktop/eval-runs/{runId}/results" = "desktop-eval-runs"
|
|
1046
|
+
|
|
1047
|
+
# Mobile agent harness model proxy (cloud Bedrock Converse). OPTIONS is
|
|
1048
|
+
# handled inside the Lambda before auth.
|
|
1049
|
+
"POST /api/model/converse" = "model-converse"
|
|
1050
|
+
"OPTIONS /api/model/converse" = "model-converse"
|
|
1051
|
+
|
|
1052
|
+
# Mobile agent harness turn persistence (append a completed turn). OPTIONS
|
|
1053
|
+
# handled inside the Lambda before auth.
|
|
1054
|
+
"POST /api/threads/record-turn" = "record-turn"
|
|
1055
|
+
"OPTIONS /api/threads/record-turn" = "record-turn"
|
|
1056
|
+
"POST /api/mobile/turn-session" = "mobile-turn-session"
|
|
1057
|
+
"OPTIONS /api/mobile/turn-session" = "mobile-turn-session"
|
|
1058
|
+
|
|
1059
|
+
# Mobile local Pi built-in tool proxy. This is intentionally separate from
|
|
1060
|
+
# /api/mcp because web_search is a ThinkWork platform capability, not an
|
|
1061
|
+
# MCP connector.
|
|
1062
|
+
"POST /api/mobile/tools/web-search" = "mobile-tools"
|
|
1063
|
+
"OPTIONS /api/mobile/tools/web-search" = "mobile-tools"
|
|
1064
|
+
"POST /api/tasks/status" = "task-status-tool"
|
|
1065
|
+
"OPTIONS /api/tasks/status" = "task-status-tool"
|
|
1066
|
+
"POST /api/work-items/status" = "task-status-tool"
|
|
1067
|
+
"OPTIONS /api/work-items/status" = "task-status-tool"
|
|
1068
|
+
|
|
1069
|
+
# Mobile agent harness MCP proxy — tenant-scoped tools/list + tools/call
|
|
1070
|
+
# over the signed-in user's Cognito idToken. One Lambda, two routes;
|
|
1071
|
+
# OPTIONS handled inside the Lambda before auth.
|
|
1072
|
+
"POST /api/mcp/tools/list" = "mcp-proxy"
|
|
1073
|
+
"OPTIONS /api/mcp/tools/list" = "mcp-proxy"
|
|
1074
|
+
"POST /api/mcp/tools/call" = "mcp-proxy"
|
|
1075
|
+
"OPTIONS /api/mcp/tools/call" = "mcp-proxy"
|
|
1076
|
+
|
|
1077
|
+
# Twenty Client Engagement app: browser -> ThinkWork REST Lambda ->
|
|
1078
|
+
# Twenty REST API with the caller's plugin activation.
|
|
1079
|
+
"ANY /api/plugin-apps/twenty/client-engagement" = "twenty-client-engagement"
|
|
1080
|
+
"ANY /api/plugin-apps/twenty/client-engagement/{proxy+}" = "twenty-client-engagement"
|
|
1081
|
+
|
|
1082
|
+
# Messages
|
|
1083
|
+
"ANY /api/messages/{proxy+}" = "messages"
|
|
1084
|
+
"ANY /api/messages" = "messages"
|
|
1085
|
+
|
|
1086
|
+
# Tenants
|
|
1087
|
+
"ANY /api/tenants/{proxy+}" = "tenants"
|
|
1088
|
+
"ANY /api/tenants" = "tenants"
|
|
1089
|
+
|
|
1090
|
+
# Users
|
|
1091
|
+
"ANY /api/users/{proxy+}" = "users"
|
|
1092
|
+
"ANY /api/users" = "users"
|
|
1093
|
+
|
|
1094
|
+
# Invites
|
|
1095
|
+
"ANY /api/invites/{proxy+}" = "invites"
|
|
1096
|
+
"ANY /api/invites" = "invites"
|
|
1097
|
+
|
|
1098
|
+
# Compliance audit-event emit (Phase 3 U6) — narrow Bearer
|
|
1099
|
+
# API_AUTH_SECRET endpoint, runtime clients post here.
|
|
1100
|
+
"POST /api/compliance/events" = "compliance-events"
|
|
1101
|
+
|
|
1102
|
+
# Skills
|
|
1103
|
+
"ANY /api/skills/{proxy+}" = "skills"
|
|
1104
|
+
"ANY /api/skills" = "skills"
|
|
1105
|
+
|
|
1106
|
+
# User Memory MCP OAuth/resource-server unblocker. These endpoints are
|
|
1107
|
+
# enough for `codex mcp login thinkwork-user-memory-dev` to discover OAuth,
|
|
1108
|
+
# register as a public PKCE client, sign the user in through Cognito, and
|
|
1109
|
+
# receive a bearer token for the User Memory MCP resource.
|
|
1110
|
+
"GET /.well-known/oauth-protected-resource" = "mcp-oauth"
|
|
1111
|
+
"GET /.well-known/oauth-protected-resource/{proxy+}" = "mcp-oauth"
|
|
1112
|
+
"GET /.well-known/oauth-authorization-server" = "mcp-oauth"
|
|
1113
|
+
"GET /.well-known/openid-configuration" = "mcp-oauth"
|
|
1114
|
+
"GET /mcp/oauth/jwks" = "mcp-oauth"
|
|
1115
|
+
"POST /mcp/oauth/register" = "mcp-oauth"
|
|
1116
|
+
"GET /mcp/oauth/authorize" = "mcp-oauth"
|
|
1117
|
+
"GET /mcp/oauth/callback" = "mcp-oauth"
|
|
1118
|
+
"POST /mcp/oauth/token" = "mcp-oauth"
|
|
1119
|
+
"POST /mcp/oauth/revoke" = "mcp-oauth"
|
|
1120
|
+
"ANY /mcp/user-memory" = "mcp-user-memory"
|
|
1121
|
+
"ANY /mcp/context-engine" = "mcp-context-engine"
|
|
1122
|
+
"ANY /mcp/open-engine" = "mcp-open-engine"
|
|
1123
|
+
|
|
1124
|
+
# Brain v0 service-auth writeback.
|
|
1125
|
+
"POST /api/brain/agent-write" = "brain-agent-write"
|
|
1126
|
+
"OPTIONS /api/brain/agent-write" = "brain-agent-write"
|
|
1127
|
+
|
|
1128
|
+
# Activity
|
|
1129
|
+
"ANY /api/activity/{proxy+}" = "activity"
|
|
1130
|
+
"ANY /api/activity" = "activity"
|
|
1131
|
+
|
|
1132
|
+
# Connections + OAuth
|
|
1133
|
+
"ANY /api/connections/{proxy+}" = "connections"
|
|
1134
|
+
"ANY /api/connections" = "connections"
|
|
1135
|
+
"GET /api/oauth/authorize" = "oauth-authorize"
|
|
1136
|
+
"GET /api/oauth/callback" = "oauth-callback"
|
|
1137
|
+
|
|
1138
|
+
# Stripe billing (unauthenticated — checkout is pre-signup; webhook is
|
|
1139
|
+
# server-to-server with Stripe signature verification).
|
|
1140
|
+
"POST /api/stripe/checkout-session" = "stripe-checkout"
|
|
1141
|
+
"OPTIONS /api/stripe/checkout-session" = "stripe-checkout"
|
|
1142
|
+
"POST /api/stripe/webhook" = "stripe-webhook"
|
|
1143
|
+
"POST /api/stripe/portal-session" = "stripe-portal"
|
|
1144
|
+
"OPTIONS /api/stripe/portal-session" = "stripe-portal"
|
|
1145
|
+
"GET /api/stripe/subscription" = "stripe-subscription"
|
|
1146
|
+
"OPTIONS /api/stripe/subscription" = "stripe-subscription"
|
|
1147
|
+
"POST /api/deployment-sessions" = "deployment-sessions"
|
|
1148
|
+
"OPTIONS /api/deployment-sessions" = "deployment-sessions"
|
|
1149
|
+
"GET /api/deployment-sessions/{sessionId}" = "deployment-sessions"
|
|
1150
|
+
"OPTIONS /api/deployment-sessions/{sessionId}" = "deployment-sessions"
|
|
1151
|
+
"POST /api/deployment-sessions/{sessionId}/bootstrap-credential-lease" = "deployment-sessions"
|
|
1152
|
+
"DELETE /api/deployment-sessions/{sessionId}/bootstrap-credential-lease" = "deployment-sessions"
|
|
1153
|
+
"OPTIONS /api/deployment-sessions/{sessionId}/bootstrap-credential-lease" = "deployment-sessions"
|
|
1154
|
+
"POST /api/deployment-sessions/{sessionId}/authority-transfer" = "deployment-sessions"
|
|
1155
|
+
"OPTIONS /api/deployment-sessions/{sessionId}/authority-transfer" = "deployment-sessions"
|
|
1156
|
+
"POST /api/deployment-sessions/{sessionId}/start" = "deployment-sessions"
|
|
1157
|
+
"OPTIONS /api/deployment-sessions/{sessionId}/start" = "deployment-sessions"
|
|
1158
|
+
"POST /api/deployment-sessions/{sessionId}/teardown" = "deployment-sessions"
|
|
1159
|
+
"OPTIONS /api/deployment-sessions/{sessionId}/teardown" = "deployment-sessions"
|
|
1160
|
+
"GET /api/auth/me" = "auth-me"
|
|
1161
|
+
"OPTIONS /api/auth/me" = "auth-me"
|
|
1162
|
+
"ANY /api/extensions/{extensionId}" = "extension-proxy"
|
|
1163
|
+
"ANY /api/extensions/{extensionId}/{proxy+}" = "extension-proxy"
|
|
1164
|
+
|
|
1165
|
+
# Routines
|
|
1166
|
+
"ANY /api/routines/{proxy+}" = "routines"
|
|
1167
|
+
"ANY /api/routines" = "routines"
|
|
1168
|
+
|
|
1169
|
+
# Budgets
|
|
1170
|
+
"ANY /api/budgets/{proxy+}" = "budgets"
|
|
1171
|
+
"ANY /api/budgets" = "budgets"
|
|
1172
|
+
|
|
1173
|
+
# Guardrails
|
|
1174
|
+
"ANY /api/guardrails/{proxy+}" = "guardrails"
|
|
1175
|
+
"ANY /api/guardrails" = "guardrails"
|
|
1176
|
+
|
|
1177
|
+
# Scheduled Jobs
|
|
1178
|
+
"ANY /api/scheduled-jobs/{proxy+}" = "scheduled-jobs"
|
|
1179
|
+
"ANY /api/scheduled-jobs" = "scheduled-jobs"
|
|
1180
|
+
"ANY /api/thread-turns/{proxy+}" = "scheduled-jobs"
|
|
1181
|
+
"ANY /api/thread-turns" = "scheduled-jobs"
|
|
1182
|
+
"ANY /api/trigger-runs/{proxy+}" = "scheduled-jobs"
|
|
1183
|
+
"ANY /api/trigger-runs" = "scheduled-jobs"
|
|
1184
|
+
|
|
1185
|
+
# Job Schedule Manager (EventBridge CRUD)
|
|
1186
|
+
"ANY /api/job-schedules/{proxy+}" = "job-schedule-manager"
|
|
1187
|
+
"ANY /api/job-schedules" = "job-schedule-manager"
|
|
1188
|
+
|
|
1189
|
+
# Integration webhooks (Unit 8 — composable-skills). Each integration
|
|
1190
|
+
# has its own Lambda + a specific route under /webhooks/{integration}/
|
|
1191
|
+
# {tenantId}. Specific routes take precedence over the {proxy+}
|
|
1192
|
+
# catch-all below, which still owns the legacy PRD-19 webhook-token
|
|
1193
|
+
# surface.
|
|
1194
|
+
"POST /webhooks/crm-opportunity/{tenantId}" = "webhook-crm-opportunity"
|
|
1195
|
+
"POST /webhooks/task-event/{tenantId}" = "webhook-task-event"
|
|
1196
|
+
|
|
1197
|
+
# Webhooks (public trigger) — legacy PRD-19 tokenized webhooks.
|
|
1198
|
+
"POST /webhooks/{proxy+}" = "webhooks"
|
|
1199
|
+
|
|
1200
|
+
# n8n agent-step bridge — public tenant-scoped credential endpoint for
|
|
1201
|
+
# stock n8n HTTP Request nodes.
|
|
1202
|
+
"POST /api/integrations/n8n/agent-steps" = "n8n-agent-step-bridge"
|
|
1203
|
+
"OPTIONS /api/integrations/n8n/agent-steps" = "n8n-agent-step-bridge"
|
|
1204
|
+
|
|
1205
|
+
# Webhooks admin
|
|
1206
|
+
"ANY /api/webhooks/{proxy+}" = "webhooks-admin"
|
|
1207
|
+
"ANY /api/webhooks" = "webhooks-admin"
|
|
1208
|
+
|
|
1209
|
+
# Workspace source fetch authorization (dynamic workspace U4).
|
|
1210
|
+
# Registered before the /api/workspaces/{proxy+} catch-all — API
|
|
1211
|
+
# Gateway HTTP APIs route to the most specific match, so these two
|
|
1212
|
+
# take precedence over the workspace-files proxy route.
|
|
1213
|
+
"POST /api/workspaces/fetch-source" = "workspace-fetch-source"
|
|
1214
|
+
"OPTIONS /api/workspaces/fetch-source" = "workspace-fetch-source"
|
|
1215
|
+
|
|
1216
|
+
# Workspace files
|
|
1217
|
+
"ANY /api/workspaces/{proxy+}" = "workspace-files"
|
|
1218
|
+
|
|
1219
|
+
# Knowledge bases
|
|
1220
|
+
"ANY /api/knowledge-bases/{proxy+}" = "knowledge-base-files"
|
|
1221
|
+
|
|
1222
|
+
# Email
|
|
1223
|
+
"POST /api/email/send" = "email-send"
|
|
1224
|
+
"POST /api/email/provider-webhook/{providerInstallId}" = "email-provider-webhook"
|
|
1225
|
+
"POST /api/email/readiness/probe" = "email-readiness-probe"
|
|
1226
|
+
|
|
1227
|
+
# Slack workspace app ingress. These unauthenticated public endpoints
|
|
1228
|
+
# verify Slack signatures in handler code before any tenant work happens.
|
|
1229
|
+
"POST /slack/events" = "slack-events"
|
|
1230
|
+
"POST /slack/slash-command" = "slack-slash-command"
|
|
1231
|
+
"POST /slack/interactivity" = "slack-interactivity"
|
|
1232
|
+
"GET /slack/oauth/install" = "slack-oauth-install"
|
|
1233
|
+
"POST /slack/oauth/install" = "slack-oauth-install"
|
|
1234
|
+
|
|
1235
|
+
# Memory
|
|
1236
|
+
"ANY /api/memory/{proxy+}" = "memory"
|
|
1237
|
+
|
|
1238
|
+
# Artifacts
|
|
1239
|
+
"POST /api/artifacts/{proxy+}" = "artifact-deliver"
|
|
1240
|
+
|
|
1241
|
+
# Recipes
|
|
1242
|
+
"POST /api/recipe-refresh" = "recipe-refresh"
|
|
1243
|
+
|
|
1244
|
+
# GitHub App
|
|
1245
|
+
"ANY /api/github-app/{proxy+}" = "github-app"
|
|
1246
|
+
"POST /api/github/webhook" = "github-app"
|
|
1247
|
+
|
|
1248
|
+
# AgentCore Code Sandbox (plan Unit 10 + Unit 11). The runtime calls
|
|
1249
|
+
# both with Bearer API_AUTH_SECRET before + after every
|
|
1250
|
+
# executeCode. 429 on quota denial, 201 on audit-row insert.
|
|
1251
|
+
"POST /api/sandbox/quota/check-and-increment" = "sandbox-quota-check"
|
|
1252
|
+
"POST /api/sandbox/invocations" = "sandbox-invocation-log"
|
|
1253
|
+
|
|
1254
|
+
# Routines ASL validator (plan 2026-05-01-004 §U5). Bearer
|
|
1255
|
+
# API_AUTH_SECRET. Chat builder + publish flow POST the candidate
|
|
1256
|
+
# ASL document; returns { valid, errors, warnings }.
|
|
1257
|
+
"POST /api/routines/validate" = "routine-asl-validator"
|
|
1258
|
+
"OPTIONS /api/routines/validate" = "routine-asl-validator"
|
|
1259
|
+
|
|
1260
|
+
# Routines step-event ingest (plan 2026-05-01-005 §U9). Task wrappers
|
|
1261
|
+
# (routine-task-python, routine-resume) POST per-step status
|
|
1262
|
+
# transitions; the EventBridge rule in routines-stepfunctions/main.tf
|
|
1263
|
+
# POSTs SFN execution-state-change events here for the agent_invoke
|
|
1264
|
+
# recipe path (no wrapper Lambda). Bearer API_AUTH_SECRET. Idempotent
|
|
1265
|
+
# via partial unique index on (execution_id, node_id, status,
|
|
1266
|
+
# started_at) — see migration 0056.
|
|
1267
|
+
"POST /api/routines/step" = "routine-step-callback"
|
|
1268
|
+
"OPTIONS /api/routines/step" = "routine-step-callback"
|
|
1269
|
+
"POST /api/routines/execution" = "routine-execution-callback"
|
|
1270
|
+
"OPTIONS /api/routines/execution" = "routine-execution-callback"
|
|
1271
|
+
|
|
1272
|
+
# chat-agent-finalize — AgentCore runtime POSTs here at end-of-turn so
|
|
1273
|
+
# the post-AgentCore bookkeeping runs out-of-band from chat-agent-invoke.
|
|
1274
|
+
# Bearer API_AUTH_SECRET. Plan 2026-05-22-006.
|
|
1275
|
+
"POST /api/threads/{threadId}/finalize" = "chat-agent-finalize"
|
|
1276
|
+
"OPTIONS /api/threads/{threadId}/finalize" = "chat-agent-finalize"
|
|
1277
|
+
|
|
1278
|
+
# chat-agent-activity — Pi runtime POSTs here mid-turn to stream live
|
|
1279
|
+
# agent activity to the Spaces thread. Bearer API_AUTH_SECRET, best-effort.
|
|
1280
|
+
# Plan 2026-06-03-001.
|
|
1281
|
+
"POST /api/threads/{threadId}/activity" = "chat-agent-activity"
|
|
1282
|
+
"OPTIONS /api/threads/{threadId}/activity" = "chat-agent-activity"
|
|
1283
|
+
|
|
1284
|
+
# ask_user_question intake — the Pi runtime POSTs a question batch
|
|
1285
|
+
# here (awaited) before returning its sentinel tool result. Served by
|
|
1286
|
+
# the SAME chat-agent-activity Lambda (route discrimination in the
|
|
1287
|
+
# handler — no new Lambda). Bearer API_AUTH_SECRET + thread-turn
|
|
1288
|
+
# ownership join; 409 on the one-pending-per-thread partial unique
|
|
1289
|
+
# index. Plan 2026-06-09-005 U2.
|
|
1290
|
+
"POST /api/threads/{threadId}/questions" = "chat-agent-activity"
|
|
1291
|
+
"OPTIONS /api/threads/{threadId}/questions" = "chat-agent-activity"
|
|
1292
|
+
|
|
1293
|
+
# Skill-run dispatcher runtime-config fetch. Service-auth GET.
|
|
1294
|
+
"GET /api/agents/runtime-config" = "agents-runtime-config"
|
|
1295
|
+
|
|
1296
|
+
# Admin-Ops MCP server — single JSON-RPC endpoint. Managed agents
|
|
1297
|
+
# (and anyone else) POST with Bearer <tenant-scoped token> issued by
|
|
1298
|
+
# the mcp-admin-keys handler below. The shared API_AUTH_SECRET is
|
|
1299
|
+
# retained as a break-glass superuser path for bootstrap/debug.
|
|
1300
|
+
"POST /mcp/admin" = "admin-ops-mcp"
|
|
1301
|
+
|
|
1302
|
+
# MCP admin key management — per-tenant Bearer token CRUD. Tokens
|
|
1303
|
+
# are shown ONCE at creation (POST returns raw value); server stores
|
|
1304
|
+
# sha256 hash only. These specific routes take precedence over the
|
|
1305
|
+
# existing `ANY /api/tenants/{proxy+}` route (tenants handler) per
|
|
1306
|
+
# API Gateway v2's most-specific-match rule.
|
|
1307
|
+
"POST /api/tenants/{tenantId}/mcp-admin-keys" = "mcp-admin-keys"
|
|
1308
|
+
"GET /api/tenants/{tenantId}/mcp-admin-keys" = "mcp-admin-keys"
|
|
1309
|
+
"DELETE /api/tenants/{tenantId}/mcp-admin-keys/{keyId}" = "mcp-admin-keys"
|
|
1310
|
+
|
|
1311
|
+
# One-shot tenant provisioning for the admin-ops MCP. Mints a fresh
|
|
1312
|
+
# tkm_ key + stores it in Secrets Manager at
|
|
1313
|
+
# thinkwork/<stage>/mcp/<tenantId>/admin-ops + upserts the
|
|
1314
|
+
# tenant_mcp_servers row so the runtime picks the server up for
|
|
1315
|
+
# any agent that gets it assigned via agent_mcp_servers.
|
|
1316
|
+
"POST /api/tenants/{tenantId}/mcp-admin-provision" = "mcp-admin-provision"
|
|
1317
|
+
|
|
1318
|
+
# MCP server admin approval (plan §U11, SI-5). Externally-sourced MCP
|
|
1319
|
+
# servers land with status='pending'; these routes flip them to
|
|
1320
|
+
# approved/rejected. Cognito JWT only (mcp-approval handler rejects
|
|
1321
|
+
# apikey callers) — the admin SPA is the sole UI surface.
|
|
1322
|
+
"POST /api/tenants/{tenantId}/mcp-servers/{serverId}/approve" = "mcp-approval"
|
|
1323
|
+
"OPTIONS /api/tenants/{tenantId}/mcp-servers/{serverId}/approve" = "mcp-approval"
|
|
1324
|
+
"POST /api/tenants/{tenantId}/mcp-servers/{serverId}/reject" = "mcp-approval"
|
|
1325
|
+
"OPTIONS /api/tenants/{tenantId}/mcp-servers/{serverId}/reject" = "mcp-approval"
|
|
1326
|
+
|
|
1327
|
+
# Finance pilot U2 — thread-attachment upload (presign + finalize).
|
|
1328
|
+
# Cognito JWT; tenant pinned via threads.tenant_id lookup. OPTIONS
|
|
1329
|
+
# is handled inside the Lambda before auth.
|
|
1330
|
+
"POST /api/threads/{threadId}/attachments/presign" = "thread-attachments-presign"
|
|
1331
|
+
"OPTIONS /api/threads/{threadId}/attachments/presign" = "thread-attachments-presign"
|
|
1332
|
+
"POST /api/threads/{threadId}/attachments/finalize" = "thread-attachments-finalize"
|
|
1333
|
+
"OPTIONS /api/threads/{threadId}/attachments/finalize" = "thread-attachments-finalize"
|
|
1334
|
+
|
|
1335
|
+
# U9-remainder of finance pilot — tenant-pinned download endpoint.
|
|
1336
|
+
"GET /api/threads/{threadId}/attachments/{attachmentId}/download" = "thread-attachment-download"
|
|
1337
|
+
"OPTIONS /api/threads/{threadId}/attachments/{attachmentId}/download" = "thread-attachment-download"
|
|
1338
|
+
|
|
1339
|
+
# Fat-folder bundle import. OPTIONS is handled inside the Lambda before auth.
|
|
1340
|
+
"POST /api/agents/{agentId}/import-bundle" = "folder-bundle-import"
|
|
1341
|
+
"OPTIONS /api/agents/{agentId}/import-bundle" = "folder-bundle-import"
|
|
1342
|
+
|
|
1343
|
+
# Resolved Capability Manifest write endpoint (plan §U15). The runtime
|
|
1344
|
+
# posts one row per agent-session-start. Shared
|
|
1345
|
+
# API_AUTH_SECRET; no tenant OAuth.
|
|
1346
|
+
"POST /api/runtime/manifests" = "manifest-log"
|
|
1347
|
+
"OPTIONS /api/runtime/manifests" = "manifest-log"
|
|
1348
|
+
|
|
1349
|
+
# SI-7 catalog-list read (plan §U15 pt 3/3). The runtime fetches
|
|
1350
|
+
# the allowed slug set once per session-start. Shared API_AUTH_SECRET.
|
|
1351
|
+
"GET /api/runtime/capability-catalog" = "capability-catalog-list"
|
|
1352
|
+
"OPTIONS /api/runtime/capability-catalog" = "capability-catalog-list"
|
|
1353
|
+
} : route_key => handler_name
|
|
1354
|
+
if !contains(local.optional_integration_handler_names, handler_name)
|
|
1062
1355
|
} : {}
|
|
1063
1356
|
}
|
|
1064
1357
|
|
|
@@ -1089,6 +1382,49 @@ resource "aws_lambda_permission" "handler_apigw" {
|
|
|
1089
1382
|
source_arn = "${aws_apigatewayv2_api.main.execution_arn}/*/*"
|
|
1090
1383
|
}
|
|
1091
1384
|
|
|
1385
|
+
################################################################################
|
|
1386
|
+
# EventBridge → routine-execution-callback
|
|
1387
|
+
################################################################################
|
|
1388
|
+
|
|
1389
|
+
resource "aws_cloudwatch_event_rule" "routine_sfn_state_change" {
|
|
1390
|
+
count = local.deploy_lambda_handlers ? 1 : 0
|
|
1391
|
+
name = "thinkwork-${var.stage}-routines-sfn-state-change"
|
|
1392
|
+
description = "Forward routine Step Functions execution state changes to the callback Lambda."
|
|
1393
|
+
|
|
1394
|
+
event_pattern = jsonencode({
|
|
1395
|
+
source = ["aws.states"]
|
|
1396
|
+
"detail-type" = ["Step Functions Execution Status Change"]
|
|
1397
|
+
detail = {
|
|
1398
|
+
stateMachineArn = [
|
|
1399
|
+
{
|
|
1400
|
+
prefix = "arn:aws:states:${var.region}:${var.account_id}:stateMachine:thinkwork-${var.stage}-routine-"
|
|
1401
|
+
},
|
|
1402
|
+
]
|
|
1403
|
+
}
|
|
1404
|
+
})
|
|
1405
|
+
|
|
1406
|
+
tags = {
|
|
1407
|
+
Name = "thinkwork-${var.stage}-routines-sfn-state-change"
|
|
1408
|
+
Stage = var.stage
|
|
1409
|
+
}
|
|
1410
|
+
}
|
|
1411
|
+
|
|
1412
|
+
resource "aws_cloudwatch_event_target" "routine_sfn_state_change" {
|
|
1413
|
+
count = local.deploy_lambda_handlers ? 1 : 0
|
|
1414
|
+
rule = aws_cloudwatch_event_rule.routine_sfn_state_change[0].name
|
|
1415
|
+
target_id = "routine-execution-callback"
|
|
1416
|
+
arn = aws_lambda_function.handler["routine-execution-callback"].arn
|
|
1417
|
+
}
|
|
1418
|
+
|
|
1419
|
+
resource "aws_lambda_permission" "routine_sfn_state_change" {
|
|
1420
|
+
count = local.deploy_lambda_handlers ? 1 : 0
|
|
1421
|
+
statement_id = "AllowEventBridgeInvokeRoutineExecutionCallback"
|
|
1422
|
+
action = "lambda:InvokeFunction"
|
|
1423
|
+
function_name = aws_lambda_function.handler["routine-execution-callback"].function_name
|
|
1424
|
+
principal = "events.amazonaws.com"
|
|
1425
|
+
source_arn = aws_cloudwatch_event_rule.routine_sfn_state_change[0].arn
|
|
1426
|
+
}
|
|
1427
|
+
|
|
1092
1428
|
# ---------------------------------------------------------------------------
|
|
1093
1429
|
# Wakeup Processor — EventBridge schedule (every 1 min)
|
|
1094
1430
|
# ---------------------------------------------------------------------------
|
|
@@ -1112,15 +1448,15 @@ resource "aws_scheduler_schedule" "wakeup_processor" {
|
|
|
1112
1448
|
}
|
|
1113
1449
|
|
|
1114
1450
|
# ---------------------------------------------------------------------------
|
|
1115
|
-
#
|
|
1451
|
+
# n8n agent-step expirer — resumes waiting n8n executions on timeout/retry
|
|
1116
1452
|
# ---------------------------------------------------------------------------
|
|
1117
1453
|
|
|
1118
|
-
resource "aws_scheduler_schedule" "
|
|
1454
|
+
resource "aws_scheduler_schedule" "n8n_agent_step_expirer" {
|
|
1119
1455
|
count = local.deploy_lambda_handlers ? 1 : 0
|
|
1120
1456
|
|
|
1121
|
-
name = "thinkwork-${var.stage}-
|
|
1457
|
+
name = "thinkwork-${var.stage}-n8n-agent-step-expirer"
|
|
1122
1458
|
group_name = "default"
|
|
1123
|
-
schedule_expression = "
|
|
1459
|
+
schedule_expression = "rate(1 minutes)"
|
|
1124
1460
|
state = "ENABLED"
|
|
1125
1461
|
|
|
1126
1462
|
flexible_time_window {
|
|
@@ -1128,24 +1464,21 @@ resource "aws_scheduler_schedule" "webhook_deliveries_cleanup" {
|
|
|
1128
1464
|
}
|
|
1129
1465
|
|
|
1130
1466
|
target {
|
|
1131
|
-
arn = aws_lambda_function.handler["
|
|
1467
|
+
arn = aws_lambda_function.handler["n8n-agent-step-expirer"].arn
|
|
1132
1468
|
role_arn = aws_iam_role.scheduler.arn
|
|
1133
1469
|
}
|
|
1134
1470
|
}
|
|
1135
1471
|
|
|
1136
1472
|
# ---------------------------------------------------------------------------
|
|
1137
|
-
#
|
|
1138
|
-
# sagas (plan §U10). WORKSPACE_BUCKET env on the Lambda role already grants
|
|
1139
|
-
# the list+delete IAM; this schedule is the hourly trigger. The sweeper's
|
|
1140
|
-
# own cutoff constant (60 min) is independent of this cron cadence.
|
|
1473
|
+
# webhook_deliveries retention cron — daily delete of rows older than 90 days
|
|
1141
1474
|
# ---------------------------------------------------------------------------
|
|
1142
1475
|
|
|
1143
|
-
resource "aws_scheduler_schedule" "
|
|
1476
|
+
resource "aws_scheduler_schedule" "webhook_deliveries_cleanup" {
|
|
1144
1477
|
count = local.deploy_lambda_handlers ? 1 : 0
|
|
1145
1478
|
|
|
1146
|
-
name = "thinkwork-${var.stage}-
|
|
1479
|
+
name = "thinkwork-${var.stage}-webhook-deliveries-cleanup"
|
|
1147
1480
|
group_name = "default"
|
|
1148
|
-
schedule_expression = "
|
|
1481
|
+
schedule_expression = "cron(0 4 * * ? *)" # daily at 04:00 UTC
|
|
1149
1482
|
state = "ENABLED"
|
|
1150
1483
|
|
|
1151
1484
|
flexible_time_window {
|
|
@@ -1153,7 +1486,7 @@ resource "aws_scheduler_schedule" "plugin_staging_sweeper" {
|
|
|
1153
1486
|
}
|
|
1154
1487
|
|
|
1155
1488
|
target {
|
|
1156
|
-
arn = aws_lambda_function.handler["
|
|
1489
|
+
arn = aws_lambda_function.handler["webhook-deliveries-cleanup"].arn
|
|
1157
1490
|
role_arn = aws_iam_role.scheduler.arn
|
|
1158
1491
|
}
|
|
1159
1492
|
}
|
|
@@ -1257,17 +1590,16 @@ resource "aws_scheduler_schedule" "eval_runs_reconciler" {
|
|
|
1257
1590
|
}
|
|
1258
1591
|
|
|
1259
1592
|
# ---------------------------------------------------------------------------
|
|
1260
|
-
#
|
|
1261
|
-
#
|
|
1262
|
-
# heartbeat also reconciles its own stale runbook tasks while it is alive.
|
|
1593
|
+
# trace_invocation_reconciler — reconciles runtime LLM usage against Bedrock
|
|
1594
|
+
# invocation logs every 5 min. Idempotent at the source-evidence/fact level.
|
|
1263
1595
|
# ---------------------------------------------------------------------------
|
|
1264
1596
|
|
|
1265
|
-
resource "aws_scheduler_schedule" "
|
|
1597
|
+
resource "aws_scheduler_schedule" "trace_invocation_reconciler" {
|
|
1266
1598
|
count = local.deploy_lambda_handlers ? 1 : 0
|
|
1267
1599
|
|
|
1268
|
-
name = "thinkwork-${var.stage}-
|
|
1600
|
+
name = "thinkwork-${var.stage}-trace-invocation-reconciler"
|
|
1269
1601
|
group_name = "default"
|
|
1270
|
-
schedule_expression = "rate(
|
|
1602
|
+
schedule_expression = "rate(5 minutes)"
|
|
1271
1603
|
state = "ENABLED"
|
|
1272
1604
|
|
|
1273
1605
|
flexible_time_window {
|
|
@@ -1275,24 +1607,169 @@ resource "aws_scheduler_schedule" "stall_monitor" {
|
|
|
1275
1607
|
}
|
|
1276
1608
|
|
|
1277
1609
|
target {
|
|
1278
|
-
arn = aws_lambda_function.handler["
|
|
1610
|
+
arn = aws_lambda_function.handler["trace-invocation-reconciler"].arn
|
|
1279
1611
|
role_arn = aws_iam_role.scheduler.arn
|
|
1280
1612
|
}
|
|
1281
1613
|
}
|
|
1282
1614
|
|
|
1615
|
+
# Bedrock model invocation logs are the provider-observed evidence source for
|
|
1616
|
+
# trace invocation reconciliation. The Bedrock setting is account/region scoped,
|
|
1617
|
+
# so keep the destination stage-neutral and let each stage's reconciler match
|
|
1618
|
+
# only rows present in its own database. Because both the log group name and
|
|
1619
|
+
# the account logging configuration are singletons per account+region, only
|
|
1620
|
+
# ONE stage may manage them (var.manage_bedrock_invocation_logging) — a second
|
|
1621
|
+
# stack collides on the log group and would clobber, then destroy, the
|
|
1622
|
+
# account-level config out from under the managing stage (harness cycle-5).
|
|
1623
|
+
locals {
|
|
1624
|
+
bedrock_invocation_log_group_name = "/thinkwork/bedrock/model-invocations"
|
|
1625
|
+
bedrock_invocation_log_group_arn = "arn:aws:logs:${var.region}:${var.account_id}:log-group:/thinkwork/bedrock/model-invocations"
|
|
1626
|
+
}
|
|
1627
|
+
|
|
1628
|
+
# Adding count re-addressed these resources (`x` → `x[0]`); without moved
|
|
1629
|
+
# blocks, existing states (dev) plan destroy+create — losing invocation-log
|
|
1630
|
+
# history and racing the same-name recreate (the private_nat
|
|
1631
|
+
# RouteAlreadyExists failure class from the cycle-4 fix).
|
|
1632
|
+
moved {
|
|
1633
|
+
from = aws_cloudwatch_log_group.bedrock_model_invocations
|
|
1634
|
+
to = aws_cloudwatch_log_group.bedrock_model_invocations[0]
|
|
1635
|
+
}
|
|
1636
|
+
|
|
1637
|
+
moved {
|
|
1638
|
+
from = aws_iam_role.bedrock_model_invocation_logging
|
|
1639
|
+
to = aws_iam_role.bedrock_model_invocation_logging[0]
|
|
1640
|
+
}
|
|
1641
|
+
|
|
1642
|
+
moved {
|
|
1643
|
+
from = aws_iam_role_policy.bedrock_model_invocation_logging
|
|
1644
|
+
to = aws_iam_role_policy.bedrock_model_invocation_logging[0]
|
|
1645
|
+
}
|
|
1646
|
+
|
|
1647
|
+
moved {
|
|
1648
|
+
from = aws_bedrock_model_invocation_logging_configuration.this
|
|
1649
|
+
to = aws_bedrock_model_invocation_logging_configuration.this[0]
|
|
1650
|
+
}
|
|
1651
|
+
|
|
1652
|
+
resource "aws_cloudwatch_log_group" "bedrock_model_invocations" {
|
|
1653
|
+
count = var.manage_bedrock_invocation_logging ? 1 : 0
|
|
1654
|
+
name = local.bedrock_invocation_log_group_name
|
|
1655
|
+
retention_in_days = 30
|
|
1656
|
+
|
|
1657
|
+
tags = {
|
|
1658
|
+
Name = "thinkwork-bedrock-model-invocations"
|
|
1659
|
+
Stage = var.stage
|
|
1660
|
+
Component = "bedrock-model-invocation-logging"
|
|
1661
|
+
}
|
|
1662
|
+
}
|
|
1663
|
+
|
|
1664
|
+
resource "aws_iam_role" "bedrock_model_invocation_logging" {
|
|
1665
|
+
count = var.manage_bedrock_invocation_logging ? 1 : 0
|
|
1666
|
+
name = "thinkwork-${var.stage}-bedrock-model-invocation-logging"
|
|
1667
|
+
|
|
1668
|
+
assume_role_policy = jsonencode({
|
|
1669
|
+
Version = "2012-10-17"
|
|
1670
|
+
Statement = [
|
|
1671
|
+
{
|
|
1672
|
+
Effect = "Allow"
|
|
1673
|
+
Principal = {
|
|
1674
|
+
Service = "bedrock.amazonaws.com"
|
|
1675
|
+
}
|
|
1676
|
+
Action = "sts:AssumeRole"
|
|
1677
|
+
Condition = {
|
|
1678
|
+
StringEquals = {
|
|
1679
|
+
"aws:SourceAccount" = var.account_id
|
|
1680
|
+
}
|
|
1681
|
+
}
|
|
1682
|
+
},
|
|
1683
|
+
]
|
|
1684
|
+
})
|
|
1685
|
+
|
|
1686
|
+
tags = {
|
|
1687
|
+
Name = "thinkwork-${var.stage}-bedrock-model-invocation-logging"
|
|
1688
|
+
Stage = var.stage
|
|
1689
|
+
Component = "bedrock-model-invocation-logging"
|
|
1690
|
+
}
|
|
1691
|
+
}
|
|
1692
|
+
|
|
1693
|
+
resource "aws_iam_role_policy" "bedrock_model_invocation_logging" {
|
|
1694
|
+
count = var.manage_bedrock_invocation_logging ? 1 : 0
|
|
1695
|
+
name = "write-bedrock-model-invocation-logs"
|
|
1696
|
+
role = aws_iam_role.bedrock_model_invocation_logging[0].id
|
|
1697
|
+
|
|
1698
|
+
policy = jsonencode({
|
|
1699
|
+
Version = "2012-10-17"
|
|
1700
|
+
Statement = [
|
|
1701
|
+
{
|
|
1702
|
+
Sid = "WriteCloudWatchInvocationLogs"
|
|
1703
|
+
Effect = "Allow"
|
|
1704
|
+
Action = [
|
|
1705
|
+
"logs:CreateLogStream",
|
|
1706
|
+
"logs:DescribeLogStreams",
|
|
1707
|
+
"logs:PutLogEvents",
|
|
1708
|
+
]
|
|
1709
|
+
Resource = [
|
|
1710
|
+
local.bedrock_invocation_log_group_arn,
|
|
1711
|
+
"${local.bedrock_invocation_log_group_arn}:log-stream:aws/bedrock/modelinvocations",
|
|
1712
|
+
"${local.bedrock_invocation_log_group_arn}:log-stream:aws/bedrock/modelinvocations*",
|
|
1713
|
+
]
|
|
1714
|
+
},
|
|
1715
|
+
{
|
|
1716
|
+
Sid = "WriteLargeInvocationPayloads"
|
|
1717
|
+
Effect = "Allow"
|
|
1718
|
+
Action = [
|
|
1719
|
+
"s3:GetBucketLocation",
|
|
1720
|
+
"s3:ListBucket",
|
|
1721
|
+
]
|
|
1722
|
+
Resource = var.bucket_arn
|
|
1723
|
+
},
|
|
1724
|
+
{
|
|
1725
|
+
Sid = "PutLargeInvocationPayloads"
|
|
1726
|
+
Effect = "Allow"
|
|
1727
|
+
Action = "s3:PutObject"
|
|
1728
|
+
Resource = "${var.bucket_arn}/bedrock/model-invocation-logs/*"
|
|
1729
|
+
},
|
|
1730
|
+
]
|
|
1731
|
+
})
|
|
1732
|
+
}
|
|
1733
|
+
|
|
1734
|
+
resource "aws_bedrock_model_invocation_logging_configuration" "this" {
|
|
1735
|
+
count = var.manage_bedrock_invocation_logging ? 1 : 0
|
|
1736
|
+
|
|
1737
|
+
logging_config {
|
|
1738
|
+
text_data_delivery_enabled = true
|
|
1739
|
+
image_data_delivery_enabled = false
|
|
1740
|
+
embedding_data_delivery_enabled = false
|
|
1741
|
+
video_data_delivery_enabled = false
|
|
1742
|
+
|
|
1743
|
+
cloudwatch_config {
|
|
1744
|
+
log_group_name = aws_cloudwatch_log_group.bedrock_model_invocations[0].name
|
|
1745
|
+
role_arn = aws_iam_role.bedrock_model_invocation_logging[0].arn
|
|
1746
|
+
|
|
1747
|
+
large_data_delivery_s3_config {
|
|
1748
|
+
bucket_name = var.bucket_name
|
|
1749
|
+
key_prefix = "bedrock/model-invocation-logs/large/"
|
|
1750
|
+
}
|
|
1751
|
+
}
|
|
1752
|
+
|
|
1753
|
+
s3_config {
|
|
1754
|
+
bucket_name = var.bucket_name
|
|
1755
|
+
key_prefix = "bedrock/model-invocation-logs/"
|
|
1756
|
+
}
|
|
1757
|
+
}
|
|
1758
|
+
|
|
1759
|
+
depends_on = [aws_iam_role_policy.bedrock_model_invocation_logging]
|
|
1760
|
+
}
|
|
1761
|
+
|
|
1283
1762
|
# ---------------------------------------------------------------------------
|
|
1284
|
-
#
|
|
1285
|
-
#
|
|
1286
|
-
# bounded batches. The handler is conservative and records per-Computer events
|
|
1287
|
-
# for every attempted action.
|
|
1763
|
+
# cost_bill_reconciler — imports AWS billing export evidence daily. Targeted
|
|
1764
|
+
# operator invokes can reconcile a specific manifest/import immediately.
|
|
1288
1765
|
# ---------------------------------------------------------------------------
|
|
1289
1766
|
|
|
1290
|
-
resource "aws_scheduler_schedule" "
|
|
1767
|
+
resource "aws_scheduler_schedule" "cost_bill_reconciler" {
|
|
1291
1768
|
count = local.deploy_lambda_handlers ? 1 : 0
|
|
1292
1769
|
|
|
1293
|
-
name = "thinkwork-${var.stage}-
|
|
1770
|
+
name = "thinkwork-${var.stage}-cost-bill-reconciler"
|
|
1294
1771
|
group_name = "default"
|
|
1295
|
-
schedule_expression = "
|
|
1772
|
+
schedule_expression = "cron(30 5 * * ? *)"
|
|
1296
1773
|
state = "ENABLED"
|
|
1297
1774
|
|
|
1298
1775
|
flexible_time_window {
|
|
@@ -1300,17 +1777,23 @@ resource "aws_scheduler_schedule" "computer_runtime_reconciler" {
|
|
|
1300
1777
|
}
|
|
1301
1778
|
|
|
1302
1779
|
target {
|
|
1303
|
-
arn = aws_lambda_function.handler["
|
|
1780
|
+
arn = aws_lambda_function.handler["cost-bill-reconciler"].arn
|
|
1304
1781
|
role_arn = aws_iam_role.scheduler.arn
|
|
1305
1782
|
}
|
|
1306
1783
|
}
|
|
1307
1784
|
|
|
1308
|
-
|
|
1785
|
+
# ---------------------------------------------------------------------------
|
|
1786
|
+
# Stall monitor — marks stalled thread turns and runbook steps failed every
|
|
1787
|
+
# minute. This is the global backstop for agent/runtime crashes; the Computer
|
|
1788
|
+
# heartbeat also reconciles its own stale runbook tasks while it is alive.
|
|
1789
|
+
# ---------------------------------------------------------------------------
|
|
1790
|
+
|
|
1791
|
+
resource "aws_scheduler_schedule" "stall_monitor" {
|
|
1309
1792
|
count = local.deploy_lambda_handlers ? 1 : 0
|
|
1310
1793
|
|
|
1311
|
-
name = "thinkwork-${var.stage}-
|
|
1794
|
+
name = "thinkwork-${var.stage}-stall-monitor"
|
|
1312
1795
|
group_name = "default"
|
|
1313
|
-
schedule_expression = "rate(1
|
|
1796
|
+
schedule_expression = "rate(1 minutes)"
|
|
1314
1797
|
state = "ENABLED"
|
|
1315
1798
|
|
|
1316
1799
|
flexible_time_window {
|
|
@@ -1318,12 +1801,12 @@ resource "aws_scheduler_schedule" "slack_dispatch" {
|
|
|
1318
1801
|
}
|
|
1319
1802
|
|
|
1320
1803
|
target {
|
|
1321
|
-
arn = aws_lambda_function.handler["
|
|
1804
|
+
arn = aws_lambda_function.handler["cron-stall-monitor"].arn
|
|
1322
1805
|
role_arn = aws_iam_role.scheduler.arn
|
|
1323
|
-
input = jsonencode({ limit = 25 })
|
|
1324
1806
|
}
|
|
1325
1807
|
}
|
|
1326
1808
|
|
|
1809
|
+
|
|
1327
1810
|
# ---------------------------------------------------------------------------
|
|
1328
1811
|
# Compounding Memory — nightly hygiene + export
|
|
1329
1812
|
# ---------------------------------------------------------------------------
|
|
@@ -1346,6 +1829,29 @@ resource "aws_scheduler_schedule" "wiki_compile_drainer" {
|
|
|
1346
1829
|
}
|
|
1347
1830
|
}
|
|
1348
1831
|
|
|
1832
|
+
# Observations → Knowledge Graph sweep (plan 2026-06-09-004 U5). Enumerates
|
|
1833
|
+
# tenants and runs an incremental observations ingest per tenant; the stable
|
|
1834
|
+
# source_ref's active-run dedupe drops overlap with operator-started runs and
|
|
1835
|
+
# the in-handler stale-run reaper clears stranded rows past the run ceiling.
|
|
1836
|
+
resource "aws_scheduler_schedule" "knowledge_graph_observations_ingest" {
|
|
1837
|
+
count = local.deploy_lambda_handlers ? 1 : 0
|
|
1838
|
+
|
|
1839
|
+
name = "thinkwork-${var.stage}-knowledge-graph-observations-ingest"
|
|
1840
|
+
group_name = "default"
|
|
1841
|
+
schedule_expression = "rate(30 minutes)"
|
|
1842
|
+
state = "ENABLED"
|
|
1843
|
+
|
|
1844
|
+
flexible_time_window {
|
|
1845
|
+
mode = "OFF"
|
|
1846
|
+
}
|
|
1847
|
+
|
|
1848
|
+
target {
|
|
1849
|
+
arn = aws_lambda_function.handler["knowledge-graph-observations-ingest"].arn
|
|
1850
|
+
role_arn = aws_iam_role.scheduler.arn
|
|
1851
|
+
input = jsonencode({ sweep = true, trigger = "scheduled" })
|
|
1852
|
+
}
|
|
1853
|
+
}
|
|
1854
|
+
|
|
1349
1855
|
resource "aws_scheduler_schedule" "wiki_lint" {
|
|
1350
1856
|
count = local.deploy_lambda_handlers ? 1 : 0
|
|
1351
1857
|
|
|
@@ -1416,18 +1922,180 @@ resource "aws_s3_bucket_lifecycle_configuration" "wiki_exports" {
|
|
|
1416
1922
|
}
|
|
1417
1923
|
}
|
|
1418
1924
|
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1925
|
+
# Canonical Company Brain artifact store. Unlike wiki_exports, this bucket
|
|
1926
|
+
# is the durable replay/projection substrate for Brain source artifacts,
|
|
1927
|
+
# ingestion manifests, migration snapshots, vault projections, and exports.
|
|
1928
|
+
resource "aws_s3_bucket" "brain_artifacts" {
|
|
1929
|
+
bucket = "thinkwork-${var.stage}-brain-artifacts"
|
|
1930
|
+
force_destroy = var.stage == "dev"
|
|
1422
1931
|
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1932
|
+
tags = {
|
|
1933
|
+
Name = "thinkwork-${var.stage}-brain-artifacts"
|
|
1934
|
+
Purpose = "company-brain-artifacts"
|
|
1935
|
+
}
|
|
1936
|
+
}
|
|
1937
|
+
|
|
1938
|
+
resource "aws_s3_bucket_public_access_block" "brain_artifacts" {
|
|
1939
|
+
bucket = aws_s3_bucket.brain_artifacts.id
|
|
1940
|
+
block_public_acls = true
|
|
1941
|
+
block_public_policy = true
|
|
1942
|
+
ignore_public_acls = true
|
|
1943
|
+
restrict_public_buckets = true
|
|
1944
|
+
}
|
|
1945
|
+
|
|
1946
|
+
resource "aws_s3_bucket_versioning" "brain_artifacts" {
|
|
1947
|
+
bucket = aws_s3_bucket.brain_artifacts.id
|
|
1948
|
+
|
|
1949
|
+
versioning_configuration {
|
|
1950
|
+
status = "Enabled"
|
|
1951
|
+
}
|
|
1952
|
+
}
|
|
1953
|
+
|
|
1954
|
+
resource "aws_s3_bucket_server_side_encryption_configuration" "brain_artifacts" {
|
|
1955
|
+
bucket = aws_s3_bucket.brain_artifacts.id
|
|
1956
|
+
|
|
1957
|
+
rule {
|
|
1958
|
+
apply_server_side_encryption_by_default {
|
|
1959
|
+
sse_algorithm = var.brain_artifacts_kms_key_arn != "" ? "aws:kms" : "AES256"
|
|
1960
|
+
kms_master_key_id = var.brain_artifacts_kms_key_arn != "" ? var.brain_artifacts_kms_key_arn : null
|
|
1961
|
+
}
|
|
1962
|
+
|
|
1963
|
+
bucket_key_enabled = var.brain_artifacts_kms_key_arn != ""
|
|
1964
|
+
}
|
|
1965
|
+
}
|
|
1966
|
+
|
|
1967
|
+
resource "aws_s3_bucket_lifecycle_configuration" "brain_artifacts" {
|
|
1968
|
+
bucket = aws_s3_bucket.brain_artifacts.id
|
|
1969
|
+
|
|
1970
|
+
rule {
|
|
1971
|
+
id = "source-artifacts-transition"
|
|
1972
|
+
status = "Enabled"
|
|
1973
|
+
|
|
1974
|
+
filter {
|
|
1975
|
+
prefix = "source-artifacts/"
|
|
1976
|
+
}
|
|
1977
|
+
|
|
1978
|
+
transition {
|
|
1979
|
+
days = 90
|
|
1980
|
+
storage_class = "STANDARD_IA"
|
|
1981
|
+
}
|
|
1982
|
+
|
|
1983
|
+
noncurrent_version_transition {
|
|
1984
|
+
noncurrent_days = 90
|
|
1985
|
+
storage_class = "STANDARD_IA"
|
|
1986
|
+
}
|
|
1987
|
+
}
|
|
1988
|
+
|
|
1989
|
+
rule {
|
|
1990
|
+
id = "ingestion-manifests-transition"
|
|
1991
|
+
status = "Enabled"
|
|
1992
|
+
|
|
1993
|
+
filter {
|
|
1994
|
+
prefix = "ingestion-manifests/"
|
|
1995
|
+
}
|
|
1996
|
+
|
|
1997
|
+
transition {
|
|
1998
|
+
days = 90
|
|
1999
|
+
storage_class = "STANDARD_IA"
|
|
2000
|
+
}
|
|
2001
|
+
|
|
2002
|
+
noncurrent_version_transition {
|
|
2003
|
+
noncurrent_days = 90
|
|
2004
|
+
storage_class = "STANDARD_IA"
|
|
2005
|
+
}
|
|
2006
|
+
}
|
|
2007
|
+
|
|
2008
|
+
rule {
|
|
2009
|
+
id = "migration-snapshots-transition"
|
|
2010
|
+
status = "Enabled"
|
|
2011
|
+
|
|
2012
|
+
filter {
|
|
2013
|
+
prefix = "migration-snapshots/"
|
|
2014
|
+
}
|
|
2015
|
+
|
|
2016
|
+
transition {
|
|
2017
|
+
days = 90
|
|
2018
|
+
storage_class = "STANDARD_IA"
|
|
2019
|
+
}
|
|
2020
|
+
|
|
2021
|
+
noncurrent_version_transition {
|
|
2022
|
+
noncurrent_days = 90
|
|
2023
|
+
storage_class = "STANDARD_IA"
|
|
2024
|
+
}
|
|
2025
|
+
}
|
|
2026
|
+
|
|
2027
|
+
rule {
|
|
2028
|
+
id = "vault-projections-transition"
|
|
2029
|
+
status = "Enabled"
|
|
2030
|
+
|
|
2031
|
+
filter {
|
|
2032
|
+
prefix = "vault-projections/"
|
|
2033
|
+
}
|
|
2034
|
+
|
|
2035
|
+
transition {
|
|
2036
|
+
days = 90
|
|
2037
|
+
storage_class = "STANDARD_IA"
|
|
2038
|
+
}
|
|
2039
|
+
|
|
2040
|
+
noncurrent_version_transition {
|
|
2041
|
+
noncurrent_days = 90
|
|
2042
|
+
storage_class = "STANDARD_IA"
|
|
2043
|
+
}
|
|
2044
|
+
}
|
|
2045
|
+
|
|
2046
|
+
rule {
|
|
2047
|
+
id = "exports-expiration"
|
|
2048
|
+
status = "Enabled"
|
|
2049
|
+
|
|
2050
|
+
filter {
|
|
2051
|
+
prefix = "exports/"
|
|
2052
|
+
}
|
|
2053
|
+
|
|
2054
|
+
transition {
|
|
2055
|
+
days = 30
|
|
2056
|
+
storage_class = "STANDARD_IA"
|
|
2057
|
+
}
|
|
2058
|
+
|
|
2059
|
+
expiration {
|
|
2060
|
+
days = 365
|
|
2061
|
+
}
|
|
2062
|
+
|
|
2063
|
+
noncurrent_version_expiration {
|
|
2064
|
+
noncurrent_days = 365
|
|
2065
|
+
}
|
|
2066
|
+
}
|
|
2067
|
+
}
|
|
2068
|
+
|
|
2069
|
+
data "aws_iam_policy_document" "brain_artifacts_bucket" {
|
|
2070
|
+
statement {
|
|
2071
|
+
sid = "DenyInsecureTransport"
|
|
2072
|
+
effect = "Deny"
|
|
2073
|
+
|
|
2074
|
+
principals {
|
|
2075
|
+
type = "*"
|
|
2076
|
+
identifiers = ["*"]
|
|
2077
|
+
}
|
|
2078
|
+
|
|
2079
|
+
actions = ["s3:*"]
|
|
2080
|
+
|
|
2081
|
+
resources = [
|
|
2082
|
+
aws_s3_bucket.brain_artifacts.arn,
|
|
2083
|
+
"${aws_s3_bucket.brain_artifacts.arn}/*",
|
|
2084
|
+
]
|
|
2085
|
+
|
|
2086
|
+
condition {
|
|
2087
|
+
test = "Bool"
|
|
2088
|
+
variable = "aws:SecureTransport"
|
|
2089
|
+
values = ["false"]
|
|
2090
|
+
}
|
|
2091
|
+
}
|
|
2092
|
+
}
|
|
2093
|
+
|
|
2094
|
+
resource "aws_s3_bucket_policy" "brain_artifacts" {
|
|
2095
|
+
bucket = aws_s3_bucket.brain_artifacts.id
|
|
2096
|
+
policy = data.aws_iam_policy_document.brain_artifacts_bucket.json
|
|
2097
|
+
|
|
2098
|
+
depends_on = [aws_s3_bucket_public_access_block.brain_artifacts]
|
|
1431
2099
|
}
|
|
1432
2100
|
|
|
1433
2101
|
resource "aws_iam_role" "scheduler" {
|
|
@@ -1462,20 +2130,16 @@ resource "aws_iam_role_policy" "scheduler_invoke" {
|
|
|
1462
2130
|
Statement = [{
|
|
1463
2131
|
Effect = "Allow"
|
|
1464
2132
|
Action = ["lambda:InvokeFunction"]
|
|
1465
|
-
#
|
|
1466
|
-
#
|
|
1467
|
-
#
|
|
1468
|
-
#
|
|
1469
|
-
#
|
|
1470
|
-
#
|
|
1471
|
-
#
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
[for k, v in aws_lambda_function.handler : v.arn],
|
|
1476
|
-
aws_lambda_function.compliance_anchor[*].arn,
|
|
1477
|
-
aws_lambda_function.compliance_anchor_watchdog[*].arn,
|
|
1478
|
-
) : []
|
|
2133
|
+
# One name-pattern wildcard instead of enumerating every handler ARN:
|
|
2134
|
+
# the enumerated form scaled with handler count × stage-name length and
|
|
2135
|
+
# blew IAM's 10,240-byte inline-policy cap for stages ≥ ~11 characters
|
|
2136
|
+
# (harness cycle-7 ledger entry; dev's 3-char stage never saw it). The
|
|
2137
|
+
# api- prefix covers every for_each handler plus the standalone
|
|
2138
|
+
# compliance-anchor and watchdog Lambdas (all named
|
|
2139
|
+
# thinkwork-<stage>-api-*).
|
|
2140
|
+
Resource = local.deploy_lambda_handlers ? [
|
|
2141
|
+
"arn:aws:lambda:${var.region}:${var.account_id}:function:thinkwork-${var.stage}-api-*",
|
|
2142
|
+
] : []
|
|
1479
2143
|
}]
|
|
1480
2144
|
})
|
|
1481
2145
|
}
|
|
@@ -1512,6 +2176,46 @@ resource "aws_ssm_parameter" "google_places_api_key" {
|
|
|
1512
2176
|
}
|
|
1513
2177
|
}
|
|
1514
2178
|
|
|
2179
|
+
########################################################################
|
|
2180
|
+
# SecureString parameter for the graphql-http Lambda's OWN Cloudflare
|
|
2181
|
+
# namespace token (plan 2026-06-12-002 U5, KTD7). Tenant slug validation
|
|
2182
|
+
# lists records under <slug>.thinkwork.ai so signup cannot take a name
|
|
2183
|
+
# delegated to a customer deployment. The token is zone-scoped DNS:Edit
|
|
2184
|
+
# on thinkwork.ai, minted SEPARATELY from the CI CLOUDFLARE_API_TOKEN
|
|
2185
|
+
# (independent rotation; a signup-path compromise doesn't burn CI), and
|
|
2186
|
+
# is deliberately NOT a Lambda env var — graphql-http's env sits at the
|
|
2187
|
+
# 4KB ceiling (#2375) — nor a runtime-config document key (secrets stay
|
|
2188
|
+
# out of the plain String document).
|
|
2189
|
+
#
|
|
2190
|
+
# Seeded with a placeholder: @thinkwork/api treats the placeholder (or a
|
|
2191
|
+
# missing parameter) as "namespace check unconfigured" and SKIPS the
|
|
2192
|
+
# Cloudflare leg with a loud log (ship-inert posture, so pre-token dev
|
|
2193
|
+
# stages keep creating tenants). The customer-domain runbook makes the
|
|
2194
|
+
# real token mandatory for stages whose deployments share the namespace.
|
|
2195
|
+
# Populate/rotate via:
|
|
2196
|
+
# aws ssm put-parameter --overwrite \
|
|
2197
|
+
# --name /thinkwork/<stage>/cloudflare-namespace-token \
|
|
2198
|
+
# --type SecureString --value <TOKEN>
|
|
2199
|
+
#
|
|
2200
|
+
# IAM: read access rides the existing ssm:GetParameter grant on
|
|
2201
|
+
# parameter/thinkwork/<stage>/* in aws_iam_policy.api_data_plane
|
|
2202
|
+
# (iam-grouped.tf), plus its kms:Decrypt-via-SSM statement.
|
|
2203
|
+
########################################################################
|
|
2204
|
+
|
|
2205
|
+
resource "aws_ssm_parameter" "cloudflare_namespace_token" {
|
|
2206
|
+
name = "/thinkwork/${var.stage}/cloudflare-namespace-token"
|
|
2207
|
+
type = "SecureString"
|
|
2208
|
+
value = "PLACEHOLDER_SET_VIA_CLI"
|
|
2209
|
+
description = "Zone-scoped Cloudflare DNS:Edit token for the thinkwork.ai namespace signup check (plan 2026-06-12-002 U5/KTD7). Placeholder = check skipped; set the real token via CLI."
|
|
2210
|
+
|
|
2211
|
+
lifecycle {
|
|
2212
|
+
# Initial population and rotation happen via `aws ssm put-parameter
|
|
2213
|
+
# --overwrite`, never via terraform var (the value must not transit
|
|
2214
|
+
# tfvars / state more than necessary).
|
|
2215
|
+
ignore_changes = [value]
|
|
2216
|
+
}
|
|
2217
|
+
}
|
|
2218
|
+
|
|
1515
2219
|
resource "aws_ssm_parameter" "lambda_arns" {
|
|
1516
2220
|
for_each = local.deploy_lambda_handlers ? {
|
|
1517
2221
|
"chat-agent-invoke-fn-arn" = aws_lambda_function.handler["chat-agent-invoke"].arn
|
|
@@ -1816,24 +2520,6 @@ resource "aws_sqs_queue" "compliance_exports" {
|
|
|
1816
2520
|
}
|
|
1817
2521
|
}
|
|
1818
2522
|
|
|
1819
|
-
# graphql-http needs sqs:SendMessage on the new queue to dispatch jobIds
|
|
1820
|
-
# from the createComplianceExport mutation. Attached to the shared
|
|
1821
|
-
# lambda role (which graphql-http assumes); scope is queue-specific.
|
|
1822
|
-
resource "aws_iam_role_policy" "compliance_exports_send" {
|
|
1823
|
-
count = local.deploy_lambda_handlers ? 1 : 0
|
|
1824
|
-
name = "compliance-exports-send"
|
|
1825
|
-
role = aws_iam_role.lambda.id
|
|
1826
|
-
|
|
1827
|
-
policy = jsonencode({
|
|
1828
|
-
Version = "2012-10-17"
|
|
1829
|
-
Statement = [{
|
|
1830
|
-
Effect = "Allow"
|
|
1831
|
-
Action = ["sqs:SendMessage"]
|
|
1832
|
-
Resource = aws_sqs_queue.compliance_exports[0].arn
|
|
1833
|
-
}]
|
|
1834
|
-
})
|
|
1835
|
-
}
|
|
1836
|
-
|
|
1837
2523
|
# Runner role's SQS receive grants — only the runner consumes the queue.
|
|
1838
2524
|
resource "aws_iam_role_policy" "compliance_exports_runner_sqs" {
|
|
1839
2525
|
count = local.deploy_lambda_handlers ? 1 : 0
|
|
@@ -1937,78 +2623,3 @@ resource "aws_cloudwatch_metric_alarm" "compliance_exports_dlq_depth" {
|
|
|
1937
2623
|
QueueName = aws_sqs_queue.compliance_exports_dlq[0].name
|
|
1938
2624
|
}
|
|
1939
2625
|
}
|
|
1940
|
-
|
|
1941
|
-
# ---------------------------------------------------------------------------
|
|
1942
|
-
# workspace-files-efs — STANDALONE Lambda that reads any Computer's workspace
|
|
1943
|
-
# files directly off the shared EFS file system. Bypasses the
|
|
1944
|
-
# computer_tasks queue for list/get operations so the admin Computer
|
|
1945
|
-
# Workspace tab is independent of runtime liveness or write-queue backlog.
|
|
1946
|
-
#
|
|
1947
|
-
# Plan: docs/plans/2026-05-13-XXX-feat-admin-computer-efs-listing-plan.md
|
|
1948
|
-
#
|
|
1949
|
-
# The Lambda mounts the `workspace_admin` access point at /mnt/efs. That
|
|
1950
|
-
# access point is rooted at /tenants on the shared EFS, so the handler
|
|
1951
|
-
# can address any Computer's workspace as
|
|
1952
|
-
# /mnt/efs/<tenantId>/computers/<computerId>/<path...>
|
|
1953
|
-
# (matches the layout written by `computerWorkspacePath` in
|
|
1954
|
-
# packages/api/src/lib/computers/runtime-control.ts:40).
|
|
1955
|
-
#
|
|
1956
|
-
# VPC config: same subnet set the Computer ECS tasks use (so the mount
|
|
1957
|
-
# targets are reachable). Dedicated security group with an EFS-SG ingress
|
|
1958
|
-
# rule defined as a sibling of the task-SG rule in the computer-runtime
|
|
1959
|
-
# module — keeps Lambda traffic auditable separately.
|
|
1960
|
-
#
|
|
1961
|
-
# Writes intentionally stay on the existing computer_tasks queue path.
|
|
1962
|
-
# Mutations have ordering semantics with the runtime's in-process state;
|
|
1963
|
-
# changing them is out of scope for this PR.
|
|
1964
|
-
# ---------------------------------------------------------------------------
|
|
1965
|
-
|
|
1966
|
-
resource "aws_lambda_function" "workspace_files_efs" {
|
|
1967
|
-
count = local.deploy_lambda_handlers ? 1 : 0
|
|
1968
|
-
|
|
1969
|
-
function_name = "thinkwork-${var.stage}-api-workspace-files-efs"
|
|
1970
|
-
role = aws_iam_role.lambda.arn
|
|
1971
|
-
handler = "index.handler"
|
|
1972
|
-
runtime = local.runtime
|
|
1973
|
-
timeout = 30
|
|
1974
|
-
memory_size = 512
|
|
1975
|
-
|
|
1976
|
-
filename = local.use_local_zips ? "${var.lambda_zips_dir}/workspace-files-efs.zip" : null
|
|
1977
|
-
source_code_hash = local.use_local_zips ? filebase64sha256("${var.lambda_zips_dir}/workspace-files-efs.zip") : null
|
|
1978
|
-
s3_bucket = local.use_remote_lambda_artifacts ? var.lambda_artifact_bucket : null
|
|
1979
|
-
s3_key = local.use_remote_lambda_artifacts ? "${local.lambda_artifact_prefix}/workspace-files-efs.zip" : null
|
|
1980
|
-
|
|
1981
|
-
vpc_config {
|
|
1982
|
-
subnet_ids = var.computer_runtime_subnet_ids
|
|
1983
|
-
security_group_ids = [var.workspace_admin_lambda_sg_id]
|
|
1984
|
-
}
|
|
1985
|
-
|
|
1986
|
-
file_system_config {
|
|
1987
|
-
arn = var.workspace_admin_efs_access_point_arn
|
|
1988
|
-
local_mount_path = "/mnt/efs"
|
|
1989
|
-
}
|
|
1990
|
-
|
|
1991
|
-
environment {
|
|
1992
|
-
variables = {
|
|
1993
|
-
STAGE = var.stage
|
|
1994
|
-
AWS_NODEJS_CONNECTION_REUSE_ENABLED = "1"
|
|
1995
|
-
WORKSPACE_EFS_ROOT = "/mnt/efs"
|
|
1996
|
-
}
|
|
1997
|
-
}
|
|
1998
|
-
|
|
1999
|
-
tags = {
|
|
2000
|
-
Name = "thinkwork-${var.stage}-api-workspace-files-efs"
|
|
2001
|
-
Handler = "workspace-files-efs"
|
|
2002
|
-
}
|
|
2003
|
-
}
|
|
2004
|
-
|
|
2005
|
-
# VPC-attached Lambdas need permission to manage ENIs. The shared lambda
|
|
2006
|
-
# role doesn't grant this by default because most handlers run outside a
|
|
2007
|
-
# VPC. AWSLambdaVPCAccessExecutionRole gives Create/Describe/DeleteNetwork
|
|
2008
|
-
# Interface — minimum scope for VPC Lambdas.
|
|
2009
|
-
resource "aws_iam_role_policy_attachment" "lambda_vpc_access" {
|
|
2010
|
-
count = local.deploy_lambda_handlers ? 1 : 0
|
|
2011
|
-
|
|
2012
|
-
role = aws_iam_role.lambda.name
|
|
2013
|
-
policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole"
|
|
2014
|
-
}
|