@atmem/architect 0.0.0-stage → 0.2.0
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/LICENSE +202 -0
- package/NOTICE +6 -0
- package/README.md +31 -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-BTLHaa3J.css +1 -0
- package/dist/assets/index-CQ2C1gKF.js +21338 -0
- package/dist/assets/index.es-DTyqIdaO.js +18 -0
- package/dist/assets/purify.es-CAi2OJFm.js +3 -0
- package/dist/assets/visual-export-Ox0j5xj5.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/atmem-APACHE-2.0.txt +202 -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/atmem-APACHE-2.0.txt +202 -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 +193 -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 +221 -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 +172 -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 +483 -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 +185 -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_context.py +58 -0
- package/server/memory_routes.py +141 -0
- package/server/memory_service.py +306 -0
- package/server/memory_worker.py +129 -0
- package/server/openai_voice.py +80 -0
- package/server/orca_handoff.py +90 -0
- package/server/packaged_app.py +9 -0
- package/server/pricing.py +190 -0
- package/server/process_control_observation.py +31 -0
- package/server/prompts.py +136 -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/server/windows_snapshot.py +119 -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 +39 -0
- package/src/ArtifactChecks.jsx +49 -0
- package/src/BlockRequirements.jsx +13 -0
- package/src/BrainActivity.jsx +11 -0
- package/src/ChatMessage.jsx +29 -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 +387 -0
- package/src/EngineeringPanel.jsx +151 -0
- package/src/FileTree.jsx +7 -0
- package/src/FinalChecklist.jsx +15 -0
- package/src/HelpNote.jsx +3 -0
- package/src/ImplementationDelivery.jsx +91 -0
- package/src/JourneyViews.jsx +403 -0
- package/src/LocationChoices.jsx +12 -0
- package/src/MemoryPanel.jsx +58 -0
- package/src/OpenAIVoicePanel.jsx +66 -0
- package/src/OutputsView.jsx +71 -0
- package/src/ProjectChecks.jsx +44 -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 +18 -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 +190 -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/final-package.mjs +34 -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 +106 -0
- package/src/journey.mjs +97 -0
- package/src/levels.mjs +145 -0
- package/src/local-agent.mjs +184 -0
- package/src/main.jsx +2481 -0
- package/src/model-policy-preflight.mjs +34 -0
- package/src/openai-voice.mjs +102 -0
- package/src/output-bundle.mjs +13 -0
- package/src/ownership-inspection.mjs +28 -0
- package/src/pack.mjs +201 -0
- package/src/pricing.mjs +85 -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 +37 -0
- package/src/useEmulation.jsx +36 -0
- package/src/useEngineeringStatus.mjs +17 -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,15 @@
|
|
|
1
|
+
import {sha256} from '@noble/hashes/sha2.js';
|
|
2
|
+
const hex=bytes=>Array.from(bytes,b=>b.toString(16).padStart(2,'0')).join('');
|
|
3
|
+
// Preserve established short addresses. Long Unicode identities use a bounded
|
|
4
|
+
// digest token; original identities remain in project/manifest/requirement links.
|
|
5
|
+
// Odd-length digest tokens cannot overlap any legacy even-length UTF-8 hex token.
|
|
6
|
+
export function identityToken(value){
|
|
7
|
+
if(typeof value!=='string'||!value)throw Error('Use a nonempty component identity.');
|
|
8
|
+
try{encodeURIComponent(value);}catch{throw Error('Use a well-formed Unicode identity; no characters were replaced.');}
|
|
9
|
+
const bytes=new TextEncoder().encode(value);
|
|
10
|
+
return bytes.length<=124?hex(bytes):'d'+hex(sha256(bytes));
|
|
11
|
+
}
|
|
12
|
+
export const resourceAddress=id=>'block_'+identityToken(id);
|
|
13
|
+
export function assertDistinctIdentifiers(ids,token=identityToken){
|
|
14
|
+
const seen=new Map();for(const id of ids){const name=token(id);if(seen.has(name))throw Error(seen.get(name)===id?'Duplicate component identity; no output was overwritten.':'Component namespace collision; retain both original identities and stop generation.');seen.set(name,id);}
|
|
15
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import {inspectTerraformModules} from './terraform-admission.mjs';
|
|
2
|
+
// Concrete links are derived from emitted files, not fabricated repository paths.
|
|
3
|
+
export function implementationMap(project,plan,files){
|
|
4
|
+
const config=JSON.parse(files['main.tf.json']),admission=inspectTerraformModules(project,plan,files,config,()=>{});
|
|
5
|
+
const components=plan.rows.map(row=>{
|
|
6
|
+
const scope=admission.scopes.get(row.id),current=scope?.config||(admission.composed?{}:config);
|
|
7
|
+
const addresses=Object.entries(current.resource||{}).flatMap(([type,items])=>Object.keys(items).filter(name=>name===row.address||name.startsWith(row.address+'_')).map(name=>(scope?.prefix||'')+type+'.'+name));
|
|
8
|
+
const generatedFiles=Object.entries(files).filter(([name,body])=>scope?name.startsWith(scope.path+'/'):name!=='resource-schedule.json'&&(!admission.composed&&row.invoice||name.includes(row.address)||typeof body==='string'&&body.includes(row.address))).map(([name])=>'terraform/'+name);
|
|
9
|
+
const variables=scope?Object.keys(current.variable||{}).map(name=>name==='review_approved'?name:scope.module+'__'+name).filter(name=>Object.hasOwn(config.variable||{},name)):Object.keys(config.variable||{}).filter(name=>!admission.composed&&row.invoice||name.startsWith(row.address+'_'));
|
|
10
|
+
return {id:row.id,...(scope?{module:scope.module,modulePath:'terraform/'+scope.path}:{}),ownership:row.existing?'existing':row.sourceExisting?'existing_source_new_deployment':'proposed',terraformAddresses:addresses,generatedFiles,requiredInputs:variables,requirements:(project.needs||[]).filter(r=>r.links?.includes(row.id)).map(r=>r.id),applicationImplementation:project.nodes.find(n=>n.id===row.id)?.data.implementation==='approval-workflow'?'shared_api_assembly_only':row.containerContract?'supplied_image_required':row.existing?'external_behavior_unverified':generatedFiles.some(p=>p.includes('/handlers/'))?'generated_runtime_unverified':generatedFiles.some(p=>p.includes('/web/')||p.includes('/applications/'))?'generated_application_unverified':row.implemented&&addresses.length?'managed_service_configuration_unverified':'not_established'};
|
|
11
|
+
});
|
|
12
|
+
const interfaces=project.edges.map(edge=>({id:edge.id,source:edge.source,target:edge.target,purpose:edge.label||'',integration:edge.integration||null,access:edge.access||null,generated:!!plan.connections.find(e=>e.id===edge.id)?.generated,requiredContractFields:['request/event schema','response/result schema','identity and authorization','timeout','retry and idempotency','error and recovery','observability','acceptance fixtures'],status:'runtime_contract_evidence_required'}));
|
|
13
|
+
return {version:1,designRevision:project.revision,components,interfaces,commands:admission.composed?['terraform init -backend=false','terraform validate',...admission.configs.filter(s=>s.path).flatMap(s=>['terraform -chdir='+s.path+' init -backend=false','terraform -chdir='+s.path+' validate','terraform -chdir='+s.path+' test'])]:['terraform init -backend=false','terraform validate','terraform test'],evidenceBoundary:'File and resource links are generated artifact facts; runtime behavior and destination account validation require separate evidence.'};
|
|
14
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// Raw conversation is retained as provenance, never presented as a finished brief.
|
|
2
|
+
export function implementationOutcome(project){
|
|
3
|
+
if(project.brief?.application?.trim())return project.brief.application.trim();
|
|
4
|
+
const recorded=String(project.requirements||'').trim();
|
|
5
|
+
if(recorded&&!recorded.includes('\n'))return `Recorded project goal (scope requires confirmation): ${recorded}`;
|
|
6
|
+
const needs=(project.needs||[]).map(r=>r.statement).filter(Boolean);
|
|
7
|
+
return `System: ${project.name||'Unnamed system'}. Structured outcome requires confirmation.${needs.length?'\n\nRecorded requirements:\n'+needs.map(s=>'- '+s).join('\n'):''}`;
|
|
8
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import {existingReferenceFiles} from './existing-references.mjs';
|
|
2
|
+
import {generationProviders} from './generation-provider.mjs';
|
|
3
|
+
// Preserve intent for unsupported workloads without fabricating a different cloud.
|
|
4
|
+
export function incompleteTerraform(project,plan,environment){
|
|
5
|
+
const providers=generationProviders(project);
|
|
6
|
+
const gaps=[...plan.gapDetails.map(g=>g.id),'provider-workload-implementation-required'];
|
|
7
|
+
const config={terraform:{required_version:'>= 1.7.0, < 2.0.0'},variable:{review_approved:{type:'bool',default:false}},locals:{unfinished_work:gaps},resource:{terraform_data:{review_gate:{input:{design_revision:project.revision,environment,requested_providers:providers},lifecycle:{precondition:[{condition:'${var.review_approved && length(local.unfinished_work) == 0}',error_message:'This workload has no complete compiler for the requested providers. Implement its required resources and connections before deployment.'}]}}}},output:{design_revision:{value:project.revision}}};
|
|
8
|
+
return {...existingReferenceFiles(project),'main.tf.json':JSON.stringify(config,null,2),'resource-schedule.json':JSON.stringify(plan,null,2),'generation-status.json':JSON.stringify({version:1,status:'implementation_required',providers,deployable:false,runtimeValidated:false,gaps},null,2),'README.md':`# Infrastructure implementation required\n\nRequested providers: ${providers.join(', ')||'not selected'}. No substitute provider or application resources have been generated. This file contains a blocking review gate only. It is not deployment infrastructure.\n\n${plan.gapDetails.map(g=>'- '+g.message).join('\n')}\n\nPreserve the design and implement the missing compiler capabilities; do not clear the gate to obtain a pass.\n`};
|
|
9
|
+
}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/** AtMem AI Architect adapters for pinned upstream modules. See docs/merge-manifest.json. */
|
|
2
|
+
import { AWS_SERVICES } from "./upstream/openarchflow/providers/aws.ts";
|
|
3
|
+
import { AZURE_SERVICES } from "./upstream/openarchflow/providers/azure.ts";
|
|
4
|
+
import { GENERIC_SERVICES } from "./upstream/openarchflow/providers/generic.ts";
|
|
5
|
+
import { CLOUDNATIVE_SERVICES } from "./upstream/openarchflow/providers/cloudnative.ts";
|
|
6
|
+
import { INTEGRATION_SERVICES } from "./upstream/openarchflow/providers/integration.ts";
|
|
7
|
+
import { TEMPLATES } from "./upstream/openarchflow/templates.ts";
|
|
8
|
+
import { parseMermaid } from "./upstream/openarchflow/import/mermaid.ts";
|
|
9
|
+
import { parseSqlDdl } from "./upstream/openarchflow/import/sql-ddl.ts";
|
|
10
|
+
import { getLayoutedElements } from "./upstream/openarchflow/layout.ts";
|
|
11
|
+
export { prettyPayload } from "./upstream/openarchflow/format-payload.ts";
|
|
12
|
+
|
|
13
|
+
const catalogues = [
|
|
14
|
+
["aws", AWS_SERVICES],
|
|
15
|
+
["azure", AZURE_SERVICES],
|
|
16
|
+
["tools", GENERIC_SERVICES],
|
|
17
|
+
["tools", CLOUDNATIVE_SERVICES],
|
|
18
|
+
["tools", INTEGRATION_SERVICES],
|
|
19
|
+
] as const;
|
|
20
|
+
export const UPSTREAM_CATALOG = catalogues.flatMap(
|
|
21
|
+
([provider, categories], group) =>
|
|
22
|
+
categories.flatMap((category, c) =>
|
|
23
|
+
category.items.map((item, i) => ({
|
|
24
|
+
id: `upstream-${group}-${c}-${i}`,
|
|
25
|
+
provider,
|
|
26
|
+
kind: "resource",
|
|
27
|
+
label: item.name,
|
|
28
|
+
description: item.description,
|
|
29
|
+
service: item.service,
|
|
30
|
+
category: category.category,
|
|
31
|
+
origin: "OpenArchFlow",
|
|
32
|
+
support: "design-only",
|
|
33
|
+
})),
|
|
34
|
+
),
|
|
35
|
+
);
|
|
36
|
+
export const UPSTREAM_TEMPLATES = TEMPLATES;
|
|
37
|
+
function convertGraph(parsed: any, name: string, provider = "tools") {
|
|
38
|
+
if (!parsed.nodes.length)
|
|
39
|
+
throw Error(
|
|
40
|
+
"No supported blocks found. Try a simple flowchart or CREATE TABLE statements.",
|
|
41
|
+
);
|
|
42
|
+
if (parsed.nodes.length > 100)
|
|
43
|
+
throw Error("Import is limited to 100 blocks.");
|
|
44
|
+
const ids = new Set(parsed.nodes.map((n: any) => n.id));
|
|
45
|
+
const edges = parsed.edges
|
|
46
|
+
.filter((e: any) => ids.has(e.source) && ids.has(e.target))
|
|
47
|
+
.map((e: any, i: number) => ({
|
|
48
|
+
id: `import-wire-${i}`,
|
|
49
|
+
source: e.source,
|
|
50
|
+
target: e.target,
|
|
51
|
+
label: String(e.label || "relationship"),
|
|
52
|
+
type: "smoothstep",
|
|
53
|
+
}));
|
|
54
|
+
const nodes = parsed.nodes.map((n: any) => ({
|
|
55
|
+
id: n.id,
|
|
56
|
+
type: "resource",
|
|
57
|
+
position: n.position,
|
|
58
|
+
data: {
|
|
59
|
+
kind: "resource",
|
|
60
|
+
provider:
|
|
61
|
+
n.data.provider === "azure"
|
|
62
|
+
? "azure"
|
|
63
|
+
: n.data.provider === "aws"
|
|
64
|
+
? "aws"
|
|
65
|
+
: provider,
|
|
66
|
+
label: String(n.data.label || "Imported block"),
|
|
67
|
+
description: "Imported architecture reference — no fixture executor",
|
|
68
|
+
service: n.data.service,
|
|
69
|
+
origin: "OpenArchFlow import",
|
|
70
|
+
config: {
|
|
71
|
+
region: "To be selected",
|
|
72
|
+
classification: "Internal",
|
|
73
|
+
timeout: 5000,
|
|
74
|
+
},
|
|
75
|
+
metadata: n.data.metadata,
|
|
76
|
+
},
|
|
77
|
+
}));
|
|
78
|
+
const layout = getLayoutedElements(nodes, edges, "LR");
|
|
79
|
+
return {
|
|
80
|
+
version: 1,
|
|
81
|
+
revision: 1,
|
|
82
|
+
name,
|
|
83
|
+
provider,
|
|
84
|
+
nodes: layout.nodes,
|
|
85
|
+
edges: layout.edges,
|
|
86
|
+
requirements:
|
|
87
|
+
"Imported architecture reference. Assign fixture behaviours explicitly before running. Relationships do not grant access or imply runtime compatibility.",
|
|
88
|
+
importReport: {
|
|
89
|
+
droppedEdges: parsed.edges.length - edges.length,
|
|
90
|
+
notice:
|
|
91
|
+
"Architecture-only import. Sequence lifelines, table port handles and non-runtime presentation are normalised; source-specific metadata is kept where available.",
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
export function importDiagram(code: string, format: string) {
|
|
96
|
+
if (code.length > 100000) throw Error("Paste fewer than 100,000 characters.");
|
|
97
|
+
if (format === "mermaid" && !/^\s*(flowchart|graph)\b/i.test(code))
|
|
98
|
+
throw Error("This integration currently supports Mermaid flowcharts only.");
|
|
99
|
+
if (format === "sql")
|
|
100
|
+
return convertGraph(parseSqlDdl(code), "Imported database schema");
|
|
101
|
+
if (format === "mermaid")
|
|
102
|
+
return convertGraph(parseMermaid(code), "Imported architecture diagram");
|
|
103
|
+
throw Error("Unsupported import format.");
|
|
104
|
+
}
|
|
105
|
+
export function importUpstreamProject(raw: any) {
|
|
106
|
+
if (!raw || !Array.isArray(raw.nodes) || !Array.isArray(raw.edges))
|
|
107
|
+
throw Error("OpenArchFlow import needs nodes and edges.");
|
|
108
|
+
const allowed = new Set(["aws", "azure", "gcp", "ibm", "tools"]);
|
|
109
|
+
const p = convertGraph(
|
|
110
|
+
raw,
|
|
111
|
+
String(raw.name || raw.diagramName || "OpenArchFlow architecture"),
|
|
112
|
+
);
|
|
113
|
+
p.nodes = p.nodes.map((n: any) => ({
|
|
114
|
+
...n,
|
|
115
|
+
data: {
|
|
116
|
+
...n.data,
|
|
117
|
+
provider: allowed.has(n.data.provider) ? n.data.provider : "tools",
|
|
118
|
+
},
|
|
119
|
+
}));
|
|
120
|
+
return p;
|
|
121
|
+
}
|
|
122
|
+
export function loadUpstreamTemplate(id: string) {
|
|
123
|
+
const t = TEMPLATES.find((t) => t.id === id);
|
|
124
|
+
if (!t) throw Error("Unknown template.");
|
|
125
|
+
return convertGraph(
|
|
126
|
+
t,
|
|
127
|
+
t.name,
|
|
128
|
+
t.category === "AWS" ? "aws" : t.category === "Azure" ? "azure" : "tools",
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
export function autoLayout(project: any) {
|
|
132
|
+
const nodes = project.nodes.map((n: any) => ({
|
|
133
|
+
...n,
|
|
134
|
+
data: { ...n.data, inputPosition: "left", outputPosition: "right" },
|
|
135
|
+
}));
|
|
136
|
+
return { ...project, ...getLayoutedElements(nodes, project.edges, "LR") };
|
|
137
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import {STRUCTURED_OPERATION_POLICY as policy} from './structured-operation-policy.mjs';
|
|
2
|
+
// Executable compiler contracts, not claims that the destination services were exercised.
|
|
3
|
+
export function interfaceContracts(project,plan){
|
|
4
|
+
const nodes=new Map(project.nodes.map(n=>[n.id,n]));
|
|
5
|
+
return project.edges.map(edge=>{
|
|
6
|
+
const source=nodes.get(edge.source),target=nodes.get(edge.target),worker=plan.structuredApiPlan?.entries.find(e=>[e.api.id,e.worker.id].includes(edge.target)||[e.api.id,e.worker.id].includes(edge.source))?.worker;
|
|
7
|
+
const common={id:edge.id,source:edge.source,target:edge.target,integration:edge.integration||null,access:edge.access||null,generated:!!plan.connections.find(e=>e.id===edge.id)?.generated,runtimeEvidence:'not_attached',contractStatus:plan.connections.find(e=>e.id===edge.id)?.generated?'generated_unverified':'required_not_generated'};
|
|
8
|
+
const invoice=plan.invoicePlan?.entries.find(entry=>entry.row.id===edge.target||entry.row.id===edge.source);
|
|
9
|
+
if(invoice&&common.generated&&edge.integration==='browser-https')return {...common,transport:'Same-origin HTTPS assets, /api/session and /api/invoices; native staff sign-in, never a provisioned browser',request:{upload:'POST /api/invoices with application/pdf bytes, maximum 10000000 bytes; no caller account, storage path/version, destination or action supplied',review:'POST /api/invoices/{id}/review: exact revision, fields and bounded notes',approve:'POST /api/invoices/{id}/approve: exact revision only',read:'GET list/detail/original/history; paginated list/history; recover extraction through supervisor-authorized POST /api/invoices/{id}/recover'},response:'202 accepted invoice snapshot on upload; subsequent reads show durable review/delivery state. Acceptance is not extraction or external-action completion.',identity:'Provider-native verified staff identity plus current SQL membership on every operation. Reviewer/supervisor roles come from live membership, never JWT role names or request/document content. JWT revocation is bounded by native token lifetime.',authorization:'Same-origin checks on mutations, strict scope/account ownership and SQL role-specific function grants. Ordinary uploaders cannot approve. Edits invalidate prior approval; approved payload digest/revision is bound to dispatch.',idempotency:'Content digest and account/workflow operation identity deduplicate upload/queue work; immutable original version/digest are server-owned. Delivery effects require the separate accounting contract.',timeouts:'Upload streaming is bounded to 15 seconds and 10 MB; review bodies to 5 seconds and 10000 bytes. Worker/parser execution limits are separate and do not imply an end-to-end SLA.',retention:'90-day application access/cleanup eligibility; original versions, native backups and scheduled cleanup have separate lifecycle/restore windows. No exact global erasure promise.',tests:['invoice_http_acceptance.py','invoice_identity_acceptance.py','invoice_web_acceptance.py','invoice_operations_acceptance.py'],runtimeEvidence:'not_attached'};
|
|
10
|
+
if(invoice&&common.generated&&edge.integration==='approved-accounting-api')return {...common,transport:'Fixed operator-reviewed HTTPS POST, no redirect or proxy-derived destination; existing accounting system remains external',contract:'normalized-action-v1',request:{headers:['Content-Type: application/json','Authorization: Bearer <separately stored worker credential>','Idempotency-Key: <stable operation UUID>'],body:['operation_id','payload_sha256','kind=document','result']},response:{http:[200,201],contentType:'application/json',maximumBytes:8192,exactFields:['operation_id','payload_sha256','external_id','status=completed']},identity:'Worker-only destination credential; API/parser/operator jobs receive none. Endpoint digest, scope and mapping version are part of the approved snapshot.',approval:'Only a current allowed approved dispatch with matching operation ID, payload digest, destination contract and result revision can call the adapter.',timeouts:'8-second HTTPS connection/read operations with a separate bounded worker/process deadline; no redirect, 202-as-completed or arbitrary error-body logging.',idempotency:'Canonical approved payload and stable key survive retries. An ambiguous/expired dispatch becomes unknown; automatic replay requires separately reviewed scoped/expiring native accounting idempotency acceptance. A no-request retry cannot erase prior uncertainty.',recovery:'Supervisor/operator inspect the existing accounting service independently by operation ID/digest before recording a verified completion receipt. Never resend an uncertain action simply to clear a failure.',tests:['durable_postgres_acceptance.py','workflow_tls_destination_fixture.py','invoice_worker_acceptance.py'],boundary:'Generated normalized adapter and local TLS fixtures do not prove compatibility with this actual accounting API. Actual provider credentials, endpoint behavior, idempotency and reconciliation must be accepted separately.'};
|
|
11
|
+
const faq=plan.publicFaqPlan?.entries.find(e=>e.row.id===edge.target);
|
|
12
|
+
if(faq&&edge.integration==='public-catalog-edit'&&common.generated)return {...common,transport:'Local operator CLI to fixed native HTTPS object-store API; no app editing endpoint',identity:'Existing authorized company editor role/group supplied as reviewed destination input; generated role grants stay separate from workload read access',request:'Inspect current catalog version; explicitly confirm public-only init or conditional upsert/delete. Full UTF-8 articles, source-owned IDs/revisions and optional HTTPS links. No secrets in bundle or chat.',response:'Native ETag/generation after successful conditional write; concurrent edit yields conflict and requires reload/review. No automatic overwrite retry.',permissions:'AWS separate assumed role Get/Put on catalog.json; Azure container-scoped Blob Data Contributor; Google bucket-scoped object get/create/delete custom role; IBM bucket-scoped Object Reader/Object Writer existing access group. Inherited permissions require separate destination review.',acceptance:'Local native-transport fixtures test conditions, source updates/deletions and unauthorized/failed writes. Effective IAM and real storage APIs remain unverified.'};
|
|
13
|
+
if(faq&&edge.integration==='browser-https'&&common.generated)return {...common,transport:'HTTPS browser and POST /api/ask on the generated public application origin',request:{text:{type:'string',maxUtf8Bytes:2000}},response:{answer:'Bounded text',citations:'At most two source-owned IDs/titles/revisions/HTTPS URLs and exact supporting quotes',abstained:'Boolean; unknown or unsupported evidence yields a canonical abstention'},identity:'Explicit anonymous public-only reader; same-origin browser requests are not authentication. No private source or article-edit HTTP endpoint.',permissions:'Dedicated workload identity reads the private public-content catalog. Separate existing company editor identity receives native conditional catalog write authority. Destination role scopes are emitted in Terraform.',sourceLifecycle:'Read current version before retrieval and recheck before returning. Exact version/digest mismatch withholds the answer; missing/inaccessible source never serves cached or empty fallback. Operator CLI edits require observed version plus confirmation and native compare-and-swap.',limits:'100 genuinely public UTF-8 articles up to 30000 bytes each; at most two complete relevant articles, no silent truncation. Questions up to 2000 UTF-8 bytes, five admitted calls per instance and excess calls receive 429.',errors:{400:'Invalid text/body',403:'Missing/wrong Origin',413:'Oversize request',429:'Concurrency exhausted',503:'Unverified policy, source changed/unavailable, or invalid/unavailable model answer'},retries:'No automatic browser/model retry; conditional editor conflict requires reload/review. Clear cancels local presentation and rejects late responses.',quality:'Exact JSON, source membership and supporting quotes are checked; these do not prove factual entailment. Real answer/citation/abstention, freshness, IAM, model latency and budget/abuse testing remain required.'};
|
|
14
|
+
const azure=plan.azureStructuredPlan?.entries.find(e=>e.row.id===edge.target);
|
|
15
|
+
const google=plan.gcpStructuredPlan?.entries.find(e=>e.row.id===edge.target);
|
|
16
|
+
const ibm=plan.ibmStructuredPlan?.entries.find(e=>e.row.id===edge.target);
|
|
17
|
+
if(ibm&&edge.integration==='browser-https'&&common.generated)return {...common,transport:'HTTPS browser and POST /api/ask on the Code Engine origin',request:{text:{type:'string',maxUtf8Bytes:ibm.maxInput}},response:{result:ibm.contract.fields,requiresHumanReview:true},identity:'App ID RS256 signed access token, exact issuer/tenant/single-client audience, authenticated Cloud Directory user and process scope. S256 PKCE and state verification; access tokens remain in browser memory. Admin-enrolled subject allowlist in the NEW owned tenant.',revocation:'JWT scope authorization lasts until expiry. Immediate revocation, existing SSO and MFA are not established. Local workspace clearing does not claim provider logout.',permissions:'Exact Code Engine compute-resource link to dedicated trusted profile. Writer on the reviewed pm-20 runtime instance includes broader instance operations. Existing watsonx project collaborator membership is separate; no static application API key.',retention:'No app input/result persistence. Scoped expiring destination-owner policy review is operator-attested evidence, not an IBM approval API. Unknown review stops before workload authentication or inference.',errors:{400:'Invalid input',401:'Missing/invalid user access',403:'Wrong origin or authorization changed while running',413:'Oversize body',429:'Concurrency exhausted',503:'Unverified policy, model unavailable or invalid result'},retries:'One bounded regional Text Chat request; no automated actions or automatic retry.',operations:'Build/scan/test emitted Python source and immutable Linux image, obtain publish authorization, supply exact existing project/registry/pull-secret/model inputs. Enroll users and review exact subjects; starts with no authorized users. Verify separate watsonx collaborator access and actual identity/model behavior before deployment.'};
|
|
18
|
+
if(google&&edge.integration==='browser-https'&&common.generated)return {...common,transport:'HTTPS browser and POST /api/ask on the generated deterministic Cloud Run URL',request:{text:{type:'string',maxUtf8Bytes:google.maxInput}},response:{result:google.contract.fields,requiresHumanReview:true},identity:'IAP organization session and existing company group grant; Cloud Run IAM admits the IAP service agent. App validates every non-health request using ES256 IAP JWT, exact audience/issuer/user/lifetime and fixed Google keys; POST requires same-origin Origin.',revocation:'IAP group/session policy; signed headers remain valid until expiry/skew. No independent continuous directory check or proven MFA behavior.',permissions:'Dedicated keyless runtime account: project-level prediction plus read-only cache/publisher-config queries. Exact repository reader grant belongs to the Cloud Run platform agent; no model-policy writes or user-managed keys.',retention:'No app persistence. Destination-owner abuse-logging review is attested with exact project/model/region/evidence digest/expiry; separate runtime cache/logging/sharing reads fail closed. This is not universal zero-retention or independent provider approval proof.',errors:{400:'Invalid input',401:'Missing/invalid IAP identity',403:'Wrong/missing Origin or identity changed while running',413:'Oversize body',429:'Concurrency exhausted',503:'Unverified policy or invalid/unavailable model result'},retries:'No automatic browser/model retry. Verify actual platform latency, region availability and quotas separately.',operations:'Build/scan/test emitted Python 3.13 source and pinned Linux image, obtain authorization to publish to existing Artifact Registry, supply exact digest and reviewed destination/group/model/policy inputs. No Terraform build/deployment provisioner.'};
|
|
19
|
+
if(azure&&edge.integration==='browser-https'&&common.generated)return {...common,transport:'HTTPS assets and POST /api/ask on the generated App Service origin',request:{text:{type:'string',maxUtf8Bytes:azure.maxInput}},response:{result:azure.contract.fields,requiresHumanReview:true},identity:'Entra single-tenant v2 RS256 delegated access token; exact API audience, browser client, access_as_user scope and assigned WorkspaceUser role. The browser uses S256 PKCE with state verification; tokens stay in memory.',revocation:'JWT claims authorize until expiry. No continuous user/group revocation or tenant MFA policy is established by this module.',permissions:'User-assigned managed identity; model inference and Reader scoped to the generated model account; AcrPull on the exact existing reviewed registry. No client/model key or directory-admin permission for runtime.',errors:{400:'Invalid input',401:'Missing/invalid/expired access token',403:'Wrong origin or access expired while running',413:'Oversize body',429:'Application concurrency exhausted',503:'Policy unverified, model unavailable or invalid output'},retention:'No app persistence; account ContentLogging=false verified before sending input. Approval and provider terms require destination review.',retries:'No automatic application retry; one model HTTP request. User-visible browser deadline 28 seconds; per-transport timeouts are not a latency SLA.',operations:'Build emitted applications/* source and pinned image, validate it, publish to the existing ACR with authorization, then supply its digest and reviewed account/model/group inputs. No Terraform provisioner or automatic deployment.'};
|
|
20
|
+
if(worker&&edge.integration==='web-rag-api')return {...common,transport:'HTTPS POST /api/ask',request:{text:{type:'string',maxUtf8Bytes:worker.settings.maxInputBytes??16000}},response:{result:worker.settings.outputContract.fields,requiresHumanReview:true},identity:'Cognito access token in Authorization: Bearer; API Gateway verifies issuer, client audience and atmem/ask scope',errors:{400:'Invalid input',403:'Unavailable/disabled user or forbidden boundary',503:'Identity/model unavailable or invalid model output'},retention:'No input or result persistence; browser tokens in memory only',retries:'No automatic browser retry; SDK makes one model attempt for this HTTP composition',revocation:'Authoritative enabled/confirmed user and subject checked before model invocation and before returning; in-flight model cost is not undone'};
|
|
21
|
+
if(worker&&edge.integration==='http-api-lambda')return {...common,request:'API Gateway v2 event with verified JWT authorizer context; body is the exact text request above',response:'Lambda proxy statusCode, no-store JSON headers and serialized result/error body',identity:'Exact account-bound Gateway route is the only generated Lambda invocation permission; handler checks API ID, route, issuer, token use, scope, client, subject and Cognito user state',timeouts:`Gateway ${policy.gatewayDeadlineMs/1000} seconds; model connect ${policy.modelConnectSeconds}/read ${policy.modelReadSeconds} seconds; identity connect ${policy.identityConnectSeconds}/read ${policy.identityReadSeconds}, policy connect ${policy.policyConnectSeconds}/read ${policy.policyReadSeconds}; ${policy.sdkAttempts} SDK attempt per call. Verify destination latency independently.`,failure:'Fail closed; do not log input, tokens, model response or provider error text'};
|
|
22
|
+
if(source?.data.implementation==='bedrock-structured'&&source.data.config?.outputContract&&edge.integration==='bedrock-converse')return {...common,operation:'Bedrock Runtime Converse',request:'Configured bounded text plus compiler-owned instruction/output schema; direct reviewed regional foundation-model ARN',response:{fields:source.data.config.outputContract.fields,validation:'Strict JSON object: exact unique fields, bounded strings/enumerations, finite numbers, strict booleans; only end_turn admitted'},permissions:'bedrock:InvokeModel scoped to the selected regional foundation-model ARN; read-only regional GetAccountDataRetention with fail-closed mode none check',quality:'Schema checks do not prove factual or classification accuracy. Representative labeled acceptance fixtures and an authorized model test remain required.'};
|
|
23
|
+
const known={
|
|
24
|
+
'browser-https':{transport:'HTTPS',purpose:'Load web assets from the selected hosting endpoint; not a request to provision the browser'},
|
|
25
|
+
'oauth-pkce':{transport:'OAuth authorization code with S256 PKCE',identity:'Random state/verifier, callback-state validation, transient verifier removed after callback, tokens in memory',authorization:'Administrator-created users and MFA; inspect the emitted pool/client configuration'},
|
|
26
|
+
'jwt-authorizer':{purpose:'Bind the generated API route to the generated user-pool issuer, client audience and required access-token scope',boundary:'Gateway token verification and application access checks are distinct'},
|
|
27
|
+
}[edge.integration];
|
|
28
|
+
return {...common,...(known||{contractStatus:'Engineering contract required; inspect emitted resources and behavior before declaring this integration complete'})};
|
|
29
|
+
});
|
|
30
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import sources from './runtime/invoice-sources.json' with{type:'json'};
|
|
2
|
+
import {invoiceDependencies}from'./invoice-dependencies.mjs';
|
|
3
|
+
import {pythonContainer}from'./python-container.mjs';
|
|
4
|
+
import base from'./runtime/python-container-lock.json'with{type:'json'};
|
|
5
|
+
import{invoiceTestFiles}from'./invoice-tests.mjs';
|
|
6
|
+
|
|
7
|
+
// Application emission alone is not a supported/cloud-qualified project. Native
|
|
8
|
+
// provider compilers and independent whole-export checks must admit composition.
|
|
9
|
+
export function invoiceApplicationFiles(provider,address){
|
|
10
|
+
if(!['aws','azure','gcp','ibm'].includes(provider)||!/^block_[0-9a-f]+$/.test(address))throw Error('Use the exact owned invoice provider and address');
|
|
11
|
+
const root='applications/'+address+'/',files={},modules=Object.keys(sources).filter(name=>name.endsWith('.py')&&name!=='invoice_parser_service.py'&&name!=='invoice_parser_cli.py');
|
|
12
|
+
const assets=['workflow_schema.sql','invoice-web.html','invoice-web.css','invoice-web.js',...(provider==='aws'?['rds-global-ca.pem']:[])];
|
|
13
|
+
for(const name of [...modules,...assets])files[root+name]=sources[name];
|
|
14
|
+
const runtime=invoiceDependencies(provider),testing=invoiceDependencies(provider,{tests:true});
|
|
15
|
+
files[root+'requirements.lock']=runtime.requirements;files[root+'dependency-sources.json']=JSON.stringify({sources:runtime.sources,resolutions:runtime.resolutions},null,2)+'\n';
|
|
16
|
+
files[root+'test-requirements.lock']=testing.requirements;files[root+'test-dependency-sources.json']=JSON.stringify({sources:testing.sources,resolutions:testing.resolutions},null,2)+'\n';
|
|
17
|
+
files[root+'invoice-deployment.json']=JSON.stringify({format:'invoice-workflow-v1',provider},null,2)+'\n';
|
|
18
|
+
files[root+'container-base.json']=JSON.stringify(base,null,2)+'\n';
|
|
19
|
+
if(provider==='aws')files[root+'rds-ca-source.json']=sources['rds-ca-source.json'];
|
|
20
|
+
files[root+'Dockerfile']=pythonContainer('invoice_native',modules,['invoice-deployment.json'],{web:false,contract:false,assets,concurrency:32});
|
|
21
|
+
files[root+'.dockerignore']='*\n!requirements.lock\n!invoice-deployment.json\n'+[...modules,...assets].map(name=>'!'+name+'\n').join('');
|
|
22
|
+
const parserRoot=root+'parser/';for(const name of ['invoice_document.py','invoice_extraction.py','structured_output.py','invoice_parser_cli.py','invoice_parser_service.py','invoice_parser_identity.py','parser-requirements.lock','invoice-parser-python-lock.json','invoice-parser-lock.json'])files[parserRoot+name]=sources[name];
|
|
23
|
+
files[parserRoot+'Dockerfile']=sources['invoice-parser.Dockerfile'];
|
|
24
|
+
files[parserRoot+'.dockerignore']='*\n!invoice_document.py\n!invoice_extraction.py\n!structured_output.py\n!invoice_parser_cli.py\n!invoice_parser_service.py\n!invoice_parser_identity.py\n!parser-requirements.lock\n';
|
|
25
|
+
files[root+'BUILD.md']=INVOICE_BUILD;
|
|
26
|
+
return {...files,...invoiceTestFiles(provider,address)};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export const INVOICE_BUILD=`# Invoice application images
|
|
30
|
+
|
|
31
|
+
This directory contains API/worker source and a separate bounded PDF/OCR image.
|
|
32
|
+
Build both as Linux/amd64 and retain source/image digests and security reports.
|
|
33
|
+
Use only the emitted exact wheel/native-package hashes and pinned container bases.
|
|
34
|
+
The IBM lock deliberately uses dateutil 3.0.0 required by its SDK; the composed queue
|
|
35
|
+
must be qualified with this dependency set, rather than borrowing another provider's
|
|
36
|
+
test result. Installer tools are removed from the application delivery image.
|
|
37
|
+
|
|
38
|
+
The API command is the image default. The dedicated worker command is
|
|
39
|
+
python -I /app/invoice_worker.py. Parser hosting overrides its default CLI with
|
|
40
|
+
python -I /app/invoice_parser_service.py. Do not run a Docker daemon in the worker.
|
|
41
|
+
Keep the parser in a separate workload with no database, model, object-store or
|
|
42
|
+
outbound action authority. Its private TLS ingress/caller restrictions are required
|
|
43
|
+
native infrastructure, not an anonymous public HTTP service. Runtime identities,
|
|
44
|
+
network and destination acceptance require separate destination checks.
|
|
45
|
+
|
|
46
|
+
The API never receives a model credential or outbound action secret. The worker
|
|
47
|
+
splits extraction and delivery into bounded child processes without database
|
|
48
|
+
configuration in their environments. The 180-second extraction deadline includes
|
|
49
|
+
object retrieval, up to 110 seconds of parsing/OCR and model/commit overhead inside
|
|
50
|
+
a 600-second domain lease. Delivery is bounded to 45 seconds; unknown external
|
|
51
|
+
outcomes require a verified same-key/same-payload idempotency contract or operator
|
|
52
|
+
reconciliation. A failed new attempt cannot erase an older uncertain side effect.
|
|
53
|
+
Child deadlines are not an OS sandbox; untrusted PDF parsing stays separate.
|
|
54
|
+
|
|
55
|
+
Default worker concurrency is one, matched to one parser slot. Twenty uploads
|
|
56
|
+
are admitted into the durable queue; they do not become twenty simultaneous OCR
|
|
57
|
+
processes. Scale worker/parser capacity together only after throughput, model quotas
|
|
58
|
+
and backpressure are tested. Capacity settings are not a price cap or SLA.
|
|
59
|
+
|
|
60
|
+
Keep credentials outside this directory and source control. Mount native CA and
|
|
61
|
+
secret files and supply the generated deployment environment. SQL role/bootstrap,
|
|
62
|
+
membership, retention/restore and reviewed external accounting contract are required
|
|
63
|
+
operational steps. Building this application does not prove those resources exist
|
|
64
|
+
or declare the complete project ready. Obtain authorization before publication,
|
|
65
|
+
account plans or deployment. Local checks do not establish cloud IAM or availability.
|
|
66
|
+
`;
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import{v,r,l}from'./invoice-builder.mjs';
|
|
2
|
+
|
|
3
|
+
// Fixed native jobs, not Terraform provisioners or API/model-accessible tools.
|
|
4
|
+
export function awsInvoiceOperations(b,n,{account,region,privateSubnets,trust}){
|
|
5
|
+
const{add,input}=b;
|
|
6
|
+
for(const key of ['operations_enabled','maintenance_enabled']){b.variable[key]={type:'bool',default:false,description:key==='operations_enabled'?'Publish the reviewed runtime image, then create fixed operator task definitions before application release.':'Enable only after successful owned SQL bootstrap and membership admission. Starts daily cleanup/hourly monitoring.'};b.examples[key]=false;b.testExpressions[key]='true';}
|
|
7
|
+
const alert=input('operator_alert_topic_arn','Existing reviewed same-account regional SNS alert topic. Its owner must authorize CloudWatch publishing and verify an actual subscribed on-call route; this package does not modify that existing policy.','arn:aws:sns:'+b.examples.region+':123456789012:reviewed-operations','^arn:aws:sns:[a-z0-9-]+:[0-9]{12}:[A-Za-z0-9_-]{1,256}$');
|
|
8
|
+
b.resource.terraform_data.review_gate.lifecycle.precondition.push({condition:'${!var.maintenance_enabled || var.operations_enabled}',error_message:'Maintenance requires the separate operator tasks.'},{condition:'${!var.applications_enabled || (var.operations_enabled && var.maintenance_enabled)}',error_message:'Bootstrap owned SQL and staff access, then enable the operating jobs before application release.'},{condition:'${startswith(var.operator_alert_topic_arn,format("arn:aws:sns:%s:%s:",var.region,var.account_id))}',error_message:'Use the reviewed existing alert route in this account and region.'});
|
|
9
|
+
b.locals.operator_deployment=b.output.operator_deployment.value;
|
|
10
|
+
add('aws_security_group',n+'_operator',{name_prefix:l('name')+'-operator-',description:'Separate fixed operator jobs: private SQL and native image/secret/log transport',vpc_id:r('aws_vpc',n,'id')});
|
|
11
|
+
add('aws_vpc_security_group_ingress_rule',n+'_database_from_operator',{security_group_id:r('aws_security_group',n+'_database','id'),ip_protocol:'tcp',from_port:5432,to_port:5432,referenced_security_group_id:r('aws_security_group',n+'_operator','id')});
|
|
12
|
+
for(const [suffix,port,target]of[['sql',5432,{referenced_security_group_id:r('aws_security_group',n+'_database','id')}],['native_https',443,{cidr_ipv4:'0.0.0.0/0'}]])add('aws_vpc_security_group_egress_rule',n+'_operator_'+suffix,{security_group_id:r('aws_security_group',n+'_operator','id'),ip_protocol:'tcp',from_port:port,to_port:port,...target});
|
|
13
|
+
add('aws_cloudwatch_log_group',n+'_operator',{name:'/ecs/'+l('name')+'/operator',retention_in_days:7});
|
|
14
|
+
add('aws_iam_role',n+'_operator_execution',{name:l('name')+'-operator-execution',assume_role_policy:trust});
|
|
15
|
+
const secret=r('aws_db_instance',n,'master_user_secret[0].secret_arn');
|
|
16
|
+
add('aws_iam_role_policy',n+'_operator_execution',{role:r('aws_iam_role',n+'_operator_execution','id'),policy:JSON.stringify({Version:'2012-10-17',Statement:[{Effect:'Allow',Action:['ecr:GetAuthorizationToken'],Resource:'*'},{Effect:'Allow',Action:['ecr:BatchGetImage','ecr:GetDownloadUrlForLayer','ecr:BatchCheckLayerAvailability'],Resource:r('aws_ecr_repository',n+'_runtime','arn')},{Effect:'Allow',Action:['logs:CreateLogStream','logs:PutLogEvents'],Resource:r('aws_cloudwatch_log_group',n+'_operator','arn')+':*'},{Effect:'Allow',Action:['secretsmanager:GetSecretValue'],Resource:secret}]})});
|
|
17
|
+
const settings={REGION:region,DATABASE_NAME:'invoice',DATABASE_HOST:r('aws_db_instance',n,'address'),DATABASE_USER:'invoice_operator',DATABASE_CA_FILE:'/app/rds-global-ca.pem',OPERATOR_DEPLOYMENT_BASE64:'${base64encode(jsonencode(local.operator_deployment))}'};
|
|
18
|
+
for(const action of ['initialize','maintain','monitor']){
|
|
19
|
+
const init={name:'prepare-tmp',image:v('runtime_image'),essential:false,user:'0:0',readonlyRootFilesystem:true,command:['python','-I','-c','import os;os.chmod("/runtime-tmp",0o1777)'],mountPoints:[{sourceVolume:'runtime-tmp',containerPath:'/runtime-tmp',readOnly:false}]};
|
|
20
|
+
const container={name:'operator',image:v('runtime_image'),essential:true,readonlyRootFilesystem:true,command:['python','-I','/app/invoice_operator_job.py',action,'--execute'],environment:Object.entries(settings).map(([name,value])=>({name,value})),secrets:[{name:'DATABASE_PASSWORD',valueFrom:secret+':password::'}],mountPoints:[{sourceVolume:'runtime-tmp',containerPath:'/tmp',readOnly:false}],dependsOn:[{containerName:'prepare-tmp',condition:'SUCCESS'}],logConfiguration:{logDriver:'awslogs',options:{'awslogs-group':r('aws_cloudwatch_log_group',n+'_operator','name'),'awslogs-region':region,'awslogs-stream-prefix':action}}};
|
|
21
|
+
add('aws_ecs_task_definition',n+'_operator_'+action,{count:'${var.operations_enabled ? 1 : 0}',family:l('name')+'-'+action,network_mode:'awsvpc',requires_compatibilities:['FARGATE'],cpu:'512',memory:'1024',execution_role_arn:r('aws_iam_role',n+'_operator_execution','arn'),volume:{name:'runtime-tmp'},runtime_platform:{operating_system_family:'LINUX',cpu_architecture:'X86_64'},container_definitions:JSON.stringify([init,container]),depends_on:['aws_iam_role_policy.'+n+'_operator_execution']});
|
|
22
|
+
}
|
|
23
|
+
add('aws_sqs_queue',n+'_operator_failures',{name:l('name')+'-operator-failures',sqs_managed_sse_enabled:true,message_retention_seconds:604800,visibility_timeout_seconds:60,lifecycle:{prevent_destroy:true}});
|
|
24
|
+
add('aws_scheduler_schedule_group',n+'_operator',{name:l('name')+'-operator'});
|
|
25
|
+
add('aws_iam_role',n+'_operator_scheduler',{count:'${var.operations_enabled ? 1 : 0}',name:l('name')+'-operator-scheduler',assume_role_policy:JSON.stringify({Version:'2012-10-17',Statement:[{Effect:'Allow',Principal:{Service:'scheduler.amazonaws.com'},Action:'sts:AssumeRole',Condition:{StringEquals:{'aws:SourceAccount':account},ArnEquals:{'aws:SourceArn':r('aws_scheduler_schedule_group',n+'_operator','arn')}}}]})});
|
|
26
|
+
add('aws_iam_role_policy',n+'_operator_scheduler',{count:'${var.operations_enabled ? 1 : 0}',role:r('aws_iam_role',n+'_operator_scheduler[0]','id'),policy:JSON.stringify({Version:'2012-10-17',Statement:[{Effect:'Allow',Action:['ecs:RunTask'],Resource:['maintain','monitor'].map(action=>r('aws_ecs_task_definition',n+'_operator_'+action+'[0]','arn')),Condition:{ArnEquals:{'ecs:cluster':r('aws_ecs_cluster',n,'arn')}}},{Effect:'Allow',Action:['iam:PassRole'],Resource:r('aws_iam_role',n+'_operator_execution','arn'),Condition:{StringEquals:{'iam:PassedToService':'ecs-tasks.amazonaws.com'}}},{Effect:'Allow',Action:['sqs:SendMessage'],Resource:r('aws_sqs_queue',n+'_operator_failures','arn')}]})});
|
|
27
|
+
for(const[action,expression]of[['maintain','cron(17 2 * * ? *)'],['monitor','rate(1 hour)']]){
|
|
28
|
+
add('aws_scheduler_schedule',n+'_'+action,{count:'${var.operations_enabled ? 1 : 0}',name:l('name')+'-'+action,group_name:r('aws_scheduler_schedule_group',n+'_operator','name'),state:'${var.maintenance_enabled ? "ENABLED" : "DISABLED"}',schedule_expression:expression,schedule_expression_timezone:'UTC',flexible_time_window:{mode:'OFF'},target:{arn:r('aws_ecs_cluster',n,'arn'),role_arn:r('aws_iam_role',n+'_operator_scheduler[0]','arn'),ecs_parameters:{task_definition_arn:r('aws_ecs_task_definition',n+'_operator_'+action+'[0]','arn'),launch_type:'FARGATE',platform_version:'1.4.0',task_count:1,enable_execute_command:false,network_configuration:{subnets:privateSubnets,security_groups:[r('aws_security_group',n+'_operator','id')],assign_public_ip:false}},dead_letter_config:{arn:r('aws_sqs_queue',n+'_operator_failures','arn')},retry_policy:{maximum_event_age_in_seconds:3600,maximum_retry_attempts:2}},depends_on:['aws_iam_role_policy.'+n+'_operator_scheduler','aws_route_table_association.'+n+'_private_0','aws_route_table_association.'+n+'_private_1']});
|
|
29
|
+
add('aws_cloudwatch_log_metric_filter',n+'_'+action+'_success',{name:l('name')+'-'+action+'-success',log_group_name:r('aws_cloudwatch_log_group',n+'_operator','name'),pattern:'{ $.format = "invoice-operator-v1" && $.action = "'+action+'" && $.status = "ok" }',metric_transformation:{name:l('name')+'-'+action+'-success',namespace:'AtMem/InvoiceOperations',value:'1',default_value:0,unit:'Count'}});
|
|
30
|
+
add('aws_cloudwatch_metric_alarm',n+'_'+action+'_missing',{alarm_name:l('name')+'-'+action+'-missing',alarm_description:'No successful '+action+' receipt in two operating periods. Inspect owned operator task logs and failed-job queue; no payload is in the count-only receipt.',namespace:'AtMem/InvoiceOperations',metric_name:l('name')+'-'+action+'-success',statistic:'Sum',period:action==='maintain'?86400:3600,evaluation_periods:2,datapoints_to_alarm:2,threshold:1,comparison_operator:'LessThanThreshold',treat_missing_data:'breaching',actions_enabled:v('maintenance_enabled'),alarm_actions:[alert],ok_actions:[alert]});
|
|
31
|
+
}
|
|
32
|
+
const taskArns=['initialize','maintain','monitor'].map(action=>r('aws_ecs_task_definition',n+'_operator_'+action+'[0]','arn'));
|
|
33
|
+
add('aws_cloudwatch_event_rule',n+'_operator_stopped',{count:'${var.operations_enabled ? 1 : 0}',name:l('name')+'-operator-stopped',event_pattern:JSON.stringify({source:['aws.ecs'],'detail-type':['ECS Task State Change'],detail:{clusterArn:[r('aws_ecs_cluster',n,'arn')],taskDefinitionArn:taskArns,lastStatus:['STOPPED'],$or:[{stopCode:['TaskFailedToStart']},{containers:{name:['operator'],exitCode:[{'anything-but':0}]}}]}})});
|
|
34
|
+
add('aws_sqs_queue_policy',n+'_operator_failures',{count:'${var.operations_enabled ? 1 : 0}',queue_url:r('aws_sqs_queue',n+'_operator_failures','id'),policy:JSON.stringify({Version:'2012-10-17',Statement:[{Effect:'Allow',Principal:{Service:'events.amazonaws.com'},Action:'sqs:SendMessage',Resource:r('aws_sqs_queue',n+'_operator_failures','arn'),Condition:{ArnEquals:{'aws:SourceArn':r('aws_cloudwatch_event_rule',n+'_operator_stopped[0]','arn')},StringEquals:{'aws:SourceAccount':account}}}]})});
|
|
35
|
+
add('aws_cloudwatch_event_target',n+'_operator_stopped',{count:'${var.operations_enabled ? 1 : 0}',rule:r('aws_cloudwatch_event_rule',n+'_operator_stopped[0]','name'),arn:r('aws_sqs_queue',n+'_operator_failures','arn'),input:JSON.stringify({format:'invoice-operator-v1',status:'failed',code:'operator_task_stopped'}),depends_on:['aws_sqs_queue_policy.'+n+'_operator_failures']});
|
|
36
|
+
add('aws_cloudwatch_metric_alarm',n+'_operator_failures',{alarm_name:l('name')+'-operator-failed',alarm_description:'Operator task or schedule invocation failed. Inspect task logs and the private failed-job queue before retrying.',namespace:'AWS/SQS',metric_name:'ApproximateNumberOfMessagesVisible',dimensions:{QueueName:r('aws_sqs_queue',n+'_operator_failures','name')},statistic:'Maximum',period:300,evaluation_periods:1,threshold:0,comparison_operator:'GreaterThanThreshold',treat_missing_data:'notBreaching',actions_enabled:v('operations_enabled'),alarm_actions:[alert]});
|
|
37
|
+
b.output.operator_jobs={value:{cluster:r('aws_ecs_cluster',n,'arn'),privateSubnets,securityGroups:[r('aws_security_group',n+'_operator','id')],taskDefinitions:Object.fromEntries(['initialize','maintain','monitor'].map(action=>[action,'${try(aws_ecs_task_definition.'+n+'_operator_'+action+'[0].arn,null)}'])),failedJobQueue:r('aws_sqs_queue',n+'_operator_failures','id'),alertTopic:alert}};
|
|
38
|
+
b.output.operator_bootstrap_request={value:{cluster:r('aws_ecs_cluster',n,'arn'),taskDefinition:'${try(aws_ecs_task_definition.'+n+'_operator_initialize[0].arn,null)}',launchType:'FARGATE',platformVersion:'1.4.0',count:1,enableExecuteCommand:false,networkConfiguration:{awsvpcConfiguration:{subnets:privateSubnets,securityGroups:[r('aws_security_group',n+'_operator','id')],assignPublicIp:'DISABLED'}}}};
|
|
39
|
+
b.files['OPERATING_JOBS.md']=AWS_OPERATING_JOBS;
|
|
40
|
+
b.assertions.push(`run "operator_before_applications" {
|
|
41
|
+
command = plan
|
|
42
|
+
variables {
|
|
43
|
+
applications_enabled = false
|
|
44
|
+
maintenance_enabled = false
|
|
45
|
+
}
|
|
46
|
+
assert {
|
|
47
|
+
condition = length(aws_ecs_task_definition.${n}_operator_initialize) == 1 && length(aws_ecs_service.${n}_api) == 0 && aws_scheduler_schedule.${n}_maintain[0].state == "DISABLED" && aws_ecs_task_definition.${n}_operator_monitor[0].task_role_arn == null
|
|
48
|
+
error_message = "Fixed bootstrap tasks precede application release; schedules remain stopped and no task role is conferred."
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
run "operating_jobs_required" {
|
|
53
|
+
command = plan
|
|
54
|
+
variables {
|
|
55
|
+
operations_enabled = false
|
|
56
|
+
maintenance_enabled = false
|
|
57
|
+
}
|
|
58
|
+
expect_failures = [terraform_data.review_gate]
|
|
59
|
+
}
|
|
60
|
+
run "operator_mutable_image_rejected" {
|
|
61
|
+
command = plan
|
|
62
|
+
variables {
|
|
63
|
+
applications_enabled = false
|
|
64
|
+
maintenance_enabled = false
|
|
65
|
+
runtime_image = "unreviewed:latest"
|
|
66
|
+
}
|
|
67
|
+
expect_failures = [var.runtime_image]
|
|
68
|
+
}
|
|
69
|
+
`);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const AWS_OPERATING_JOBS=`# Fixed AWS invoice operating jobs
|
|
73
|
+
|
|
74
|
+
These are generated definitions and commands, not evidence of a deployed service.
|
|
75
|
+
Obtain destination authorization before apply, publication or RunTask. Keep an
|
|
76
|
+
existing reviewed same-account regional SNS topic in operator_alert_topic_arn.
|
|
77
|
+
Its owner must authorize CloudWatch publishing and verify an actual subscribed
|
|
78
|
+
on-call route. If encrypted, the topic must use a compatible customer-managed KMS
|
|
79
|
+
key whose policy admits CloudWatch; the default alias/aws/sns key is not sufficient. This package does not adopt or modify the existing topic/policy.
|
|
80
|
+
|
|
81
|
+
1. Foundation: applications_enabled=false, operations_enabled=false,
|
|
82
|
+
maintenance_enabled=false. Review/apply only when authorized; publish the
|
|
83
|
+
scanned immutable runtime and parser images to the emitted ECR repositories.
|
|
84
|
+
2. Bootstrap definitions: operations_enabled=true, applications_enabled=false,
|
|
85
|
+
maintenance_enabled=false, runtime_image set to the owned immutable digest.
|
|
86
|
+
This creates fixed tasks and disabled schedules; it does not execute SQL.
|
|
87
|
+
3. From the authorized foundation state, write the nonsecret bootstrap request:
|
|
88
|
+
|
|
89
|
+
terraform output -json operator_bootstrap_request > .local/bootstrap.json
|
|
90
|
+
aws ecs run-task --cli-input-json file://.local/bootstrap.json
|
|
91
|
+
|
|
92
|
+
Use the same reviewed AWS account/region. Retain the returned task ARN, wait
|
|
93
|
+
for STOPPED and check operator exitCode=0 plus an initialized:true receipt in
|
|
94
|
+
the initialize log stream. A successful RunTask response alone only admits
|
|
95
|
+
scheduling; it does not prove SQL initialization. Failed start/nonzero exit
|
|
96
|
+
events reach the private operator-failures queue. No task role, accounting
|
|
97
|
+
credential, model or object authority is conferred on the operator container.
|
|
98
|
+
The execution role resolves only the managed RDS admin password field, image
|
|
99
|
+
and logs. The connection verifies the regional RDS CA/hostname. SQL transactions
|
|
100
|
+
and an advisory lock protect owned retries; existing passwords are preserved.
|
|
101
|
+
4. Invite verified Cognito users and admit explicit application roles through
|
|
102
|
+
invoice_operator.py membership as described in OPERATIONS.md. No invitation
|
|
103
|
+
or sign-in silently grants reviewer/owner authority. Populate the accounting
|
|
104
|
+
secret outside Terraform/source. Retain native membership/denial checks.
|
|
105
|
+
5. Release: applications_enabled=true, operations_enabled=true,
|
|
106
|
+
maintenance_enabled=true. The review gate refuses application release without
|
|
107
|
+
the operating definitions/schedules enabled. This flag does not prove step 3
|
|
108
|
+
or 4 ran: retain their actual destination receipts before approving release.
|
|
109
|
+
|
|
110
|
+
Daily maintenance runs at 02:17 UTC. It removes at most twenty batches of 500
|
|
111
|
+
expired SQL operations, with separate transactions and exact account/namespace
|
|
112
|
+
ownership. Live execution jobs/leases refuse deletion. Table locks serialize
|
|
113
|
+
concurrent submissions, preserving new/young operations. Remaining backlog returns
|
|
114
|
+
nonzero; retry after inspecting count-only logs. Object lifecycle expiry remains
|
|
115
|
+
independent and asynchronous. No scheduler IAM role can launch the bootstrap task.
|
|
116
|
+
|
|
117
|
+
Hourly monitoring uses a read-only SQL transaction and emits scoped state counts.
|
|
118
|
+
Pending/approved work unchanged for two hours, expired execution leases, dead or
|
|
119
|
+
unknown outcomes and records overdue for cleanup by two days need attention.
|
|
120
|
+
These are operational starting thresholds, not a promised throughput/latency SLA.
|
|
121
|
+
Both jobs have a 15-minute process deadline; SQL waits/statements are bounded.
|
|
122
|
+
|
|
123
|
+
Scheduler invocation failures go to the encrypted seven-day failure queue with
|
|
124
|
+
bounded retries. Task failed-to-start/nonzero operator exits also reach that queue;
|
|
125
|
+
this matters because RunTask acceptance is not application success. Queue alarms
|
|
126
|
+
and missing-success-receipt alarms publish to the reviewed existing SNS topic.
|
|
127
|
+
Daily/hourly heartbeat alarms breach after two missing periods. Bootstrap failures
|
|
128
|
+
alarm as well; no bootstrap is scheduled. Operator logs retain seven days and do
|
|
129
|
+
not include document data, subjects, amounts or SQL/password exception text.
|
|
130
|
+
|
|
131
|
+
Test alert delivery, stopped-task routing, missed schedules, private SQL/TLS,
|
|
132
|
+
native secret rotation and effective IAM in an authorized destination. Cloud
|
|
133
|
+
availability, notification delivery and managed restore remain unverified by local
|
|
134
|
+
schema/mocks. Keep restore/quarantine/reconciliation isolated and explicitly paused;
|
|
135
|
+
daily cleanup does not authorize replaying uncertain external accounting effects.
|
|
136
|
+
`;
|