@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
|
+
import aws from './runtime/aws-web-python-lock.json' with {type:'json'};
|
|
2
|
+
import azure from './runtime/azure-python-lock.json' with {type:'json'};
|
|
3
|
+
import gcp from './runtime/web-python-lock.json' with {type:'json'};
|
|
4
|
+
import ibm from './runtime/ibm-python-lock.json' with {type:'json'};
|
|
5
|
+
import durable from './runtime/durable-python-lock.json' with {type:'json'};
|
|
6
|
+
import testing from './runtime/azure-test-lock.json' with {type:'json'};
|
|
7
|
+
|
|
8
|
+
const normalize=name=>name.toLowerCase().replaceAll(/[_.]+/g,'-');
|
|
9
|
+
function entries(lock){
|
|
10
|
+
const result=[];let current;
|
|
11
|
+
for(const line of lock.requirements.trim().split('\n')){
|
|
12
|
+
if(!line.trim())continue;
|
|
13
|
+
if(lock===testing&&line==='-r requirements.lock')continue; // Already merged above.
|
|
14
|
+
const start=/^([A-Za-z0-9_.-]+)==([^\s\\]+)((?:\s+--hash=sha256:[0-9a-f]{64})*)(?:\s*\\)?$/.exec(line);
|
|
15
|
+
if(start){current={name:normalize(start[1]),version:start[2],hashes:new Set([...start[3].matchAll(/--hash=sha256:([0-9a-f]{64})/g)].map(match=>match[1]))};result.push(current);continue;}
|
|
16
|
+
const hash=/^\s+--hash=sha256:([0-9a-f]{64})(?:\s*\\)?$/.exec(line);
|
|
17
|
+
if(!hash||!current)throw Error('Invoice dependencies must be exact reviewed version/hash records');current.hashes.add(hash[1]);
|
|
18
|
+
}
|
|
19
|
+
if(!result.length||result.some(entry=>!entry.hashes.size)||new Set(result.map(e=>e.name)).size!==result.length)throw Error('Incomplete or duplicate reviewed dependency records');return result;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// One explicit composition decision, not a general dependency-conflict override.
|
|
23
|
+
// IBM SDK 3.28.2 requires dateutil >=3,<3.1; Procrastinate/croniter accept it.
|
|
24
|
+
// The resulting queue composition still requires independent runtime tests.
|
|
25
|
+
export function invoiceDependencies(provider,{tests=false}={}){
|
|
26
|
+
const native={aws,azure,gcp,ibm}[provider];if(!native)throw Error('Unsupported invoice dependency provider');
|
|
27
|
+
const locks=[native,durable,...(tests?[testing]:[])],merged=new Map(),resolutions=[];
|
|
28
|
+
for(const lock of locks)for(const entry of entries(lock)){
|
|
29
|
+
if(provider==='aws'&&entry.name==='mangum')continue; // Fargate, not Lambda.
|
|
30
|
+
const previous=merged.get(entry.name);
|
|
31
|
+
if(previous&&previous.version!==entry.version){
|
|
32
|
+
if(provider==='ibm'&&entry.name==='python-dateutil'&&new Set([previous.version,entry.version]).size===2&&[previous.version,entry.version].every(v=>['2.9.0.post0','3.0.0'].includes(v))){
|
|
33
|
+
merged.set(entry.name,previous.version==='3.0.0'?previous:entry);resolutions.push({name:entry.name,selected:'3.0.0',otherReviewedPin:'2.9.0.post0',reason:'IBM SDK requires >=3,<3.1; queue dependency permits it. Whole composition qualification is mandatory.'});continue;
|
|
34
|
+
}throw Error('Unreviewed invoice dependency conflict for '+entry.name);
|
|
35
|
+
}
|
|
36
|
+
if(previous)for(const hash of entry.hashes)previous.hashes.add(hash);else merged.set(entry.name,entry);
|
|
37
|
+
}
|
|
38
|
+
const records=[...merged.values()].sort((a,b)=>a.name.localeCompare(b.name));
|
|
39
|
+
const requirements=records.map(e=>e.name+'=='+e.version+' \\\n'+[...e.hashes].sort().map((h,i,all)=>' --hash=sha256:'+h+(i<all.length-1?' \\':'')).join('\n')).join('\n')+'\n';
|
|
40
|
+
const sourceMap=new Map();for(const lock of locks)for(const source of lock.sources){const key=normalize(source.name),selected=merged.get(key);if(selected?.version===source.version)sourceMap.set(key,source);}
|
|
41
|
+
if(records.some(record=>!sourceMap.has(record.name)))throw Error('Missing dependency provenance');
|
|
42
|
+
return{requirements,sources:[...sourceMap.values()],resolutions,scope:'Reviewed dependency union; generation is not a runtime/clean-security claim'};
|
|
43
|
+
}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import{v,r,l}from'./invoice-builder.mjs';
|
|
2
|
+
|
|
3
|
+
export function gcpInvoiceOperations(b,n,{destination,region,sa,member,proxy}){
|
|
4
|
+
const{add,input}=b;
|
|
5
|
+
for(const key of ['operations_enabled','maintenance_enabled']){b.variable[key]={type:'bool',default:false,description:key==='operations_enabled'?'After immutable image publication, create fixed private SQL operator jobs before application release.':'Enable daily cleanup/hourly monitor after owned SQL bootstrap. Verify live telemetry/notification acceptance before application release.'};b.examples[key]=false;b.testExpressions[key]='true';}
|
|
6
|
+
const channel=input('operator_notification_channel','Existing verified on-call Cloud Monitoring channel in this project, referenced without modification.','projects/'+b.examples.project_id+'/notificationChannels/123456789012','^projects/[a-z][a-z0-9-]{4,28}[a-z0-9]/notificationChannels/[0-9]+$');
|
|
7
|
+
b.resource.terraform_data.review_gate.lifecycle.precondition.push({condition:'${!var.maintenance_enabled || var.operations_enabled}',error_message:'Scheduled maintenance requires separate operator jobs.'},{condition:'${!var.applications_enabled || (var.operations_enabled && var.maintenance_enabled)}',error_message:'Complete owned SQL, membership and operating telemetry acceptance before application release.'},{condition:'${startswith(var.operator_notification_channel,format("projects/%s/notificationChannels/",var.project_id))}',error_message:'Use the reviewed notification channel in this destination project.'});
|
|
8
|
+
b.locals.operator_deployment=b.output.operator_deployment.value;
|
|
9
|
+
for(const[purpose,service]of[['scheduler','cloudscheduler.googleapis.com'],['logging','logging.googleapis.com'],['monitoring','monitoring.googleapis.com']])add('google_project_service',n+'_'+purpose,{project:destination,service,disable_on_destroy:false});
|
|
10
|
+
add('google_project_service_identity',n+'_scheduler',{provider:'google-beta',project:destination,service:'cloudscheduler.googleapis.com',depends_on:['google_project_service.'+n+'_scheduler']});
|
|
11
|
+
add('google_project_iam_member',n+'_scheduler_service_agent',{project:destination,role:'roles/cloudscheduler.serviceAgent',member:r('google_project_service_identity',n+'_scheduler','member')});
|
|
12
|
+
add('google_service_account',n+'_scheduler',{project:destination,account_id:l('name')+'-scheduler',display_name:'Only invoke owned maintenance/monitor jobs; no SQL/data/bootstrap/override authority',depends_on:['google_project_service.'+n+'_identity']});
|
|
13
|
+
const settings={DATABASE_NAME:'invoice',DATABASE_CONNECTION_NAME:r('google_sql_database_instance',n,'connection_name'),DATABASE_TRANSPORT:'cloudsql-private-proxy',DATABASE_SERVICE_ACCOUNT:sa('ops','email'),OPERATOR_PROXY_SHUTDOWN:'cloudsql-private-proxy',OPERATOR_DEPLOYMENT_BASE64:'${base64encode(jsonencode(local.operator_deployment))}'};
|
|
14
|
+
for(const action of ['initialize','maintain','monitor']){
|
|
15
|
+
const operator={name:'operator',image:v('runtime_image'),command:['python','-I','/app/invoice_operator_job.py',action,'--execute'],resources:{limits:{cpu:'1',memory:'1Gi'}},env:Object.entries(settings).map(([name,value])=>({name,value}))};
|
|
16
|
+
// Stable concurrent startup; the operator waits on /startup itself and always
|
|
17
|
+
// POSTs /quitquitquit, so a completed/failed task cannot leave this sidecar alive.
|
|
18
|
+
const sidecar={name:'cloud-sql-proxy',image:proxy.image,args:['--private-ip','--address=127.0.0.1','--port=5432','--structured-logs','--lazy-refresh','--health-check','--http-address=127.0.0.1','--http-port=9090','--quitquitquit','--admin-port=9091','--exit-zero-on-sigterm',r('google_sql_database_instance',n,'connection_name')],resources:{limits:{cpu:'1',memory:'256Mi'}}};
|
|
19
|
+
add('google_cloud_run_v2_job',n+'_operator_'+action,{count:'${var.operations_enabled ? 1 : 0}',project:destination,name:l('name')+'-'+action,location:region,deletion_protection:true,launch_stage:'GA',template:{parallelism:1,task_count:1,template:{service_account:sa('ops','email'),execution_environment:'EXECUTION_ENVIRONMENT_GEN2',timeout:'960s',max_retries:0,containers:[operator,sidecar],vpc_access:{egress:'PRIVATE_RANGES_ONLY',network_interfaces:{network:r('google_compute_network',n,'name'),subnetwork:r('google_compute_subnetwork',n,'name')}}}},depends_on:['google_project_service.'+n+'_run','google_artifact_registry_repository_iam_member.'+n,'google_sql_database.'+n,'google_sql_user.'+n+'_ops','google_sql_user.'+n+'_api','google_sql_user.'+n+'_worker','google_project_iam_member.'+n+'_ops_connect','google_project_iam_member.'+n+'_ops_login']});
|
|
20
|
+
if(action==='initialize')continue;
|
|
21
|
+
add('google_cloud_run_v2_job_iam_member',n+'_operator_'+action,{count:'${var.operations_enabled ? 1 : 0}',project:destination,location:region,name:r('google_cloud_run_v2_job',n+'_operator_'+action+'[0]','name'),role:'roles/run.invoker',member:'serviceAccount:'+r('google_service_account',n+'_scheduler','email')});
|
|
22
|
+
add('google_cloud_scheduler_job',n+'_'+action,{count:'${var.operations_enabled ? 1 : 0}',project:destination,region,name:l('name')+'-'+action,schedule:action==='maintain'?'17 2 * * *':'7 * * * *',time_zone:'Etc/UTC',paused:'${!var.maintenance_enabled}',attempt_deadline:'180s',retry_config:{retry_count:2,min_backoff_duration:'10s',max_backoff_duration:'60s',max_retry_duration:'300s'},http_target:{http_method:'POST',uri:'https://run.googleapis.com/v2/projects/'+destination+'/locations/'+region+'/jobs/'+l('name')+'-'+action+':run',body:'${base64encode("{}")}',headers:{'Content-Type':'application/json'},oauth_token:{service_account_email:r('google_service_account',n+'_scheduler','email'),scope:'https://www.googleapis.com/auth/cloud-platform'}},depends_on:['google_project_service.'+n+'_scheduler','google_project_iam_member.'+n+'_scheduler_service_agent','google_cloud_run_v2_job_iam_member.'+n+'_operator_'+action]});
|
|
23
|
+
}
|
|
24
|
+
const jobNames=['initialize','maintain','monitor'].map(action=>'resource.labels.job_name="'+l('name')+'-'+action+'"').join(' OR ');
|
|
25
|
+
const failures='resource.type="cloud_run_job" AND resource.labels.location="'+region+'" AND ('+jobNames+') AND ((jsonPayload.format="invoice-operator-v1" AND (jsonPayload.status="failed" OR jsonPayload.status="attention" OR jsonPayload.status="backlog")) OR severity>=ERROR)';
|
|
26
|
+
const schedulerFailures='resource.type="cloud_scheduler_job" AND resource.labels.location="'+region+'" AND (resource.labels.job_id="'+l('name')+'-maintain" OR resource.labels.job_id="'+l('name')+'-monitor") AND severity>=ERROR';
|
|
27
|
+
const success='resource.type="cloud_run_job" AND resource.labels.location="'+region+'" AND resource.labels.job_name="'+l('name')+'-monitor" AND jsonPayload.format="invoice-operator-v1" AND jsonPayload.action="monitor" AND jsonPayload.status="ok"';
|
|
28
|
+
for(const[purpose,filter]of[['failed',failures],['scheduler_failed',schedulerFailures],['monitor_success',success]]){
|
|
29
|
+
add('google_logging_metric',n+'_'+purpose,{project:destination,name:l('name')+'-'+purpose,filter,metric_descriptor:{metric_kind:'DELTA',value_type:'INT64',unit:'1'},depends_on:['google_project_service.'+n+'_logging']});
|
|
30
|
+
b.files['monitoring/'+purpose+'.filter']=filter+'\n';
|
|
31
|
+
}
|
|
32
|
+
for(const[purpose,resourceType]of[['failed','cloud_run_job'],['scheduler_failed','cloud_scheduler_job']])add('google_monitoring_alert_policy',n+'_'+purpose,{project:destination,display_name:l('name')+'-'+purpose,combiner:'OR',enabled:v('operations_enabled'),notification_channels:[channel],conditions:[{display_name:'Owned operator or scheduler failure',condition_threshold:{filter:'resource.type="'+resourceType+'" AND metric.type="logging.googleapis.com/user/'+l('name')+'-'+purpose+'"',comparison:'COMPARISON_GT',threshold_value:0,duration:'0s',aggregations:[{alignment_period:'600s',per_series_aligner:'ALIGN_SUM'}],trigger:{count:1}}}],alert_strategy:{auto_close:'1800s'},documentation:{mime_type:'text/markdown',content:'Inspect the owned operator execution/logs and private SQL path. A RunJob acceptance response does not prove task success. Never replay uncertain accounting effects.'},depends_on:['google_project_service.'+n+'_monitoring','google_logging_metric.'+n+'_'+purpose]});
|
|
33
|
+
// Google absence has a <24h trigger ceiling and requires an initial sample.
|
|
34
|
+
// Hourly monitoring checks SQL's 92-day overdue invariant instead of emitting
|
|
35
|
+
// an invalid 48-hour metric-absence rule for a once-daily maintenance job.
|
|
36
|
+
add('google_monitoring_alert_policy',n+'_monitor_missing',{project:destination,display_name:l('name')+'-monitor-missing',combiner:'OR',enabled:v('maintenance_enabled'),notification_channels:[channel],conditions:[{display_name:'No successful hourly SQL monitor',condition_absent:{filter:'resource.type="cloud_run_job" AND metric.type="logging.googleapis.com/user/'+l('name')+'-monitor_success"',duration:'7200s',aggregations:[{alignment_period:'600s',per_series_aligner:'ALIGN_SUM'}],trigger:{count:1}}}],alert_strategy:{auto_close:'1800s'},documentation:{mime_type:'text/markdown',content:'This absence rule needs an actual successful measurement after policy installation/modification. Run monitor and verify its metric before release. Hourly SQL monitoring reports overdue retention; a never-started metric is not an armed heartbeat.'},depends_on:['google_project_service.'+n+'_monitoring','google_logging_metric.'+n+'_monitor_success']});
|
|
37
|
+
b.output.operator_start_urls={value:Object.fromEntries(['initialize','maintain','monitor'].map(action=>[action,'https://run.googleapis.com/v2/projects/'+destination+'/locations/'+region+'/jobs/'+l('name')+'-'+action+':run']))};
|
|
38
|
+
b.output.operator_bootstrap_url={value:'https://run.googleapis.com/v2/projects/'+destination+'/locations/'+region+'/jobs/'+l('name')+'-initialize:run',description:'Use only after reviewed operating-job resources have actually been applied.'};
|
|
39
|
+
b.output.operator_jobs={value:{project:destination,region,serviceAccount:sa('ops','email'),schedulerServiceAccount:r('google_service_account',n+'_scheduler','email'),notificationChannel:channel,names:Object.fromEntries(['initialize','maintain','monitor'].map(action=>[action,l('name')+'-'+action]))}};
|
|
40
|
+
b.files['OPERATING_JOBS.md']=GCP_OPERATING_JOBS;
|
|
41
|
+
b.files['scripts/run-operator.py']=GCP_OPERATOR_RUNNER;
|
|
42
|
+
b.assertions.push(`run "operator_before_applications" {
|
|
43
|
+
command = plan
|
|
44
|
+
variables {
|
|
45
|
+
applications_enabled = false
|
|
46
|
+
maintenance_enabled = false
|
|
47
|
+
staff_principals = []
|
|
48
|
+
}
|
|
49
|
+
assert {
|
|
50
|
+
condition = length(google_cloud_run_v2_job.${n}_operator_initialize) == 1 && google_cloud_scheduler_job.${n}_maintain[0].paused && length(google_cloud_run_v2_service.${n}_api) == 0
|
|
51
|
+
error_message = "Manual bootstrap must precede scheduled maintenance and application release."
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
run "operator_private_proxy_and_caller" {
|
|
55
|
+
command = plan
|
|
56
|
+
assert {
|
|
57
|
+
condition = google_cloud_run_v2_job.${n}_operator_monitor[0].template[0].template[0].service_account == google_service_account.${n}_ops.email && google_cloud_run_v2_job.${n}_operator_monitor[0].template[0].template[0].max_retries == 0 && contains(google_cloud_run_v2_job.${n}_operator_monitor[0].template[0].template[0].containers[1].args,"--quitquitquit") && google_cloud_run_v2_job_iam_member.${n}_operator_maintain[0].member == "serviceAccount:\${google_service_account.${n}_scheduler.email}"
|
|
58
|
+
error_message = "Separate SQL operator, private terminating proxy and job-scoped invoker are required."
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
run "operating_jobs_required" {
|
|
62
|
+
command = plan
|
|
63
|
+
variables {
|
|
64
|
+
operations_enabled = false
|
|
65
|
+
maintenance_enabled = false
|
|
66
|
+
}
|
|
67
|
+
expect_failures = [terraform_data.review_gate]
|
|
68
|
+
}
|
|
69
|
+
run "operator_mutable_image_rejected" {
|
|
70
|
+
command = plan
|
|
71
|
+
variables {
|
|
72
|
+
applications_enabled = false
|
|
73
|
+
maintenance_enabled = false
|
|
74
|
+
runtime_image = "unreviewed:latest"
|
|
75
|
+
}
|
|
76
|
+
expect_failures = [var.runtime_image]
|
|
77
|
+
}
|
|
78
|
+
`);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const GCP_OPERATING_JOBS=`# Google invoice operating jobs
|
|
82
|
+
|
|
83
|
+
Obtain authorization before account writes, apply, publication or RunJob. Fixed
|
|
84
|
+
operator jobs are not API/model tools. The existing project, verified staff and
|
|
85
|
+
notification channel are referenced, never replaced. Verify the existing channel's
|
|
86
|
+
actual on-call recipients and delivery. Review organization log placement/retention
|
|
87
|
+
and effective inherited IAM; this package does not rewrite existing logging sinks.
|
|
88
|
+
Operator receipts contain counts/status, not invoices, subjects or amounts.
|
|
89
|
+
|
|
90
|
+
Foundation: applications_enabled=false, operations_enabled=false,
|
|
91
|
+
maintenance_enabled=false. Publish reviewed immutable runtime/parser images into
|
|
92
|
+
the owned regional repository only when authorized. With runtime_image supplied,
|
|
93
|
+
set operations_enabled=true and keep maintenance/applications false. The three
|
|
94
|
+
fixed jobs exist; daily/hourly schedules remain paused.
|
|
95
|
+
|
|
96
|
+
As the separately authorized destination operator, preview the emitted command:
|
|
97
|
+
|
|
98
|
+
python3 scripts/run-operator.py initialize
|
|
99
|
+
|
|
100
|
+
Then add --execute for the authorized destination. The helper reads nonsecret
|
|
101
|
+
Terraform outputs and invokes gcloud with exact project/region/name and --wait,
|
|
102
|
+
without shell interpolation, overrides or exposing OAuth tokens. Use maintain or
|
|
103
|
+
monitor for the other fixed jobs. Install/authenticate the reviewed Google Cloud
|
|
104
|
+
CLI beforehand. The exact operator_start_urls REST outputs are also available.
|
|
105
|
+
Do not use public invokers or application roles to launch privileged SQL work. RunJob acceptance is asynchronous: retain the actual
|
|
106
|
+
completed execution/exit status and initialized:true receipt before continuing.
|
|
107
|
+
|
|
108
|
+
The ops service account intentionally has separate cloudsqlsuperuser SQL authority.
|
|
109
|
+
API/worker IAM SQL users must already exist. Bootstrap verifies native IAM markers,
|
|
110
|
+
owned identities, exact schema/grants and scope, never creates a substitute native
|
|
111
|
+
IAM user or adopts unrelated roles. Managed Cloud SQL role mutation, native IAM and
|
|
112
|
+
effective privileges require destination checks; local PostgreSQL is not Cloud SQL.
|
|
113
|
+
Admit verified staff SQL memberships separately; IAP access alone is insufficient.
|
|
114
|
+
Populate the accounting secret outside Terraform/source and outside operator jobs.
|
|
115
|
+
|
|
116
|
+
Each job has one task, parallelism one, no native retry and a 960-second task limit.
|
|
117
|
+
Its operator waits up to 30 seconds on the pinned proxy's own loopback startup
|
|
118
|
+
endpoint, uses a 900-second work deadline and always calls the loopback shutdown
|
|
119
|
+
endpoint. Initial SQL connection transport failures retry at most three times with
|
|
120
|
+
fresh credentials; authentication/permission/schema errors do not. No insecure
|
|
121
|
+
remote connection, public SQL IP or configurable proxy URL is introduced. The
|
|
122
|
+
maintained proxy uses private IP/upstream TLS and a fixed instance. A failed shutdown
|
|
123
|
+
cannot emit an ok heartbeat; native task timeout remains the final failure bound.
|
|
124
|
+
|
|
125
|
+
Next enable maintenance_enabled=true while applications_enabled=false. Cleanup
|
|
126
|
+
runs 02:17 UTC daily, monitor at minute 7 hourly. The scheduler uses its own invoker
|
|
127
|
+
identity scoped to maintain/monitor only, OAuth, bounded retries and no bootstrap
|
|
128
|
+
or override/SQL authority. Its service agent has the required native role.
|
|
129
|
+
Manually run monitor and verify a real success metric AFTER policy installation/
|
|
130
|
+
modification: Google's absence policy does not arm from a never-written metric.
|
|
131
|
+
The two-hour monitor absence rule plus failures and hourly SQL retention-overdue
|
|
132
|
+
checks cover operating progress. No invalid 48-hour absence condition is emitted.
|
|
133
|
+
Native platform ERROR logs and count-only failed/attention/backlog receipts alert;
|
|
134
|
+
inspect execution history as well. Test failed scheduling/execution, first-sample,
|
|
135
|
+
missing runs and channel delivery before final applications_enabled=true release.
|
|
136
|
+
|
|
137
|
+
Daily cleanup is bounded to twenty 500-record transactions and refuses live jobs/
|
|
138
|
+
leases; younger/concurrent work is preserved. Original-object expiry is separate
|
|
139
|
+
and asynchronous. Restore/quarantine/reconciliation remain isolated and paused.
|
|
140
|
+
Local schemas/mocks and fixture SQL do not prove Cloud SQL IAM/TLS, scheduling,
|
|
141
|
+
metric/log ingestion, notification delivery or managed restore. Retain those actual
|
|
142
|
+
destination acceptance receipts; no production readiness is inferred from a URL.
|
|
143
|
+
`;
|
|
144
|
+
|
|
145
|
+
const GCP_OPERATOR_RUNNER=String.raw`"""Preview or explicitly execute one owned Google operator job from Terraform outputs."""
|
|
146
|
+
import argparse
|
|
147
|
+
import json
|
|
148
|
+
import re
|
|
149
|
+
import subprocess
|
|
150
|
+
import sys
|
|
151
|
+
|
|
152
|
+
def unique(pairs):
|
|
153
|
+
result={}
|
|
154
|
+
for key,value in pairs:
|
|
155
|
+
if key in result:raise ValueError('Duplicate output field')
|
|
156
|
+
result[key]=value
|
|
157
|
+
return result
|
|
158
|
+
|
|
159
|
+
def command(action,configuration):
|
|
160
|
+
if action not in {'initialize','maintain','monitor'}or not isinstance(configuration,dict):raise ValueError('Use an owned fixed operator action')
|
|
161
|
+
project=configuration.get('project');region=configuration.get('region');names=configuration.get('names')
|
|
162
|
+
if not isinstance(project,str)or not re.fullmatch(r'[a-z][a-z0-9-]{4,28}[a-z0-9]',project)or not isinstance(region,str)or not re.fullmatch(r'[a-z]+-[a-z]+[1-9][0-9]?',region):raise ValueError('Use the emitted destination')
|
|
163
|
+
if not isinstance(names,dict)or set(names)!={'initialize','maintain','monitor'}or any(not isinstance(name,str)or not re.fullmatch(r'[a-z][a-z0-9-]{1,61}[a-z0-9]',name)for name in names.values())or len(set(names.values()))!=3:raise ValueError('Use distinct owned job names')
|
|
164
|
+
return ['gcloud','run','jobs','execute',names[action],'--project',project,'--region',region,'--wait','--format=json']
|
|
165
|
+
|
|
166
|
+
def main():
|
|
167
|
+
parser=argparse.ArgumentParser(description=__doc__);parser.add_argument('action',choices=['initialize','maintain','monitor']);parser.add_argument('--execute',action='store_true');args=parser.parse_args()
|
|
168
|
+
result=subprocess.run(['terraform','output','-json','operator_jobs'],capture_output=True,check=True,timeout=30)
|
|
169
|
+
selected=command(args.action,json.loads(result.stdout,object_pairs_hook=unique))
|
|
170
|
+
if not args.execute:
|
|
171
|
+
print(json.dumps({'willWrite':False,'command':selected}));return 0
|
|
172
|
+
return subprocess.run(selected,timeout=1200).returncode
|
|
173
|
+
|
|
174
|
+
if __name__=='__main__':
|
|
175
|
+
try:sys.exit(main())
|
|
176
|
+
except Exception:
|
|
177
|
+
print('Operator invocation failed. Check the owned Terraform state, authenticated destination and job execution receipt.',file=sys.stderr);sys.exit(1)
|
|
178
|
+
`;
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import {invoiceBuilder,v,r,l}from'./invoice-builder.mjs';
|
|
2
|
+
import {CLOUD_PROVIDER_LOCKS}from'./cloud-provider-locks.mjs';
|
|
3
|
+
import {gcpInvoiceOperations}from'./invoice-gcp-operations.mjs';
|
|
4
|
+
import proxy from'./runtime/cloud-sql-proxy-lock.json'with{type:'json'};
|
|
5
|
+
import proxyReview from'./runtime/cloud-sql-proxy-security-review.json'with{type:'json'};
|
|
6
|
+
|
|
7
|
+
// Native composition under qualification. Account/model approvals are not invented.
|
|
8
|
+
export function gcpInvoiceTerraform(project,row,environment='staging'){
|
|
9
|
+
if(row.provider!=='gcp')throw Error('Google invoice compilation cannot substitute another cloud');
|
|
10
|
+
if(proxyReview.imageIndex!==proxy.image||proxyReview.status!=='reviewed-not-affected-by-listed-findings'||proxyReview.platform!=='linux/amd64')throw Error('Repeat the exact Cloud SQL proxy dependency review before changing its artifact');
|
|
11
|
+
const b=invoiceBuilder(project,row,environment),{input,add,region}=b,n=row.address;
|
|
12
|
+
const destination=input('project_id','Existing organization-owned Google Cloud destination project.','reviewed-project','^[a-z][a-z0-9-]{4,28}[a-z0-9]$');
|
|
13
|
+
const model=input('model_id','Explicit compatible regional Gemini model; verify current regional availability, lifecycle and quotas.','gemini-reviewed-version','^gemini-[a-z0-9.-]{1,80}$');
|
|
14
|
+
const endpoint=input('accounting_endpoint','Existing reviewed accounting HTTPS adapter, never recreated.','https://accounting.example.test/actions','^https://[A-Za-z0-9.-]+(:[0-9]{1,5})?(/[^?#@ ]*)?$');
|
|
15
|
+
const scope=input('accounting_scope','Reviewed accounting scope bound to every approval.','owned-team','^[A-Za-z0-9_.:/-]{1,200}$');
|
|
16
|
+
for(const purpose of ['runtime','parser']){
|
|
17
|
+
input(purpose+'_image','Exact immutable image in this package-owned Artifact Registry. Empty during foundation.','australia-southeast1-docker.pkg.dev/reviewed-project/reviewed-repository/'+purpose+'@sha256:'+'a'.repeat(64));
|
|
18
|
+
b.variable[purpose+'_image'].default='';b.variable[purpose+'_image'].validation={condition:'${!('+(purpose==='runtime'?'var.applications_enabled || var.operations_enabled':'var.applications_enabled')+') || can(regex("@sha256:[0-9a-f]{64}$",var.'+purpose+'_image))}',error_message:'Release requires the reviewed immutable image digest.'};
|
|
19
|
+
b.resource.terraform_data.review_gate.lifecycle.precondition.push({condition:'${!('+(purpose==='runtime'?'var.applications_enabled || var.operations_enabled':'var.applications_enabled')+') || startswith(var.'+purpose+'_image,format("%s-docker.pkg.dev/%s/%s/'+purpose+'@sha256:",var.region,var.project_id,local.name))}',error_message:'Use the package-owned regional Artifact Registry and immutable image.'});
|
|
20
|
+
}
|
|
21
|
+
b.variable.staff_principals={type:'set(string)',default:[],description:'Explicit existing staff IAP user/group IAM principals. SQL membership independently governs review/approval.',validation:{condition:'${alltrue([for principal in var.staff_principals : can(regex("^(user|group):[^@ ]+@[^@ ]+[.][^@ ]+$",principal))])}',error_message:'Supply explicit user/group principals; public principals are prohibited.'}};b.examples.staff_principals=['group:invoice-staff@example.test'];
|
|
22
|
+
b.variable.policy_review_base64={type:'string',default:'',description:'Scoped expiring owner review of actual model privacy/abuse-monitoring terms. Empty blocks inference, never self-approved.'};b.examples.policy_review_base64='';
|
|
23
|
+
b.variable.replay_review_base64={type:'string',default:'',description:'Scoped expiring accounting replay acceptance. Empty disables automatic uncertain replay.'};b.examples.replay_review_base64='';
|
|
24
|
+
b.data.google_project={destination:{project_id:destination}};const number=r('data.google_project','destination','number');
|
|
25
|
+
b.resource.terraform_data.review_gate.lifecycle.precondition.push({condition:'${!var.applications_enabled || length(var.staff_principals)>0}',error_message:'Review exact existing staff IAP admission before release.'});
|
|
26
|
+
Object.assign(b.locals,{public_origin:'${format("https://%s-api-%s.%s.run.app",local.name,data.google_project.destination.number,var.region)}',parser_origin:'${format("https://%s-parser-%s.%s.run.app",local.name,data.google_project.destination.number,var.region)}',parser_endpoint:'${format("%s/extract",local.parser_origin)}',destination_contract:{id:'normalized-action-v1',endpointSha256:'${sha256(var.accounting_endpoint)}',scope,mappingVersion:1},destination_contract_base64:'${base64encode(jsonencode(local.destination_contract))}'});
|
|
27
|
+
const services={run:'run.googleapis.com',iap:'iap.googleapis.com',model:'aiplatform.googleapis.com',registry:'artifactregistry.googleapis.com',database:'sqladmin.googleapis.com',network:'compute.googleapis.com',peering:'servicenetworking.googleapis.com',secrets:'secretmanager.googleapis.com',identity:'iam.googleapis.com'};
|
|
28
|
+
for(const[purpose,service]of Object.entries(services))add('google_project_service',n+'_'+purpose,{project:destination,service,disable_on_destroy:false});
|
|
29
|
+
for(const purpose of ['run','iap'])add('google_project_service_identity',n+'_'+purpose,{provider:'google-beta',project:destination,service:services[purpose],depends_on:['google_project_service.'+n+'_'+purpose]});
|
|
30
|
+
add('google_compute_network',n,{project:destination,name:l('name'),auto_create_subnetworks:false,depends_on:['google_project_service.'+n+'_network']});
|
|
31
|
+
add('google_compute_subnetwork',n,{project:destination,name:l('name'),region,network:r('google_compute_network',n,'id'),ip_cidr_range:'10.86.0.0/24',private_ip_google_access:true});
|
|
32
|
+
add('google_compute_global_address',n+'_database',{project:destination,name:l('name')+'-database',purpose:'VPC_PEERING',address_type:'INTERNAL',prefix_length:16,address:'10.89.0.0',network:r('google_compute_network',n,'id')});
|
|
33
|
+
add('google_service_networking_connection',n,{network:r('google_compute_network',n,'id'),service:'servicenetworking.googleapis.com',reserved_peering_ranges:[r('google_compute_global_address',n+'_database','name')],deletion_policy:'ABANDON',depends_on:['google_project_service.'+n+'_peering']});
|
|
34
|
+
for(const purpose of ['api','worker','parser','ops'])add('google_service_account',n+'_'+purpose,{project:destination,account_id:l('name')+'-'+purpose,display_name:'Invoice '+purpose+'; separate least-privilege purpose',depends_on:['google_project_service.'+n+'_identity']});
|
|
35
|
+
const sa=(purpose,attribute)=>r('google_service_account',n+'_'+purpose,attribute),member=purpose=>'serviceAccount:'+sa(purpose,'email');
|
|
36
|
+
add('google_sql_database_instance',n,{project:destination,name:l('name'),region,database_version:'POSTGRES_17',deletion_protection:true,settings:{tier:'db-custom-2-7680',edition:'ENTERPRISE',availability_type:'REGIONAL',deletion_protection_enabled:true,disk_type:'PD_SSD',disk_size:20,disk_autoresize:true,disk_autoresize_limit:100,ip_configuration:{ipv4_enabled:false,private_network:r('google_compute_network',n,'id'),ssl_mode:'TRUSTED_CLIENT_CERTIFICATE_REQUIRED'},backup_configuration:{enabled:true,point_in_time_recovery_enabled:true,transaction_log_retention_days:7,location:region,backup_retention_settings:{retained_backups:7,retention_unit:'COUNT'}},database_flags:[{name:'cloudsql.iam_authentication',value:'on'},{name:'log_statement',value:'none'},{name:'log_min_error_statement',value:'panic'},{name:'log_parameter_max_length_on_error',value:'0'}],insights_config:{query_insights_enabled:false,record_application_tags:false,record_client_address:false}},lifecycle:{prevent_destroy:true},depends_on:['google_project_service.'+n+'_database','google_service_networking_connection.'+n]});
|
|
37
|
+
add('google_sql_database',n,{project:destination,name:'invoice',instance:r('google_sql_database_instance',n,'name'),charset:'UTF8',collation:'en_US.UTF8',deletion_policy:'ABANDON'});
|
|
38
|
+
for(const purpose of ['api','worker','ops']){
|
|
39
|
+
add('google_sql_user',n+'_'+purpose,{project:destination,name:'${trimsuffix(google_service_account.'+n+'_'+purpose+'.email,".gserviceaccount.com")}',instance:r('google_sql_database_instance',n,'name'),type:'CLOUD_IAM_SERVICE_ACCOUNT',database_roles:purpose==='ops'?['cloudsqlsuperuser']:[],deletion_policy:'ABANDON'});
|
|
40
|
+
for(const[role,suffix]of [['roles/cloudsql.client','connect'],['roles/cloudsql.instanceUser','login']])add('google_project_iam_member',n+'_'+purpose+'_'+suffix,{project:destination,role,member:member(purpose)});
|
|
41
|
+
}
|
|
42
|
+
add('google_storage_bucket',n,{project:destination,name:destination+'-'+l('name')+'-invoices',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:0},lifecycle_rule:[{action:{type:'Delete'},condition:{age:90}}],lifecycle:{prevent_destroy:true}});
|
|
43
|
+
add('google_project_iam_custom_role',n+'_upload',{project:destination,role_id:'${replace(local.name,"-","_")}_documents',title:'Invoice immutable document upload/read',permissions:['storage.objects.create','storage.objects.get'],stage:'GA'});
|
|
44
|
+
add('google_storage_bucket_iam_member',n+'_upload',{bucket:r('google_storage_bucket',n,'name'),role:r('google_project_iam_custom_role',n+'_upload','name'),member:member('api')});
|
|
45
|
+
add('google_storage_bucket_iam_member',n+'_read',{bucket:r('google_storage_bucket',n,'name'),role:'roles/storage.objectViewer',member:member('worker')});
|
|
46
|
+
add('google_project_iam_custom_role',n+'_model',{project:destination,role_id:'${replace(local.name,"-","_")}_model',title:'Invoice model and read-only policy inspection',permissions:['aiplatform.endpoints.predict','aiplatform.cacheConfigs.get','aiplatform.endpoints.fetchPublisherModelConfig'],stage:'GA'});
|
|
47
|
+
add('google_project_iam_member',n+'_model',{project:destination,role:r('google_project_iam_custom_role',n+'_model','name'),member:member('worker'),depends_on:['google_project_service.'+n+'_model']});
|
|
48
|
+
add('google_artifact_registry_repository',n,{project:destination,location:region,repository_id:l('name'),format:'DOCKER',docker_config:{immutable_tags:true},cleanup_policy_dry_run:true,lifecycle:{prevent_destroy:true},depends_on:['google_project_service.'+n+'_registry']});
|
|
49
|
+
add('google_artifact_registry_repository_iam_member',n,{project:destination,location:region,repository:r('google_artifact_registry_repository',n,'name'),role:'roles/artifactregistry.reader',member:r('google_project_service_identity',n+'_run','member')});
|
|
50
|
+
add('google_secret_manager_secret',n+'_destination',{project:destination,secret_id:l('name')+'-accounting-token',replication:{user_managed:{replicas:{location:region}}},lifecycle:{prevent_destroy:true},depends_on:['google_project_service.'+n+'_secrets']});
|
|
51
|
+
add('google_secret_manager_secret_iam_member',n,{project:destination,secret_id:r('google_secret_manager_secret',n+'_destination','secret_id'),role:'roles/secretmanager.secretAccessor',member:member('worker')});
|
|
52
|
+
const common={PROJECT_ID:destination,PROJECT_NUMBER:number,REGION:region,ACCOUNT_ID:l('account_uuid'),WORKFLOW_NAMESPACE:'invoice',DATABASE_NAME:'invoice',DATABASE_CONNECTION_NAME:r('google_sql_database_instance',n,'connection_name'),DATABASE_TRANSPORT:'cloudsql-private-proxy',DOCUMENT_BUCKET:r('google_storage_bucket',n,'name'),DESTINATION_CONTRACT_BASE64:l('destination_contract_base64')};
|
|
53
|
+
for(const purpose of ['api','worker','parser']){
|
|
54
|
+
const name=l('name')+'-'+purpose;
|
|
55
|
+
const settings=purpose==='parser'?{}:purpose==='api'?{...common,SERVICE_NAME:name,PUBLIC_ORIGIN:l('public_origin'),DATABASE_SERVICE_ACCOUNT:sa('api','email')}:{...common,DATABASE_SERVICE_ACCOUNT:sa('worker','email'),PARSER_ENDPOINT:l('parser_endpoint'),PARSER_AUDIENCE:l('parser_origin'),MODEL_ID:model,MAX_OUTPUT_TOKENS:'2048',POLICY_REVIEW_BASE64:v('policy_review_base64'),DESTINATION_ENDPOINT:endpoint,DESTINATION_SCOPE:scope,DESTINATION_REPLAY_REVIEW_BASE64:v('replay_review_base64')};
|
|
56
|
+
const application={name:'application',image:v(purpose==='parser'?'parser_image':'runtime_image'),ports:{container_port:8080},resources:{limits:{cpu:'1',memory:purpose==='parser'?'2Gi':'1Gi'},cpu_idle:false,startup_cpu_boost:true},env:[...Object.entries(settings).map(([name,value])=>({name,value})),...(purpose==='worker'?[{name:'DESTINATION_TOKEN',value_source:{secret_key_ref:{secret:r('google_secret_manager_secret',n+'_destination','secret_id'),version:'latest'}}}]:[])],startup_probe:{http_get:{path:'/healthz',port:8080},initial_delay_seconds:0,period_seconds:5,timeout_seconds:2,failure_threshold:24},...(purpose==='api'?{}:{command:['python','-I','/app/'+(purpose==='worker'?'invoice_worker.py':'invoice_parser_service.py')]}),...(purpose==='parser'?{}:{depends_on:['cloud-sql-proxy']})};
|
|
57
|
+
const sidecar={name:'cloud-sql-proxy',image:proxy.image,args:['--private-ip','--address=127.0.0.1','--port=5432','--structured-logs',r('google_sql_database_instance',n,'connection_name')],resources:{limits:{cpu:'1',memory:'256Mi'},cpu_idle:false},startup_probe:{tcp_socket:{port:5432},period_seconds:5,timeout_seconds:2,failure_threshold:24}};
|
|
58
|
+
add('google_cloud_run_v2_service',n+'_'+purpose,{count:'${var.applications_enabled ? 1 : 0}',project:destination,name,location:region,deletion_protection:true,ingress:purpose==='worker'?'INGRESS_TRAFFIC_INTERNAL_ONLY':'INGRESS_TRAFFIC_ALL',iap_enabled:purpose==='api',invoker_iam_disabled:false,labels:{managed_by:'atmem-ai-architect',environment},template:{service_account:sa(purpose,'email'),execution_environment:'EXECUTION_ENVIRONMENT_GEN2',timeout:purpose==='parser'?'150s':'300s',max_instance_request_concurrency:purpose==='api'?32:purpose==='parser'?1:1,scaling:{min_instance_count:1,max_instance_count:1},containers:[application,...(purpose==='parser'?[]:[sidecar])],...(purpose==='parser'?{}:{vpc_access:{egress:'PRIVATE_RANGES_ONLY',network_interfaces:{network:r('google_compute_network',n,'name'),subnetwork:r('google_compute_subnetwork',n,'name')}}})},depends_on:['google_project_service.'+n+'_run','google_artifact_registry_repository_iam_member.'+n,'google_secret_manager_secret_iam_member.'+n,'google_project_iam_member.'+n+'_model','google_project_service_identity.'+n+'_iap',...(purpose==='parser'?[]:['google_sql_user.'+n+'_'+purpose,'google_project_iam_member.'+n+'_'+purpose+'_connect','google_project_iam_member.'+n+'_'+purpose+'_login'])]});
|
|
59
|
+
}
|
|
60
|
+
add('google_cloud_run_v2_service_iam_member',n+'_api',{count:'${var.applications_enabled ? 1 : 0}',project:destination,location:region,name:r('google_cloud_run_v2_service',n+'_api[0]','name'),role:'roles/run.invoker',member:r('google_project_service_identity',n+'_iap','member')});
|
|
61
|
+
add('google_cloud_run_v2_service_iam_member',n+'_parser',{count:'${var.applications_enabled ? 1 : 0}',project:destination,location:region,name:r('google_cloud_run_v2_service',n+'_parser[0]','name'),role:'roles/run.invoker',member:member('worker')});
|
|
62
|
+
add('google_iap_web_cloud_run_service_iam_member',n,{for_each:'${var.applications_enabled ? var.staff_principals : toset([])}',project:destination,location:region,cloud_run_service_name:l('name')+'-api',role:'roles/iap.httpsResourceAccessor',member:'${each.value}',depends_on:['google_cloud_run_v2_service.'+n+'_api']});
|
|
63
|
+
b.output.application_url={value:l('public_origin')};b.output.registry={value:region+'-docker.pkg.dev/'+destination+'/'+l('name')};
|
|
64
|
+
b.output.operator_deployment={value:{provider:'gcp',deploymentId:l('account_uuid'),accountId:l('account_uuid'),namespace:'invoice',tenantId:null,bindings:Object.fromEntries(['api','worker'].map(purpose=>[purpose,{name:'${trimsuffix(google_service_account.'+n+'_'+purpose+'.email,".gserviceaccount.com")}',principal:sa(purpose,'email'),created_by_package:true}]))}};
|
|
65
|
+
gcpInvoiceOperations(b,n,{destination,region,sa,member,proxy});
|
|
66
|
+
b.output.database_bootstrap={value:{connectionName:r('google_sql_database_instance',n,'connection_name'),database:'invoice',operatorServiceAccount:sa('ops','email'),operatorRole:'Intentional separate operator cloudsqlsuperuser; never an application identity.',proxyImage:proxy.image}};
|
|
67
|
+
b.files['CLOUD_SQL_PROXY_SECURITY_REVIEW.json']=JSON.stringify(proxyReview,null,2)+'\n';
|
|
68
|
+
b.files['CLOUD_SQL_PROXY.md']='Use the exact upstream proxy image '+proxy.image+' (version '+proxy.version+'). The maintained proxy enforces upstream TLS and private-IP connection; only same-instance 127.0.0.1:5432 is exposed to API/worker. No insecure native-host fallback or shared writable Unix volume is used. Cloud SQL client/login IAM is project-scoped; SQL identities/grants and the fixed proxy instance constrain the data connection. Native IAM/CA/connection and inherited permissions require authorized destination checks.\n';
|
|
69
|
+
b.files['CLOUD_SQL_PROXY.md']+='\nCLOUD_SQL_PROXY_SECURITY_REVIEW.json records the exact AMD64 image/binary review. Three module-version findings remain in inventory, but independent binary analysis plus an affected compiled control establishes that their vulnerable packages are absent from this artifact. This is scoped applicability evidence, not a blanket security approval. Repeat the review if the image or findings change.\n';
|
|
70
|
+
b.assertions.push(`run "private_database_and_identity" {\n command = plan\n assert {\n condition = !google_sql_database_instance.${n}.settings[0].ip_configuration[0].ipv4_enabled && google_sql_database_instance.${n}.settings[0].availability_type == "REGIONAL" && google_storage_bucket.${n}.public_access_prevention == "enforced"\n error_message = "Retain private database, regional recovery and nonpublic documents."\n }\n assert {\n condition = google_cloud_run_v2_service.${n}_api[0].iap_enabled && !google_cloud_run_v2_service.${n}_api[0].invoker_iam_disabled && google_cloud_run_v2_service_iam_member.${n}_parser[0].member == "serviceAccount:\${google_service_account.${n}_worker.email}"\n error_message = "Staff authentication and worker-only parser invocation are required."\n }\n}\nrun "private_proxy_and_worker_cpu" {\n command = plan\n assert {\n condition = google_cloud_run_v2_service.${n}_worker[0].template[0].containers[0].resources[0].cpu_idle == false && google_cloud_run_v2_service.${n}_worker[0].template[0].scaling[0].min_instance_count == 1 && contains(google_cloud_run_v2_service.${n}_worker[0].template[0].containers[1].args,"--private-ip") && contains(google_cloud_run_v2_service.${n}_worker[0].template[0].containers[1].args,"--address=127.0.0.1")\n error_message = "Keep worker CPU allocated and the maintained private-IP proxy scoped to loopback."\n }\n}\nrun "foundation_only" {\n command = plan\n variables {\n applications_enabled = false\n operations_enabled = false\n maintenance_enabled = false\n }\n assert {\n condition = length(google_cloud_run_v2_service.${n}_api) == 0 && length(google_cloud_run_v2_service.${n}_worker) == 0 && length(google_cloud_run_v2_service.${n}_parser) == 0\n error_message = "Bootstrap and publication precede application release."\n }\n}\nrun "mutable_image_rejected" {\n command = plan\n variables { runtime_image = "unreviewed:latest" }\n expect_failures = [var.runtime_image]\n}\nrun "foreign_registry_rejected" {\n command = plan\n variables { runtime_image = "foreign.example.test/runtime@sha256:${'a'.repeat(64)}" }\n expect_failures = [terraform_data.review_gate]\n}`);
|
|
71
|
+
const seed=b.seed;
|
|
72
|
+
for(const purpose of ['runtime','parser'])b.testExpressions[purpose+'_image']='format("'+(row.region||'australia-southeast1')+'-docker.pkg.dev/reviewed-project/invoice-%s/'+purpose+'@sha256:'+'a'.repeat(64)+'",substr(sha256('+JSON.stringify(seed)+'),0,12))';
|
|
73
|
+
let mock='mock_provider "google" {\n override_during = plan\n mock_data "google_project" { defaults={ number="123456789012" } }\n}\nmock_provider "google-beta" {\n override_during = plan\n mock_resource "google_project_service_identity" { defaults={ email="service-123456789012@gcp-sa-iap.iam.gserviceaccount.com",member="serviceAccount:service-123456789012@gcp-sa-iap.iam.gserviceaccount.com" } }\n}\n';
|
|
74
|
+
for(const purpose of ['api','worker','parser','ops','scheduler'])mock+='override_resource {\n override_during = plan\n target = google_service_account.'+n+'_'+purpose+'\n values = '+JSON.stringify({email:'invoice-'+purpose+'@reviewed-project.iam.gserviceaccount.com',member:'serviceAccount:invoice-'+purpose+'@reviewed-project.iam.gserviceaccount.com'})+'\n}\n';
|
|
75
|
+
for(const[purpose,email]of [['run','service-123456789012@serverless-robot-prod.iam.gserviceaccount.com'],['iap','service-123456789012@gcp-sa-iap.iam.gserviceaccount.com'],['scheduler','service-123456789012@gcp-sa-cloudscheduler.iam.gserviceaccount.com']])mock+='override_resource {\n override_during = plan\n target = google_project_service_identity.'+n+'_'+purpose+'\n values = '+JSON.stringify({email,member:'serviceAccount:'+email})+'\n}\n';
|
|
76
|
+
mock+='override_resource {\n override_during = plan\n target = google_sql_database_instance.'+n+'\n values = '+JSON.stringify({connection_name:'reviewed-project:australia-southeast1:invoice-fixture'})+'\n}\n';
|
|
77
|
+
return b.finish({google:{project:destination},'google-beta':{project:destination}},{google:{source:'hashicorp/google',version:'7.46.2'},'google-beta':{source:'hashicorp/google-beta',version:'7.46.2'}},CLOUD_PROVIDER_LOCKS.gcp+'\n'+CLOUD_PROVIDER_LOCKS.gcpBeta,mock,GCP_INVOICE_GUIDE);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const GCP_INVOICE_GUIDE=`# Google invoice workflow (under qualification)
|
|
81
|
+
|
|
82
|
+
Cloud Run/IAP API, continuously allocated private worker, separate IAM-protected
|
|
83
|
+
parser, maintained private-IP Cloud SQL Auth Proxy, regional HA IAM-authenticated
|
|
84
|
+
PostgreSQL, versioned private regional documents and separately populated regional
|
|
85
|
+
secret. Existing project, staff identities and accounting system are preserved.
|
|
86
|
+
|
|
87
|
+
The API receives no model/action authority. Only the worker invokes the parser;
|
|
88
|
+
the parser has no emitted data/model grants or database/proxy sidecar. The proxy's
|
|
89
|
+
local TCP connection stays inside the workload, with upstream TLS and IAM checked
|
|
90
|
+
by the pinned maintained proxy. No Cloud SQL public IP or plaintext remote fallback.
|
|
91
|
+
Application and worker SQL users receive explicit restricted bootstrap grants; the
|
|
92
|
+
separate operator IAM user intentionally has administrative SQL authority.
|
|
93
|
+
|
|
94
|
+
Review organization-owned IAP setup, actual model geography/lifecycle, privacy
|
|
95
|
+
policy evidence, inherited IAM and regional quotas/costs. Missing scoped model-policy
|
|
96
|
+
review blocks inference. The application never self-approves or modifies project
|
|
97
|
+
logging/cache/abuse policies. Native private connectivity, token roles and managed
|
|
98
|
+
restore still require destination checks. OPERATING_JOBS.md supplies fixed private
|
|
99
|
+
bootstrap, daily/hourly jobs, scoped OAuth scheduling and count-only log alerts.
|
|
100
|
+
The operator waits for and explicitly terminates its job-only proxy sidecar.
|
|
101
|
+
See OPERATIONS.md and CLOUD_SQL_PROXY.md; whole-project acceptance remains pending.
|
|
102
|
+
Native operator scheduling/bootstrap and whole-export qualification are unfinished;
|
|
103
|
+
this compiler fixture is not a complete benchmark project or deployment evidence.
|
|
104
|
+
`;
|