@atmem/architect 0.0.0-stage → 0.2.0-alpha.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CONSTITUTION.md +144 -0
- package/README.md +33 -2
- package/agent-skills/discovery/SKILL.md +48 -0
- package/agent-skills/discovery/topics.json +139 -0
- package/agent-skills/generation-capabilities.json +760 -0
- package/agent-skills/service-lifecycle.json +21 -0
- package/agent-skills/specialists/architecture/SKILL.md +15 -0
- package/agent-skills/specialists/aws/SKILL.md +17 -0
- package/agent-skills/specialists/azure/SKILL.md +7 -0
- package/agent-skills/specialists/composition/SKILL.md +17 -0
- package/agent-skills/specialists/devops/SKILL.md +10 -0
- package/agent-skills/specialists/finops/SKILL.md +7 -0
- package/agent-skills/specialists/gcp/SKILL.md +7 -0
- package/agent-skills/specialists/ibm/SKILL.md +7 -0
- package/agent-skills/specialists/manifest.json +13 -0
- package/agent-skills/specialists/pulumi/SKILL.md +7 -0
- package/agent-skills/specialists/security/SKILL.md +7 -0
- package/agent-skills/specialists/terraform/SKILL.md +14 -0
- package/agent-skills/upstream/aws/LICENSE +175 -0
- package/agent-skills/upstream/aws/SKILL.md +125 -0
- package/agent-skills/upstream/azure/LICENSE +21 -0
- package/agent-skills/upstream/azure/SKILL.md +387 -0
- package/agent-skills/upstream/gcp/LICENSE +202 -0
- package/agent-skills/upstream/gcp/SKILL.md +159 -0
- package/agent-skills/upstream/manifest.json +57 -0
- package/agent-skills/upstream/pulumi/LICENSE +201 -0
- package/agent-skills/upstream/pulumi/SKILL.md +501 -0
- package/agent-skills/upstream/terraform/LICENSE +373 -0
- package/agent-skills/upstream/terraform/SKILL.md +316 -0
- package/agent-skills/workflows/workflows.json +601 -0
- package/cli/architect.mjs +3 -0
- package/cli/runtime.mjs +115 -0
- package/dist/assets/html2canvas.esm-QH1iLAAe.js +22 -0
- package/dist/assets/index-B97MkVMs.css +1 -0
- package/dist/assets/index-qtCM2D7O.js +21271 -0
- package/dist/assets/index.es-C6C0sneB.js +18 -0
- package/dist/assets/purify.es-CAi2OJFm.js +3 -0
- package/dist/assets/visual-export-DjbjgQbA.js +173 -0
- package/dist/favicon.svg +2 -0
- package/dist/fonts/DM-Sans-OFL.txt +93 -0
- package/dist/fonts/Manrope-OFL.txt +93 -0
- package/dist/fonts/NotoSans-Regular.ttf +0 -0
- package/dist/fonts/OFL.txt +94 -0
- package/dist/fonts/dm-sans-latin-wght-normal.woff2 +0 -0
- package/dist/fonts/manrope-latin-wght-normal.woff2 +0 -0
- package/dist/index.html +4 -0
- package/dist/licenses/aws-architect-LICENSE.txt +17 -0
- package/dist/licenses/aws-mcp-LICENSE.txt +175 -0
- package/dist/licenses/aws-mcp-NOTICE.txt +1 -0
- package/dist/licenses/cloud-emulation-notices.txt +36619 -0
- package/dist/licenses/dependency-notices.txt +6379 -0
- package/dist/licenses/emulation-notices.txt +717 -0
- package/dist/licenses/github-copilot-sdk-LICENSE.txt +21 -0
- package/dist/licenses/memory-dependency-notices.txt +3319 -0
- package/dist/licenses/openarchflow-LICENSE.txt +21 -0
- package/dist/licenses/python-dependency-notices.txt +11951 -0
- package/docs/upstream-lock.json +26 -0
- package/knowledge/engineering-practices.json +536 -0
- package/package.json +30 -4
- package/packaging/uv-release-lock.json +54 -0
- package/public/licenses/aws-architect-LICENSE.txt +17 -0
- package/public/licenses/aws-mcp-LICENSE.txt +175 -0
- package/public/licenses/aws-mcp-NOTICE.txt +1 -0
- package/public/licenses/cloud-emulation-notices.txt +36619 -0
- package/public/licenses/dependency-notices.txt +6379 -0
- package/public/licenses/emulation-notices.txt +717 -0
- package/public/licenses/github-copilot-sdk-LICENSE.txt +21 -0
- package/public/licenses/memory-dependency-notices.txt +3319 -0
- package/public/licenses/openarchflow-LICENSE.txt +21 -0
- package/public/licenses/python-dependency-notices.txt +11951 -0
- package/scripts/terraform-render.mjs +8 -0
- package/server/__init__.py +0 -0
- package/server/abstraction.py +28 -0
- package/server/agent_runtime.py +153 -0
- package/server/app.py +257 -0
- package/server/architect.py +112 -0
- package/server/architecture_activity.py +67 -0
- package/server/attachments.py +101 -0
- package/server/cloud-emulation-requirements.txt +29 -0
- package/server/codex_app_server.py +219 -0
- package/server/codex_engineering_backend.py +266 -0
- package/server/codex_worker_policy.py +170 -0
- package/server/contracts.py +315 -0
- package/server/copilot_worker.py +16 -0
- package/server/dependency_mirror.py +54 -0
- package/server/design_patch.py +43 -0
- package/server/emulation-requirements.txt +8 -0
- package/server/emulation_adapters.py +20 -0
- package/server/emulation_routes.py +98 -0
- package/server/emulation_worker.py +351 -0
- package/server/engineering_artifacts.py +215 -0
- package/server/engineering_assets/application-runtime.json +4372 -0
- package/server/engineering_assets/architecture_work.schema.json +79 -0
- package/server/engineering_assets/materialize_runtime.py +62 -0
- package/server/engineering_assets/prepare_tools.py +96 -0
- package/server/engineering_assets/sql_validation.py +59 -0
- package/server/engineering_contexts.py +120 -0
- package/server/engineering_delivery.py +210 -0
- package/server/engineering_finalization.py +210 -0
- package/server/engineering_handoff.py +163 -0
- package/server/engineering_jobs.py +206 -0
- package/server/engineering_knowledge.py +75 -0
- package/server/engineering_reconciliation.py +159 -0
- package/server/engineering_routes.py +469 -0
- package/server/engineering_sessions.py +273 -0
- package/server/engineering_tools.py +166 -0
- package/server/generation_lint.py +18 -0
- package/server/local_providers.py +181 -0
- package/server/local_validation.py +236 -0
- package/server/memory-requirements.lock +181 -0
- package/server/memory-requirements.txt +6 -0
- package/server/memory_routes.py +82 -0
- package/server/memory_service.py +273 -0
- package/server/memory_worker.py +66 -0
- package/server/openai_voice.py +80 -0
- package/server/packaged_app.py +9 -0
- package/server/pricing.py +84 -0
- package/server/process_control_observation.py +31 -0
- package/server/prompts.py +123 -0
- package/server/public_faq_emulation_worker.py +44 -0
- package/server/requirements.lock +1618 -0
- package/server/requirements.txt +68 -0
- package/server/runtime_dependency_locks.py +27 -0
- package/server/runtime_evidence.py +93 -0
- package/server/settings.py +14 -0
- package/server/skills.py +103 -0
- package/server/storage_emulation_worker.py +160 -0
- package/server/structured_emulation_worker.py +48 -0
- package/server/terraform_routes.py +118 -0
- package/server/upstream/__init__.py +0 -0
- package/server/upstream/agent/__init__.py +1 -0
- package/server/upstream/agent/aws_architect.py +600 -0
- package/server/upstream/agent/config/__init__.py +1 -0
- package/server/upstream/agent/config/agent_config.py +82 -0
- package/server/upstream/agent/config/prompts.py +138 -0
- package/server/upstream/agent/rate_limiter.py +62 -0
- package/server/upstream/utils/__init__.py +1 -0
- package/server/upstream/utils/file_writer.py +43 -0
- package/server/validation_applicability.py +85 -0
- package/server/validation_jobs.py +252 -0
- package/server/validation_workers.py +48 -0
- package/server/voice_routes.py +91 -0
- package/server/voice_worker.py +26 -0
- package/specs/028-convergence-evaluation/evidence/20261110-ibm-invoice-native/registry-structured/qualification.json +72 -0
- package/specs/028-convergence-evaluation/evidence/20261110-invoice-runtime/durable-current/receipt.json +61 -0
- package/specs/029-general-purpose-engine/evidence/20261111-runtime-dependencies/sdk/receipt.json +22 -0
- package/src/ArchitectureActivity.jsx +54 -0
- package/src/ArchitectureWorkPanel.jsx +46 -0
- package/src/ArtifactChecks.jsx +49 -0
- package/src/BlockRequirements.jsx +13 -0
- package/src/BrainActivity.jsx +11 -0
- package/src/ChatMessage.jsx +19 -0
- package/src/ChatResizeHandle.jsx +6 -0
- package/src/CodePreview.jsx +8 -0
- package/src/ComponentReview.jsx +31 -0
- package/src/DeliveryViews.jsx +59 -0
- package/src/EmulationPanel.jsx +44 -0
- package/src/EngagementViews.jsx +385 -0
- package/src/EngineeringPanel.jsx +151 -0
- package/src/ImplementationDelivery.jsx +55 -0
- package/src/JourneyViews.jsx +400 -0
- package/src/MemoryPanel.jsx +46 -0
- package/src/OpenAIVoicePanel.jsx +65 -0
- package/src/OutputsView.jsx +65 -0
- package/src/TerraformView.jsx +57 -0
- package/src/WorkbenchDialogs.jsx +532 -0
- package/src/activity-presentation.mjs +28 -0
- package/src/ai-qualification-scenarios.mjs +31 -0
- package/src/approval-application-files.mjs +32 -0
- package/src/approval-applications.mjs +82 -0
- package/src/approval-spec-kit.mjs +30 -0
- package/src/architecture-activity.css +28 -0
- package/src/architecture-activity.mjs +63 -0
- package/src/architecture-work.mjs +176 -0
- package/src/artifact-work.mjs +103 -0
- package/src/async-documents.mjs +191 -0
- package/src/atflow.css +1140 -0
- package/src/atforma.css +748 -0
- package/src/atmem-tokens.css +79 -0
- package/src/aws-preflight.mjs +60 -0
- package/src/aws-public-faq.mjs +102 -0
- package/src/aws-validation-scenarios.mjs +10 -0
- package/src/aws-validation.mjs +48 -0
- package/src/azure-plan-mocks.mjs +25 -0
- package/src/azure-structured.mjs +133 -0
- package/src/bedrock-summary.mjs +152 -0
- package/src/bounded-rag.mjs +60 -0
- package/src/brand.css +9 -0
- package/src/canvas-view.mjs +28 -0
- package/src/capability-composition.mjs +44 -0
- package/src/chat-attachments.mjs +13 -0
- package/src/cloud-provider-locks.mjs +9 -0
- package/src/cloud-storage-scenarios.mjs +2 -0
- package/src/component-review.mjs +55 -0
- package/src/composition-spec-kit.mjs +30 -0
- package/src/consultation-context.mjs +15 -0
- package/src/consultation.mjs +52 -0
- package/src/container-contracts.mjs +5 -0
- package/src/container-inspection.mjs +75 -0
- package/src/container-runtime.mjs +30 -0
- package/src/container-security-inspection.mjs +49 -0
- package/src/container-terraform.mjs +109 -0
- package/src/conversation.mjs +17 -0
- package/src/core.mjs +863 -0
- package/src/cross-cloud-storage.mjs +100 -0
- package/src/delivery-capabilities.mjs +25 -0
- package/src/delivery.mjs +58 -0
- package/src/deployment-ownership.mjs +10 -0
- package/src/deployment-region.mjs +11 -0
- package/src/derive.mjs +31 -0
- package/src/design-build-flow.mjs +10 -0
- package/src/diagram-attention.mjs +24 -0
- package/src/discovery.mjs +359 -0
- package/src/document.mjs +170 -0
- package/src/emulation-feedback.mjs +61 -0
- package/src/emulation-guidance.mjs +37 -0
- package/src/engagement.mjs +274 -0
- package/src/engineering-client.mjs +73 -0
- package/src/engineering-defaults.mjs +17 -0
- package/src/engineering.css +31 -0
- package/src/enterprise-application.mjs +76 -0
- package/src/enterprise-aws-host-infrastructure.mjs +62 -0
- package/src/enterprise-aws-host-tests.mjs +15 -0
- package/src/enterprise-aws-infrastructure-tests.mjs +38 -0
- package/src/enterprise-aws-infrastructure.mjs +138 -0
- package/src/enterprise-google-infrastructure.mjs +84 -0
- package/src/enterprise-google-tests.mjs +25 -0
- package/src/estimate.mjs +188 -0
- package/src/existing-references.mjs +18 -0
- package/src/external-identities.mjs +17 -0
- package/src/faq-lambda-build.mjs +28 -0
- package/src/gcp-structured.mjs +104 -0
- package/src/generation-provider.mjs +7 -0
- package/src/generation-quality.mjs +69 -0
- package/src/handoff.mjs +141 -0
- package/src/ibm-registry.mjs +12 -0
- package/src/ibm-structured.mjs +103 -0
- package/src/identifiers.mjs +15 -0
- package/src/implementation-map.mjs +14 -0
- package/src/implementation-outcome.mjs +8 -0
- package/src/incomplete-terraform.mjs +9 -0
- package/src/integrations.ts +137 -0
- package/src/interface-contracts.mjs +30 -0
- package/src/invoice-application.mjs +66 -0
- package/src/invoice-aws-operations.mjs +136 -0
- package/src/invoice-aws.mjs +143 -0
- package/src/invoice-azure-operations.mjs +147 -0
- package/src/invoice-azure.mjs +134 -0
- package/src/invoice-builder.mjs +35 -0
- package/src/invoice-dependencies.mjs +43 -0
- package/src/invoice-gcp-operations.mjs +178 -0
- package/src/invoice-gcp.mjs +104 -0
- package/src/invoice-ibm-operations.mjs +278 -0
- package/src/invoice-ibm.mjs +142 -0
- package/src/invoice-operations.mjs +143 -0
- package/src/invoice-plan.mjs +45 -0
- package/src/invoice-region.mjs +6 -0
- package/src/invoice-spec-kit.mjs +61 -0
- package/src/invoice-state.mjs +7 -0
- package/src/invoice-terraform.mjs +29 -0
- package/src/invoice-tests.mjs +122 -0
- package/src/journey-workspace.css +72 -0
- package/src/journey.mjs +87 -0
- package/src/levels.mjs +145 -0
- package/src/local-agent.mjs +184 -0
- package/src/main.jsx +2458 -0
- package/src/model-policy-preflight.mjs +34 -0
- package/src/openai-voice.mjs +102 -0
- package/src/output-bundle.mjs +11 -0
- package/src/ownership-inspection.mjs +28 -0
- package/src/pack.mjs +201 -0
- package/src/pricing.mjs +31 -0
- package/src/production-state.mjs +8 -0
- package/src/project-copy.mjs +10 -0
- package/src/project-file.mjs +160 -0
- package/src/project-links.mjs +3 -0
- package/src/protected-state.mjs +43 -0
- package/src/public-faq-builder.mjs +19 -0
- package/src/public-faq-clouds.mjs +251 -0
- package/src/public-faq.mjs +122 -0
- package/src/pulumi.mjs +123 -0
- package/src/python-container.mjs +25 -0
- package/src/python-runtime.mjs +50 -0
- package/src/rag-handler.mjs +43 -0
- package/src/rag-web-assets.mjs +52 -0
- package/src/rag-web.mjs +68 -0
- package/src/records.mjs +177 -0
- package/src/resources.mjs +163 -0
- package/src/review.mjs +252 -0
- package/src/runtime/EnterpriseDocument.java +89 -0
- package/src/runtime/approved_http_destination.py +72 -0
- package/src/runtime/aws-lambda-qualification-lock.json +7 -0
- package/src/runtime/aws-python-lock.json +82 -0
- package/src/runtime/aws-web-python-lock.json +887 -0
- package/src/runtime/aws_json_model.py +42 -0
- package/src/runtime/azure-python-lock.json +863 -0
- package/src/runtime/azure-sources.json +8 -0
- package/src/runtime/azure-test-lock.json +23 -0
- package/src/runtime/azure_acceptance.py +192 -0
- package/src/runtime/azure_structured.py +153 -0
- package/src/runtime/bounded_rag.py +126 -0
- package/src/runtime/catalog_admin.py +70 -0
- package/src/runtime/cloud-sql-proxy-lock.json +8 -0
- package/src/runtime/cloud-sql-proxy-security-review.json +30 -0
- package/src/runtime/connector_cli.py +50 -0
- package/src/runtime/connector_sync.py +70 -0
- package/src/runtime/durable-python-lock.json +247 -0
- package/src/runtime/durable_workflow.py +325 -0
- package/src/runtime/enterprise-application-manifest.json +110 -0
- package/src/runtime/enterprise-application-sources.json +266 -0
- package/src/runtime/enterprise-auth-python-lock.json +592 -0
- package/src/runtime/enterprise-aws-host-bootstrap-source.json +1 -0
- package/src/runtime/enterprise-aws-host-probe-source.json +1 -0
- package/src/runtime/enterprise-aws-task-template.json +235 -0
- package/src/runtime/enterprise-document-lock.json +18 -0
- package/src/runtime/enterprise-document.Dockerfile +15 -0
- package/src/runtime/enterprise-runtime-aws-python-lock.json +1115 -0
- package/src/runtime/enterprise-runtime-azure-python-lock.json +1106 -0
- package/src/runtime/enterprise-runtime-gcp-python-lock.json +1060 -0
- package/src/runtime/enterprise-runtime-ibm-python-lock.json +1096 -0
- package/src/runtime/enterprise-runtime-python-lock.json +1058 -0
- package/src/runtime/enterprise-runtime.Dockerfile +15 -0
- package/src/runtime/enterprise-web-app.js +1 -0
- package/src/runtime/enterprise-web-entry.js +105 -0
- package/src/runtime/enterprise-web-lock.json +29 -0
- package/src/runtime/enterprise-web-notices.txt +229 -0
- package/src/runtime/enterprise-web.css +4 -0
- package/src/runtime/enterprise-web.html +8 -0
- package/src/runtime/enterprise_audit.py +91 -0
- package/src/runtime/enterprise_audit_schema.sql +25 -0
- package/src/runtime/enterprise_auth_schema.sql +67 -0
- package/src/runtime/enterprise_auth_store.py +241 -0
- package/src/runtime/enterprise_aws_host_bootstrap.py +120 -0
- package/src/runtime/enterprise_aws_host_probe.py +105 -0
- package/src/runtime/enterprise_aws_hosts.py +136 -0
- package/src/runtime/enterprise_aws_jobs.py +300 -0
- package/src/runtime/enterprise_aws_objects.py +93 -0
- package/src/runtime/enterprise_aws_transfer.py +83 -0
- package/src/runtime/enterprise_azure_batch_api.py +128 -0
- package/src/runtime/enterprise_azure_host.py +599 -0
- package/src/runtime/enterprise_azure_jobs.py +294 -0
- package/src/runtime/enterprise_azure_objects.py +234 -0
- package/src/runtime/enterprise_azure_pool.py +161 -0
- package/src/runtime/enterprise_azure_transfer.py +122 -0
- package/src/runtime/enterprise_configuration.py +136 -0
- package/src/runtime/enterprise_document.py +116 -0
- package/src/runtime/enterprise_document_cli.py +32 -0
- package/src/runtime/enterprise_document_contract.py +54 -0
- package/src/runtime/enterprise_document_job.py +109 -0
- package/src/runtime/enterprise_document_jobs.py +122 -0
- package/src/runtime/enterprise_document_jobs_schema.sql +23 -0
- package/src/runtime/enterprise_extraction_cache.py +186 -0
- package/src/runtime/enterprise_extraction_schema.sql +17 -0
- package/src/runtime/enterprise_google_jobs.py +275 -0
- package/src/runtime/enterprise_google_transfer.py +85 -0
- package/src/runtime/enterprise_http.py +212 -0
- package/src/runtime/enterprise_identity.py +52 -0
- package/src/runtime/enterprise_knowledge.py +152 -0
- package/src/runtime/enterprise_models.py +94 -0
- package/src/runtime/enterprise_native.py +181 -0
- package/src/runtime/enterprise_oauth.py +132 -0
- package/src/runtime/enterprise_operator.py +160 -0
- package/src/runtime/enterprise_parser_service.py +136 -0
- package/src/runtime/enterprise_parser_transport.py +68 -0
- package/src/runtime/enterprise_queries.py +255 -0
- package/src/runtime/enterprise_queries_schema.sql +27 -0
- package/src/runtime/enterprise_query_service.py +111 -0
- package/src/runtime/enterprise_secrets.py +110 -0
- package/src/runtime/enterprise_sessions.py +95 -0
- package/src/runtime/enterprise_sources.py +260 -0
- package/src/runtime/enterprise_web.py +39 -0
- package/src/runtime/enterprise_worker.py +68 -0
- package/src/runtime/export_contract_acceptance.py +18 -0
- package/src/runtime/faq-output-contract.json +40 -0
- package/src/runtime/faq-web-app.js +41 -0
- package/src/runtime/faq-web.css +1 -0
- package/src/runtime/faq-web.html +6 -0
- package/src/runtime/gcp-sources.json +9 -0
- package/src/runtime/gcp_acceptance.py +110 -0
- package/src/runtime/gcp_structured.py +150 -0
- package/src/runtime/http_acceptance.py +39 -0
- package/src/runtime/iap-web-app.js +36 -0
- package/src/runtime/iap-web-source.json +1 -0
- package/src/runtime/ibm-python-lock.json +856 -0
- package/src/runtime/ibm-sources.json +9 -0
- package/src/runtime/ibm_acceptance.py +133 -0
- package/src/runtime/ibm_structured.py +113 -0
- package/src/runtime/invoice-azapi-provider-lock.json +7 -0
- package/src/runtime/invoice-ibm-provider-lock.json +7 -0
- package/src/runtime/invoice-parser-lock.json +1199 -0
- package/src/runtime/invoice-parser-python-lock.json +56 -0
- package/src/runtime/invoice-parser.Dockerfile +190 -0
- package/src/runtime/invoice-sources.json +58 -0
- package/src/runtime/invoice-test-sources.json +24 -0
- package/src/runtime/invoice-web.css +2 -0
- package/src/runtime/invoice-web.html +12 -0
- package/src/runtime/invoice-web.js +112 -0
- package/src/runtime/invoice_configuration.py +17 -0
- package/src/runtime/invoice_document.py +95 -0
- package/src/runtime/invoice_extraction.py +96 -0
- package/src/runtime/invoice_http.py +129 -0
- package/src/runtime/invoice_identity.py +5 -0
- package/src/runtime/invoice_maintenance.py +40 -0
- package/src/runtime/invoice_native.py +77 -0
- package/src/runtime/invoice_object_store.py +153 -0
- package/src/runtime/invoice_operations.py +108 -0
- package/src/runtime/invoice_operator.py +79 -0
- package/src/runtime/invoice_operator_core.py +39 -0
- package/src/runtime/invoice_operator_job.py +147 -0
- package/src/runtime/invoice_parser_cli.py +17 -0
- package/src/runtime/invoice_parser_identity.py +39 -0
- package/src/runtime/invoice_parser_service.py +89 -0
- package/src/runtime/invoice_parser_transport.py +89 -0
- package/src/runtime/invoice_processing.py +24 -0
- package/src/runtime/invoice_retention.py +16 -0
- package/src/runtime/invoice_runtime_secrets.py +43 -0
- package/src/runtime/invoice_stage.py +80 -0
- package/src/runtime/invoice_web.py +39 -0
- package/src/runtime/invoice_worker.py +50 -0
- package/src/runtime/lambda_faq.py +5 -0
- package/src/runtime/parser-requirements.lock +4 -0
- package/src/runtime/policy_review.py +18 -0
- package/src/runtime/postgres-qualification-lock.json +21 -0
- package/src/runtime/public-faq-sources.json +22 -0
- package/src/runtime/public_catalog_admin.py +122 -0
- package/src/runtime/public_catalog_store.py +125 -0
- package/src/runtime/public_faq.py +144 -0
- package/src/runtime/public_faq_app.py +49 -0
- package/src/runtime/python-container-lock.json +18 -0
- package/src/runtime/rag-sources.json +10 -0
- package/src/runtime/rag_acceptance.py +60 -0
- package/src/runtime/rag_aws_adapter.py +95 -0
- package/src/runtime/rds-ca-source.json +9 -0
- package/src/runtime/rds-global-ca.pem +2888 -0
- package/src/runtime/state-contract-check-source.json +4 -0
- package/src/runtime/state_contract_check.py +338 -0
- package/src/runtime/structured-source.json +1 -0
- package/src/runtime/structured-web-app.js +71 -0
- package/src/runtime/structured-web-source.json +1 -0
- package/src/runtime/structured_http.py +105 -0
- package/src/runtime/structured_output.py +48 -0
- package/src/runtime/web-python-lock.json +802 -0
- package/src/runtime/web_user_admin.py +44 -0
- package/src/runtime/workflow_application.py +62 -0
- package/src/runtime/workflow_bindings.py +128 -0
- package/src/runtime/workflow_configuration.py +40 -0
- package/src/runtime/workflow_connection.py +105 -0
- package/src/runtime/workflow_contract.py +54 -0
- package/src/runtime/workflow_database.py +94 -0
- package/src/runtime/workflow_errors.py +6 -0
- package/src/runtime/workflow_http.py +178 -0
- package/src/runtime/workflow_identity.py +69 -0
- package/src/runtime/workflow_payload.py +118 -0
- package/src/runtime/workflow_process_stage.py +88 -0
- package/src/runtime/workflow_profile.py +91 -0
- package/src/runtime/workflow_review.py +106 -0
- package/src/runtime/workflow_role_bootstrap.py +104 -0
- package/src/runtime/workflow_schema.sql +72 -0
- package/src/runtime/workflow_worker.py +142 -0
- package/src/runtime-settings.mjs +15 -0
- package/src/s3-access.mjs +14 -0
- package/src/source-contracts.mjs +17 -0
- package/src/spec-kit.mjs +186 -0
- package/src/state-custody.mjs +32 -0
- package/src/state-inspection.mjs +45 -0
- package/src/state-spec-kit.mjs +13 -0
- package/src/storage-tests.mjs +25 -0
- package/src/structured-api.mjs +133 -0
- package/src/structured-contract.mjs +19 -0
- package/src/structured-operation-policy.mjs +2 -0
- package/src/structured-web.mjs +17 -0
- package/src/style.css +1 -0
- package/src/system-description.mjs +26 -0
- package/src/terraform-admission.mjs +66 -0
- package/src/terraform-composition.mjs +83 -0
- package/src/terraform-expressions.mjs +46 -0
- package/src/terraform-validation-coverage.mjs +11 -0
- package/src/terraform.mjs +128 -0
- package/src/text-statistics.mjs +51 -0
- package/src/upstream/openarchflow/format-payload.ts +26 -0
- package/src/upstream/openarchflow/import/mermaid.ts +205 -0
- package/src/upstream/openarchflow/import/sql-ddl.ts +109 -0
- package/src/upstream/openarchflow/layout.ts +54 -0
- package/src/upstream/openarchflow/providers/aws.ts +196 -0
- package/src/upstream/openarchflow/providers/azure.ts +126 -0
- package/src/upstream/openarchflow/providers/cloudnative.ts +71 -0
- package/src/upstream/openarchflow/providers/generic.ts +227 -0
- package/src/upstream/openarchflow/providers/integration.ts +22 -0
- package/src/upstream/openarchflow/providers/types.ts +2 -0
- package/src/upstream/openarchflow/templates.ts +937 -0
- package/src/upstream-catalog.mjs +10 -0
- package/src/useChatScroll.jsx +36 -0
- package/src/useEmulation.jsx +36 -0
- package/src/validation-receipt.mjs +10 -0
- package/src/visual-export.mjs +92 -0
- package/src/voice-conversation.mjs +117 -0
- package/src/work-intake.mjs +24 -0
- package/src/workflow-runtime-inventory.mjs +3 -0
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/* Generated from packages/tokens/src/tokens.json — do not edit by hand.
|
|
2
|
+
One definition per token; light and dark in a single light-dark() call. */
|
|
3
|
+
:root {
|
|
4
|
+
color-scheme: light;
|
|
5
|
+
--color-bg: light-dark(#FAFBF9, #0D1011);
|
|
6
|
+
--color-card: light-dark(#FFFFFF, #0D1011);
|
|
7
|
+
--color-card-raised: light-dark(#F2F8F6, #151A1C);
|
|
8
|
+
--color-ink: light-dark(#172033, #F3F7F7);
|
|
9
|
+
--color-muted: light-dark(#5F6A7C, #A9BABC);
|
|
10
|
+
--color-line: light-dark(#E1E7EF, #687779);
|
|
11
|
+
--color-line-strong: light-dark(#7A8696, #7B8B8D);
|
|
12
|
+
--color-brand: light-dark(#1F777C, #5FD0D6);
|
|
13
|
+
--color-brand-text: light-dark(#1D7176, #5FD0D6);
|
|
14
|
+
--color-brand-soft: light-dark(#E8F5F2, #12343A);
|
|
15
|
+
--color-brand-ink: light-dark(#FFFFFF, #082729);
|
|
16
|
+
--color-good: light-dark(#166B45, #57C793);
|
|
17
|
+
--color-good-soft: light-dark(#E1F1E8, #123528);
|
|
18
|
+
--color-warn: light-dark(#8A5A00, #E0AC4B);
|
|
19
|
+
--color-warn-soft: light-dark(#F7EDD9, #382A10);
|
|
20
|
+
--color-bad: light-dark(#A62531, #F0808B);
|
|
21
|
+
--color-bad-soft: light-dark(#F8E4E6, #3A171C);
|
|
22
|
+
--color-unknown: light-dark(#5A616B, #9AA2AD);
|
|
23
|
+
--color-unknown-soft: light-dark(#ECEAE5, #22262D);
|
|
24
|
+
--color-signal: light-dark(#5B45C7, #A996FF);
|
|
25
|
+
--color-signal-soft: light-dark(#EAE5FA, #241D45);
|
|
26
|
+
--color-danger-action: light-dark(#8E1B25, #FF9AA3);
|
|
27
|
+
--type-family-sans: 'DM Sans', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
|
|
28
|
+
--type-family-display: 'Manrope', 'DM Sans', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif;
|
|
29
|
+
--type-family-mono: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, 'Liberation Mono', monospace;
|
|
30
|
+
--type-display: clamp(2.2rem, 1.4rem + 3.2vw, 3.8rem);
|
|
31
|
+
--type-verdict: 1.6875rem;
|
|
32
|
+
--type-h2: clamp(1.25rem, 1.1rem + 0.6vw, 1.6rem);
|
|
33
|
+
--type-h3: 0.9375rem;
|
|
34
|
+
--type-body: 0.9375rem;
|
|
35
|
+
--type-body-lg: 1.0625rem;
|
|
36
|
+
--type-small: 0.8125rem;
|
|
37
|
+
--type-eyebrow: 0.65625rem;
|
|
38
|
+
--type-weight-regular: 400;
|
|
39
|
+
--type-weight-medium: 500;
|
|
40
|
+
--type-weight-semi: 600;
|
|
41
|
+
--type-weight-heavy: 800;
|
|
42
|
+
--type-leading-tight: 1.15;
|
|
43
|
+
--type-leading-body: 1.55;
|
|
44
|
+
--type-tracking-eyebrow: 0.08em;
|
|
45
|
+
--space-1: 0.25rem;
|
|
46
|
+
--space-2: 0.5rem;
|
|
47
|
+
--space-3: 0.75rem;
|
|
48
|
+
--space-4: 1rem;
|
|
49
|
+
--space-5: 1.5rem;
|
|
50
|
+
--space-6: 2rem;
|
|
51
|
+
--space-7: 3rem;
|
|
52
|
+
--space-8: 4.5rem;
|
|
53
|
+
--space-9: 6.5rem;
|
|
54
|
+
--radius-sm: 6px;
|
|
55
|
+
--radius-md: 10px;
|
|
56
|
+
--radius-lg: 16px;
|
|
57
|
+
--radius-pill: 999px;
|
|
58
|
+
--elevation-card: 0 1px 2px rgba(23, 32, 51, 0.04), 0 8px 24px rgba(23, 32, 51, 0.05);
|
|
59
|
+
--elevation-raised: 0 2px 4px rgba(23, 32, 51, 0.05), 0 20px 48px rgba(23, 32, 51, 0.09);
|
|
60
|
+
--motion-fast: 120ms;
|
|
61
|
+
--motion-medium: 220ms;
|
|
62
|
+
--motion-ease: cubic-bezier(0.2, 0.6, 0.3, 1);
|
|
63
|
+
--layout-measure: 68ch;
|
|
64
|
+
--layout-page: 1200px;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/* Light is the default; dark applies only when the visitor chooses it. */
|
|
68
|
+
:root[data-theme="dark"] {
|
|
69
|
+
color-scheme: dark;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/* Motion tokens collapse to zero rather than being conditionally applied,
|
|
73
|
+
so every consumer honours reduced motion without opting in. */
|
|
74
|
+
@media (prefers-reduced-motion: reduce) {
|
|
75
|
+
:root {
|
|
76
|
+
--motion-fast: 0ms;
|
|
77
|
+
--motion-medium: 0ms;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import lock from './runtime/aws-python-lock.json' with {type:'json'};
|
|
2
|
+
export function awsPreflightFiles(){return {
|
|
3
|
+
'preflight-requirements.lock':lock.requirements,
|
|
4
|
+
'preflight-aws.py':`"""Read-only checks against a saved Terraform plan; never applies or changes quotas."""
|
|
5
|
+
import argparse
|
|
6
|
+
import json
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
import boto3
|
|
9
|
+
from botocore.config import Config
|
|
10
|
+
|
|
11
|
+
def concurrency_requirement(plan):
|
|
12
|
+
required=0
|
|
13
|
+
for item in plan.get("resource_changes",[]):
|
|
14
|
+
if item.get("type")!="aws_lambda_function":continue
|
|
15
|
+
change=item["change"]
|
|
16
|
+
if change.get("actions")==["delete"]:continue
|
|
17
|
+
after=(change.get("after") or {}).get("reserved_concurrent_executions")
|
|
18
|
+
before=(change.get("before") or {}).get("reserved_concurrent_executions")
|
|
19
|
+
if not isinstance(after,int) or after<1:raise ValueError("A positive explicit function concurrency bound is required")
|
|
20
|
+
# A replacement must reserve fresh capacity; do not rely on destruction ordering.
|
|
21
|
+
previous=before if isinstance(before,int) and before>0 and "delete" not in change.get("actions",[]) else 0
|
|
22
|
+
required+=max(0,after-previous)
|
|
23
|
+
return required
|
|
24
|
+
|
|
25
|
+
def check_concurrency(plan,limits):
|
|
26
|
+
needed=concurrency_requirement(plan)
|
|
27
|
+
available=max(0,int(limits["UnreservedConcurrentExecutions"])-100)
|
|
28
|
+
return {"name":"lambda-reserved-concurrency-capacity","passed":needed<=available,"additionalRequired":needed,"availableForReservation":available,"accountLimit":limits["ConcurrentExecutions"],"action":None if needed<=available else "Request and wait for an appropriate regional concurrency quota increase; do not remove the per-function limit to bypass this check."}
|
|
29
|
+
|
|
30
|
+
def main():
|
|
31
|
+
parser=argparse.ArgumentParser(description=__doc__)
|
|
32
|
+
parser.add_argument("--plan-json",type=Path,required=True)
|
|
33
|
+
parser.add_argument("--receipt",type=Path,required=True)
|
|
34
|
+
args=parser.parse_args();plan=json.loads(args.plan_json.read_text())
|
|
35
|
+
values={key:entry.get("value") for key,entry in plan.get("variables",{}).items()}
|
|
36
|
+
account=values.get("aws_account_id");region=values.get("aws_region")
|
|
37
|
+
if not isinstance(account,str) or len(account)!=12 or not account.isdigit() or not isinstance(region,str):raise SystemExit("The plan must contain the reviewed AWS account and region")
|
|
38
|
+
session=boto3.Session(region_name=region)
|
|
39
|
+
config=Config(connect_timeout=5,read_timeout=20,retries={"total_max_attempts":2},ignore_configured_endpoint_urls=True)
|
|
40
|
+
identity=session.client("sts",config=config).get_caller_identity()
|
|
41
|
+
if identity["Account"]!=account:raise SystemExit("Account mismatch; target service checks were not run")
|
|
42
|
+
checks=[]
|
|
43
|
+
if any(r.get("type")=="aws_lambda_function" for r in plan.get("resource_changes",[])):
|
|
44
|
+
limits=session.client("lambda",config=config).get_account_settings()["AccountLimit"]
|
|
45
|
+
checks.append(check_concurrency(plan,limits))
|
|
46
|
+
models=sorted({value for key,value in values.items() if key.endswith("_model_id") and isinstance(value,str)})
|
|
47
|
+
if models:
|
|
48
|
+
bedrock=session.client("bedrock",config=config)
|
|
49
|
+
for model in models:
|
|
50
|
+
availability=bedrock.get_foundation_model_availability(modelId=model)
|
|
51
|
+
details=bedrock.get_foundation_model(modelIdentifier=model)["modelDetails"]
|
|
52
|
+
checks.append({"name":"bedrock-control-plane-availability","modelId":model,"passed":availability.get("authorizationStatus")=="AUTHORIZED" and availability.get("regionAvailability")=="AVAILABLE" and availability.get("entitlementAvailability")=="AVAILABLE" and "ON_DEMAND" in details.get("inferenceTypesSupported",[]),"runtimeInvocation":"not_tested"})
|
|
53
|
+
result={"kind":"read-only-account-preflight","status":"passed" if all(c["passed"] for c in checks) else "blocked","accountSuffix":account[-4:],"region":region,"checks":checks,"deployment":"not_run","limitations":"Does not establish apply permissions, model quality, runtime authorization, recovery, billing or production readiness."}
|
|
54
|
+
args.receipt.parent.mkdir(parents=True,exist_ok=True);args.receipt.write_text(json.dumps(result,indent=2)+"\\n")
|
|
55
|
+
print(json.dumps(result))
|
|
56
|
+
if result["status"]!="passed":raise SystemExit(1)
|
|
57
|
+
if __name__=="__main__":main()
|
|
58
|
+
`,
|
|
59
|
+
'PREFLIGHT.md':'# Verify account prerequisites before applying\n\nAfter reviewing `terraform plan -out=reviewed.tfplan`, write `terraform show -json reviewed.tfplan > reviewed-plan.json`. Treat both files as sensitive. Create a local Python virtual environment and install `preflight-requirements.lock` using `pip install --require-hashes --only-binary=:all: -r preflight-requirements.lock`. With the standard AWS credential chain set to the reviewed account, run `python preflight-aws.py --plan-json reviewed-plan.json --receipt preflight-receipt.json`.\n\nThe script reads STS identity, regional Lambda reservation capacity and selected Bedrock model control-plane availability. It never creates resources, changes quotas or invokes a model. A quota shortfall must be resolved before apply; do not remove concurrency limits to bypass it. Bedrock catalog access is not proof of Converse runtime access or model quality.\n\nApply only the reviewed plan after all account, policy, cost, operational and application checks are satisfied. Rerun checks when the plan or account changes.\n',
|
|
60
|
+
};}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import {builder,v,ref} from './public-faq-builder.mjs';
|
|
2
|
+
import {CLOUD_PROVIDER_LOCKS} from './cloud-provider-locks.mjs';
|
|
3
|
+
import {faqLambdaBuild} from './faq-lambda-build.mjs';
|
|
4
|
+
|
|
5
|
+
// A small synchronous public FAQ does not need App Runner eligibility, an ECR
|
|
6
|
+
// repository or a continuously running load balancer/container. No service
|
|
7
|
+
// lifecycle exception is delegated to the visitor or hidden behind a mock pass.
|
|
8
|
+
export function awsPublicFaqTerraform(project,plan,environment='staging'){
|
|
9
|
+
const b=builder(project,plan,environment,'aws'),{input,add}=b;
|
|
10
|
+
const account=input('account_id','Reviewed destination AWS account; approved operator credential chain only.','123456789012','^[0-9]{12}$');
|
|
11
|
+
const region=input('region','Reviewed commercial AWS region with Lambda, HTTP API and the direct regional Bedrock model; no cross-region inference fallback.','ap-southeast-2','^[a-z]{2}-[a-z]+-[0-9]$');
|
|
12
|
+
const entries=plan.publicFaqPlan.entries;
|
|
13
|
+
if(entries.every(e=>e.row.region===entries[0].row.region)&&/^[a-z]{2}-[a-z]+-[0-9]$/.test(entries[0].row.region)){b.variable.region.default=entries[0].row.region;b.examples.region=entries[0].row.region;}
|
|
14
|
+
b.data.aws_caller_identity={destination:{}};
|
|
15
|
+
b.resource.terraform_data.review_gate.lifecycle.precondition.push({condition:'${data.aws_caller_identity.destination.account_id == var.account_id}',error_message:'Approved operator must target the reviewed AWS account.'});
|
|
16
|
+
for(const {row}of entries){
|
|
17
|
+
const n=row.address,name=input(n+'_name','Unique application and IAM role name.','reviewed-public-help','^[a-z][a-z0-9-]{3,28}[a-z0-9]$');
|
|
18
|
+
const model=input(n+'_model_id','Reviewed direct regional Converse foundation model ID; verify availability, quotas, context size, terms and retention-none compatibility.','anthropic.reviewed-model-v1:0','^[a-z0-9][a-z0-9.-]*:[0-9]+$');
|
|
19
|
+
const editor=input(n+'_editor_principal_arn','Existing authorized same-account company editor role; it alone may assume the separate catalog editor role.','arn:aws:iam::123456789012:role/reviewed-company-editors','^arn:aws:iam::[0-9]{12}:role/[A-Za-z0-9_+=,.@/-]{1,512}$');
|
|
20
|
+
b.resource.terraform_data.review_gate.lifecycle.precondition.push({condition:'${split(":", var.'+n+'_editor_principal_arn)[4] == var.account_id}',error_message:'Existing editor role must belong to the reviewed account.'});
|
|
21
|
+
add('aws_s3_bucket',n,{bucket:account+'-'+name+'-catalog',force_destroy:false,lifecycle:{prevent_destroy:true}});
|
|
22
|
+
const bucket=ref('aws_s3_bucket',n,'id'),bucketArn=ref('aws_s3_bucket',n,'arn'),objectArn=bucketArn+'/catalog.json';
|
|
23
|
+
add('aws_s3_bucket_public_access_block',n,{bucket,block_public_acls:true,block_public_policy:true,ignore_public_acls:true,restrict_public_buckets:true});
|
|
24
|
+
add('aws_s3_bucket_ownership_controls',n,{bucket,rule:{object_ownership:'BucketOwnerEnforced'}});
|
|
25
|
+
add('aws_s3_bucket_server_side_encryption_configuration',n,{bucket,rule:{apply_server_side_encryption_by_default:{sse_algorithm:'AES256'},bucket_key_enabled:false}});
|
|
26
|
+
add('aws_s3_bucket_versioning',n,{bucket,versioning_configuration:{status:'Enabled'}});
|
|
27
|
+
add('aws_s3_bucket_lifecycle_configuration',n,{bucket,rule:{id:'expire-old-catalog-versions',status:'Enabled',filter:{prefix:''},noncurrent_version_expiration:{noncurrent_days:7},abort_incomplete_multipart_upload:{days_after_initiation:1}},depends_on:['aws_s3_bucket_versioning.'+n]});
|
|
28
|
+
add('aws_s3_bucket_policy',n,{bucket,policy:JSON.stringify({Version:'2012-10-17',Statement:[{Sid:'RequireTLS',Effect:'Deny',Principal:'*',Action:'s3:*',Resource:[bucketArn,bucketArn+'/*'],Condition:{Bool:{'aws:SecureTransport':'false','aws:PrincipalIsAWSService':'false'}}}]}),depends_on:['aws_s3_bucket_public_access_block.'+n]});
|
|
29
|
+
add('aws_iam_role',n,{name:name+'-runtime',assume_role_policy:JSON.stringify({Version:'2012-10-17',Statement:[{Effect:'Allow',Principal:{Service:'lambda.amazonaws.com'},Action:'sts:AssumeRole'}]})});
|
|
30
|
+
add('aws_cloudwatch_log_group',n,{name:'/aws/lambda/'+name,retention_in_days:7});
|
|
31
|
+
add('aws_iam_role_policy',n,{role:ref('aws_iam_role',n,'id'),policy:JSON.stringify({Version:'2012-10-17',Statement:[{Effect:'Allow',Action:['s3:GetObject'],Resource:objectArn},{Effect:'Allow',Action:['bedrock:InvokeModel'],Resource:'arn:aws:bedrock:'+region+'::foundation-model/'+model},{Effect:'Allow',Action:['bedrock:GetAccountDataRetention','bedrock:GetModelInvocationLoggingConfiguration'],Resource:'*',Condition:{StringEquals:{'aws:RequestedRegion':region}}},{Effect:'Allow',Action:['logs:CreateLogStream','logs:PutLogEvents'],Resource:ref('aws_cloudwatch_log_group',n,'arn')+':*'}]})});
|
|
32
|
+
add('aws_iam_role',n+'_editor',{name:name+'-catalog-editor',assume_role_policy:JSON.stringify({Version:'2012-10-17',Statement:[{Effect:'Allow',Principal:{AWS:editor},Action:'sts:AssumeRole'}]})});
|
|
33
|
+
add('aws_iam_role_policy',n+'_editor',{role:ref('aws_iam_role',n+'_editor','id'),policy:JSON.stringify({Version:'2012-10-17',Statement:[{Effect:'Allow',Action:['s3:GetObject','s3:PutObject'],Resource:objectArn}]})});
|
|
34
|
+
add('aws_apigatewayv2_api',n,{name,protocol_type:'HTTP',disable_execute_api_endpoint:false});
|
|
35
|
+
const origin=ref('aws_apigatewayv2_api',n,'api_endpoint'),settings={REGION:region,ACCOUNT_ID:account,MODEL_ID:model,MAX_OUTPUT_TOKENS:'1024',CATALOG_BUCKET:bucket,PUBLIC_ORIGIN:origin};
|
|
36
|
+
add('aws_lambda_function',n,{function_name:name,role:ref('aws_iam_role',n,'arn'),runtime:'python3.13',handler:'lambda_faq.handler',architectures:['x86_64'],filename:'${path.module}/build/'+n+'.zip',source_code_hash:'${filebase64sha256("${path.module}/build/'+n+'.zip")}',timeout:29,memory_size:512,reserved_concurrent_executions:5,publish:true,environment:{variables:settings},logging_config:{log_format:'JSON',application_log_level:'WARN',system_log_level:'WARN'},depends_on:['aws_iam_role_policy.'+n,'aws_s3_bucket_policy.'+n,'aws_s3_bucket_server_side_encryption_configuration.'+n,'aws_s3_bucket_versioning.'+n,'aws_cloudwatch_log_group.'+n]});
|
|
37
|
+
add('aws_lambda_alias',n,{name:'live',function_name:ref('aws_lambda_function',n,'function_name'),function_version:ref('aws_lambda_function',n,'version')});
|
|
38
|
+
add('aws_apigatewayv2_integration',n,{api_id:ref('aws_apigatewayv2_api',n,'id'),integration_type:'AWS_PROXY',integration_uri:ref('aws_lambda_alias',n,'invoke_arn'),payload_format_version:'2.0',timeout_milliseconds:29000});
|
|
39
|
+
add('aws_apigatewayv2_route',n,{api_id:ref('aws_apigatewayv2_api',n,'id'),route_key:'$default',authorization_type:'NONE',target:'integrations/'+ref('aws_apigatewayv2_integration',n,'id')});
|
|
40
|
+
add('aws_apigatewayv2_stage',n,{api_id:ref('aws_apigatewayv2_api',n,'id'),name:'$default',auto_deploy:true,default_route_settings:{throttling_burst_limit:10,throttling_rate_limit:10},depends_on:['aws_apigatewayv2_route.'+n]});
|
|
41
|
+
add('aws_lambda_permission',n,{statement_id:'OnlyOwnedHttpApi',action:'lambda:InvokeFunction',function_name:ref('aws_lambda_function',n,'function_name'),qualifier:ref('aws_lambda_alias',n,'name'),principal:'apigateway.amazonaws.com',source_account:account,source_arn:ref('aws_apigatewayv2_api',n,'execution_arn')+'/*/*'});
|
|
42
|
+
b.output[n+'_url']={value:origin+'/'};b.output[n+'_catalog']={value:{bucket,region}};b.output[n+'_editor_role_arn']={value:ref('aws_iam_role',n+'_editor','arn')};b.source(row);
|
|
43
|
+
b.assertions.push(`run "${n}_public_boundary" {\n command = plan\n assert {\n condition = aws_s3_bucket_public_access_block.${n}.block_public_policy && aws_s3_bucket_public_access_block.${n}.restrict_public_buckets && !aws_s3_bucket.${n}.force_destroy\n error_message = "Only the app is public; catalog storage remains private and protected."\n }\n assert {\n condition = jsondecode(aws_iam_role_policy.${n}.policy).Statement[0].Action == ["s3:GetObject"] && toset(jsondecode(aws_iam_role_policy.${n}_editor.policy).Statement[0].Action) == toset(["s3:GetObject", "s3:PutObject"])\n error_message = "Workload read and separate conditional editor write authority must stay distinct."\n }\n assert {\n condition = aws_lambda_function.${n}.reserved_concurrent_executions == 5 && aws_lambda_function.${n}.timeout == 29 && aws_apigatewayv2_integration.${n}.payload_format_version == "2.0" && aws_apigatewayv2_route.${n}.authorization_type == "NONE"\n error_message = "This explicit public-only synchronous module uses bounded Lambda concurrency and the implemented HTTP API v2 event contract."\n }\n assert {\n condition = aws_lambda_permission.${n}.source_account == var.account_id && aws_lambda_permission.${n}.qualifier == "live"\n error_message = "Only the owned account/API may invoke the published live alias."\n }\n}`);
|
|
44
|
+
}
|
|
45
|
+
Object.assign(b.files,faqLambdaBuild(entries.map(e=>e.row.address)));
|
|
46
|
+
const config={terraform:{required_version:'>= 1.17.1, < 2.0.0',required_providers:{aws:{source:'hashicorp/aws',version:'6.72.0'}}},provider:{aws:{region,allowed_account_ids:[account],default_tags:{tags:{ManagedBy:'AtMem AI Architect',Environment:environment}}}}};
|
|
47
|
+
const mocks=`mock_provider "aws" {\n override_during = plan\n mock_data "aws_caller_identity" { defaults = { account_id = "${b.examples.account_id}" } }\n mock_resource "aws_iam_role" { defaults = { arn = "arn:aws:iam::${b.examples.account_id}:role/mock-role" } }\n mock_resource "aws_s3_bucket" { defaults = { id = "mock-catalog", arn = "arn:aws:s3:::mock-catalog" } }\n mock_resource "aws_cloudwatch_log_group" { defaults = { arn = "arn:aws:logs:${b.examples.region}:${b.examples.account_id}:log-group:/aws/lambda/mock" } }\n mock_resource "aws_lambda_function" { defaults = { arn = "arn:aws:lambda:${b.examples.region}:${b.examples.account_id}:function:mock", version = "1" } }\n mock_resource "aws_lambda_alias" { defaults = { arn = "arn:aws:lambda:${b.examples.region}:${b.examples.account_id}:function:mock:live", invoke_arn = "arn:aws:apigateway:${b.examples.region}:lambda:path/2015-03-31/functions/arn:aws:lambda:${b.examples.region}:${b.examples.account_id}:function:mock:live/invocations" } }\n mock_resource "aws_apigatewayv2_api" { defaults = { id = "mockapi1234", api_endpoint = "https://mockapi1234.execute-api.${b.examples.region}.amazonaws.com", execution_arn = "arn:aws:execute-api:${b.examples.region}:${b.examples.account_id}:mockapi1234" } }\n}\n`;
|
|
48
|
+
b.assertions.push(`run "wrong_account_blocked" {\n command = plan\n variables { account_id = "999999999999" }\n expect_failures = [terraform_data.review_gate]\n}`);
|
|
49
|
+
return b.finish(config,CLOUD_PROVIDER_LOCKS.aws,mocks,AWS_PUBLIC_FAQ_GUIDE);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export const AWS_PUBLIC_FAQ_GUIDE=`# AWS public-only FAQ: Lambda and HTTP API
|
|
53
|
+
|
|
54
|
+
This small synchronous public assistant uses generated Python 3.13 source with the
|
|
55
|
+
hash-pinned Mangum ASGI adapter, a published Lambda version/live alias and HTTP API
|
|
56
|
+
v2. It has no App Runner eligibility requirement, ECR dependency, always-on task or
|
|
57
|
+
load balancer. AWS closed App Runner to new customers; do not silently substitute
|
|
58
|
+
it or ask a basic visitor to resolve that restriction.
|
|
59
|
+
|
|
60
|
+
Run python3 build-runtime.py first. It builds the exact Linux x86_64 wheel closure
|
|
61
|
+
and deterministic ZIP from applications/* source, metadata and web assets. Retain
|
|
62
|
+
build/artifact-hashes.json. Run emitted faq_acceptance.py and the real Mangum HTTP
|
|
63
|
+
API event tests in a matching isolated Python environment; qualify the exact ZIP
|
|
64
|
+
inside the reviewed AWS Python 3.13 Linux runtime. Schema/mock/local tests never
|
|
65
|
+
establish real Lambda, IAM or model behavior. There is no Terraform execution hook.
|
|
66
|
+
|
|
67
|
+
The private S3 catalog has public-access blocks, TLS-only policy, AES256 encryption,
|
|
68
|
+
owner-enforced ownership, versioning and seven-day noncurrent expiry. Runtime has
|
|
69
|
+
GetObject only on catalog.json, direct selected regional Bedrock InvokeModel and
|
|
70
|
+
read-only regional retention/logging checks. A separate role assumed by the
|
|
71
|
+
existing reviewed company editor has Get/Put only on catalog.json. Article removal
|
|
72
|
+
conditionally rewrites the manifest; no object DELETE or bucket administration
|
|
73
|
+
is granted. Review inherited IAM and recovery/version-erasure requirements.
|
|
74
|
+
|
|
75
|
+
Seed genuinely public articles via the separate operator CLI before traffic. No
|
|
76
|
+
private source, arbitrary URL fetch, editing HTTP endpoint, end-user sign-in,
|
|
77
|
+
question/answer persistence or content-bearing application log is implemented.
|
|
78
|
+
Only the owned account/API receives permission to invoke the published live alias.
|
|
79
|
+
Same-origin checks are browser hygiene, not visitor authentication. Runtime logs
|
|
80
|
+
are WARN-only with seven-day retention; review all platform/audit logging separately.
|
|
81
|
+
|
|
82
|
+
Converse requests JSON with independently checked schema, source IDs and exact
|
|
83
|
+
quotes. It does not claim constrained Bedrock grammar, whose first compilation
|
|
84
|
+
can exceed this 29-second boundary. The app fails closed on invalid output, stale
|
|
85
|
+
or inaccessible source, unknown retention or enabled model text logging. It never
|
|
86
|
+
changes account-wide model policy. Verify actual model availability, retention-none
|
|
87
|
+
eligibility, region/context/quota/terms and real answer/citation/abstention/latency.
|
|
88
|
+
Long-running work requires the separate durable workflow contract, not a longer
|
|
89
|
+
synchronous timeout or a falsely successful response.
|
|
90
|
+
|
|
91
|
+
Reserved Lambda concurrency is five, with bounded HTTP API throttles. These are
|
|
92
|
+
capacity controls, not an invoice cap, anonymous abuse protection or SLA. Verify
|
|
93
|
+
destination concurrency quota, cold starts, current prices, budgets and abuse policy.
|
|
94
|
+
No prices are invented. Protect state and variable files. Review account/region,
|
|
95
|
+
native Terraform schemas/tests and a separately authorized real plan before apply.
|
|
96
|
+
No export proves deployment; production state/backup/operations remain gated.
|
|
97
|
+
|
|
98
|
+
References:
|
|
99
|
+
- https://docs.aws.amazon.com/apprunner/latest/dg/apprunner-availability-change.html
|
|
100
|
+
- https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html
|
|
101
|
+
- https://mangum.fastapiexpert.com/adapter/
|
|
102
|
+
`;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// Synthetic acceptance scenarios, not deployment configurations or invented customer requirements.
|
|
2
|
+
export const AWS_SCENARIOS = [
|
|
3
|
+
{id:'01-private-storage',name:'Private document storage',prompt:'I need a private place on AWS to store a small set of synthetic text documents for a deployment test. Keep public access blocked and enable encryption and versioning. This first scenario only needs storage; no AI, database or web application.',expected:['s3'],checks:['Authorized upload/download preserves bytes','Unauthenticated access is denied','Versioning/encryption/public-access settings verified','Approved cleanup leaves no scenario resources']},
|
|
4
|
+
{id:'02-document-compute',name:'Document statistics',prompt:'Build a small AWS application that accepts a synthetic text document through an authenticated invocation and returns its word count and character count. Use serverless compute, a least-privilege execution identity and operational logs. No model or public anonymous endpoint is needed.',expected:['lambda'],checks:['Known input returns exact counts','Malformed and oversized payloads are rejected','Unauthorized invocation fails','Updated application version is observable']},
|
|
5
|
+
{id:'03-async-documents',name:'Asynchronous document processing',prompt:'On AWS, when a synthetic text file arrives in private object storage, queue it and process it with a serverless worker. Save its word count as a result. Duplicate deliveries must be safe, failures must retry, and poison messages must go to a dead-letter queue.',expected:['s3','sqs','lambda'],checks:['Upload produces a stored result','Duplicate events do not corrupt results','Poison event reaches dead-letter queue','Recovery/replay succeeds']},
|
|
6
|
+
{id:'04-model-summary',name:'Model-backed summarization',prompt:'Build an authenticated AWS service that summarizes synthetic text using Amazon Bedrock. Include runtime, model invocation permissions and operational logging. Model selection and region availability must be verified before deployment. Bound request size, output tokens, retries and invocation concurrency.',expected:['bedrock'],checks:['Approved model returns a summary of the supplied text','Token/request limits enforced','Denied model access and throttling handled','Logs exclude sensitive input']},
|
|
7
|
+
{id:'05-cited-rag',name:'Cited answers from documents',prompt:'Build an AWS assistant that answers questions from a small synthetic document collection with source citations. Include ingestion, retrieval/indexing, model generation and an application interface. It must say when evidence is insufficient, and reflect document updates and deletions. For this first end-to-end qualification, use the approved bounded keyword-retrieval mode for at most 100 small documents; managed vector retrieval will be qualified separately.',expected:['bedrock'],checks:['Known questions retrieve expected evidence','Citations refer to supplied documents','Unsupported question abstains','Updates/deletions change retrieval results']},
|
|
8
|
+
{id:'06-permission-rag',name:'Permission-aware retrieval',prompt:'Build an authenticated AWS knowledge assistant for synthetic users Alice and Bob with different document permissions. Enforce access and employee region before evidence reaches the model. Restricted titles, snippets and citations must not leak. Test revoked permissions and unknown identity; these must fail safely. Use the approved bounded keyword-retrieval mode for this first test, with IAM-authenticated API access and authoritative employee-region mappings.',expected:['bedrock'],checks:['Alice cannot retrieve Bob-only evidence','No restricted title/snippet/citation leakage','Revocation propagates within agreed bound','Unknown identity/region is denied']},
|
|
9
|
+
{id:'07-enterprise-connectors',name:'External sources and channels',prompt:'Design an AWS knowledge assistant that reads approved documents from existing SharePoint and Confluence systems and provides cited answers through a web application, with Teams as a later channel. Preserve source permissions, updates and deletes. For this stage use the approved local normalized source-contract test servers and bounded keyword retrieval. Keep the requested web application as required scope; an HTTP API alone does not complete that channel. Treat those existing systems as external dependencies; include recovery and audit behavior without claiming native vendor API or real tenant compatibility.',expected:['bedrock'],checks:['Approved source connection synchronizes documents','Source deletes and ACL changes propagate','Source outage retries and recovers','Authenticated channel preserves identity and citations']},
|
|
10
|
+
];
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
// Mechanical architecture checks. These do not establish deployed behavior or model quality.
|
|
2
|
+
export function assessAwsArchitecture(project,scenario){
|
|
3
|
+
const nodes=project.nodes.filter(n=>n.data.kind!=='note');
|
|
4
|
+
const text=n=>String(n.data.service||n.data.label||'').toLowerCase();
|
|
5
|
+
const has=re=>nodes.some(n=>n.data.provider==='aws'&&re.test(text(n)));
|
|
6
|
+
const ids=new Set(nodes.map(n=>n.id));
|
|
7
|
+
const edges=project.edges.filter(e=>ids.has(e.source)&&ids.has(e.target));
|
|
8
|
+
const visited=new Set(nodes.length?[nodes[0].id]:[]);
|
|
9
|
+
for(let changed=true;changed;){changed=false;for(const e of edges)if(visited.has(e.source)!==visited.has(e.target)){visited.add(e.source);visited.add(e.target);changed=true;}}
|
|
10
|
+
const checks=[{id:'nonempty',passed:nodes.length>0},{id:'unique-component-ids',passed:ids.size===nodes.length},{id:'valid-edge-endpoints',passed:project.edges.every(e=>project.nodes.some(n=>n.id===e.source)&&project.nodes.some(n=>n.id===e.target))},{id:'connected-graph',passed:nodes.length>0&&visited.size===nodes.length},{id:'aws-proposed-components',passed:nodes.filter(n=>n.data.origin!=='existing'&&n.data.role!=='human').every(n=>n.data.provider==='aws')},...scenario.expected.map(name=>({id:`service-${name}`,passed:has(new RegExp(name,'i'))}))];
|
|
11
|
+
if(scenario.id==='01-private-storage')checks.push({id:'storage-only-scope',passed:!has(/bedrock|lambda|opensearch|dynamodb|ecs|app\s*runner/)},{id:'operator-access-contract',passed:nodes.some(n=>n.data.binding==='aws-iam-principal'&&n.data.provider==='tools'&&n.data.origin==='existing'&&edges.some(e=>e.source===n.id&&e.access==='s3-read-write'&&nodes.some(t=>t.id===e.target&&t.data.provider==='aws'&&/\bs3\b/.test(text(t)))))});
|
|
12
|
+
if(['03-async-documents','04-model-summary','05-cited-rag','06-permission-rag','07-enterprise-connectors'].includes(scenario.id))checks.push({id:'connected-components',passed:project.edges.length>0&&nodes.every(n=>project.edges.some(e=>e.source===n.id||e.target===n.id))});
|
|
13
|
+
if(scenario.id==='03-async-documents'){
|
|
14
|
+
const queues=nodes.filter(n=>/sqs/.test(text(n)));
|
|
15
|
+
checks.push({id:'queue-connected-to-worker',passed:queues.some(q=>project.edges.some(e=>e.source===q.id&&nodes.some(n=>n.id===e.target&&/lambda/.test(text(n)))))});
|
|
16
|
+
}
|
|
17
|
+
if(['05-cited-rag','06-permission-rag','07-enterprise-connectors'].includes(scenario.id))checks.push({id:'retrieval-component',passed:has(/opensearch|knowledge\s*base|retriev|search|vector/)||nodes.some(n=>n.data.role==='index'||n.data.implementation==='bounded-rag-catalog')});
|
|
18
|
+
if(scenario.id==='06-permission-rag')checks.push({id:'identity-or-access-component',passed:has(/identity|cognito|single.sign|authoriz|permission|access/)||nodes.some(n=>n.data.provider==='aws'&&n.data.implementation==='iam-rag-api')});
|
|
19
|
+
if(scenario.id==='07-enterprise-connectors')checks.push({id:'web-application-component',passed:nodes.some(n=>n.data.implementation==='rag-web-app')});
|
|
20
|
+
if(scenario.id==='07-enterprise-connectors')for(const source of ['sharepoint','confluence'])checks.push({id:`existing-${source}`,passed:nodes.some(n=>text(n).includes(source)&&n.data.origin==='existing')});
|
|
21
|
+
return {passed:checks.every(c=>c.passed),checks,limitations:'Structural checks only. Application correctness, security, service availability and deployment require independent evidence.'};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// A conservative decision about the next validation stage, never a probability of success.
|
|
25
|
+
// Only the local test runner supplies evidence; model prose is not execution evidence.
|
|
26
|
+
export function assessAwsDeploymentCandidate(project, scenario, terraform, evidence = {}) {
|
|
27
|
+
const architecture=assessAwsArchitecture(project,scenario);
|
|
28
|
+
const blockers=architecture.checks.filter(c=>!c.passed).map(c=>({id:`architecture-${c.id}`,owner:'architecture',message:`Architecture check failed: ${c.id}`}));
|
|
29
|
+
const add=(id,owner,message)=>blockers.push({id,owner,message});
|
|
30
|
+
const resources=terraform?.resource||{};
|
|
31
|
+
const count=Object.entries(resources).filter(([type])=>type.startsWith('aws_')).reduce((sum,[,items])=>sum+Object.keys(items||{}).length,0);
|
|
32
|
+
if(!count)add('no-cloud-resources','generator','No AWS resources are emitted; a valid review gate is not a deployment.');
|
|
33
|
+
const expected={s3:'aws_s3_bucket',lambda:'aws_lambda_function',sqs:'aws_sqs_queue'};
|
|
34
|
+
for(const family of scenario.expected)if(expected[family]&&!Object.keys(resources[expected[family]]||{}).length)add(`missing-${family}`,'generator',`Required ${expected[family]} is absent from the export.`);
|
|
35
|
+
const unfinished=terraform?.locals?.unfinished_work;
|
|
36
|
+
if(!Array.isArray(unfinished))add('missing-coverage-evidence','generator','Export does not declare unresolved implementation coverage.');
|
|
37
|
+
else for(const gap of unfinished)add(`unfinished-${gap}`,'implementation',`Unresolved generated work: ${gap}`);
|
|
38
|
+
if(scenario.id!=='01-private-storage'&&evidence.applicationTests!=='passed')add('application-not-qualified','application','No executable application acceptance evidence for this artifact.');
|
|
39
|
+
if(evidence.providerSchema!=='passed')add('provider-schema-unverified','validation','Run provider-schema validation against this exact export.');
|
|
40
|
+
if(evidence.requirementsReview!=='passed')add('requirements-review-unverified','review','Review requirements against emitted configuration, including identity, limits, region, costs and cleanup.');
|
|
41
|
+
return {status:blockers.length?'blocked':'ready_for_account_plan',awsResourceCount:count,blockers,
|
|
42
|
+
cloudPlan:evidence.cloudPlan||'not_run',deployment:evidence.deployment||'not_run',
|
|
43
|
+
limitations:'No numerical success probability is justified. Schema validity does not prove complete coverage, runtime behavior or deployability. A ready-for-plan result is not permission to deploy.'};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function awsRefinementPrompt(assessment) {
|
|
47
|
+
return `Review this same architecture and its generated Terraform. Keep the original scenario scope and preserve valid component IDs and existing systems. Validation findings: ${JSON.stringify(assessment.blockers)}. Correct architecture defects through a proposal where supported. For missing native resources, application code or integrations, explain the product implementation gap and next concrete engineering action; do not claim a diagram edit implemented it. Do not remove required components, weaken acceptance checks or clear unfinished-work gates to obtain a pass. Do not claim tests ran or request deployment. Identify what remains unverified.`;
|
|
48
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// Only computed upstream identities/IDs are supplied. Never override the web-app
|
|
2
|
+
// configuration under test: its cross-field and ID validation must actually run.
|
|
3
|
+
export function azurePlanMocks({subscription,tenant,resourceGroup,addresses,entra=false}){
|
|
4
|
+
const rg='/subscriptions/'+subscription+'/resourceGroups/'+resourceGroup;
|
|
5
|
+
const guid=n=>'00000000-0000-4000-8000-'+String(n).padStart(12,'0');
|
|
6
|
+
let text=`mock_provider "azurerm" {\n override_during = plan\n mock_data "azurerm_client_config" { defaults = { subscription_id = "${subscription}", tenant_id = "${tenant}" } }\n}\n`;
|
|
7
|
+
if(entra)text+='mock_provider "azuread" { override_during = plan }\n';
|
|
8
|
+
const override=(target,values)=>{text+='override_resource {\n override_during = plan\n target = '+target+'\n values = '+JSON.stringify(values)+'\n}\n';};
|
|
9
|
+
addresses.forEach((n,i)=>{
|
|
10
|
+
const seed=100+i*10;
|
|
11
|
+
override('azurerm_user_assigned_identity.'+n,{id:rg+'/providers/Microsoft.ManagedIdentity/userAssignedIdentities/mock-runtime-'+i,client_id:guid(seed),principal_id:guid(seed+1)});
|
|
12
|
+
override('azurerm_service_plan.'+n,{id:rg+'/providers/Microsoft.Web/serverFarms/mock-plan-'+i});
|
|
13
|
+
override('azurerm_cognitive_account.'+n,{id:rg+'/providers/Microsoft.CognitiveServices/accounts/mock-ai-'+i,endpoint:'https://mock-ai-'+i+'.openai.azure.com/'});
|
|
14
|
+
if(entra){
|
|
15
|
+
override('azuread_application_registration.'+n,{id:'/applications/'+guid(seed+2),client_id:guid(seed+3)});
|
|
16
|
+
override('azuread_application_registration.'+n+'_spa',{id:'/applications/'+guid(seed+4),client_id:guid(seed+5)});
|
|
17
|
+
override('azuread_service_principal.'+n,{object_id:guid(seed+6)});
|
|
18
|
+
}else{
|
|
19
|
+
const storage=rg+'/providers/Microsoft.Storage/storageAccounts/mockstorage'+i;
|
|
20
|
+
override('azurerm_storage_account.'+n,{id:storage});
|
|
21
|
+
override('azurerm_storage_container.'+n,{id:storage+'/blobServices/default/containers/public-catalog'});
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
return text;
|
|
25
|
+
}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import {azurePlanMocks} from './azure-plan-mocks.mjs';
|
|
2
|
+
import {pythonContainer} from './python-container.mjs';
|
|
3
|
+
import sources from './runtime/azure-sources.json' with {type:'json'};
|
|
4
|
+
import lock from './runtime/azure-python-lock.json' with {type:'json'};
|
|
5
|
+
import testLock from './runtime/azure-test-lock.json' with {type:'json'};
|
|
6
|
+
import base from './runtime/python-container-lock.json' with {type:'json'};
|
|
7
|
+
import {STRUCTURED_WEB_HTML,STRUCTURED_WEB_CSS,STRUCTURED_WEB_JS} from './structured-web.mjs';
|
|
8
|
+
import {structuredContract} from './structured-contract.mjs';
|
|
9
|
+
import {existingDeployment} from './deployment-ownership.mjs';
|
|
10
|
+
import {existingReferenceFiles} from './existing-references.mjs';
|
|
11
|
+
import {CLOUD_PROVIDER_LOCKS} from './cloud-provider-locks.mjs';
|
|
12
|
+
|
|
13
|
+
export function azureStructuredPlan(project,rows){
|
|
14
|
+
const entries=[];
|
|
15
|
+
for(const node of project.nodes){
|
|
16
|
+
if(node.data.provider!=='azure'||node.data.implementation!=='azure-structured-app'||node.data.service!=='Azure App Service'||existingDeployment(node))continue;
|
|
17
|
+
const contract=structuredContract(node.data.config?.outputContract);
|
|
18
|
+
if(!contract)continue;
|
|
19
|
+
const maxInput=node.data.config?.maxInputBytes??20000,maxTokens=node.data.config?.maxOutputTokens??1024;
|
|
20
|
+
if(!Number.isInteger(maxInput)||maxInput<1||maxInput>20000||!Number.isInteger(maxTokens)||maxTokens<32||maxTokens>4096)throw Error('Azure structured application limits must be 1–20000 input bytes and 32–4096 output tokens.');
|
|
21
|
+
entries.push({row:rows.find(r=>r.id===node.id),contract,maxInput,maxTokens});
|
|
22
|
+
}
|
|
23
|
+
const ids=new Set(entries.map(e=>e.row.id));
|
|
24
|
+
const browsers=new Set(project.nodes.filter(n=>existingDeployment(n)&&n.data.provider==='tools'&&n.data.binding==='web-browser').map(n=>n.id));
|
|
25
|
+
const edges=project.edges.filter(e=>e.integration==='browser-https'&&browsers.has(e.source)&&ids.has(e.target));
|
|
26
|
+
return {entries,componentIds:[...ids],edgeIds:edges.map(e=>e.id)};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const v=n=>'${var.'+n+'}',ref=(type,n,key)=>'${'+type+'.'+n+'.'+key+'}';
|
|
30
|
+
export function azureStructuredTerraform(project,plan,environment='staging'){
|
|
31
|
+
const entries=plan.azureStructuredPlan.entries;
|
|
32
|
+
if(!entries.length)throw Error('No Azure structured application composition.');
|
|
33
|
+
const variable={review_approved:{type:'bool',default:false,description:'Approve only after reviewing the emitted code, destination, identity, policy, costs and plan.'}};
|
|
34
|
+
const examples={review_approved:false},resource={},output={},files={},tests=[];
|
|
35
|
+
const input=(name,description,example,pattern)=>{
|
|
36
|
+
variable[name]={type:'string',nullable:false,description,validation:{condition:pattern?'${can(regex('+JSON.stringify(pattern)+', var.'+name+'))}':'${length(trimspace(var.'+name+')) > 0}',error_message:'Supply the reviewed '+name+' value.'}};
|
|
37
|
+
examples[name]=example;return v(name);
|
|
38
|
+
};
|
|
39
|
+
const uuid='^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$';
|
|
40
|
+
const subscription=input('subscription_id','Expected destination Azure subscription. Terraform uses the operator credential chain.','11111111-1111-1111-1111-111111111111',uuid);
|
|
41
|
+
const tenant=input('tenant_id','Expected company Microsoft Entra tenant. Both providers are bound to this tenant.','22222222-2222-2222-2222-222222222222',uuid);
|
|
42
|
+
const rg=input('resource_group_name','Existing reviewed destination resource group. This module does not import or recreate it.','reviewed-application-rg','^[A-Za-z0-9_.()-]{1,90}$');
|
|
43
|
+
const registry=input('registry_name','Existing Azure Container Registry name, with standard RBAC registry permission mode. No registry is recreated.','reviewedregistry','^[a-z0-9]{5,50}$');
|
|
44
|
+
const registryRg=input('registry_resource_group_name','Existing registry resource group in the selected subscription.','reviewed-registry-rg','^[A-Za-z0-9_.()-]{1,90}$');
|
|
45
|
+
const registryId='/subscriptions/'+subscription+'/resourceGroups/'+registryRg+'/providers/Microsoft.ContainerRegistry/registries/'+registry;
|
|
46
|
+
const registryUrl='https://'+registry+'.azurecr.io';
|
|
47
|
+
const add=(type,name,body)=>((resource[type]||={})[name]={...body,depends_on:['terraform_data.review_gate',...(body.depends_on||[])]});
|
|
48
|
+
const gaps=[...plan.gapDetails.map(g=>g.id),...(environment==='production'?['production-state-backup-and-operating-review-required']:[])];
|
|
49
|
+
resource.terraform_data={review_gate:{input:{design_revision:project.revision,environment},lifecycle:{precondition:[{condition:'${var.review_approved && length(local.unfinished_work) == 0}',error_message:'Resolve required implementation work and review the exact destination and emitted package.'}]}}};
|
|
50
|
+
for(const {row,contract,maxInput,maxTokens} of entries){
|
|
51
|
+
const n=row.address;
|
|
52
|
+
const name=input(n+'_name','Unique application name. This composition includes API, browser, Entra registrations and a regional Azure OpenAI deployment.','reviewed-app','^[a-z][a-z0-9-]{4,28}[a-z0-9]$');
|
|
53
|
+
const location=input(n+'_location','Reviewed application/model region. Regional Standard model availability, version and quota must be verified.','australiaeast','^[a-z][a-z0-9]{2,39}$');
|
|
54
|
+
if(/^[a-z][a-z0-9]{2,39}$/.test(row.region)){variable[n+'_location'].default=row.region;examples[n+'_location']=row.region;}
|
|
55
|
+
const repository=input(n+'_repository','Existing registry repository to which the generated, tested application image will be pushed.','architect/app','^[a-z0-9]+(?:[._/-][a-z0-9]+)*$');
|
|
56
|
+
const digest=input(n+'_image_digest','SHA-256 digest from building this emitted source, not a placeholder image. Use the documented two-phase build/push then Terraform plan.','sha256:'+'0'.repeat(64),'^sha256:[0-9a-f]{64}$');
|
|
57
|
+
const modelName=input(n+'_model_name','Reviewed Azure OpenAI chat model; verify regional Standard availability and API compatibility. No model or price is invented.','REVIEW_MODEL');
|
|
58
|
+
const modelVersion=input(n+'_model_version','Explicit supported model version. Review lifecycle and quota in the destination before planning.','REVIEW_VERSION');
|
|
59
|
+
const group=input(n+'_access_group_object_id','Existing Entra security group allowed to use this API. Group assignment requires Entra P1/P2; no users or groups are created.','33333333-3333-3333-3333-333333333333',uuid);
|
|
60
|
+
const tags={ManagedBy:'AtMem AI Architect',Environment:environment,Component:n};
|
|
61
|
+
add('azurerm_user_assigned_identity',n,{name:name+'-runtime',location,resource_group_name:rg,tags});
|
|
62
|
+
add('azurerm_service_plan',n,{name:name+'-plan',location,resource_group_name:rg,os_type:'Linux',sku_name:'B1',worker_count:1,tags});
|
|
63
|
+
add('azurerm_cognitive_account',n,{name:name+'-ai',location,resource_group_name:rg,kind:'OpenAI',sku_name:'S0',custom_subdomain_name:name+'-ai',local_auth_enabled:false,public_network_access_enabled:true,tags,lifecycle:{prevent_destroy:true}});
|
|
64
|
+
add('azurerm_cognitive_deployment',n,{name:'structured-operation',cognitive_account_id:ref('azurerm_cognitive_account',n,'id'),version_upgrade_option:'NoAutoUpgrade',model:{format:'OpenAI',name:modelName,version:modelVersion},sku:{name:'Standard',capacity:1}});
|
|
65
|
+
const principal=ref('azurerm_user_assigned_identity',n,'principal_id');
|
|
66
|
+
add('azurerm_role_assignment',n,{scope:ref('azurerm_cognitive_account',n,'id'),role_definition_name:'Cognitive Services OpenAI User',principal_id:principal});
|
|
67
|
+
add('azurerm_role_assignment',n+'_policy',{scope:ref('azurerm_cognitive_account',n,'id'),role_definition_name:'Reader',principal_id:principal});
|
|
68
|
+
add('azurerm_role_assignment',n+'_pull',{scope:registryId,role_definition_name:'AcrPull',principal_id:principal});
|
|
69
|
+
const registration={display_name:name,sign_in_audience:'AzureADMyOrg',requested_access_token_version:2,implicit_access_token_issuance_enabled:false,implicit_id_token_issuance_enabled:false};
|
|
70
|
+
add('azuread_application_registration',n,registration);
|
|
71
|
+
add('azuread_application_registration',n+'_spa',{...registration,display_name:name+'-browser'});
|
|
72
|
+
const apiId=ref('azuread_application_registration',n,'id'),apiClient=ref('azuread_application_registration',n,'client_id'),spaId=ref('azuread_application_registration',n+'_spa','id'),spaClient=ref('azuread_application_registration',n+'_spa','client_id');
|
|
73
|
+
const role='${uuidv5("dns", format("%s:%s:workspace-user", var.tenant_id, var.'+n+'_name))}';
|
|
74
|
+
const scope='${uuidv5("dns", format("%s:%s:access-as-user", var.tenant_id, var.'+n+'_name))}';
|
|
75
|
+
add('azuread_application_identifier_uri',n,{application_id:apiId,identifier_uri:'api://'+apiClient});
|
|
76
|
+
add('azuread_application_permission_scope',n,{application_id:apiId,scope_id:scope,value:'access_as_user',type:'Admin',admin_consent_display_name:'Use the structured AI workspace',admin_consent_description:'Submit input for a bounded AI operation as the signed-in user.'});
|
|
77
|
+
add('azuread_application_app_role',n,{application_id:apiId,role_id:role,allowed_member_types:['User'],display_name:'Workspace user',description:'Use the structured AI operation.',value:'WorkspaceUser'});
|
|
78
|
+
add('azuread_service_principal',n,{client_id:apiClient,app_role_assignment_required:true,depends_on:['azuread_application_app_role.'+n]});
|
|
79
|
+
add('azuread_service_principal',n+'_spa',{client_id:spaClient,app_role_assignment_required:false});
|
|
80
|
+
add('azuread_app_role_assignment',n,{app_role_id:role,principal_object_id:group,resource_object_id:ref('azuread_service_principal',n,'object_id')});
|
|
81
|
+
add('azuread_application_api_access',n,{application_id:spaId,api_client_id:apiClient,scope_ids:[scope],depends_on:['azuread_application_permission_scope.'+n]});
|
|
82
|
+
add('azuread_application_pre_authorized',n,{application_id:apiId,authorized_client_id:spaClient,permission_ids:[scope],depends_on:['azuread_application_permission_scope.'+n]});
|
|
83
|
+
add('azurerm_linux_web_app',n,{name,location,resource_group_name:rg,service_plan_id:ref('azurerm_service_plan',n,'id'),https_only:true,ftp_publish_basic_authentication_enabled:false,webdeploy_publish_basic_authentication_enabled:false,identity:{type:'UserAssigned',identity_ids:[ref('azurerm_user_assigned_identity',n,'id')]},site_config:{always_on:true,minimum_tls_version:'1.2',scm_minimum_tls_version:'1.2',ftps_state:'Disabled',http2_enabled:true,remote_debugging_enabled:false,health_check_path:'/healthz',health_check_eviction_time_in_min:2,container_registry_use_managed_identity:true,container_registry_managed_identity_client_id:ref('azurerm_user_assigned_identity',n,'client_id'),application_stack:{docker_registry_url:registryUrl,docker_image_name:repository+'@'+digest}},app_settings:{WEBSITES_PORT:'8080',TENANT_ID:tenant,API_CLIENT_ID:apiClient,SPA_CLIENT_ID:spaClient,MANAGED_IDENTITY_CLIENT_ID:ref('azurerm_user_assigned_identity',n,'client_id'),MODEL_RESOURCE_ID:ref('azurerm_cognitive_account',n,'id'),MODEL_ENDPOINT:ref('azurerm_cognitive_account',n,'endpoint'),MODEL_DEPLOYMENT:ref('azurerm_cognitive_deployment',n,'name'),MAX_INPUT_BYTES:String(maxInput),MAX_OUTPUT_TOKENS:String(maxTokens),OUTPUT_CONTRACT_BASE64:btoa(unescape(encodeURIComponent(JSON.stringify(contract))))},tags,depends_on:['azurerm_role_assignment.'+n,'azurerm_role_assignment.'+n+'_policy','azurerm_role_assignment.'+n+'_pull','azuread_application_pre_authorized.'+n,'azuread_app_role_assignment.'+n]});
|
|
84
|
+
add('azuread_application_redirect_uris',n,{application_id:spaId,type:'SPA',redirect_uris:['https://'+ref('azurerm_linux_web_app',n,'default_hostname')+'/']});
|
|
85
|
+
output[n+'_url']={value:'https://'+ref('azurerm_linux_web_app',n,'default_hostname')+'/'};
|
|
86
|
+
output[n+'_model_resource_id']={value:ref('azurerm_cognitive_account',n,'id')};
|
|
87
|
+
const folder='applications/'+n+'/';
|
|
88
|
+
for(const [path,body] of Object.entries(sources))files[folder+path]=body;
|
|
89
|
+
files[folder+'web/index.html']=STRUCTURED_WEB_HTML;
|
|
90
|
+
files[folder+'web/app.css']=STRUCTURED_WEB_CSS;
|
|
91
|
+
files[folder+'web/app.js']=STRUCTURED_WEB_JS;
|
|
92
|
+
files[folder+'output-contract.json']=JSON.stringify(contract,null,2);
|
|
93
|
+
files[folder+'requirements.lock']=lock.requirements;
|
|
94
|
+
files[folder+'test-requirements.lock']=testLock.requirements;
|
|
95
|
+
files[folder+'test-dependency-sources.json']=JSON.stringify(testLock.sources,null,2);
|
|
96
|
+
files[folder+'dependency-sources.json']=JSON.stringify(lock.sources,null,2);
|
|
97
|
+
files[folder+'container-base.json']=JSON.stringify(base,null,2);
|
|
98
|
+
files[folder+'Dockerfile']=pythonContainer('azure_structured',['azure_structured.py','structured_output.py','structured_http.py']);
|
|
99
|
+
files[folder+'.dockerignore']='*\n!requirements.lock\n!output-contract.json\n!azure_structured.py\n!structured_output.py\n!structured_http.py\n!web/\n!web/*\n';
|
|
100
|
+
files[folder+'BUILD.md']=`# Generated Azure application\n\nThis source implements the browser, delegated Entra API authorization and bounded model operation. It is not a supplied-image placeholder. From this directory, create an isolated environment with python3.13 -m venv .venv, run .venv/bin/python -m pip install --only-binary=:all: --require-hashes -r test-requirements.lock, then .venv/bin/python azure_acceptance.py -v. Test dependencies have a separate hash-locked file and source receipts. Tests use cryptographic keys and scripted network boundaries; they do not access Azure.\n\nBuild on a clean Docker host: docker build --platform linux/amd64 --pull -t REVIEWED_REGISTRY.azurecr.io/REVIEWED_REPOSITORY:REVIEWED_BUILD .\n\nInspect and scan the image, run container startup and acceptance checks, then, with authorization, authenticate to the existing ACR and push it. Record the registry digest and supply it as ${n}_image_digest. The Terraform configuration uses managed-identity pull and never builds/pushes images or executes a provisioner. Building and publishing an image is separate from running Terraform. The base image and all Python wheels are hash pinned; record exact source/image hashes. Update deliberately and rerun tests/scans.\n\nThe test-requirements.lock file adds pinned httpx/HTTP transport tooling for FastAPI TestClient; those development tools are not packaged into the image. Test fixture config lives in azure_acceptance.py; never use fixture values as deployment credentials or production configuration.\n`;
|
|
101
|
+
tests.push(`run "${n}_security" {\n command = plan\n assert {\n condition = azurerm_linux_web_app.${n}.https_only && !azurerm_linux_web_app.${n}.ftp_publish_basic_authentication_enabled && !azurerm_linux_web_app.${n}.webdeploy_publish_basic_authentication_enabled && !azurerm_cognitive_account.${n}.local_auth_enabled\n error_message = "TLS and managed identity are required; basic publishing and model keys are disabled."\n }\n assert {\n condition = azurerm_cognitive_deployment.${n}.sku[0].name == "Standard" && azurerm_cognitive_deployment.${n}.version_upgrade_option == "NoAutoUpgrade"\n error_message = "Do not silently select a global deployment or model upgrade."\n }\n assert {\n condition = azuread_service_principal.${n}.app_role_assignment_required && azuread_application_registration.${n}.requested_access_token_version == 2\n error_message = "Tenant-specific v2 access and explicit group assignment are required."\n }\n}\nrun "${n}_reject_mutable_image" {\n command = plan\n variables { ${n}_image_digest = "latest" }\n expect_failures = [var.${n}_image_digest]\n}`);
|
|
102
|
+
}
|
|
103
|
+
const config={terraform:{required_version:'>= 1.7.0, < 2.0.0',required_providers:{azurerm:{source:'hashicorp/azurerm',version:'4.81.0'},azuread:{source:'hashicorp/azuread',version:'3.10.0'}}},provider:{azurerm:{features:{},subscription_id:subscription,tenant_id:tenant,resource_provider_registrations:'none'},azuread:{tenant_id:tenant}},variable,locals:{unfinished_work:gaps},resource,output};
|
|
104
|
+
const values=Object.entries({...examples,review_approved:true}).map(([key,val])=>key+' = '+JSON.stringify(val)).join('\n');
|
|
105
|
+
return {...files,...existingReferenceFiles(project),'.terraform.lock.hcl':CLOUD_PROVIDER_LOCKS.azure+'\n'+CLOUD_PROVIDER_LOCKS.azuread,'.gitignore':'.terraform/\n*.tfstate*\n*.tfplan\n*.tfvars\n*.tfvars.json\n!deployment.tfvars.json.example\n.venv/\n__pycache__/\n','main.tf.json':JSON.stringify(config,null,2),'resource-schedule.json':JSON.stringify(plan,null,2),'deployment.tfvars.json.example':JSON.stringify(examples,null,2),'tests/azure-structured.tftest.hcl':azurePlanMocks({subscription:examples.subscription_id,tenant:examples.tenant_id,resourceGroup:examples.resource_group_name,addresses:entries.map(e=>e.row.address),entra:true})+`variables {\n${values}\n}\n${tests.join('\n')}\nrun "unapproved_blocked" {\n command = plan\n variables { review_approved = false }\n expect_failures = [terraform_data.review_gate]\n}\n`,'README.md':AZURE_STRUCTURED_GUIDE};
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export const AZURE_STRUCTURED_GUIDE=`# Azure structured AI application
|
|
109
|
+
|
|
110
|
+
Each explicitly selected azure-structured-app block is a composed application module: Linux App Service, browser, API, user-assigned runtime identity, regional Azure OpenAI account/deployment, two Entra app registrations, an API scope/role, and an assignment of an existing company group. It does not create users/groups, import existing applications or implement arbitrary other blocks. See resource-schedule.json for unresolved scope. Public TLS endpoints use identity enforcement; private networking is not implemented by this module.
|
|
111
|
+
|
|
112
|
+
The emitted Python 3.13 application verifies signed RS256 Entra v2 access tokens for the exact tenant, API audience, browser client, delegated scope and assigned WorkspaceUser role. ID tokens, app-only tokens and forwarded identity headers grant no API access. Keys are fetched from the fixed tenant endpoint with bounded retrieval and rotation caching. Bearer tokens authorize until expiry: group removal, disabling a user and logout do not immediately revoke an already issued token. Tenant Conditional Access/MFA and any continuous-revocation requirement require destination policy/engineering and real tests. Entra P1/P2 is needed for group assignments. Provisioning Entra registrations/role assignments needs separately reviewed administrator/Graph permissions; the runtime receives none of those permissions.
|
|
113
|
+
|
|
114
|
+
Runtime identity receives model inference access and account-scoped Reader for policy checks, plus AcrPull on the exact existing registry. These are not subscription-wide Owner grants. Registry mode must support AcrPull and accept ARM audience tokens for managed-identity pulls; an ABAC-enabled or network-protected registry needs a different reviewed assignment/network integration. No static credential, model key or client secret is emitted. Protect Terraform state: providers may retain sensitive service attributes even when no output exposes a key.
|
|
115
|
+
|
|
116
|
+
Input/results are not persisted by the app. Before inference, a read-only ARM check requires the exact model account and ContentLogging=false capability. This capability requires approved modified abuse monitoring; the app cannot self-approve it. Missing approval, policy outage or unknown state blocks inference with a clear setup error, without sending the user input to the model. It never modifies account-wide policy. Review provider processing, monitoring, residency and account terms separately; Standard regional model deployment alone does not prove whole-system residency. Model/account availability, compatible model/version, quotas, prices and this policy approval need authorized destination checks. No availability or privacy approval is invented.
|
|
117
|
+
|
|
118
|
+
Build/test the emitted applications first using each applications/*/BUILD.md. Build and push to an existing reviewed ACR, retain exact source/image digests, then supply deployment inputs. No Terraform provisioners or bootstrap cloud actions run automatically. Register Microsoft.Web, Microsoft.CognitiveServices and Microsoft.ManagedIdentity separately under authorized subscription control; automatic registration is disabled. Both providers are pinned to the expected tenant/subscription and use the operator credential chain.
|
|
119
|
+
|
|
120
|
+
The API requests strict JSON Schema output with the documented response_format contract and independently validates the returned JSON. Select a regional deployment/version that supports structured outputs; unsupported model/configuration errors fail closed, without silently switching model or removing the schema. String length limits remain enforced by the application because the provider schema subset does not support maxLength.
|
|
121
|
+
|
|
122
|
+
Use terraform init -backend=false, terraform validate and terraform test for provider schemas and mock configuration checks. Review actual destination inputs and an authorized plan separately. Production is blocked until state, backup and operations are reviewed. App Service B1 and a single process are an initial bounded deployment, not a high-availability SLA. Per-process concurrency/output limits and model quota bound traffic; they are not an invoice cap. No request bodies, tokens or model text are logged by the application; review platform-level logging separately.
|
|
123
|
+
|
|
124
|
+
The model returns flat schema-checked fields with a human-review marker. No tool/action is executed. Output validation does not prove factual or classification accuracy. Run representative model-quality tests, real sign-in/role/expiry tests, image startup/scan, policy checks and an authorized account plan before deployment. This export itself proves no deployment.
|
|
125
|
+
|
|
126
|
+
References:
|
|
127
|
+
- https://learn.microsoft.com/en-us/entra/identity-platform/claims-validation
|
|
128
|
+
- https://learn.microsoft.com/en-us/entra/identity-platform/howto-add-app-roles-in-apps
|
|
129
|
+
- https://learn.microsoft.com/en-us/azure/ai-services/openai/concepts/abuse-monitoring
|
|
130
|
+
- https://learn.microsoft.com/en-us/rest/api/aifoundry/azureopenai/chat
|
|
131
|
+
- https://registry.terraform.io/providers/hashicorp/azurerm/4.81.0/docs/resources/linux_web_app
|
|
132
|
+
- https://registry.terraform.io/providers/hashicorp/azuread/3.10.0/docs
|
|
133
|
+
`;
|