@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,43 @@
|
|
|
1
|
+
const definitions={
|
|
2
|
+
s3:{type:'s3',settings:{encrypt:true,use_lockfile:true},example:'bucket = "REVIEWED_PROTECTED_STATE_BUCKET"\nkey = "REVIEWED_PROJECT/production.tfstate"\nregion = "REVIEWED_STATE_REGION"\n',guide:'Use a separate private, encrypted, versioned S3 state bucket under the accepted custody/residency boundary. Terraform 1.17 uses native S3 lock files (use_lockfile=true), not an invented DynamoDB dependency. Restrict ListBucket to the project prefix and GetObject/PutObject to its state key; the corresponding .tflock also needs DeleteObject. Do not grant state DeleteObject merely for locking. Use the standard authorized AWS credential chain, never backend access_key/secret_key values.',source:'https://developer.hashicorp.com/terraform/language/backend/s3'},
|
|
3
|
+
azurerm:{type:'azurerm',settings:{use_azuread_auth:true},example:'storage_account_name = "REVIEWED_PRIVATE_STATE_ACCOUNT"\ncontainer_name = "REVIEWED_STATE_CONTAINER"\nkey = "REVIEWED_PROJECT/production.tfstate"\ntenant_id = "REVIEWED_DIRECTORY_TENANT_UUID"\nsubscription_id = "REVIEWED_STATE_SUBSCRIPTION_UUID"\n',guide:'Use a separate reviewed private Azure Blob state container with versioning/recovery and the accepted residency. Native Blob leases implement state locking. use_azuread_auth=true uses Entra data-plane authentication; grant only reviewed container-scoped state access. Configure the approved Azure CLI, managed identity or workload federation through its documented environment chain; do not export storage account keys, SAS tokens or client secrets into backend.hcl. Verify the exact state subscription/tenant and effective inherited rights independently.',source:'https://developer.hashicorp.com/terraform/language/backend/azurerm'},
|
|
4
|
+
gcs:{type:'gcs',settings:{},example:'bucket = "REVIEWED_PRIVATE_VERSIONED_STATE_BUCKET"\nprefix = "REVIEWED_PROJECT/production"\n',guide:'Use a separately bootstrapped private, versioned GCS state bucket under the reviewed project/custody/residency boundary. Terraform supports native state locking. Give the authorized state operator scoped object access, preserving unrelated bucket IAM; use the reviewed Google credential/workload-identity chain, never an embedded service-account key. Review encryption/key ownership, inherited grants, version recovery and the exact project/bucket/prefix. The state bucket is not the invoice originals bucket.',source:'https://developer.hashicorp.com/terraform/language/backend/gcs'},
|
|
5
|
+
http:{type:'http',settings:{},example:'address = "https://REVIEWED_PRIVATE_STATE_SERVICE/EXACT_PROJECT_PRODUCTION_STATE"\nlock_address = "https://REVIEWED_PRIVATE_STATE_SERVICE/EXACT_PROJECT_PRODUCTION_STATE/lock"\nunlock_address = "https://REVIEWED_PRIVATE_STATE_SERVICE/EXACT_PROJECT_PRODUCTION_STATE/lock"\nlock_method = "POST"\nunlock_method = "DELETE"\nretry_wait_min = 5\n',guide:'Use the existing reviewed private platform state service implementing Terraform HTTP state and lock/unlock semantics, not a generic object URL or an unverified S3-compatible IBM COS lock assumption. The example selects POST/DELETE locking; verify the actual platform protocol and owner-safe lock behavior before use. Keep the service in the accepted custody/residency boundary. Configure TF_HTTP_USERNAME/TF_HTTP_PASSWORD or reviewed mutual-TLS environment credentials, never credentials in backend.hcl. No state platform is deployed by this module.',source:'https://developer.hashicorp.com/terraform/language/backend/http'}
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export const PROTECTED_BACKENDS=Object.freeze(Object.keys(definitions));
|
|
9
|
+
export function protectedState(backendType,{title='Terraform state and environment ownership',environment='production'}={}){
|
|
10
|
+
const definition=definitions[backendType];if(!definition)throw Error('Choose an explicit supported state backend; no target-provider fallback.');
|
|
11
|
+
if(!['staging','production','qualification'].includes(environment))throw Error('Use an explicit supported state environment.');
|
|
12
|
+
return {backend:{[definition.type]:structuredClone(definition.settings)},files:{'backend.hcl.example':definition.example.replaceAll('production',environment).replaceAll('PRODUCTION',environment.toUpperCase()),'STATE.md':'# '+title+'\n\nSelected backend contract: '+definition.type+'.\n\n'+definition.guide.replace('invoice originals bucket','application data bucket')+'\n\n'+COMMON+'\nReference: '+definition.source+'\n'}};
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const COMMON=`Staging/qualification default to local state only for isolated local validation.
|
|
16
|
+
Production declares the provider-specific protected backend with no account names,
|
|
17
|
+
endpoints or credentials embedded. The existing state store is a separate platform
|
|
18
|
+
prerequisite, not an application resource. If the destination repository
|
|
19
|
+
already has another reviewed backend, preserve it through an explicit state/owner
|
|
20
|
+
decision and validate compatibility before any authorized migration.
|
|
21
|
+
|
|
22
|
+
Keep backend.hcl private and excluded from source. Do not put authentication values
|
|
23
|
+
in configuration or command arguments: Terraform can retain backend arguments in
|
|
24
|
+
its local metadata and saved plans. State can contain provider-computed identity
|
|
25
|
+
credentials even when runtime SQL/accounting secret payloads are supplied outside
|
|
26
|
+
Terraform. Restrict readers, protect backups/plans, and review retention/key policy.
|
|
27
|
+
Never disable TLS verification or use -lock=false to bypass an unavailable lock.
|
|
28
|
+
|
|
29
|
+
Local-only checks: terraform init -backend=false, terraform validate, terraform test.
|
|
30
|
+
Before authorized production planning, verify the existing protected state store
|
|
31
|
+
on an isolated approved state: concurrent clients must conflict on one lock, an
|
|
32
|
+
unrelated identity must not unlock it, and version recovery must preserve the
|
|
33
|
+
expected digest. Record actual service version, access, custody and recovery proof.
|
|
34
|
+
Then run terraform init -backend-config=backend.hcl through the approved credential
|
|
35
|
+
chain. Platform/account access, store creation and migrations require authorization.
|
|
36
|
+
|
|
37
|
+
Each deployment environment has a distinct physical resource-name seed. Use separate
|
|
38
|
+
staging/production state paths and reviewed immutable image/account/policy inputs;
|
|
39
|
+
never point production at staging state. Keep a verified private state backup before
|
|
40
|
+
an authorized migration and inspect exact lineage. Do not -reconfigure/-migrate-state
|
|
41
|
+
over a mismatched lineage. No external accounting service or actor is imported or
|
|
42
|
+
recreated. Resource deletion protections do not prove backup, restore or availability.
|
|
43
|
+
`;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import {publicFaqFiles} from './public-faq.mjs';
|
|
2
|
+
import {existingReferenceFiles} from './existing-references.mjs';
|
|
3
|
+
export const v=n=>'${var.'+n+'}',ref=(type,n,key)=>'${'+type+'.'+n+'.'+key+'}';
|
|
4
|
+
export 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}$';
|
|
5
|
+
export function builder(project,plan,environment,provider){
|
|
6
|
+
if(!plan.publicFaqPlan?.entries.length||plan.publicFaqPlan.entries.some(e=>e.provider!==provider))throw Error('A public FAQ adapter must match every proposed application provider; no cross-cloud substitution.');
|
|
7
|
+
const variable={review_approved:{type:'bool',default:false}},examples={review_approved:false},resource={},output={},files={},data={},assertions=[];
|
|
8
|
+
const gaps=[...plan.gapDetails.map(g=>g.id),...(environment==='production'?['production-state-backup-and-operating-review-required']:[])];
|
|
9
|
+
resource.terraform_data={review_gate:{input:{design_revision:project.revision,environment},lifecycle:{precondition:[{condition:'${var.review_approved && length(local.unfinished_work) == 0}',error_message:'Review the source, public-only publication boundary, destination, native roles, model policy, costs and unresolved scope before deployment.'}]}}};
|
|
10
|
+
const input=(name,description,example,pattern)=>{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.'}};examples[name]=example;return v(name);};
|
|
11
|
+
const add=(type,name,body)=>((resource[type]||={})[name]={...body,depends_on:['terraform_data.review_gate',...(body.depends_on||[])]});
|
|
12
|
+
const source=row=>Object.assign(files,publicFaqFiles(provider,row.address));
|
|
13
|
+
function finish(config,lock,mock,guide){
|
|
14
|
+
const values=Object.entries({...examples,review_approved:true}).map(([name,value])=>name+' = '+JSON.stringify(value)).join('\n');
|
|
15
|
+
return {...files,...existingReferenceFiles(project),'.terraform.lock.hcl':lock,'main.tf.json':JSON.stringify({...config,variable,data,locals:{unfinished_work:gaps},resource,output},null,2),'resource-schedule.json':JSON.stringify(plan,null,2),'deployment.tfvars.json.example':JSON.stringify(examples,null,2),'.gitignore':'.terraform/\n*.tfstate*\n*.tfplan\n*.tfvars\n*.tfvars.json\n!deployment.tfvars.json.example\n.venv/\nbuild/\n*.zip\n__pycache__/\n','tests/public-faq.tftest.hcl':mock+'\nvariables {\n'+values+'\n}\n'+assertions.join('\n')+'\nrun "unapproved_blocked" {\n command = plan\n variables { review_approved = false }\n expect_failures = [terraform_data.review_gate]\n}\n','README.md':guide};
|
|
16
|
+
}
|
|
17
|
+
return {variable,examples,resource,output,files,data,assertions,input,add,source,finish};
|
|
18
|
+
}
|
|
19
|
+
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
import {ibmRegistryHostExpression,ibmRegistryRegionValidation}from'./ibm-registry.mjs';
|
|
2
|
+
import {azurePlanMocks} from './azure-plan-mocks.mjs';
|
|
3
|
+
import {CLOUD_PROVIDER_LOCKS} from './cloud-provider-locks.mjs';
|
|
4
|
+
export {awsPublicFaqTerraform} from './aws-public-faq.mjs';
|
|
5
|
+
import {builder,v,ref,UUID} from './public-faq-builder.mjs';
|
|
6
|
+
|
|
7
|
+
export function azurePublicFaqTerraform(project,plan,environment='staging'){
|
|
8
|
+
const b=builder(project,plan,environment,'azure'),{input,add}=b;
|
|
9
|
+
const subscription=input('subscription_id','Expected destination Azure subscription; operator credential chain only.','11111111-1111-1111-1111-111111111111',UUID);
|
|
10
|
+
const tenant=input('tenant_id','Expected destination tenant. Existing editor identity is preserved.','22222222-2222-2222-2222-222222222222',UUID);
|
|
11
|
+
const rg=input('resource_group_name','Existing reviewed resource group; not recreated or imported.','reviewed-applications','^[A-Za-z0-9_.()-]{1,90}$');
|
|
12
|
+
const registry=input('registry_name','Existing RBAC-mode ACR that accepts the ARM audience for managed identity.','reviewedregistry','^[a-z0-9]{5,50}$');
|
|
13
|
+
const registryRg=input('registry_resource_group_name','Existing registry resource group in this subscription.','reviewed-registry-rg','^[A-Za-z0-9_.()-]{1,90}$');
|
|
14
|
+
b.data.azurerm_client_config={destination:{}};
|
|
15
|
+
b.resource.terraform_data.review_gate.lifecycle.precondition.push({condition:'${data.azurerm_client_config.destination.subscription_id == var.subscription_id && data.azurerm_client_config.destination.tenant_id == var.tenant_id}',error_message:'Operator identity must match the reviewed tenant and subscription.'});
|
|
16
|
+
const registryId='/subscriptions/'+subscription+'/resourceGroups/'+registryRg+'/providers/Microsoft.ContainerRegistry/registries/'+registry;
|
|
17
|
+
for(const {row}of plan.publicFaqPlan.entries){
|
|
18
|
+
const n=row.address,name=input(n+'_name','Unique public application name; internal managed services belong to this composition.','reviewed-public-help','^[a-z][a-z0-9-]{3,18}[a-z0-9]$');
|
|
19
|
+
const region=input(n+'_region','Reviewed application, storage and Regional Standard model location. Verify actual model/version/quotas and processing geography.','australiaeast','^[a-z][a-z0-9]{2,39}$');
|
|
20
|
+
if(/^[a-z][a-z0-9]{2,39}$/.test(row.region)){b.variable[n+'_region'].default=row.region;b.examples[n+'_region']=row.region;}
|
|
21
|
+
const repository=input(n+'_repository','Build/publish path for this emitted application in the existing registry.','architect/public-help','^[a-z0-9]+(?:[._/-][a-z0-9]+)*$');
|
|
22
|
+
const digest=input(n+'_image_digest','Exact built, scanned, tested and authorized-published image digest.','sha256:'+'0'.repeat(64),'^sha256:[0-9a-f]{64}$');
|
|
23
|
+
const model=input(n+'_model_name','Reviewed regional model supporting strict JSON Schema output; no availability or price is invented.','REVIEW_MODEL');
|
|
24
|
+
const version=input(n+'_model_version','Exact supported model version; verify lifecycle and Standard regional availability.','REVIEW_VERSION');
|
|
25
|
+
const editor=input(n+'_editor_group_object_id','Existing Entra editor security-group object ID; no group/users are created. It receives only public-container data access.','33333333-3333-3333-3333-333333333333',UUID);
|
|
26
|
+
const tags={ManagedBy:'AtMem AI Architect',Environment:environment,Component:n};
|
|
27
|
+
add('azurerm_user_assigned_identity',n,{name:name+'-runtime',location:region,resource_group_name:rg,tags});
|
|
28
|
+
add('azurerm_service_plan',n,{name:name+'-plan',location:region,resource_group_name:rg,os_type:'Linux',sku_name:'B1',worker_count:1,tags});
|
|
29
|
+
add('azurerm_cognitive_account',n,{name:name+'-ai',location:region,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}});
|
|
30
|
+
add('azurerm_cognitive_deployment',n,{name:'public-faq',cognitive_account_id:ref('azurerm_cognitive_account',n,'id'),version_upgrade_option:'NoAutoUpgrade',model:{format:'OpenAI',name:model,version},sku:{name:'Standard',capacity:1}});
|
|
31
|
+
const storage='${format("faq%s", substr(sha256(format("%s:%s", var.subscription_id, var.'+n+'_name)), 0, 20))}';
|
|
32
|
+
add('azurerm_storage_account',n,{name:storage,location:region,resource_group_name:rg,account_tier:'Standard',account_replication_type:'LRS',https_traffic_only_enabled:true,min_tls_version:'TLS1_2',allow_nested_items_to_be_public:false,shared_access_key_enabled:false,default_to_oauth_authentication:true,public_network_access_enabled:true,blob_properties:{versioning_enabled:true,delete_retention_policy:{days:7},container_delete_retention_policy:{days:7}},tags,lifecycle:{prevent_destroy:true}});
|
|
33
|
+
add('azurerm_storage_container',n,{name:'public-catalog',storage_account_id:ref('azurerm_storage_account',n,'id'),container_access_type:'private',lifecycle:{prevent_destroy:true}});
|
|
34
|
+
const principal=ref('azurerm_user_assigned_identity',n,'principal_id');
|
|
35
|
+
for(const [suffix,scope,role]of [['',ref('azurerm_cognitive_account',n,'id'),'Cognitive Services OpenAI User'],['_policy',ref('azurerm_cognitive_account',n,'id'),'Reader'],['_pull',registryId,'AcrPull'],['_catalog',ref('azurerm_storage_container',n,'id'),'Storage Blob Data Reader']])add('azurerm_role_assignment',n+suffix,{scope,role_definition_name:role,principal_id:principal,principal_type:'ServicePrincipal',skip_service_principal_aad_check:true});
|
|
36
|
+
add('azurerm_role_assignment',n+'_editor',{scope:ref('azurerm_storage_container',n,'id'),role_definition_name:'Storage Blob Data Contributor',principal_id:editor,principal_type:'Group'});
|
|
37
|
+
add('azurerm_linux_web_app',n,{name,location:region,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:'https://'+registry+'.azurecr.io',docker_image_name:repository+'@'+digest}},app_settings:{WEBSITES_PORT:'8080',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_OUTPUT_TOKENS:'1024',CATALOG_ACCOUNT:ref('azurerm_storage_account',n,'name'),CATALOG_CONTAINER:ref('azurerm_storage_container',n,'name')},tags,depends_on:['azurerm_role_assignment.'+n,'azurerm_role_assignment.'+n+'_policy','azurerm_role_assignment.'+n+'_pull','azurerm_role_assignment.'+n+'_catalog']});
|
|
38
|
+
b.output[n+'_url']={value:'https://'+ref('azurerm_linux_web_app',n,'default_hostname')+'/'};
|
|
39
|
+
b.output[n+'_catalog']={value:{storage_account:ref('azurerm_storage_account',n,'name'),container:ref('azurerm_storage_container',n,'name'),region}};
|
|
40
|
+
b.source(row);
|
|
41
|
+
b.assertions.push(`run "${n}_public_boundary" {\n command = plan\n assert {\n condition = azurerm_storage_container.${n}.container_access_type == "private" && !azurerm_storage_account.${n}.shared_access_key_enabled && !azurerm_storage_account.${n}.allow_nested_items_to_be_public\n error_message = "Public answers must not make the object store public or enable storage keys."\n }\n assert {\n condition = azurerm_role_assignment.${n}_catalog.role_definition_name == "Storage Blob Data Reader" && azurerm_role_assignment.${n}_editor.role_definition_name == "Storage Blob Data Contributor" && azurerm_role_assignment.${n}_catalog.principal_id != azurerm_role_assignment.${n}_editor.principal_id\n error_message = "Runtime read and authorized editor write identities must remain separate."\n }\n assert {\n condition = azurerm_linux_web_app.${n}.https_only && !azurerm_cognitive_account.${n}.local_auth_enabled\n error_message = "TLS and workload identity are required."\n }\n}\nrun "${n}_mutable_image_blocked" {\n command = plan\n variables { ${n}_image_digest = "latest" }\n expect_failures = [var.${n}_image_digest]\n}`);
|
|
42
|
+
}
|
|
43
|
+
const config={terraform:{required_version:'>= 1.17.1, < 2.0.0',required_providers:{azurerm:{source:'hashicorp/azurerm',version:'4.81.0'}}},provider:{azurerm:{subscription_id:subscription,tenant_id:tenant,features:{},storage_use_azuread:true}}};
|
|
44
|
+
return b.finish(config,CLOUD_PROVIDER_LOCKS.azure,azurePlanMocks({subscription:b.examples.subscription_id,tenant:b.examples.tenant_id,resourceGroup:b.examples.resource_group_name,addresses:plan.publicFaqPlan.entries.map(e=>e.row.address)}),AZURE_PUBLIC_FAQ_GUIDE);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export const AZURE_PUBLIC_FAQ_GUIDE=`# Azure public-only FAQ composition
|
|
48
|
+
|
|
49
|
+
The generated Python browser/API is intentionally anonymous. Its dedicated managed
|
|
50
|
+
identity can read only this private public-article container and invoke/read policy
|
|
51
|
+
on its generated regional model account. A separate existing Entra editor group
|
|
52
|
+
receives container-scoped data contributor access. No application HTTP endpoint
|
|
53
|
+
edits articles. No users/groups, existing resource group or ACR are recreated.
|
|
54
|
+
This is not a private enterprise knowledge assistant or existing-SSO integration.
|
|
55
|
+
|
|
56
|
+
Shared storage keys and anonymous blob access are disabled; the Azure provider
|
|
57
|
+
uses Entra for storage access. App Service basic publishing/debug/FTP are disabled;
|
|
58
|
+
the application uses managed identity for image pulls. Verify the existing registry
|
|
59
|
+
uses standard RBAC and accepts the ARM audience. No registry credential or model
|
|
60
|
+
key is exported. Public TLS endpoints use IAM/RBAC; private networking is not
|
|
61
|
+
implemented. Review inherited permissions and current tenant/subscription context.
|
|
62
|
+
|
|
63
|
+
See applications/*/BUILD.md for exact source/test/build and conditional editor CLI
|
|
64
|
+
steps. Protect Terraform state and variables. Seed only genuinely public articles
|
|
65
|
+
with the authorized editor before admitting traffic; a missing/inaccessible source
|
|
66
|
+
does not become an empty catalog or a cached answer. Blob versions and seven-day
|
|
67
|
+
soft deletion are recovery features, not an immediate erasure guarantee. Review
|
|
68
|
+
recovery and costs. Anonymous access plus concurrency/instance/output limits is
|
|
69
|
+
not an invoice cap; approve and test destination abuse controls and budget policy.
|
|
70
|
+
|
|
71
|
+
Choose a compatible regional Standard structured-output model/version and verify
|
|
72
|
+
actual quotas, prices and geography. Runtime requires approved ContentLogging=false
|
|
73
|
+
before inference and never writes that account-wide setting. Provider/platform
|
|
74
|
+
logging and identity/control-plane processing require separate review. No app
|
|
75
|
+
question/answer persistence or content-bearing application logs are implemented.
|
|
76
|
+
Real model answer/citation/abstention and latency tests remain required.
|
|
77
|
+
|
|
78
|
+
Use Terraform 1.17.1+, terraform init -backend=false, terraform validate and
|
|
79
|
+
terraform test. These mock checks do not prove real Azure IAM, managed identity,
|
|
80
|
+
storage conditionals or model quality. Obtain explicit authorization for registry
|
|
81
|
+
publication, cloud access, a real account plan and deployment. Production state,
|
|
82
|
+
backup and operating review remain gated; no export proves deployment.
|
|
83
|
+
`;
|
|
84
|
+
|
|
85
|
+
export function gcpPublicFaqTerraform(project,plan,environment='staging'){
|
|
86
|
+
const b=builder(project,plan,environment,'gcp'),{input,add}=b;
|
|
87
|
+
const projectId=input('project_id','Existing reviewed Google project with billing; no project is recreated.','reviewed-project','^[a-z][a-z0-9-]{4,28}[a-z0-9]$');
|
|
88
|
+
const registryLocation=input('registry_location','Location of the existing Artifact Registry Docker repository.','australia-southeast1','^[a-z]+(?:-[a-z]+[0-9])?$');
|
|
89
|
+
const registry=input('registry_repository','Existing Docker repository in this project; preserved.','reviewed-images','^[a-z][a-z0-9-]{1,61}[a-z0-9]$');
|
|
90
|
+
b.data.google_project={destination:{project_id:projectId}};
|
|
91
|
+
for(const [name,service]of Object.entries({run:'run.googleapis.com',model:'aiplatform.googleapis.com',storage:'storage.googleapis.com',registry:'artifactregistry.googleapis.com'}))add('google_project_service','required_'+name,{project:projectId,service,disable_on_destroy:false});
|
|
92
|
+
add('google_project_service_identity','run',{provider:'google-beta',project:projectId,service:'run.googleapis.com',depends_on:['google_project_service.required_run']});
|
|
93
|
+
add('google_artifact_registry_repository_iam_member','image_pull',{project:projectId,location:registryLocation,repository:registry,role:'roles/artifactregistry.reader',member:ref('google_project_service_identity','run','member'),depends_on:['google_project_service.required_registry']});
|
|
94
|
+
const number='${data.google_project.destination.number}';
|
|
95
|
+
for(const {row}of plan.publicFaqPlan.entries){
|
|
96
|
+
const n=row.address,name=input(n+'_name','Unique short Cloud Run/runtime name. The generated deterministic URL is used for this public browser.','reviewed-public-help','^[a-z][a-z0-9-]{3,18}[a-z0-9]$');
|
|
97
|
+
const region=input(n+'_region','Reviewed single-region application, catalog and model location; no global model fallback.','australia-southeast1','^[a-z]+-[a-z]+[0-9]$');
|
|
98
|
+
if(/^[a-z]+-[a-z]+[0-9]$/.test(row.region)){b.variable[n+'_region'].default=row.region;b.examples[n+'_region']=row.region;}
|
|
99
|
+
const repository=input(n+'_image_repository','Path for the emitted image in the existing registry.','architect/public-help','^[a-z0-9]+(?:[._/-][a-z0-9]+)*$');
|
|
100
|
+
const digest=input(n+'_image_digest','Built, scanned, tested and authorized-published emitted image digest.','sha256:'+'0'.repeat(64),'^sha256:[0-9a-f]{64}$');
|
|
101
|
+
const model=input(n+'_model_id','Compatible reviewed regional Gemini model/version with structured JSON output; verify lifecycle, quota, context size and prices.','gemini-reviewed-version','^gemini-[a-z0-9.-]{1,80}$');
|
|
102
|
+
const editor=input(n+'_editor_group','Existing authorized Google editor group email. No users/groups are created.','help-editors@example.test','^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$');
|
|
103
|
+
const review=n+'_policy_review';b.variable[review]={type:'object({ projectId = string, region = string, model = string, abuseLogging = string, approvedBy = string, evidenceSha256 = string, expiresAt = string })',nullable:false,description:'Scoped expiring destination-owner review of actual abuse-monitoring terms/exemption. Operator attestation, not a fabricated approval API; runtime separately reads caching/model logging/sharing settings.'};b.examples[review]={projectId:'reviewed-project',region:b.examples[n+'_region'],model:'gemini-reviewed-version',abuseLogging:'REVIEW_REQUIRED',approvedBy:'REVIEW_REQUIRED',evidenceSha256:'0'.repeat(64),expiresAt:'REPLACE_AFTER_REVIEW'};
|
|
104
|
+
add('google_service_account',n,{project:projectId,account_id:name,display_name:'Public FAQ runtime; no catalog edit permission'});
|
|
105
|
+
const member='serviceAccount:'+ref('google_service_account',n,'email');
|
|
106
|
+
add('google_project_iam_custom_role',n,{project:projectId,role_id:'${replace(var.'+n+'_name, "-", "_")}_model',title:'FAQ model invocation and read-only policy',permissions:['aiplatform.endpoints.predict','aiplatform.cacheConfigs.get','aiplatform.endpoints.fetchPublisherModelConfig'],stage:'GA'});
|
|
107
|
+
add('google_project_iam_member',n,{project:projectId,role:ref('google_project_iam_custom_role',n,'name'),member,depends_on:['google_project_service.required_model']});
|
|
108
|
+
add('google_storage_bucket',n,{project:projectId,name:projectId+'-'+name+'-public',location:region,storage_class:'STANDARD',uniform_bucket_level_access:true,public_access_prevention:'enforced',force_destroy:false,versioning:{enabled:true},soft_delete_policy:{retention_duration_seconds:604800},lifecycle_rule:{action:{type:'Delete'},condition:{days_since_noncurrent_time:7}},lifecycle:{prevent_destroy:true},depends_on:['google_project_service.required_storage']});
|
|
109
|
+
for(const [suffix,permissions]of [['_catalog',['storage.objects.get']],['_editor',['storage.objects.get','storage.objects.create','storage.objects.delete']]])add('google_project_iam_custom_role',n+suffix,{project:projectId,role_id:'${replace(var.'+n+'_name, "-", "_")}'+suffix,title:suffix==='_catalog'?'FAQ current catalog reader':'FAQ conditional catalog editor',permissions,stage:'GA'});
|
|
110
|
+
add('google_storage_bucket_iam_member',n,{bucket:ref('google_storage_bucket',n,'name'),role:ref('google_project_iam_custom_role',n+'_catalog','name'),member});
|
|
111
|
+
add('google_storage_bucket_iam_member',n+'_editor',{bucket:ref('google_storage_bucket',n,'name'),role:ref('google_project_iam_custom_role',n+'_editor','name'),member:'group:'+editor});
|
|
112
|
+
const origin='https://'+name+'-'+number+'.'+region+'.run.app',settings={PROJECT_ID:projectId,REGION:region,MODEL_ID:model,PUBLIC_ORIGIN:origin,MAX_OUTPUT_TOKENS:'1024',CATALOG_BUCKET:ref('google_storage_bucket',n,'name'),POLICY_REVIEW_BASE64:'${base64encode(jsonencode(var.'+review+'))}'};
|
|
113
|
+
add('google_cloud_run_v2_service',n,{project:projectId,name,location:region,deletion_protection:true,ingress:'INGRESS_TRAFFIC_ALL',invoker_iam_disabled:false,iap_enabled:false,labels:{managed_by:'atmem-ai-architect',environment},template:{service_account:ref('google_service_account',n,'email'),timeout:'30s',max_instance_request_concurrency:5,scaling:{min_instance_count:0,max_instance_count:2},containers:{name:'application',image:registryLocation+'-docker.pkg.dev/'+projectId+'/'+registry+'/'+repository+'@'+digest,ports:{container_port:8080},resources:{limits:{cpu:'1',memory:'512Mi'},cpu_idle:true,startup_cpu_boost:true},env:Object.entries(settings).map(([name,value])=>({name,value})),startup_probe:{http_get:{path:'/healthz',port:8080},initial_delay_seconds:0,period_seconds:5,timeout_seconds:2,failure_threshold:12}}},depends_on:['google_project_service.required_run','google_project_service_identity.run','google_artifact_registry_repository_iam_member.image_pull','google_project_iam_member.'+n,'google_storage_bucket_iam_member.'+n]});
|
|
114
|
+
// Anonymous invocation is intentional for this public-only application, never
|
|
115
|
+
// applied to a private module or the bucket itself. Org policy must allow it.
|
|
116
|
+
add('google_cloud_run_v2_service_iam_member',n,{project:projectId,location:region,name:ref('google_cloud_run_v2_service',n,'name'),role:'roles/run.invoker',member:'allUsers'});
|
|
117
|
+
b.output[n+'_url']={value:origin};b.output[n+'_catalog']={value:{bucket:ref('google_storage_bucket',n,'name'),region}};b.source(row);
|
|
118
|
+
b.assertions.push(`run "${n}_public_boundary" {\n command = plan\n assert {\n condition = google_storage_bucket.${n}.public_access_prevention == "enforced" && google_storage_bucket.${n}.uniform_bucket_level_access && !google_storage_bucket.${n}.force_destroy\n error_message = "Only the app is public; the catalog bucket stays private and protected."\n }\n assert {\n condition = google_cloud_run_v2_service_iam_member.${n}.member == "allUsers" && google_cloud_run_v2_service_iam_member.${n}.role == "roles/run.invoker" && !google_cloud_run_v2_service.${n}.iap_enabled\n error_message = "This explicit public-only application has anonymous invocation, not an invented end-user identity."\n }\n assert {\n condition = toset(google_project_iam_custom_role.${n}_catalog.permissions) == toset(["storage.objects.get"]) && google_storage_bucket_iam_member.${n}_editor.member == "group:\${var.${n}_editor_group}"\n error_message = "Runtime read and native editor write authority must remain separate."\n }\n}\nrun "${n}_mutable_image_blocked" {\n command = plan\n variables { ${n}_image_digest = "latest" }\n expect_failures = [var.${n}_image_digest]\n}`);
|
|
119
|
+
}
|
|
120
|
+
const config={terraform:{required_version:'>= 1.17.1, < 2.0.0',required_providers:{google:{source:'hashicorp/google',version:'7.46.2'},'google-beta':{source:'hashicorp/google-beta',version:'7.46.2'}}},provider:{google:{project:projectId},'google-beta':{project:projectId}}};
|
|
121
|
+
return b.finish(config,CLOUD_PROVIDER_LOCKS.gcp+'\n'+CLOUD_PROVIDER_LOCKS.gcpBeta,'mock_provider "google" {\n override_during = plan\n mock_data "google_project" { defaults = { number = "123456789012" } }\n mock_resource "google_service_account" { defaults = { email = "runtime@reviewed-project.iam.gserviceaccount.com" } }\n}\nmock_provider "google-beta" {\n override_during = plan\n mock_resource "google_project_service_identity" { defaults = { email = "service-123456789012@serverless-robot-prod.iam.gserviceaccount.com", member = "serviceAccount:service-123456789012@serverless-robot-prod.iam.gserviceaccount.com" } }\n}\n',GCP_PUBLIC_FAQ_GUIDE);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export const GCP_PUBLIC_FAQ_GUIDE=`# Google public-only FAQ composition
|
|
125
|
+
|
|
126
|
+
Only this explicitly selected public Cloud Run browser/API receives anonymous
|
|
127
|
+
run.invoker access. Its catalog bucket remains private with public access
|
|
128
|
+
prevention and uniform IAM. The dedicated runtime has a bucket-scoped custom
|
|
129
|
+
object-reader role; a separate existing company editor group has get/create/delete
|
|
130
|
+
only on that public catalog bucket. There is no HTTP editing route. No private
|
|
131
|
+
source, arbitrary URL fetch, user identity or enterprise authorization is implied.
|
|
132
|
+
|
|
133
|
+
Existing project, registry and editor group are preserved. Required APIs are never
|
|
134
|
+
disabled on destroy. The Cloud Run platform agent, not the application, receives
|
|
135
|
+
reader access on the exact existing image repository. The runtime has narrow
|
|
136
|
+
project-level prediction and read-only cache/model-policy access; no policy writes
|
|
137
|
+
or user-managed key is emitted. Google-beta is used only for the documented service
|
|
138
|
+
identity resource. Reconcile inherited IAM and organization restrictions on public
|
|
139
|
+
invocation; do not disable organization policy to bypass a failure.
|
|
140
|
+
|
|
141
|
+
See applications/*/BUILD.md. Seed genuinely public articles using the authorized
|
|
142
|
+
editor and native generation preconditions; updates/deletes never fall back to
|
|
143
|
+
stale or inaccessible evidence. Versioning, noncurrent-version expiry and seven-day
|
|
144
|
+
soft deletion support recovery and are not an immediate erasure guarantee. Runtime
|
|
145
|
+
never retrieves a historical generation selected by a visitor. No question/answer
|
|
146
|
+
persistence or content-bearing app logs are implemented; review platform logging.
|
|
147
|
+
|
|
148
|
+
The owner policy review is scoped/expiring operator-attested evidence, not an IBM,
|
|
149
|
+
Google or other fabricated provider approval API. Runtime separately requires
|
|
150
|
+
disabled project caching and disabled model request/response logging/sharing.
|
|
151
|
+
The documented global cache-control read sends no question text; review that
|
|
152
|
+
control-plane processing and actual model geography/terms against residency needs.
|
|
153
|
+
Model availability/context/quotas, prices, anonymous abuse controls, budgets and
|
|
154
|
+
real answer/citation/abstention/latency tests remain destination checks. Concurrency,
|
|
155
|
+
token and instance bounds are not an invoice cap or SLA.
|
|
156
|
+
|
|
157
|
+
Use Terraform 1.17.1+; run init -backend=false, validate and test. These native schema
|
|
158
|
+
and mock plans do not establish actual IAM, model or deployed behavior. Build, scan
|
|
159
|
+
and test the exact source/image; obtain authorization before publishing, cloud
|
|
160
|
+
access, real account plan or deployment. Production state/operations remain gated.
|
|
161
|
+
`;
|
|
162
|
+
|
|
163
|
+
export function ibmPublicFaqTerraform(project,plan,environment='staging'){
|
|
164
|
+
const b=builder(project,plan,environment,'ibm'),{input,add}=b;
|
|
165
|
+
const account=input('account_id','Existing destination IBM account; no account is created.','a'.repeat(32),'^[0-9a-f]{32}$');
|
|
166
|
+
const region=input('region','Reviewed regional Code Engine, COS and watsonx model destination.','au-syd','^[a-z]{2}-[a-z]+$');
|
|
167
|
+
const entries=plan.publicFaqPlan.entries;
|
|
168
|
+
if(entries.every(e=>e.row.region===entries[0].row.region)&&/^[a-z]{2}-[a-z]+$/.test(entries[0].row.region)){b.variable.region.default=entries[0].row.region;b.examples.region=entries[0].row.region;}
|
|
169
|
+
b.variable.region.validation=ibmRegistryRegionValidation();
|
|
170
|
+
const ceProject=input('code_engine_project_id','Existing reviewed Code Engine project; never recreate or import it.','11111111-1111-1111-1111-111111111111',UUID);
|
|
171
|
+
const registry=input('registry_namespace','Existing regional IBM Container Registry namespace.','reviewed-namespace','^[a-z0-9]+(?:[-_][a-z0-9]+)*$');
|
|
172
|
+
const pullSecret=input('registry_pull_secret','Existing registry-pull secret NAME in that project; no credential value is exported.','reviewed-registry-pull','^[a-z][a-z0-9-]{1,61}[a-z0-9]$');
|
|
173
|
+
b.data.ibm_code_engine_project={destination:{project_id:ceProject}};
|
|
174
|
+
b.resource.terraform_data.review_gate.lifecycle.precondition.push({condition:'${data.ibm_code_engine_project.destination.account_id == var.account_id && data.ibm_code_engine_project.destination.region == var.region}',error_message:'Existing Code Engine project must match the reviewed account and region.'});
|
|
175
|
+
for(const {row}of entries){
|
|
176
|
+
const n=row.address,name=input(n+'_name','Unique application and trusted-profile name.','reviewed-public-help','^[a-z][a-z0-9-]{2,38}[a-z0-9]$');
|
|
177
|
+
const repository=input(n+'_image_repository','Path for this emitted image in the existing namespace.','architect/public-help','^[a-z0-9]+(?:[._/-][a-z0-9]+)*$');
|
|
178
|
+
const digest=input(n+'_image_digest','Built, scanned, tested and authorized-published image digest.','sha256:'+'0'.repeat(64),'^sha256:[0-9a-f]{64}$');
|
|
179
|
+
const wxProject=input(n+'_watsonx_project_id','Existing watsonx data-platform project. Add the trusted profile as an authorized collaborator and associate the runtime instance.','22222222-2222-2222-2222-222222222222',UUID);
|
|
180
|
+
const instance=input(n+'_runtime_instance_id','Existing associated watsonx Runtime instance GUID.','33333333-3333-3333-3333-333333333333',UUID);
|
|
181
|
+
const model=input(n+'_model_id','Reviewed regional Text Chat JSON-object model; verify lifecycle, quotas and geography.','ibm/reviewed-model','^[a-z0-9][a-z0-9_.-]{0,79}/[a-z0-9][a-z0-9_.-]{0,99}$');
|
|
182
|
+
const editor=input(n+'_editor_access_group_id','Existing authorized company editor access-group ID. No group or user is created.','AccessGroup-44444444-4444-4444-4444-444444444444','^AccessGroup-[0-9a-fA-F-]{36}$');
|
|
183
|
+
const bucket=input(n+'_catalog_bucket','Globally unique regional bucket dedicated to genuinely public article content; the bucket itself remains private.','reviewed-public-catalog-unique','^[a-z][a-z0-9-]{1,61}[a-z0-9]$');
|
|
184
|
+
const review=n+'_policy_review';b.variable[review]={type:'object({ accountId = string, projectId = string, runtimeInstanceId = string, region = string, model = string, retentionReview = string, approvedBy = string, evidenceSha256 = string, expiresAt = string })',nullable:false,description:'Scoped expiring destination-owner review of actual model/provider retention and processing terms. Operator-attested evidence, not a provider approval API.'};b.examples[review]={accountId:b.examples.account_id,projectId:b.examples[n+'_watsonx_project_id'],runtimeInstanceId:b.examples[n+'_runtime_instance_id'],region:b.examples.region,model:b.examples[n+'_model_id'],retentionReview:'REVIEW_REQUIRED',approvedBy:'REVIEW_REQUIRED',evidenceSha256:'0'.repeat(64),expiresAt:'REPLACE_AFTER_REVIEW'};
|
|
185
|
+
add('ibm_resource_instance',n+'_catalog',{name:name+'-public-catalog',service:'cloud-object-storage',plan:'standard',location:'global',resource_group_id:'${data.ibm_code_engine_project.destination.resource_group_id}',lifecycle:{prevent_destroy:true,postcondition:[{condition:'${self.account_id == var.account_id}',error_message:'Catalog instance must belong to the reviewed account.'}]}});
|
|
186
|
+
add('ibm_cos_bucket',n,{bucket_name:bucket,resource_instance_id:ref('ibm_resource_instance',n+'_catalog','id'),region_location:region,storage_class:'standard',endpoint_type:'public',force_delete:false,object_versioning:{enable:true},noncurrent_version_expiration:{enable:true,noncurrent_days:7,prefix:'',rule_id:'expire-old-catalog-versions'},lifecycle:{prevent_destroy:true}});
|
|
187
|
+
add('ibm_iam_trusted_profile',n,{name,description:'Public FAQ compute identity; no catalog write or end-user authority'});
|
|
188
|
+
add('ibm_iam_trusted_profile_link',n,{profile_id:ref('ibm_iam_trusted_profile',n,'profile_id'),cr_type:'CE',link:{crn:'${data.ibm_code_engine_project.destination.crn}',component_name:ref('ibm_code_engine_app',n,'name'),component_type:'app'}});
|
|
189
|
+
add('ibm_iam_trusted_profile_policy',n,{iam_id:ref('ibm_iam_trusted_profile',n,'iam_id'),roles:['Writer'],resources:{service:'pm-20',resource_instance_id:instance,region},description:'Existing watsonx runtime-instance scope. Writer is broader than prediction-only; project membership remains separate.'});
|
|
190
|
+
const catalogScope={service:'cloud-object-storage',resource_instance_id:ref('ibm_resource_instance',n+'_catalog','guid'),resource_type:'bucket',resource:ref('ibm_cos_bucket',n,'bucket_name')};
|
|
191
|
+
add('ibm_iam_trusted_profile_policy',n+'_catalog',{iam_id:ref('ibm_iam_trusted_profile',n,'iam_id'),roles:['Object Reader'],resources:catalogScope});
|
|
192
|
+
// Article deletion rewrites catalog.json; object DELETE is intentionally absent.
|
|
193
|
+
// Object Writer includes object metadata/retention writes; it is not a custom
|
|
194
|
+
// put-only role. It cannot administer this bucket or grant public access.
|
|
195
|
+
add('ibm_iam_access_group_policy',n+'_editor',{access_group_id:editor,roles:['Object Reader','Object Writer'],resources:catalogScope});
|
|
196
|
+
const settings={ACCOUNT_ID:account,WATSONX_PROJECT_ID:wxProject,RUNTIME_INSTANCE_ID:instance,MODEL_REGION:region,MODEL_ID:model,IAM_PROFILE_ID:ref('ibm_iam_trusted_profile',n,'profile_id'),MAX_OUTPUT_TOKENS:'1024',CATALOG_BUCKET:ref('ibm_cos_bucket',n,'bucket_name'),POLICY_REVIEW_BASE64:'${base64encode(jsonencode(var.'+review+'))}'};
|
|
197
|
+
add('ibm_code_engine_app',n,{project_id:ceProject,name,image_reference:ibmRegistryHostExpression()+'/'+registry+'/'+repository+'@'+digest,image_secret:pullSecret,image_port:8080,managed_domain_mappings:'local_public',run_as_user:10001,run_compute_resource_token_enabled:true,scale_cpu_limit:'0.5',scale_memory_limit:'1G',scale_min_instances:0,scale_max_instances:2,scale_concurrency:5,scale_concurrency_target:5,scale_request_timeout:30,run_env_variables:Object.entries(settings).map(([name,value])=>({name,value,type:'literal'})),probe_readiness:{type:'http',path:'/healthz',port:8080,initial_delay:2,interval:5,timeout:2,failure_threshold:12},depends_on:['ibm_iam_trusted_profile_policy.'+n,'ibm_iam_trusted_profile_policy.'+n+'_catalog']});
|
|
198
|
+
b.assertions.push(`run "${n}_sydney_registry" {\n command = plan\n assert {\n condition = var.region != "au-syd" || startswith(ibm_code_engine_app.${n}.image_reference,"au.icr.io/")\n error_message = "Sydney uses au.icr.io; region concatenation cannot select a valid registry."\n }\n}`);
|
|
199
|
+
b.output[n+'_url']={value:ref('ibm_code_engine_app',n,'endpoint')};b.output[n+'_catalog']={value:{bucket,region}};b.output[n+'_trusted_profile_iam_id']={value:ref('ibm_iam_trusted_profile',n,'iam_id')};b.source(row);
|
|
200
|
+
b.assertions.push(`run "${n}_public_boundary" {\n command = plan\n assert {\n condition = ibm_iam_trusted_profile_policy.${n}_catalog.roles == tolist(["Object Reader"]) && ibm_iam_trusted_profile_policy.${n}_catalog.resources[0].resource_type == "bucket" && ibm_iam_trusted_profile_policy.${n}_catalog.resources[0].resource == var.${n}_catalog_bucket\n error_message = "Runtime may read only the dedicated catalog bucket; no write or public-access grant."\n }\n assert {\n condition = toset(ibm_iam_access_group_policy.${n}_editor.roles) == toset(["Object Reader", "Object Writer"]) && ibm_iam_access_group_policy.${n}_editor.resources[0].resource_type == "bucket" && ibm_iam_access_group_policy.${n}_editor.access_group_id == var.${n}_editor_access_group_id\n error_message = "Separate existing editors have bucket-scoped object access, never Manager or bucket Writer."\n }\n assert {\n condition = !ibm_cos_bucket.${n}.force_delete && ibm_cos_bucket.${n}.object_versioning[0].enable && ibm_code_engine_app.${n}.run_compute_resource_token_enabled && ibm_code_engine_app.${n}.run_as_user == 10001\n error_message = "Protect catalog recovery and use nonroot keyless compute identity."\n }\n}\nrun "${n}_mutable_image_blocked" {\n command = plan\n variables { ${n}_image_digest = "latest" }\n expect_failures = [var.${n}_image_digest]\n}`);
|
|
201
|
+
}
|
|
202
|
+
const config={terraform:{required_version:'>= 1.17.1, < 2.0.0',required_providers:{ibm:{source:'IBM-Cloud/ibm',version:'1.89.0'}}},provider:{ibm:{region}}};
|
|
203
|
+
const mocks=`mock_provider "ibm" {\n override_during = plan\n mock_data "ibm_code_engine_project" { defaults = { account_id = "${b.examples.account_id}", region = "${b.examples.region}", resource_group_id = "${'b'.repeat(32)}", crn = "crn:v1:bluemix:public:codeengine:${b.examples.region}:a/${b.examples.account_id}:11111111-1111-1111-1111-111111111111::" } }\n mock_resource "ibm_resource_instance" { defaults = { account_id = "${b.examples.account_id}", id = "crn:v1:bluemix:public:cloud-object-storage:global:a/${b.examples.account_id}:55555555-5555-5555-5555-555555555555::", guid = "55555555-5555-5555-5555-555555555555" } }\n}\n`;
|
|
204
|
+
b.assertions.push(`run "wrong_account_blocked" {\n command = plan\n variables { account_id = "${'c'.repeat(32)}" }\n expect_failures = [terraform_data.review_gate]\n}`);
|
|
205
|
+
return b.finish(config,CLOUD_PROVIDER_LOCKS.ibm,mocks,IBM_PUBLIC_FAQ_GUIDE);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
export const IBM_PUBLIC_FAQ_GUIDE=`# IBM public-only FAQ composition
|
|
209
|
+
|
|
210
|
+
The anonymous browser/API uses a dedicated Code Engine trusted profile linked only
|
|
211
|
+
to this existing project and this new app. The runtime receives Object Reader on
|
|
212
|
+
the exact private COS bucket; a separate existing company access group receives
|
|
213
|
+
Object Reader and Object Writer on that bucket. Object Writer includes object
|
|
214
|
+
metadata and retention operations, not merely PUT; it does not administer buckets
|
|
215
|
+
or make them public. Article deletion conditionally replaces catalog.json; no
|
|
216
|
+
object DELETE grant or application HTTP editing route is needed. No public-access
|
|
217
|
+
group policy is emitted. Reconcile inherited account/group policies, which can
|
|
218
|
+
override narrower grants. Public endpoint routing does not mean anonymous storage.
|
|
219
|
+
|
|
220
|
+
COS uses a global service instance with a single regional data bucket, encryption
|
|
221
|
+
at rest managed by IBM and TLS. Control-plane geography requires separate review.
|
|
222
|
+
Versioning and seven-day noncurrent expiry aid recovery, not immediate erasure.
|
|
223
|
+
The runtime reads only the current catalog, checks it again before returning an
|
|
224
|
+
answer and withholds stale/unsupported evidence. Questions/answers are not persisted
|
|
225
|
+
or written to application logs. Private networking/customer-managed keys are not
|
|
226
|
+
implemented. This public-only application is not a private knowledge assistant.
|
|
227
|
+
|
|
228
|
+
Existing Code Engine project, namespace/pull-secret, watsonx project and associated
|
|
229
|
+
runtime instance remain intact. The profile gets Writer on that exact pm-20
|
|
230
|
+
instance; this is broader than prediction-only. Add the generated profile as a
|
|
231
|
+
minimum supported project collaborator and verify the association/model separately.
|
|
232
|
+
App creation precedes its compute link to avoid a Terraform cycle; health is
|
|
233
|
+
liveness, not model readiness. No app API key or end-user identity is invented.
|
|
234
|
+
|
|
235
|
+
See applications/*/BUILD.md for editor/build/testing commands. Supply a scoped,
|
|
236
|
+
expiring destination-owner policy review and test real IAM, compute token exchange,
|
|
237
|
+
conditional storage edits, source updates/deletions, model citations/abstention and
|
|
238
|
+
latency. The policy review is operator evidence, not a fabricated provider API.
|
|
239
|
+
Review current model availability, quotas, processing terms, prices, anonymous
|
|
240
|
+
abuse controls and budget policy. Instance/concurrency/token limits are not an
|
|
241
|
+
invoice cap. Protect state/variables. Native schema/mocks and local runtime tests
|
|
242
|
+
do not establish account-plan or deployed behavior. Obtain authorization before
|
|
243
|
+
image publication, cloud access, real plans or deployment; production operating
|
|
244
|
+
and state/backup review remain gated.
|
|
245
|
+
|
|
246
|
+
References:
|
|
247
|
+
- https://cloud.ibm.com/docs/cloud-object-storage?topic=cloud-object-storage-iam-bucket-permissions
|
|
248
|
+
- https://cloud.ibm.com/docs/iam?topic=iam-iam-service-roles-actions
|
|
249
|
+
- https://cloud.ibm.com/docs/cloud-object-storage?topic=cloud-object-storage-upload
|
|
250
|
+
- https://cloud.ibm.com/docs/codeengine?topic=codeengine-trusted-profiles-authentication-file
|
|
251
|
+
`;
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import outputSchema from './runtime/faq-output-contract.json' with {type:'json'};
|
|
2
|
+
import sources from './runtime/public-faq-sources.json' with {type:'json'};
|
|
3
|
+
import awsLock from './runtime/aws-web-python-lock.json' with {type:'json'};
|
|
4
|
+
import azureLock from './runtime/azure-python-lock.json' with {type:'json'};
|
|
5
|
+
import webLock from './runtime/web-python-lock.json' with {type:'json'};
|
|
6
|
+
import ibmLock from './runtime/ibm-python-lock.json' with {type:'json'};
|
|
7
|
+
import testLock from './runtime/azure-test-lock.json' with {type:'json'};
|
|
8
|
+
import base from './runtime/python-container-lock.json' with {type:'json'};
|
|
9
|
+
import {pythonContainer} from './python-container.mjs';
|
|
10
|
+
import {existingDeployment} from './deployment-ownership.mjs';
|
|
11
|
+
|
|
12
|
+
export const PUBLIC_FAQ_SERVICES={aws:'AWS Lambda',azure:'Azure App Service',gcp:'Google Cloud Run',ibm:'IBM Code Engine'};
|
|
13
|
+
const locks={aws:awsLock,azure:azureLock,gcp:webLock,ibm:ibmLock};
|
|
14
|
+
const adapters={aws:['aws_json_model.py','lambda_faq.py'],azure:['azure_structured.py'],gcp:['gcp_structured.py','policy_review.py'],ibm:['ibm_structured.py','policy_review.py']};
|
|
15
|
+
|
|
16
|
+
export function publicFaqPlan(project,rows){
|
|
17
|
+
const entries=[];
|
|
18
|
+
for(const node of project.nodes){
|
|
19
|
+
const d=node.data,row=rows.find(r=>r.id===node.id);
|
|
20
|
+
if(!row||d.implementation!=='public-faq-app'||d.service!==PUBLIC_FAQ_SERVICES[d.provider]||existingDeployment(node)||d.origin==='existing')continue;
|
|
21
|
+
if(d.config?.outputContract)throw Error('Public FAQ uses its built-in cited-answer contract; preserve custom operation requirements as separate implementation work.');
|
|
22
|
+
for(const [key,value]of Object.entries({maxInputBytes:2000,maxArticleBytes:30000,maxArticles:100}))if(d.config?.[key]!==undefined&&d.config[key]!==value)throw Error('The public FAQ recipe declares '+key+' = '+value+'; a different explicit limit requires generator implementation, not silent substitution.');
|
|
23
|
+
entries.push({row,provider:d.provider});
|
|
24
|
+
}
|
|
25
|
+
const ids=new Set(entries.map(e=>e.row.id)),browsers=new Set(project.nodes.filter(n=>existingDeployment(n)&&n.data.provider==='tools'&&n.data.binding==='web-browser').map(n=>n.id));
|
|
26
|
+
const editors=new Set(project.nodes.filter(n=>existingDeployment(n)&&n.data.provider==='tools'&&n.data.binding==='public-catalog-editor').map(n=>n.id));
|
|
27
|
+
const editorEdges=project.edges.filter(e=>e.integration==='public-catalog-edit'&&editors.has(e.source)&&ids.has(e.target));
|
|
28
|
+
return {entries,componentIds:[...ids],editorIds:[...new Set(editorEdges.map(e=>e.source))],edgeIds:[...project.edges.filter(e=>e.integration==='browser-https'&&browsers.has(e.source)&&ids.has(e.target)),...editorEdges].map(e=>e.id)};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// This emits source, not a coverage claim. Public registration requires each
|
|
32
|
+
// provider's complete hosting/storage/identity composition and qualification.
|
|
33
|
+
export function publicFaqFiles(provider,address){
|
|
34
|
+
if(!adapters[provider]||!/^block_[0-9a-f]+$/.test(address))throw Error('Invalid owned public FAQ application address/provider');
|
|
35
|
+
const folder='applications/'+address+'/',files={},modules=['public_faq.py','public_catalog_store.py','public_faq_app.py','structured_http.py','structured_output.py',...adapters[provider]];
|
|
36
|
+
for(const name of [...modules,'public_catalog_admin.py'])files[folder+name]=sources[name];
|
|
37
|
+
for(const name of ['web/index.html','web/app.css','web/app.js'])files[folder+name]=sources[name];
|
|
38
|
+
for(const kind of ['core','http','catalog_admin','catalog_store']){
|
|
39
|
+
const name='faq_'+kind+'_acceptance.py';let code=sources[name];
|
|
40
|
+
if(kind==='catalog_store'&&provider!=='aws'){
|
|
41
|
+
const start=code.indexOf('class S3CatalogContractTests('),end=code.indexOf('class ConditionalConcurrencyTests(');
|
|
42
|
+
if(start<0||end<=start)throw Error('Provider-specific test boundary changed; review it before emission');
|
|
43
|
+
code=code.slice(0,start)+code.slice(end);
|
|
44
|
+
code=code.replace(/^import boto3\n/m,'').replace(/^from botocore\.[^\n]+\n/gm,'');
|
|
45
|
+
}
|
|
46
|
+
files[folder+name]=code;
|
|
47
|
+
}
|
|
48
|
+
if(provider==='aws')files[folder+'faq_lambda_acceptance.py']=sources['faq_lambda_acceptance.py'];
|
|
49
|
+
files[folder+'faq_acceptance.py']='"""Local public-only lifecycle/HTTP/transport checks; not cloud IAM or model quality."""\nfrom faq_core_acceptance import PublicFaqCoreTests\nfrom faq_http_acceptance import PublicFaqHttpTests\nfrom faq_catalog_admin_acceptance import CatalogAdminTests\nfrom faq_catalog_store_acceptance import HttpCatalogContractTests,ConditionalConcurrencyTests'+(provider==='aws'?',S3CatalogContractTests':'')+(provider==='aws'?'\nfrom faq_lambda_acceptance import PublicFaqLambdaTests':'')+'\nimport unittest\nif __name__=="__main__":unittest.main()\n';
|
|
50
|
+
const lock=locks[provider];files[folder+'requirements.lock']=lock.requirements;files[folder+'dependency-sources.json']=JSON.stringify(lock.sources,null,2);
|
|
51
|
+
files[folder+'test-requirements.lock']=testLock.requirements;files[folder+'test-dependency-sources.json']=JSON.stringify(testLock.sources,null,2);
|
|
52
|
+
files[folder+'container-base.json']=JSON.stringify(base,null,2);
|
|
53
|
+
files[folder+'output-contract.json']=JSON.stringify(outputSchema,null,2);
|
|
54
|
+
files[folder+'faq-deployment.json']=JSON.stringify({format:'public-faq-v1',provider},null,2);
|
|
55
|
+
files[folder+'Dockerfile']=pythonContainer('public_faq_app',modules,['faq-deployment.json']);
|
|
56
|
+
files[folder+'.dockerignore']='*\n!requirements.lock\n!output-contract.json\n!faq-deployment.json\n'+modules.map(n=>'!'+n+'\n').join('')+'!web/\n!web/*\n';
|
|
57
|
+
files[folder+'BUILD.md']=provider==='aws'?PUBLIC_FAQ_BUILD.replace(/Build this directory as Linux\/amd64[\s\S]*?host applies identical filesystem isolation[.]\n/, 'For AWS deployment, run python3 build-runtime.py from the Terraform root. This builds a deterministic Python 3.13 Linux x86_64 Lambda ZIP with hash-locked wheels, source, owned metadata and browser assets. Retain build/artifact-hashes.json. Test the actual ZIP in the reviewed Lambda Linux runtime and scan its dependencies. The Dockerfile is an optional portable local web-runtime check; it is not the Lambda deployment artifact. No registry publication or image input is required. Obtain explicit cloud authorization before any account plan or deployment.\n'):PUBLIC_FAQ_BUILD;
|
|
58
|
+
return files;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export const PUBLIC_FAQ_BUILD=`# Generated public FAQ application
|
|
62
|
+
|
|
63
|
+
Use an isolated Python 3.13 environment. Install test-requirements.lock with
|
|
64
|
+
--only-binary=:all: --require-hashes, then run faq_acceptance.py -v. The source
|
|
65
|
+
tests use synthetic public articles and explicit transport fixtures. They do not
|
|
66
|
+
establish real IAM, model quality, service availability or deployment behavior.
|
|
67
|
+
|
|
68
|
+
Build this directory as Linux/amd64 with its emitted Dockerfile, run startup and
|
|
69
|
+
acceptance checks on the exact image, scan it and retain source/image digests.
|
|
70
|
+
Obtain authorization before authenticating to a registry or publishing an image.
|
|
71
|
+
Supply the reviewed immutable release inputs required by this provider's Terraform.
|
|
72
|
+
The runtime runs nonroot; use a read-only filesystem and writable temporary space
|
|
73
|
+
where the destination supports it. Local read-only checks do not prove the cloud
|
|
74
|
+
host applies identical filesystem isolation.
|
|
75
|
+
|
|
76
|
+
The anonymous API can only read the dedicated public catalog and invoke the
|
|
77
|
+
reviewed regional model. It has no HTTP editing endpoint. Never grant the runtime
|
|
78
|
+
catalog write, private-source, account-admin or model-policy-write permissions.
|
|
79
|
+
Review inherited destination IAM in addition to the emitted grants. An explicit
|
|
80
|
+
public marker does not automatically classify or approve document content: the
|
|
81
|
+
authorized editor is responsible for selecting genuinely public help articles.
|
|
82
|
+
|
|
83
|
+
Authorize the separate editor using the emitted native role and a short-lived
|
|
84
|
+
credential. Keep credentials and article files outside this source bundle. Use
|
|
85
|
+
public_catalog_admin.py --help, then inspect, init, upsert or delete as appropriate.
|
|
86
|
+
Initial creation requires --expected-version create. Later edits require the exact
|
|
87
|
+
observed version and --confirm-write. The native conditional write must succeed;
|
|
88
|
+
conflicts require reloading and reviewing the change. Never retry a write blindly
|
|
89
|
+
after an unconfirmed response. Editor flags express intent; the cloud IAM role
|
|
90
|
+
remains the authorization boundary. Do not pass a browser user token as an editor
|
|
91
|
+
credential. Token files must be operator-owned and private.
|
|
92
|
+
|
|
93
|
+
Seed the catalog explicitly before allowing traffic. Initialization reads every
|
|
94
|
+
file in a dedicated public .txt/.md directory, supports spaces/Unicode names and
|
|
95
|
+
creates stable distinct source IDs. It rejects symlinks, invalid UTF-8, oversized
|
|
96
|
+
files or unsupported entries rather than silently omitting articles. Later updates
|
|
97
|
+
and deletions change the current manifest; any retained backup versions require a
|
|
98
|
+
separately reviewed operator recovery path. The API never falls back to cached or
|
|
99
|
+
inaccessible source data. A changed source during inference withholds that answer.
|
|
100
|
+
|
|
101
|
+
The bounded lexical retriever admits up to 100 articles of 30000 UTF-8 bytes each;
|
|
102
|
+
the acceptance project starts with twenty. It supplies at most two full relevant
|
|
103
|
+
articles, without cutting sentences. Citation IDs and quotes are independently
|
|
104
|
+
verified against that exact evidence. URLs/titles come from the approved catalog,
|
|
105
|
+
not the model. Syntax and quote membership do not prove factual entailment: run a
|
|
106
|
+
representative real-model answer/citation/abstention evaluation before deployment.
|
|
107
|
+
|
|
108
|
+
The provider schema remains stable across queries to avoid a new grammar for every
|
|
109
|
+
source combination. The bounded synchronous AWS adapter uses independently decoded
|
|
110
|
+
JSON, not a claimed provider-constrained grammar: Bedrock's new-schema compilation
|
|
111
|
+
can take around 90 seconds and cannot silently fit a 29-second HTTP path. Other
|
|
112
|
+
adapters use their documented output modes with the same independent decoder.
|
|
113
|
+
Unsupported model/output responses fail closed; no model or region is silently
|
|
114
|
+
substituted. The browser does not retry model calls automatically.
|
|
115
|
+
|
|
116
|
+
Verify current regional model support, data handling, identity/control-plane
|
|
117
|
+
processing, quotas and prices with retained evidence. Limits on input, output,
|
|
118
|
+
concurrency and instance count are not an invoice cap, availability or latency SLA.
|
|
119
|
+
No question/answer persistence or content-bearing application logs are implemented;
|
|
120
|
+
review provider/platform logging and retention separately. Private enterprise
|
|
121
|
+
connectors, user tenancy, payments and durable workflows are different capabilities.
|
|
122
|
+
`;
|
package/src/pulumi.mjs
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/** AtMem AI Architect's initial Pulumi interchange. Does not execute infrastructure commands. */
|
|
2
|
+
export function importPulumiSnapshot(raw) {
|
|
3
|
+
const deployment = raw?.deployment || raw;
|
|
4
|
+
if (
|
|
5
|
+
!deployment ||
|
|
6
|
+
!Array.isArray(deployment.resources) ||
|
|
7
|
+
deployment.resources.length > 1000
|
|
8
|
+
)
|
|
9
|
+
throw Error(
|
|
10
|
+
"Expected a Pulumi stack export with deployment.resources (up to 1,000 resources).",
|
|
11
|
+
);
|
|
12
|
+
if(deployment.resources.some(r=>!r||typeof r!=='object'||typeof r.type!=='string'||typeof r.urn!=='string'))throw Error('Pulumi resource metadata is invalid; no resource was silently discarded.');
|
|
13
|
+
const resources = deployment.resources
|
|
14
|
+
.filter(
|
|
15
|
+
(r) =>
|
|
16
|
+
typeof r.type === "string" &&
|
|
17
|
+
typeof r.urn === "string" &&
|
|
18
|
+
!r.type.startsWith("pulumi:"),
|
|
19
|
+
)
|
|
20
|
+
.map((r, i) => {
|
|
21
|
+
const name=r.urn.split("::").at(-1);
|
|
22
|
+
if(!r.urn.startsWith('urn:pulumi:')||r.urn.length>600||!r.type||r.type.length>200||!name||name.length>150)throw Error('Pulumi resource identity exceeds the supported metadata bounds or is invalid; nothing was clipped. Preserve the original export.');
|
|
23
|
+
return ({
|
|
24
|
+
id: `observed-${i}`,
|
|
25
|
+
urn: r.urn,
|
|
26
|
+
type: r.type,
|
|
27
|
+
name,
|
|
28
|
+
provider: r.type.startsWith("aws:")
|
|
29
|
+
? "aws"
|
|
30
|
+
: r.type.startsWith("azure")
|
|
31
|
+
? "azure"
|
|
32
|
+
: r.type.startsWith("gcp:")
|
|
33
|
+
? "gcp"
|
|
34
|
+
: r.type.startsWith("ibm:")
|
|
35
|
+
? "ibm"
|
|
36
|
+
: "tools",
|
|
37
|
+
});});
|
|
38
|
+
if(new Set(resources.map(r=>r.urn)).size!==resources.length)throw Error('Duplicate Pulumi resource identities require an explicit ownership decision; no resource was selected or discarded.');
|
|
39
|
+
// Never retain inputs, outputs, secret envelopes, credentials, provider config or raw state.
|
|
40
|
+
return {
|
|
41
|
+
kind: "imported-pulumi-snapshot",
|
|
42
|
+
importedAt: new Date().toISOString(),
|
|
43
|
+
liveRefresh: false,
|
|
44
|
+
resources,
|
|
45
|
+
notice:
|
|
46
|
+
"Imported state metadata only. Not a live cloud refresh. Inputs and outputs were discarded.",
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
export function snapshotToProject(snapshot) {
|
|
50
|
+
if (snapshot.resources.length > 100)
|
|
51
|
+
throw Error("Select a snapshot with at most 100 resources for the canvas.");
|
|
52
|
+
return {
|
|
53
|
+
version: 1,
|
|
54
|
+
revision: 1,
|
|
55
|
+
name: "Pulumi snapshot — proposed design import",
|
|
56
|
+
provider: "tools",
|
|
57
|
+
requirements:
|
|
58
|
+
"Explicitly imported resource references from a Pulumi stack export. No properties, secrets, cloud access or live drift verification are included.",
|
|
59
|
+
...(snapshot.resources.some(r=>r.urn)?{extensions:{externalReferences:{version:1,references:snapshot.resources.filter(r=>r.urn).map(r=>({componentId:r.id,source:'pulumi-stack-export',externalId:r.urn,resourceType:r.type}))}}}:{}),
|
|
60
|
+
nodes: snapshot.resources.map((r, i) => ({
|
|
61
|
+
id: r.id,
|
|
62
|
+
type: "resource",
|
|
63
|
+
position: { x: (i % 3) * 310, y: Math.floor(i / 3) * 230 },
|
|
64
|
+
data: {
|
|
65
|
+
label: r.name,
|
|
66
|
+
provider: r.provider,
|
|
67
|
+
kind: "resource",
|
|
68
|
+
description: r.type,
|
|
69
|
+
origin: "existing",
|
|
70
|
+
binding: "existing-service",
|
|
71
|
+
service: r.type,
|
|
72
|
+
config: {
|
|
73
|
+
region: "Unknown — not imported",
|
|
74
|
+
classification: "Internal",
|
|
75
|
+
timeout: 5000,
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
})),
|
|
79
|
+
edges: [],
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
export function pulumiScaffold(project, environment = "staging") {
|
|
83
|
+
const graph = project.nodes.map((n) => ({
|
|
84
|
+
id: n.id,
|
|
85
|
+
name: n.data.label,
|
|
86
|
+
provider: n.data.provider,
|
|
87
|
+
kind: n.data.kind,
|
|
88
|
+
dependsOn: project.edges
|
|
89
|
+
.filter((e) => e.target === n.id)
|
|
90
|
+
.map((e) => e.source),
|
|
91
|
+
}));
|
|
92
|
+
return {
|
|
93
|
+
"Pulumi.yaml":
|
|
94
|
+
"name: atforma-design\nruntime: nodejs\ndescription: AtMem AI Architect architecture scaffold; no cloud resource implementations\n",
|
|
95
|
+
"package.json": JSON.stringify(
|
|
96
|
+
{
|
|
97
|
+
name: "atforma-design",
|
|
98
|
+
private: true,
|
|
99
|
+
scripts: { typecheck: "tsc --noEmit" },
|
|
100
|
+
dependencies: { "@pulumi/pulumi": "3.273.0" },
|
|
101
|
+
devDependencies: { typescript: "5.9.3", "@types/node": "22.19.11" },
|
|
102
|
+
},
|
|
103
|
+
null,
|
|
104
|
+
2,
|
|
105
|
+
),
|
|
106
|
+
"tsconfig.json": JSON.stringify(
|
|
107
|
+
{
|
|
108
|
+
compilerOptions: {
|
|
109
|
+
target: "ES2022",
|
|
110
|
+
module: "commonjs",
|
|
111
|
+
strict: true,
|
|
112
|
+
esModuleInterop: true,
|
|
113
|
+
skipLibCheck: true,
|
|
114
|
+
},
|
|
115
|
+
include: ["index.ts"],
|
|
116
|
+
},
|
|
117
|
+
null,
|
|
118
|
+
2,
|
|
119
|
+
),
|
|
120
|
+
"index.ts": `import * as pulumi from '@pulumi/pulumi';\n\n// AtMem AI Architect revision ${project.revision}; ${environment}.\n// These metadata components are NOT cloud resources.\n// Implement reviewed provider-native resources before any infrastructure deployment.\nconst design = ${JSON.stringify(graph, null, 2)};\nconst blocks = new Map<string, pulumi.ComponentResource>();\nconst remaining = new Map(design.map(block => [block.id, block]));\nwhile (remaining.size) {\n let progress = false;\n for (const [id, block] of remaining) {\n if (block.dependsOn.every(parent => blocks.has(parent))) {\n blocks.set(id, new pulumi.ComponentResource('atforma:design:Block', id, { label: block.name, provider: block.provider, kind: block.kind }, { protect: true, dependsOn: block.dependsOn.map(parent => blocks.get(parent)!) }));\n remaining.delete(id); progress = true;\n }\n }\n if (!progress) throw new Error('Design contains cycles or missing dependencies');\n}\nexport const designRevision = ${project.revision};\nexport const environment = ${JSON.stringify(environment)};\nexport const cloudResourcesImplemented = false;\n`,
|
|
121
|
+
"README.md": `# AtMem AI Architect Pulumi scaffold\n\nDesign revision ${project.revision}; environment ${environment}.\n\nThis scaffold registers metadata ComponentResources only. It does not provision cloud resources, create network connections, enforce IAM, or implement AI inference. Wire dependencies express ordering only. Do not treat a successful preview of this scaffold as cloud validation.\n\nNext: implement provider-specific resource constructors and configuration, review costs/permissions, then run Pulumi preview in a separately configured staging stack.\n\nPulumi import brings existing resources into management; refresh updates recorded state from cloud reality. Neither automatically reconstructs an arbitrary application graph or edits its source code. AtMem AI Architect currently imports sanitised metadata from stack-export JSON; it does not execute import, refresh, preview, or update.\n`,
|
|
122
|
+
};
|
|
123
|
+
}
|