@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.
Files changed (512) hide show
  1. package/CONSTITUTION.md +144 -0
  2. package/LICENSE +202 -0
  3. package/NOTICE +6 -0
  4. package/README.md +31 -2
  5. package/agent-skills/discovery/SKILL.md +48 -0
  6. package/agent-skills/discovery/topics.json +139 -0
  7. package/agent-skills/generation-capabilities.json +760 -0
  8. package/agent-skills/service-lifecycle.json +21 -0
  9. package/agent-skills/specialists/architecture/SKILL.md +15 -0
  10. package/agent-skills/specialists/aws/SKILL.md +17 -0
  11. package/agent-skills/specialists/azure/SKILL.md +7 -0
  12. package/agent-skills/specialists/composition/SKILL.md +17 -0
  13. package/agent-skills/specialists/devops/SKILL.md +10 -0
  14. package/agent-skills/specialists/finops/SKILL.md +7 -0
  15. package/agent-skills/specialists/gcp/SKILL.md +7 -0
  16. package/agent-skills/specialists/ibm/SKILL.md +7 -0
  17. package/agent-skills/specialists/manifest.json +13 -0
  18. package/agent-skills/specialists/pulumi/SKILL.md +7 -0
  19. package/agent-skills/specialists/security/SKILL.md +7 -0
  20. package/agent-skills/specialists/terraform/SKILL.md +14 -0
  21. package/agent-skills/upstream/aws/LICENSE +175 -0
  22. package/agent-skills/upstream/aws/SKILL.md +125 -0
  23. package/agent-skills/upstream/azure/LICENSE +21 -0
  24. package/agent-skills/upstream/azure/SKILL.md +387 -0
  25. package/agent-skills/upstream/gcp/LICENSE +202 -0
  26. package/agent-skills/upstream/gcp/SKILL.md +159 -0
  27. package/agent-skills/upstream/manifest.json +57 -0
  28. package/agent-skills/upstream/pulumi/LICENSE +201 -0
  29. package/agent-skills/upstream/pulumi/SKILL.md +501 -0
  30. package/agent-skills/upstream/terraform/LICENSE +373 -0
  31. package/agent-skills/upstream/terraform/SKILL.md +316 -0
  32. package/agent-skills/workflows/workflows.json +601 -0
  33. package/cli/architect.mjs +3 -0
  34. package/cli/runtime.mjs +115 -0
  35. package/dist/assets/html2canvas.esm-QH1iLAAe.js +22 -0
  36. package/dist/assets/index-BTLHaa3J.css +1 -0
  37. package/dist/assets/index-CQ2C1gKF.js +21338 -0
  38. package/dist/assets/index.es-DTyqIdaO.js +18 -0
  39. package/dist/assets/purify.es-CAi2OJFm.js +3 -0
  40. package/dist/assets/visual-export-Ox0j5xj5.js +173 -0
  41. package/dist/favicon.svg +2 -0
  42. package/dist/fonts/DM-Sans-OFL.txt +93 -0
  43. package/dist/fonts/Manrope-OFL.txt +93 -0
  44. package/dist/fonts/NotoSans-Regular.ttf +0 -0
  45. package/dist/fonts/OFL.txt +94 -0
  46. package/dist/fonts/dm-sans-latin-wght-normal.woff2 +0 -0
  47. package/dist/fonts/manrope-latin-wght-normal.woff2 +0 -0
  48. package/dist/index.html +4 -0
  49. package/dist/licenses/atmem-APACHE-2.0.txt +202 -0
  50. package/dist/licenses/aws-architect-LICENSE.txt +17 -0
  51. package/dist/licenses/aws-mcp-LICENSE.txt +175 -0
  52. package/dist/licenses/aws-mcp-NOTICE.txt +1 -0
  53. package/dist/licenses/cloud-emulation-notices.txt +36619 -0
  54. package/dist/licenses/dependency-notices.txt +6379 -0
  55. package/dist/licenses/emulation-notices.txt +717 -0
  56. package/dist/licenses/github-copilot-sdk-LICENSE.txt +21 -0
  57. package/dist/licenses/memory-dependency-notices.txt +3319 -0
  58. package/dist/licenses/openarchflow-LICENSE.txt +21 -0
  59. package/dist/licenses/python-dependency-notices.txt +11951 -0
  60. package/docs/upstream-lock.json +26 -0
  61. package/knowledge/engineering-practices.json +536 -0
  62. package/package.json +30 -4
  63. package/packaging/uv-release-lock.json +54 -0
  64. package/public/licenses/atmem-APACHE-2.0.txt +202 -0
  65. package/public/licenses/aws-architect-LICENSE.txt +17 -0
  66. package/public/licenses/aws-mcp-LICENSE.txt +175 -0
  67. package/public/licenses/aws-mcp-NOTICE.txt +1 -0
  68. package/public/licenses/cloud-emulation-notices.txt +36619 -0
  69. package/public/licenses/dependency-notices.txt +6379 -0
  70. package/public/licenses/emulation-notices.txt +717 -0
  71. package/public/licenses/github-copilot-sdk-LICENSE.txt +21 -0
  72. package/public/licenses/memory-dependency-notices.txt +3319 -0
  73. package/public/licenses/openarchflow-LICENSE.txt +21 -0
  74. package/public/licenses/python-dependency-notices.txt +11951 -0
  75. package/scripts/terraform-render.mjs +8 -0
  76. package/server/__init__.py +0 -0
  77. package/server/abstraction.py +28 -0
  78. package/server/agent_runtime.py +153 -0
  79. package/server/app.py +257 -0
  80. package/server/architect.py +112 -0
  81. package/server/architecture_activity.py +67 -0
  82. package/server/attachments.py +101 -0
  83. package/server/cloud-emulation-requirements.txt +29 -0
  84. package/server/codex_app_server.py +219 -0
  85. package/server/codex_engineering_backend.py +266 -0
  86. package/server/codex_worker_policy.py +193 -0
  87. package/server/contracts.py +315 -0
  88. package/server/copilot_worker.py +16 -0
  89. package/server/dependency_mirror.py +54 -0
  90. package/server/design_patch.py +43 -0
  91. package/server/emulation-requirements.txt +8 -0
  92. package/server/emulation_adapters.py +20 -0
  93. package/server/emulation_routes.py +98 -0
  94. package/server/emulation_worker.py +351 -0
  95. package/server/engineering_artifacts.py +221 -0
  96. package/server/engineering_assets/application-runtime.json +4372 -0
  97. package/server/engineering_assets/architecture_work.schema.json +79 -0
  98. package/server/engineering_assets/materialize_runtime.py +62 -0
  99. package/server/engineering_assets/prepare_tools.py +96 -0
  100. package/server/engineering_assets/sql_validation.py +59 -0
  101. package/server/engineering_contexts.py +120 -0
  102. package/server/engineering_delivery.py +210 -0
  103. package/server/engineering_finalization.py +210 -0
  104. package/server/engineering_handoff.py +172 -0
  105. package/server/engineering_jobs.py +206 -0
  106. package/server/engineering_knowledge.py +75 -0
  107. package/server/engineering_reconciliation.py +159 -0
  108. package/server/engineering_routes.py +483 -0
  109. package/server/engineering_sessions.py +273 -0
  110. package/server/engineering_tools.py +166 -0
  111. package/server/generation_lint.py +18 -0
  112. package/server/local_providers.py +185 -0
  113. package/server/local_validation.py +236 -0
  114. package/server/memory-requirements.lock +181 -0
  115. package/server/memory-requirements.txt +6 -0
  116. package/server/memory_context.py +58 -0
  117. package/server/memory_routes.py +141 -0
  118. package/server/memory_service.py +306 -0
  119. package/server/memory_worker.py +129 -0
  120. package/server/openai_voice.py +80 -0
  121. package/server/orca_handoff.py +90 -0
  122. package/server/packaged_app.py +9 -0
  123. package/server/pricing.py +190 -0
  124. package/server/process_control_observation.py +31 -0
  125. package/server/prompts.py +136 -0
  126. package/server/public_faq_emulation_worker.py +44 -0
  127. package/server/requirements.lock +1618 -0
  128. package/server/requirements.txt +68 -0
  129. package/server/runtime_dependency_locks.py +27 -0
  130. package/server/runtime_evidence.py +93 -0
  131. package/server/settings.py +14 -0
  132. package/server/skills.py +103 -0
  133. package/server/storage_emulation_worker.py +160 -0
  134. package/server/structured_emulation_worker.py +48 -0
  135. package/server/terraform_routes.py +118 -0
  136. package/server/upstream/__init__.py +0 -0
  137. package/server/upstream/agent/__init__.py +1 -0
  138. package/server/upstream/agent/aws_architect.py +600 -0
  139. package/server/upstream/agent/config/__init__.py +1 -0
  140. package/server/upstream/agent/config/agent_config.py +82 -0
  141. package/server/upstream/agent/config/prompts.py +138 -0
  142. package/server/upstream/agent/rate_limiter.py +62 -0
  143. package/server/upstream/utils/__init__.py +1 -0
  144. package/server/upstream/utils/file_writer.py +43 -0
  145. package/server/validation_applicability.py +85 -0
  146. package/server/validation_jobs.py +252 -0
  147. package/server/validation_workers.py +48 -0
  148. package/server/voice_routes.py +91 -0
  149. package/server/voice_worker.py +26 -0
  150. package/server/windows_snapshot.py +119 -0
  151. package/specs/028-convergence-evaluation/evidence/20261110-ibm-invoice-native/registry-structured/qualification.json +72 -0
  152. package/specs/028-convergence-evaluation/evidence/20261110-invoice-runtime/durable-current/receipt.json +61 -0
  153. package/specs/029-general-purpose-engine/evidence/20261111-runtime-dependencies/sdk/receipt.json +22 -0
  154. package/src/ArchitectureActivity.jsx +54 -0
  155. package/src/ArchitectureWorkPanel.jsx +39 -0
  156. package/src/ArtifactChecks.jsx +49 -0
  157. package/src/BlockRequirements.jsx +13 -0
  158. package/src/BrainActivity.jsx +11 -0
  159. package/src/ChatMessage.jsx +29 -0
  160. package/src/ChatResizeHandle.jsx +6 -0
  161. package/src/CodePreview.jsx +8 -0
  162. package/src/ComponentReview.jsx +31 -0
  163. package/src/DeliveryViews.jsx +59 -0
  164. package/src/EmulationPanel.jsx +44 -0
  165. package/src/EngagementViews.jsx +387 -0
  166. package/src/EngineeringPanel.jsx +151 -0
  167. package/src/FileTree.jsx +7 -0
  168. package/src/FinalChecklist.jsx +15 -0
  169. package/src/HelpNote.jsx +3 -0
  170. package/src/ImplementationDelivery.jsx +91 -0
  171. package/src/JourneyViews.jsx +403 -0
  172. package/src/LocationChoices.jsx +12 -0
  173. package/src/MemoryPanel.jsx +58 -0
  174. package/src/OpenAIVoicePanel.jsx +66 -0
  175. package/src/OutputsView.jsx +71 -0
  176. package/src/ProjectChecks.jsx +44 -0
  177. package/src/TerraformView.jsx +57 -0
  178. package/src/WorkbenchDialogs.jsx +532 -0
  179. package/src/activity-presentation.mjs +28 -0
  180. package/src/ai-qualification-scenarios.mjs +31 -0
  181. package/src/approval-application-files.mjs +32 -0
  182. package/src/approval-applications.mjs +82 -0
  183. package/src/approval-spec-kit.mjs +30 -0
  184. package/src/architecture-activity.css +28 -0
  185. package/src/architecture-activity.mjs +63 -0
  186. package/src/architecture-work.mjs +176 -0
  187. package/src/artifact-work.mjs +103 -0
  188. package/src/async-documents.mjs +191 -0
  189. package/src/atflow.css +1140 -0
  190. package/src/atforma.css +748 -0
  191. package/src/atmem-tokens.css +79 -0
  192. package/src/aws-preflight.mjs +60 -0
  193. package/src/aws-public-faq.mjs +102 -0
  194. package/src/aws-validation-scenarios.mjs +10 -0
  195. package/src/aws-validation.mjs +48 -0
  196. package/src/azure-plan-mocks.mjs +25 -0
  197. package/src/azure-structured.mjs +133 -0
  198. package/src/bedrock-summary.mjs +152 -0
  199. package/src/bounded-rag.mjs +60 -0
  200. package/src/brand.css +9 -0
  201. package/src/canvas-view.mjs +28 -0
  202. package/src/capability-composition.mjs +44 -0
  203. package/src/chat-attachments.mjs +13 -0
  204. package/src/cloud-provider-locks.mjs +9 -0
  205. package/src/cloud-storage-scenarios.mjs +2 -0
  206. package/src/component-review.mjs +55 -0
  207. package/src/composition-spec-kit.mjs +30 -0
  208. package/src/consultation-context.mjs +15 -0
  209. package/src/consultation.mjs +52 -0
  210. package/src/container-contracts.mjs +5 -0
  211. package/src/container-inspection.mjs +75 -0
  212. package/src/container-runtime.mjs +30 -0
  213. package/src/container-security-inspection.mjs +49 -0
  214. package/src/container-terraform.mjs +109 -0
  215. package/src/conversation.mjs +18 -0
  216. package/src/core.mjs +863 -0
  217. package/src/cross-cloud-storage.mjs +100 -0
  218. package/src/delivery-capabilities.mjs +25 -0
  219. package/src/delivery.mjs +58 -0
  220. package/src/deployment-ownership.mjs +10 -0
  221. package/src/deployment-region.mjs +11 -0
  222. package/src/derive.mjs +31 -0
  223. package/src/design-build-flow.mjs +10 -0
  224. package/src/diagram-attention.mjs +24 -0
  225. package/src/discovery.mjs +359 -0
  226. package/src/document.mjs +170 -0
  227. package/src/emulation-feedback.mjs +61 -0
  228. package/src/emulation-guidance.mjs +37 -0
  229. package/src/engagement.mjs +274 -0
  230. package/src/engineering-client.mjs +73 -0
  231. package/src/engineering-defaults.mjs +17 -0
  232. package/src/engineering.css +31 -0
  233. package/src/enterprise-application.mjs +76 -0
  234. package/src/enterprise-aws-host-infrastructure.mjs +62 -0
  235. package/src/enterprise-aws-host-tests.mjs +15 -0
  236. package/src/enterprise-aws-infrastructure-tests.mjs +38 -0
  237. package/src/enterprise-aws-infrastructure.mjs +138 -0
  238. package/src/enterprise-google-infrastructure.mjs +84 -0
  239. package/src/enterprise-google-tests.mjs +25 -0
  240. package/src/estimate.mjs +190 -0
  241. package/src/existing-references.mjs +18 -0
  242. package/src/external-identities.mjs +17 -0
  243. package/src/faq-lambda-build.mjs +28 -0
  244. package/src/final-package.mjs +34 -0
  245. package/src/gcp-structured.mjs +104 -0
  246. package/src/generation-provider.mjs +7 -0
  247. package/src/generation-quality.mjs +69 -0
  248. package/src/handoff.mjs +141 -0
  249. package/src/ibm-registry.mjs +12 -0
  250. package/src/ibm-structured.mjs +103 -0
  251. package/src/identifiers.mjs +15 -0
  252. package/src/implementation-map.mjs +14 -0
  253. package/src/implementation-outcome.mjs +8 -0
  254. package/src/incomplete-terraform.mjs +9 -0
  255. package/src/integrations.ts +137 -0
  256. package/src/interface-contracts.mjs +30 -0
  257. package/src/invoice-application.mjs +66 -0
  258. package/src/invoice-aws-operations.mjs +136 -0
  259. package/src/invoice-aws.mjs +143 -0
  260. package/src/invoice-azure-operations.mjs +147 -0
  261. package/src/invoice-azure.mjs +134 -0
  262. package/src/invoice-builder.mjs +35 -0
  263. package/src/invoice-dependencies.mjs +43 -0
  264. package/src/invoice-gcp-operations.mjs +178 -0
  265. package/src/invoice-gcp.mjs +104 -0
  266. package/src/invoice-ibm-operations.mjs +278 -0
  267. package/src/invoice-ibm.mjs +142 -0
  268. package/src/invoice-operations.mjs +143 -0
  269. package/src/invoice-plan.mjs +45 -0
  270. package/src/invoice-region.mjs +6 -0
  271. package/src/invoice-spec-kit.mjs +61 -0
  272. package/src/invoice-state.mjs +7 -0
  273. package/src/invoice-terraform.mjs +29 -0
  274. package/src/invoice-tests.mjs +122 -0
  275. package/src/journey-workspace.css +106 -0
  276. package/src/journey.mjs +97 -0
  277. package/src/levels.mjs +145 -0
  278. package/src/local-agent.mjs +184 -0
  279. package/src/main.jsx +2481 -0
  280. package/src/model-policy-preflight.mjs +34 -0
  281. package/src/openai-voice.mjs +102 -0
  282. package/src/output-bundle.mjs +13 -0
  283. package/src/ownership-inspection.mjs +28 -0
  284. package/src/pack.mjs +201 -0
  285. package/src/pricing.mjs +85 -0
  286. package/src/production-state.mjs +8 -0
  287. package/src/project-copy.mjs +10 -0
  288. package/src/project-file.mjs +160 -0
  289. package/src/project-links.mjs +3 -0
  290. package/src/protected-state.mjs +43 -0
  291. package/src/public-faq-builder.mjs +19 -0
  292. package/src/public-faq-clouds.mjs +251 -0
  293. package/src/public-faq.mjs +122 -0
  294. package/src/pulumi.mjs +123 -0
  295. package/src/python-container.mjs +25 -0
  296. package/src/python-runtime.mjs +50 -0
  297. package/src/rag-handler.mjs +43 -0
  298. package/src/rag-web-assets.mjs +52 -0
  299. package/src/rag-web.mjs +68 -0
  300. package/src/records.mjs +177 -0
  301. package/src/resources.mjs +163 -0
  302. package/src/review.mjs +252 -0
  303. package/src/runtime/EnterpriseDocument.java +89 -0
  304. package/src/runtime/approved_http_destination.py +72 -0
  305. package/src/runtime/aws-lambda-qualification-lock.json +7 -0
  306. package/src/runtime/aws-python-lock.json +82 -0
  307. package/src/runtime/aws-web-python-lock.json +887 -0
  308. package/src/runtime/aws_json_model.py +42 -0
  309. package/src/runtime/azure-python-lock.json +863 -0
  310. package/src/runtime/azure-sources.json +8 -0
  311. package/src/runtime/azure-test-lock.json +23 -0
  312. package/src/runtime/azure_acceptance.py +192 -0
  313. package/src/runtime/azure_structured.py +153 -0
  314. package/src/runtime/bounded_rag.py +126 -0
  315. package/src/runtime/catalog_admin.py +70 -0
  316. package/src/runtime/cloud-sql-proxy-lock.json +8 -0
  317. package/src/runtime/cloud-sql-proxy-security-review.json +30 -0
  318. package/src/runtime/connector_cli.py +50 -0
  319. package/src/runtime/connector_sync.py +70 -0
  320. package/src/runtime/durable-python-lock.json +247 -0
  321. package/src/runtime/durable_workflow.py +325 -0
  322. package/src/runtime/enterprise-application-manifest.json +110 -0
  323. package/src/runtime/enterprise-application-sources.json +266 -0
  324. package/src/runtime/enterprise-auth-python-lock.json +592 -0
  325. package/src/runtime/enterprise-aws-host-bootstrap-source.json +1 -0
  326. package/src/runtime/enterprise-aws-host-probe-source.json +1 -0
  327. package/src/runtime/enterprise-aws-task-template.json +235 -0
  328. package/src/runtime/enterprise-document-lock.json +18 -0
  329. package/src/runtime/enterprise-document.Dockerfile +15 -0
  330. package/src/runtime/enterprise-runtime-aws-python-lock.json +1115 -0
  331. package/src/runtime/enterprise-runtime-azure-python-lock.json +1106 -0
  332. package/src/runtime/enterprise-runtime-gcp-python-lock.json +1060 -0
  333. package/src/runtime/enterprise-runtime-ibm-python-lock.json +1096 -0
  334. package/src/runtime/enterprise-runtime-python-lock.json +1058 -0
  335. package/src/runtime/enterprise-runtime.Dockerfile +15 -0
  336. package/src/runtime/enterprise-web-app.js +1 -0
  337. package/src/runtime/enterprise-web-entry.js +105 -0
  338. package/src/runtime/enterprise-web-lock.json +29 -0
  339. package/src/runtime/enterprise-web-notices.txt +229 -0
  340. package/src/runtime/enterprise-web.css +4 -0
  341. package/src/runtime/enterprise-web.html +8 -0
  342. package/src/runtime/enterprise_audit.py +91 -0
  343. package/src/runtime/enterprise_audit_schema.sql +25 -0
  344. package/src/runtime/enterprise_auth_schema.sql +67 -0
  345. package/src/runtime/enterprise_auth_store.py +241 -0
  346. package/src/runtime/enterprise_aws_host_bootstrap.py +120 -0
  347. package/src/runtime/enterprise_aws_host_probe.py +105 -0
  348. package/src/runtime/enterprise_aws_hosts.py +136 -0
  349. package/src/runtime/enterprise_aws_jobs.py +300 -0
  350. package/src/runtime/enterprise_aws_objects.py +93 -0
  351. package/src/runtime/enterprise_aws_transfer.py +83 -0
  352. package/src/runtime/enterprise_azure_batch_api.py +128 -0
  353. package/src/runtime/enterprise_azure_host.py +599 -0
  354. package/src/runtime/enterprise_azure_jobs.py +294 -0
  355. package/src/runtime/enterprise_azure_objects.py +234 -0
  356. package/src/runtime/enterprise_azure_pool.py +161 -0
  357. package/src/runtime/enterprise_azure_transfer.py +122 -0
  358. package/src/runtime/enterprise_configuration.py +136 -0
  359. package/src/runtime/enterprise_document.py +116 -0
  360. package/src/runtime/enterprise_document_cli.py +32 -0
  361. package/src/runtime/enterprise_document_contract.py +54 -0
  362. package/src/runtime/enterprise_document_job.py +109 -0
  363. package/src/runtime/enterprise_document_jobs.py +122 -0
  364. package/src/runtime/enterprise_document_jobs_schema.sql +23 -0
  365. package/src/runtime/enterprise_extraction_cache.py +186 -0
  366. package/src/runtime/enterprise_extraction_schema.sql +17 -0
  367. package/src/runtime/enterprise_google_jobs.py +275 -0
  368. package/src/runtime/enterprise_google_transfer.py +85 -0
  369. package/src/runtime/enterprise_http.py +212 -0
  370. package/src/runtime/enterprise_identity.py +52 -0
  371. package/src/runtime/enterprise_knowledge.py +152 -0
  372. package/src/runtime/enterprise_models.py +94 -0
  373. package/src/runtime/enterprise_native.py +181 -0
  374. package/src/runtime/enterprise_oauth.py +132 -0
  375. package/src/runtime/enterprise_operator.py +160 -0
  376. package/src/runtime/enterprise_parser_service.py +136 -0
  377. package/src/runtime/enterprise_parser_transport.py +68 -0
  378. package/src/runtime/enterprise_queries.py +255 -0
  379. package/src/runtime/enterprise_queries_schema.sql +27 -0
  380. package/src/runtime/enterprise_query_service.py +111 -0
  381. package/src/runtime/enterprise_secrets.py +110 -0
  382. package/src/runtime/enterprise_sessions.py +95 -0
  383. package/src/runtime/enterprise_sources.py +260 -0
  384. package/src/runtime/enterprise_web.py +39 -0
  385. package/src/runtime/enterprise_worker.py +68 -0
  386. package/src/runtime/export_contract_acceptance.py +18 -0
  387. package/src/runtime/faq-output-contract.json +40 -0
  388. package/src/runtime/faq-web-app.js +41 -0
  389. package/src/runtime/faq-web.css +1 -0
  390. package/src/runtime/faq-web.html +6 -0
  391. package/src/runtime/gcp-sources.json +9 -0
  392. package/src/runtime/gcp_acceptance.py +110 -0
  393. package/src/runtime/gcp_structured.py +150 -0
  394. package/src/runtime/http_acceptance.py +39 -0
  395. package/src/runtime/iap-web-app.js +36 -0
  396. package/src/runtime/iap-web-source.json +1 -0
  397. package/src/runtime/ibm-python-lock.json +856 -0
  398. package/src/runtime/ibm-sources.json +9 -0
  399. package/src/runtime/ibm_acceptance.py +133 -0
  400. package/src/runtime/ibm_structured.py +113 -0
  401. package/src/runtime/invoice-azapi-provider-lock.json +7 -0
  402. package/src/runtime/invoice-ibm-provider-lock.json +7 -0
  403. package/src/runtime/invoice-parser-lock.json +1199 -0
  404. package/src/runtime/invoice-parser-python-lock.json +56 -0
  405. package/src/runtime/invoice-parser.Dockerfile +190 -0
  406. package/src/runtime/invoice-sources.json +58 -0
  407. package/src/runtime/invoice-test-sources.json +24 -0
  408. package/src/runtime/invoice-web.css +2 -0
  409. package/src/runtime/invoice-web.html +12 -0
  410. package/src/runtime/invoice-web.js +112 -0
  411. package/src/runtime/invoice_configuration.py +17 -0
  412. package/src/runtime/invoice_document.py +95 -0
  413. package/src/runtime/invoice_extraction.py +96 -0
  414. package/src/runtime/invoice_http.py +129 -0
  415. package/src/runtime/invoice_identity.py +5 -0
  416. package/src/runtime/invoice_maintenance.py +40 -0
  417. package/src/runtime/invoice_native.py +77 -0
  418. package/src/runtime/invoice_object_store.py +153 -0
  419. package/src/runtime/invoice_operations.py +108 -0
  420. package/src/runtime/invoice_operator.py +79 -0
  421. package/src/runtime/invoice_operator_core.py +39 -0
  422. package/src/runtime/invoice_operator_job.py +147 -0
  423. package/src/runtime/invoice_parser_cli.py +17 -0
  424. package/src/runtime/invoice_parser_identity.py +39 -0
  425. package/src/runtime/invoice_parser_service.py +89 -0
  426. package/src/runtime/invoice_parser_transport.py +89 -0
  427. package/src/runtime/invoice_processing.py +24 -0
  428. package/src/runtime/invoice_retention.py +16 -0
  429. package/src/runtime/invoice_runtime_secrets.py +43 -0
  430. package/src/runtime/invoice_stage.py +80 -0
  431. package/src/runtime/invoice_web.py +39 -0
  432. package/src/runtime/invoice_worker.py +50 -0
  433. package/src/runtime/lambda_faq.py +5 -0
  434. package/src/runtime/parser-requirements.lock +4 -0
  435. package/src/runtime/policy_review.py +18 -0
  436. package/src/runtime/postgres-qualification-lock.json +21 -0
  437. package/src/runtime/public-faq-sources.json +22 -0
  438. package/src/runtime/public_catalog_admin.py +122 -0
  439. package/src/runtime/public_catalog_store.py +125 -0
  440. package/src/runtime/public_faq.py +144 -0
  441. package/src/runtime/public_faq_app.py +49 -0
  442. package/src/runtime/python-container-lock.json +18 -0
  443. package/src/runtime/rag-sources.json +10 -0
  444. package/src/runtime/rag_acceptance.py +60 -0
  445. package/src/runtime/rag_aws_adapter.py +95 -0
  446. package/src/runtime/rds-ca-source.json +9 -0
  447. package/src/runtime/rds-global-ca.pem +2888 -0
  448. package/src/runtime/state-contract-check-source.json +4 -0
  449. package/src/runtime/state_contract_check.py +338 -0
  450. package/src/runtime/structured-source.json +1 -0
  451. package/src/runtime/structured-web-app.js +71 -0
  452. package/src/runtime/structured-web-source.json +1 -0
  453. package/src/runtime/structured_http.py +105 -0
  454. package/src/runtime/structured_output.py +48 -0
  455. package/src/runtime/web-python-lock.json +802 -0
  456. package/src/runtime/web_user_admin.py +44 -0
  457. package/src/runtime/workflow_application.py +62 -0
  458. package/src/runtime/workflow_bindings.py +128 -0
  459. package/src/runtime/workflow_configuration.py +40 -0
  460. package/src/runtime/workflow_connection.py +105 -0
  461. package/src/runtime/workflow_contract.py +54 -0
  462. package/src/runtime/workflow_database.py +94 -0
  463. package/src/runtime/workflow_errors.py +6 -0
  464. package/src/runtime/workflow_http.py +178 -0
  465. package/src/runtime/workflow_identity.py +69 -0
  466. package/src/runtime/workflow_payload.py +118 -0
  467. package/src/runtime/workflow_process_stage.py +88 -0
  468. package/src/runtime/workflow_profile.py +91 -0
  469. package/src/runtime/workflow_review.py +106 -0
  470. package/src/runtime/workflow_role_bootstrap.py +104 -0
  471. package/src/runtime/workflow_schema.sql +72 -0
  472. package/src/runtime/workflow_worker.py +142 -0
  473. package/src/runtime-settings.mjs +15 -0
  474. package/src/s3-access.mjs +14 -0
  475. package/src/source-contracts.mjs +17 -0
  476. package/src/spec-kit.mjs +186 -0
  477. package/src/state-custody.mjs +32 -0
  478. package/src/state-inspection.mjs +45 -0
  479. package/src/state-spec-kit.mjs +13 -0
  480. package/src/storage-tests.mjs +25 -0
  481. package/src/structured-api.mjs +133 -0
  482. package/src/structured-contract.mjs +19 -0
  483. package/src/structured-operation-policy.mjs +2 -0
  484. package/src/structured-web.mjs +17 -0
  485. package/src/style.css +1 -0
  486. package/src/system-description.mjs +26 -0
  487. package/src/terraform-admission.mjs +66 -0
  488. package/src/terraform-composition.mjs +83 -0
  489. package/src/terraform-expressions.mjs +46 -0
  490. package/src/terraform-validation-coverage.mjs +11 -0
  491. package/src/terraform.mjs +128 -0
  492. package/src/text-statistics.mjs +51 -0
  493. package/src/upstream/openarchflow/format-payload.ts +26 -0
  494. package/src/upstream/openarchflow/import/mermaid.ts +205 -0
  495. package/src/upstream/openarchflow/import/sql-ddl.ts +109 -0
  496. package/src/upstream/openarchflow/layout.ts +54 -0
  497. package/src/upstream/openarchflow/providers/aws.ts +196 -0
  498. package/src/upstream/openarchflow/providers/azure.ts +126 -0
  499. package/src/upstream/openarchflow/providers/cloudnative.ts +71 -0
  500. package/src/upstream/openarchflow/providers/generic.ts +227 -0
  501. package/src/upstream/openarchflow/providers/integration.ts +22 -0
  502. package/src/upstream/openarchflow/providers/types.ts +2 -0
  503. package/src/upstream/openarchflow/templates.ts +937 -0
  504. package/src/upstream-catalog.mjs +10 -0
  505. package/src/useChatScroll.jsx +37 -0
  506. package/src/useEmulation.jsx +36 -0
  507. package/src/useEngineeringStatus.mjs +17 -0
  508. package/src/validation-receipt.mjs +10 -0
  509. package/src/visual-export.mjs +92 -0
  510. package/src/voice-conversation.mjs +117 -0
  511. package/src/work-intake.mjs +24 -0
  512. package/src/workflow-runtime-inventory.mjs +3 -0
@@ -0,0 +1,160 @@
1
+ import {approvalProfiles} from './approval-applications.mjs';
2
+ import {validateArchitectureWork} from './architecture-work.mjs';
3
+ import {validateStateCustody} from './state-custody.mjs';
4
+ import {validateExternalReferences} from './external-identities.mjs';
5
+ // The durable project file: atforma.project 2.0.0. See specs/002-project-model.
6
+ import { validateImport } from "./core.mjs";
7
+
8
+ export const FORMAT = "atmem.ai-architect.project";
9
+ export const FORMAT_VERSION = "2.3.0";
10
+ export const APPROVAL_FORMAT_VERSION = "3.0.0";
11
+ const approvalFormat=nodes=>Array.isArray(nodes)&&nodes.some(n=>n.data?.implementation==='approval-workflow'||n.data?.approvalProfile!=null);
12
+ export const MAX_FILE_BYTES = 2_000_000;
13
+ const GENERATOR = "atmem-ai-architect 0.2.0";
14
+
15
+ // Section keys the 2.0 reader understands; anything else is kept in extensions.
16
+ const KNOWN_TOP = ["format", "formatVersion", "meta", "design", "discovery", "requirements", "assumptions", "openQuestions", "decisions", "options", "estimate", "review", "extensions"];
17
+ const KNOWN = {
18
+ meta: ["id", "name", "createdAt", "updatedAt", "revision", "generator", "domain"],
19
+ design: ["provider", "nodes", "edges"],
20
+ discovery: ["problem", "brief", "useCases", "gate", "facts", "workflow", "asked", "lastAsked", "sketchOffered"],
21
+ review: ["accepted"],
22
+ };
23
+
24
+ const SECRET_VALUE = [
25
+ /AKIA[0-9A-Z]{16}/,
26
+ /sk-ant-[A-Za-z0-9_-]{20,}/,
27
+ /sk-[A-Za-z0-9_-]{20,}/,
28
+ /AIza[0-9A-Za-z_-]{35}/,
29
+ /ghp_[A-Za-z0-9]{36}/,
30
+ /-----BEGIN [A-Z ]*PRIVATE KEY-----/,
31
+ ];
32
+ const SECRET_KEY = /^(password|secret|apiKey|api_key|accessKey|access_key|token|clientSecret|client_secret)$/i;
33
+
34
+ // Paths of values that look like credentials.
35
+ export function findCredentials(value, path = "") {
36
+ if (typeof value === "string") return SECRET_VALUE.some((re) => re.test(value)) ? [path || "(root)"] : [];
37
+ if (Array.isArray(value)) return value.flatMap((v, i) => findCredentials(v, `${path}[${i}]`));
38
+ if (value && typeof value === "object")
39
+ return Object.entries(value).flatMap(([k, v]) => {
40
+ const at = path ? `${path}.${k}` : k;
41
+ if (SECRET_KEY.test(k) && typeof v === "string" && v.trim()) return [at];
42
+ return findCredentials(v, at);
43
+ });
44
+ return [];
45
+ }
46
+
47
+ function refuseCredentials(value, verb) {
48
+ const found = findCredentials(value);
49
+ if (found.length)
50
+ throw Error(`${verb} refused: ${found.slice(0, 3).join(", ")}${found.length > 3 ? "…" : ""} looks like a credential. Remove it and try again.`);
51
+ }
52
+
53
+ function unknown(section, allowed) {
54
+ return Object.fromEntries(Object.entries(section || {}).filter(([k]) => !allowed.includes(k)));
55
+ }
56
+
57
+ export function toProjectFile(project, now = new Date()) {
58
+ validateStateCustody(project.extensions?.terraformState);
59
+ validateExternalReferences(project);
60
+ approvalProfiles(project);
61
+ const {
62
+ version, revision, name, provider, domain, requirements, nodes, edges,
63
+ brief, useCases, gate, needs, assumptions, openQuestions, decisions, assessment,
64
+ facts, workflow, asked, lastAsked, sketchOffered, estimate, reviewAccepted,
65
+ id, createdAt, extensions, importReport, ...rest
66
+ } = project;
67
+ const file = {
68
+ format: FORMAT,
69
+ formatVersion: approvalFormat(nodes)?APPROVAL_FORMAT_VERSION:FORMAT_VERSION,
70
+ meta: {
71
+ id: id || crypto.randomUUID(),
72
+ name,
73
+ createdAt: createdAt || now.toISOString(),
74
+ updatedAt: now.toISOString(),
75
+ revision,
76
+ generator: GENERATOR,
77
+ ...(domain ? { domain } : {}),
78
+ },
79
+ design: { provider: provider || "tools", nodes, edges },
80
+ discovery: {
81
+ problem: requirements || "",
82
+ ...(brief ? { brief } : {}),
83
+ ...(useCases ? { useCases } : {}),
84
+ ...(gate ? { gate } : {}),
85
+ ...(facts ? { facts } : {}),
86
+ ...(workflow ? { workflow } : {}),
87
+ ...(asked ? { asked } : {}),
88
+ ...(lastAsked ? { lastAsked } : {}),
89
+ ...(sketchOffered ? { sketchOffered } : {}),
90
+ },
91
+ requirements: needs || [],
92
+ assumptions: assumptions || [],
93
+ openQuestions: openQuestions || [],
94
+ decisions: decisions || [],
95
+ ...(assessment ? { options: assessment } : {}),
96
+ ...(estimate ? { estimate } : {}),
97
+ ...(reviewAccepted ? { review: { accepted: reviewAccepted } } : {}),
98
+ // Browser-only fields the file format doesn't name yet are preserved, not dropped.
99
+ extensions: { ...(extensions || {}), ...rest },
100
+ };
101
+ if(file.extensions.architectureWork!==undefined)validateArchitectureWork(file.extensions.architectureWork);
102
+ refuseCredentials(file, "Export");
103
+ if(new TextEncoder().encode(JSON.stringify(file)).length>MAX_FILE_BYTES)throw Error("Project files must be 2 MB or smaller; no content was truncated.");
104
+ return file;
105
+ }
106
+
107
+ // Returns the browser project plus what happened, so the UI can say so.
108
+ export function fromProjectFile(raw) {
109
+ if (!raw || typeof raw !== "object") throw Error("Not a project file.");
110
+ refuseCredentials(raw, "Import");
111
+ if (raw.format === undefined && raw.version === 1)
112
+ return { project: validateImport(raw), migrated: true, from: "workbench v1" };
113
+ if (![FORMAT,"atforma.project"].includes(raw.format)) throw Error("Not an AtMem AI Architect project file.");
114
+ const [major] = String(raw.formatVersion || "").split(".").map(Number);
115
+ if (major !== 2 && !(raw.formatVersion===APPROVAL_FORMAT_VERSION&&approvalFormat(raw.design?.nodes)))
116
+ throw Error(`This file is format ${raw.formatVersion}; this version of AtMem AI Architect reads ${FORMAT_VERSION}. Update AtMem AI Architect to open it.`);
117
+ const meta = raw.meta || {},
118
+ design = raw.design || {},
119
+ discovery = raw.discovery || {};
120
+ const extensions = {
121
+ ...(raw.extensions || {}),
122
+ ...unknown(raw, KNOWN_TOP),
123
+ ...Object.fromEntries(
124
+ Object.entries(KNOWN)
125
+ .map(([section, allowed]) => [section, unknown(raw[section], allowed)])
126
+ .filter(([, extra]) => Object.keys(extra).length)
127
+ .map(([section, extra]) => [`${section}.extra`, extra]),
128
+ ),
129
+ };
130
+ const project = validateImport({
131
+ version: 1,
132
+ revision: meta.revision,
133
+ name: meta.name,
134
+ provider: design.provider,
135
+ ...(meta.domain ? { domain: meta.domain } : {}),
136
+ id: meta.id,
137
+ createdAt: meta.createdAt,
138
+ requirements: discovery.problem || "",
139
+ nodes: design.nodes,
140
+ edges: design.edges,
141
+ ...(discovery.brief ? { brief: discovery.brief } : {}),
142
+ ...(discovery.useCases ? { useCases: discovery.useCases } : {}),
143
+ ...(discovery.gate ? { gate: discovery.gate } : {}),
144
+ ...Object.fromEntries(["facts", "workflow", "asked", "lastAsked", "sketchOffered"].filter((k) => discovery[k] !== undefined).map((k) => [k, discovery[k]])),
145
+ ...(raw.estimate ? { estimate: raw.estimate } : {}),
146
+ ...(raw.review?.accepted ? { reviewAccepted: raw.review.accepted } : {}),
147
+ needs: raw.requirements || [],
148
+ assumptions: raw.assumptions || [],
149
+ openQuestions: raw.openQuestions || [],
150
+ decisions: raw.decisions || [],
151
+ ...(raw.options ? { assessment: raw.options } : {}),
152
+ ...(Object.keys(extensions).length ? { extensions } : {}),
153
+ });
154
+ return { project, migrated: raw.format !== FORMAT || raw.formatVersion !== (approvalFormat(project.nodes)?APPROVAL_FORMAT_VERSION:FORMAT_VERSION), from: raw.formatVersion };
155
+ }
156
+
157
+ export function parseProjectFile(textContent) {
158
+ if (new TextEncoder().encode(textContent).length > MAX_FILE_BYTES) throw Error("Project files must be 2 MB or smaller.");
159
+ return fromProjectFile(JSON.parse(textContent));
160
+ }
@@ -0,0 +1,3 @@
1
+ export function projectIdFromUrl(value){
2
+ try{const id=new URL(value).searchParams.get('project');return id&&/^[A-Za-z0-9-]{8,64}$/.test(id)?id:null;}catch{return null;}
3
+ }
@@ -0,0 +1,43 @@
1
+ const definitions={
2
+ s3:{type:'s3',settings:{encrypt:true,use_lockfile:true},example:'bucket = "REVIEWED_PROTECTED_STATE_BUCKET"\nkey = "REVIEWED_PROJECT/production.tfstate"\nregion = "REVIEWED_STATE_REGION"\n',guide:'Use a separate private, encrypted, versioned S3 state bucket under the accepted custody/residency boundary. Terraform 1.17 uses native S3 lock files (use_lockfile=true), not an invented DynamoDB dependency. Restrict ListBucket to the project prefix and GetObject/PutObject to its state key; the corresponding .tflock also needs DeleteObject. Do not grant state DeleteObject merely for locking. Use the standard authorized AWS credential chain, never backend access_key/secret_key values.',source:'https://developer.hashicorp.com/terraform/language/backend/s3'},
3
+ azurerm:{type:'azurerm',settings:{use_azuread_auth:true},example:'storage_account_name = "REVIEWED_PRIVATE_STATE_ACCOUNT"\ncontainer_name = "REVIEWED_STATE_CONTAINER"\nkey = "REVIEWED_PROJECT/production.tfstate"\ntenant_id = "REVIEWED_DIRECTORY_TENANT_UUID"\nsubscription_id = "REVIEWED_STATE_SUBSCRIPTION_UUID"\n',guide:'Use a separate reviewed private Azure Blob state container with versioning/recovery and the accepted residency. Native Blob leases implement state locking. use_azuread_auth=true uses Entra data-plane authentication; grant only reviewed container-scoped state access. Configure the approved Azure CLI, managed identity or workload federation through its documented environment chain; do not export storage account keys, SAS tokens or client secrets into backend.hcl. Verify the exact state subscription/tenant and effective inherited rights independently.',source:'https://developer.hashicorp.com/terraform/language/backend/azurerm'},
4
+ gcs:{type:'gcs',settings:{},example:'bucket = "REVIEWED_PRIVATE_VERSIONED_STATE_BUCKET"\nprefix = "REVIEWED_PROJECT/production"\n',guide:'Use a separately bootstrapped private, versioned GCS state bucket under the reviewed project/custody/residency boundary. Terraform supports native state locking. Give the authorized state operator scoped object access, preserving unrelated bucket IAM; use the reviewed Google credential/workload-identity chain, never an embedded service-account key. Review encryption/key ownership, inherited grants, version recovery and the exact project/bucket/prefix. The state bucket is not the invoice originals bucket.',source:'https://developer.hashicorp.com/terraform/language/backend/gcs'},
5
+ http:{type:'http',settings:{},example:'address = "https://REVIEWED_PRIVATE_STATE_SERVICE/EXACT_PROJECT_PRODUCTION_STATE"\nlock_address = "https://REVIEWED_PRIVATE_STATE_SERVICE/EXACT_PROJECT_PRODUCTION_STATE/lock"\nunlock_address = "https://REVIEWED_PRIVATE_STATE_SERVICE/EXACT_PROJECT_PRODUCTION_STATE/lock"\nlock_method = "POST"\nunlock_method = "DELETE"\nretry_wait_min = 5\n',guide:'Use the existing reviewed private platform state service implementing Terraform HTTP state and lock/unlock semantics, not a generic object URL or an unverified S3-compatible IBM COS lock assumption. The example selects POST/DELETE locking; verify the actual platform protocol and owner-safe lock behavior before use. Keep the service in the accepted custody/residency boundary. Configure TF_HTTP_USERNAME/TF_HTTP_PASSWORD or reviewed mutual-TLS environment credentials, never credentials in backend.hcl. No state platform is deployed by this module.',source:'https://developer.hashicorp.com/terraform/language/backend/http'}
6
+ };
7
+
8
+ export const PROTECTED_BACKENDS=Object.freeze(Object.keys(definitions));
9
+ export function protectedState(backendType,{title='Terraform state and environment ownership',environment='production'}={}){
10
+ const definition=definitions[backendType];if(!definition)throw Error('Choose an explicit supported state backend; no target-provider fallback.');
11
+ if(!['staging','production','qualification'].includes(environment))throw Error('Use an explicit supported state environment.');
12
+ return {backend:{[definition.type]:structuredClone(definition.settings)},files:{'backend.hcl.example':definition.example.replaceAll('production',environment).replaceAll('PRODUCTION',environment.toUpperCase()),'STATE.md':'# '+title+'\n\nSelected backend contract: '+definition.type+'.\n\n'+definition.guide.replace('invoice originals bucket','application data bucket')+'\n\n'+COMMON+'\nReference: '+definition.source+'\n'}};
13
+ }
14
+
15
+ const COMMON=`Staging/qualification default to local state only for isolated local validation.
16
+ Production declares the provider-specific protected backend with no account names,
17
+ endpoints or credentials embedded. The existing state store is a separate platform
18
+ prerequisite, not an application resource. If the destination repository
19
+ already has another reviewed backend, preserve it through an explicit state/owner
20
+ decision and validate compatibility before any authorized migration.
21
+
22
+ Keep backend.hcl private and excluded from source. Do not put authentication values
23
+ in configuration or command arguments: Terraform can retain backend arguments in
24
+ its local metadata and saved plans. State can contain provider-computed identity
25
+ credentials even when runtime SQL/accounting secret payloads are supplied outside
26
+ Terraform. Restrict readers, protect backups/plans, and review retention/key policy.
27
+ Never disable TLS verification or use -lock=false to bypass an unavailable lock.
28
+
29
+ Local-only checks: terraform init -backend=false, terraform validate, terraform test.
30
+ Before authorized production planning, verify the existing protected state store
31
+ on an isolated approved state: concurrent clients must conflict on one lock, an
32
+ unrelated identity must not unlock it, and version recovery must preserve the
33
+ expected digest. Record actual service version, access, custody and recovery proof.
34
+ Then run terraform init -backend-config=backend.hcl through the approved credential
35
+ chain. Platform/account access, store creation and migrations require authorization.
36
+
37
+ Each deployment environment has a distinct physical resource-name seed. Use separate
38
+ staging/production state paths and reviewed immutable image/account/policy inputs;
39
+ never point production at staging state. Keep a verified private state backup before
40
+ an authorized migration and inspect exact lineage. Do not -reconfigure/-migrate-state
41
+ over a mismatched lineage. No external accounting service or actor is imported or
42
+ recreated. Resource deletion protections do not prove backup, restore or availability.
43
+ `;
@@ -0,0 +1,19 @@
1
+ import {publicFaqFiles} from './public-faq.mjs';
2
+ import {existingReferenceFiles} from './existing-references.mjs';
3
+ export const v=n=>'${var.'+n+'}',ref=(type,n,key)=>'${'+type+'.'+n+'.'+key+'}';
4
+ export const UUID='^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$';
5
+ export function builder(project,plan,environment,provider){
6
+ if(!plan.publicFaqPlan?.entries.length||plan.publicFaqPlan.entries.some(e=>e.provider!==provider))throw Error('A public FAQ adapter must match every proposed application provider; no cross-cloud substitution.');
7
+ const variable={review_approved:{type:'bool',default:false}},examples={review_approved:false},resource={},output={},files={},data={},assertions=[];
8
+ const gaps=[...plan.gapDetails.map(g=>g.id),...(environment==='production'?['production-state-backup-and-operating-review-required']:[])];
9
+ resource.terraform_data={review_gate:{input:{design_revision:project.revision,environment},lifecycle:{precondition:[{condition:'${var.review_approved && length(local.unfinished_work) == 0}',error_message:'Review the source, public-only publication boundary, destination, native roles, model policy, costs and unresolved scope before deployment.'}]}}};
10
+ const input=(name,description,example,pattern)=>{variable[name]={type:'string',nullable:false,description,validation:{condition:pattern?'${can(regex('+JSON.stringify(pattern)+', var.'+name+'))}':'${length(trimspace(var.'+name+')) > 0}',error_message:'Supply the reviewed '+name+' value.'}};examples[name]=example;return v(name);};
11
+ const add=(type,name,body)=>((resource[type]||={})[name]={...body,depends_on:['terraform_data.review_gate',...(body.depends_on||[])]});
12
+ const source=row=>Object.assign(files,publicFaqFiles(provider,row.address));
13
+ function finish(config,lock,mock,guide){
14
+ const values=Object.entries({...examples,review_approved:true}).map(([name,value])=>name+' = '+JSON.stringify(value)).join('\n');
15
+ return {...files,...existingReferenceFiles(project),'.terraform.lock.hcl':lock,'main.tf.json':JSON.stringify({...config,variable,data,locals:{unfinished_work:gaps},resource,output},null,2),'resource-schedule.json':JSON.stringify(plan,null,2),'deployment.tfvars.json.example':JSON.stringify(examples,null,2),'.gitignore':'.terraform/\n*.tfstate*\n*.tfplan\n*.tfvars\n*.tfvars.json\n!deployment.tfvars.json.example\n.venv/\nbuild/\n*.zip\n__pycache__/\n','tests/public-faq.tftest.hcl':mock+'\nvariables {\n'+values+'\n}\n'+assertions.join('\n')+'\nrun "unapproved_blocked" {\n command = plan\n variables { review_approved = false }\n expect_failures = [terraform_data.review_gate]\n}\n','README.md':guide};
16
+ }
17
+ return {variable,examples,resource,output,files,data,assertions,input,add,source,finish};
18
+ }
19
+
@@ -0,0 +1,251 @@
1
+ import {ibmRegistryHostExpression,ibmRegistryRegionValidation}from'./ibm-registry.mjs';
2
+ import {azurePlanMocks} from './azure-plan-mocks.mjs';
3
+ import {CLOUD_PROVIDER_LOCKS} from './cloud-provider-locks.mjs';
4
+ export {awsPublicFaqTerraform} from './aws-public-faq.mjs';
5
+ import {builder,v,ref,UUID} from './public-faq-builder.mjs';
6
+
7
+ export function azurePublicFaqTerraform(project,plan,environment='staging'){
8
+ const b=builder(project,plan,environment,'azure'),{input,add}=b;
9
+ const subscription=input('subscription_id','Expected destination Azure subscription; operator credential chain only.','11111111-1111-1111-1111-111111111111',UUID);
10
+ const tenant=input('tenant_id','Expected destination tenant. Existing editor identity is preserved.','22222222-2222-2222-2222-222222222222',UUID);
11
+ const rg=input('resource_group_name','Existing reviewed resource group; not recreated or imported.','reviewed-applications','^[A-Za-z0-9_.()-]{1,90}$');
12
+ const registry=input('registry_name','Existing RBAC-mode ACR that accepts the ARM audience for managed identity.','reviewedregistry','^[a-z0-9]{5,50}$');
13
+ const registryRg=input('registry_resource_group_name','Existing registry resource group in this subscription.','reviewed-registry-rg','^[A-Za-z0-9_.()-]{1,90}$');
14
+ b.data.azurerm_client_config={destination:{}};
15
+ b.resource.terraform_data.review_gate.lifecycle.precondition.push({condition:'${data.azurerm_client_config.destination.subscription_id == var.subscription_id && data.azurerm_client_config.destination.tenant_id == var.tenant_id}',error_message:'Operator identity must match the reviewed tenant and subscription.'});
16
+ const registryId='/subscriptions/'+subscription+'/resourceGroups/'+registryRg+'/providers/Microsoft.ContainerRegistry/registries/'+registry;
17
+ for(const {row}of plan.publicFaqPlan.entries){
18
+ const n=row.address,name=input(n+'_name','Unique public application name; internal managed services belong to this composition.','reviewed-public-help','^[a-z][a-z0-9-]{3,18}[a-z0-9]$');
19
+ const region=input(n+'_region','Reviewed application, storage and Regional Standard model location. Verify actual model/version/quotas and processing geography.','australiaeast','^[a-z][a-z0-9]{2,39}$');
20
+ if(/^[a-z][a-z0-9]{2,39}$/.test(row.region)){b.variable[n+'_region'].default=row.region;b.examples[n+'_region']=row.region;}
21
+ const repository=input(n+'_repository','Build/publish path for this emitted application in the existing registry.','architect/public-help','^[a-z0-9]+(?:[._/-][a-z0-9]+)*$');
22
+ const digest=input(n+'_image_digest','Exact built, scanned, tested and authorized-published image digest.','sha256:'+'0'.repeat(64),'^sha256:[0-9a-f]{64}$');
23
+ const model=input(n+'_model_name','Reviewed regional model supporting strict JSON Schema output; no availability or price is invented.','REVIEW_MODEL');
24
+ const version=input(n+'_model_version','Exact supported model version; verify lifecycle and Standard regional availability.','REVIEW_VERSION');
25
+ const editor=input(n+'_editor_group_object_id','Existing Entra editor security-group object ID; no group/users are created. It receives only public-container data access.','33333333-3333-3333-3333-333333333333',UUID);
26
+ const tags={ManagedBy:'AtMem AI Architect',Environment:environment,Component:n};
27
+ add('azurerm_user_assigned_identity',n,{name:name+'-runtime',location:region,resource_group_name:rg,tags});
28
+ add('azurerm_service_plan',n,{name:name+'-plan',location:region,resource_group_name:rg,os_type:'Linux',sku_name:'B1',worker_count:1,tags});
29
+ add('azurerm_cognitive_account',n,{name:name+'-ai',location:region,resource_group_name:rg,kind:'OpenAI',sku_name:'S0',custom_subdomain_name:name+'-ai',local_auth_enabled:false,public_network_access_enabled:true,tags,lifecycle:{prevent_destroy:true}});
30
+ add('azurerm_cognitive_deployment',n,{name:'public-faq',cognitive_account_id:ref('azurerm_cognitive_account',n,'id'),version_upgrade_option:'NoAutoUpgrade',model:{format:'OpenAI',name:model,version},sku:{name:'Standard',capacity:1}});
31
+ const storage='${format("faq%s", substr(sha256(format("%s:%s", var.subscription_id, var.'+n+'_name)), 0, 20))}';
32
+ add('azurerm_storage_account',n,{name:storage,location:region,resource_group_name:rg,account_tier:'Standard',account_replication_type:'LRS',https_traffic_only_enabled:true,min_tls_version:'TLS1_2',allow_nested_items_to_be_public:false,shared_access_key_enabled:false,default_to_oauth_authentication:true,public_network_access_enabled:true,blob_properties:{versioning_enabled:true,delete_retention_policy:{days:7},container_delete_retention_policy:{days:7}},tags,lifecycle:{prevent_destroy:true}});
33
+ add('azurerm_storage_container',n,{name:'public-catalog',storage_account_id:ref('azurerm_storage_account',n,'id'),container_access_type:'private',lifecycle:{prevent_destroy:true}});
34
+ const principal=ref('azurerm_user_assigned_identity',n,'principal_id');
35
+ for(const [suffix,scope,role]of [['',ref('azurerm_cognitive_account',n,'id'),'Cognitive Services OpenAI User'],['_policy',ref('azurerm_cognitive_account',n,'id'),'Reader'],['_pull',registryId,'AcrPull'],['_catalog',ref('azurerm_storage_container',n,'id'),'Storage Blob Data Reader']])add('azurerm_role_assignment',n+suffix,{scope,role_definition_name:role,principal_id:principal,principal_type:'ServicePrincipal',skip_service_principal_aad_check:true});
36
+ add('azurerm_role_assignment',n+'_editor',{scope:ref('azurerm_storage_container',n,'id'),role_definition_name:'Storage Blob Data Contributor',principal_id:editor,principal_type:'Group'});
37
+ add('azurerm_linux_web_app',n,{name,location:region,resource_group_name:rg,service_plan_id:ref('azurerm_service_plan',n,'id'),https_only:true,ftp_publish_basic_authentication_enabled:false,webdeploy_publish_basic_authentication_enabled:false,identity:{type:'UserAssigned',identity_ids:[ref('azurerm_user_assigned_identity',n,'id')]},site_config:{always_on:true,minimum_tls_version:'1.2',scm_minimum_tls_version:'1.2',ftps_state:'Disabled',http2_enabled:true,remote_debugging_enabled:false,health_check_path:'/healthz',health_check_eviction_time_in_min:2,container_registry_use_managed_identity:true,container_registry_managed_identity_client_id:ref('azurerm_user_assigned_identity',n,'client_id'),application_stack:{docker_registry_url:'https://'+registry+'.azurecr.io',docker_image_name:repository+'@'+digest}},app_settings:{WEBSITES_PORT:'8080',MANAGED_IDENTITY_CLIENT_ID:ref('azurerm_user_assigned_identity',n,'client_id'),MODEL_RESOURCE_ID:ref('azurerm_cognitive_account',n,'id'),MODEL_ENDPOINT:ref('azurerm_cognitive_account',n,'endpoint'),MODEL_DEPLOYMENT:ref('azurerm_cognitive_deployment',n,'name'),MAX_OUTPUT_TOKENS:'1024',CATALOG_ACCOUNT:ref('azurerm_storage_account',n,'name'),CATALOG_CONTAINER:ref('azurerm_storage_container',n,'name')},tags,depends_on:['azurerm_role_assignment.'+n,'azurerm_role_assignment.'+n+'_policy','azurerm_role_assignment.'+n+'_pull','azurerm_role_assignment.'+n+'_catalog']});
38
+ b.output[n+'_url']={value:'https://'+ref('azurerm_linux_web_app',n,'default_hostname')+'/'};
39
+ b.output[n+'_catalog']={value:{storage_account:ref('azurerm_storage_account',n,'name'),container:ref('azurerm_storage_container',n,'name'),region}};
40
+ b.source(row);
41
+ b.assertions.push(`run "${n}_public_boundary" {\n command = plan\n assert {\n condition = azurerm_storage_container.${n}.container_access_type == "private" && !azurerm_storage_account.${n}.shared_access_key_enabled && !azurerm_storage_account.${n}.allow_nested_items_to_be_public\n error_message = "Public answers must not make the object store public or enable storage keys."\n }\n assert {\n condition = azurerm_role_assignment.${n}_catalog.role_definition_name == "Storage Blob Data Reader" && azurerm_role_assignment.${n}_editor.role_definition_name == "Storage Blob Data Contributor" && azurerm_role_assignment.${n}_catalog.principal_id != azurerm_role_assignment.${n}_editor.principal_id\n error_message = "Runtime read and authorized editor write identities must remain separate."\n }\n assert {\n condition = azurerm_linux_web_app.${n}.https_only && !azurerm_cognitive_account.${n}.local_auth_enabled\n error_message = "TLS and workload identity are required."\n }\n}\nrun "${n}_mutable_image_blocked" {\n command = plan\n variables { ${n}_image_digest = "latest" }\n expect_failures = [var.${n}_image_digest]\n}`);
42
+ }
43
+ const config={terraform:{required_version:'>= 1.17.1, < 2.0.0',required_providers:{azurerm:{source:'hashicorp/azurerm',version:'4.81.0'}}},provider:{azurerm:{subscription_id:subscription,tenant_id:tenant,features:{},storage_use_azuread:true}}};
44
+ return b.finish(config,CLOUD_PROVIDER_LOCKS.azure,azurePlanMocks({subscription:b.examples.subscription_id,tenant:b.examples.tenant_id,resourceGroup:b.examples.resource_group_name,addresses:plan.publicFaqPlan.entries.map(e=>e.row.address)}),AZURE_PUBLIC_FAQ_GUIDE);
45
+ }
46
+
47
+ export const AZURE_PUBLIC_FAQ_GUIDE=`# Azure public-only FAQ composition
48
+
49
+ The generated Python browser/API is intentionally anonymous. Its dedicated managed
50
+ identity can read only this private public-article container and invoke/read policy
51
+ on its generated regional model account. A separate existing Entra editor group
52
+ receives container-scoped data contributor access. No application HTTP endpoint
53
+ edits articles. No users/groups, existing resource group or ACR are recreated.
54
+ This is not a private enterprise knowledge assistant or existing-SSO integration.
55
+
56
+ Shared storage keys and anonymous blob access are disabled; the Azure provider
57
+ uses Entra for storage access. App Service basic publishing/debug/FTP are disabled;
58
+ the application uses managed identity for image pulls. Verify the existing registry
59
+ uses standard RBAC and accepts the ARM audience. No registry credential or model
60
+ key is exported. Public TLS endpoints use IAM/RBAC; private networking is not
61
+ implemented. Review inherited permissions and current tenant/subscription context.
62
+
63
+ See applications/*/BUILD.md for exact source/test/build and conditional editor CLI
64
+ steps. Protect Terraform state and variables. Seed only genuinely public articles
65
+ with the authorized editor before admitting traffic; a missing/inaccessible source
66
+ does not become an empty catalog or a cached answer. Blob versions and seven-day
67
+ soft deletion are recovery features, not an immediate erasure guarantee. Review
68
+ recovery and costs. Anonymous access plus concurrency/instance/output limits is
69
+ not an invoice cap; approve and test destination abuse controls and budget policy.
70
+
71
+ Choose a compatible regional Standard structured-output model/version and verify
72
+ actual quotas, prices and geography. Runtime requires approved ContentLogging=false
73
+ before inference and never writes that account-wide setting. Provider/platform
74
+ logging and identity/control-plane processing require separate review. No app
75
+ question/answer persistence or content-bearing application logs are implemented.
76
+ Real model answer/citation/abstention and latency tests remain required.
77
+
78
+ Use Terraform 1.17.1+, terraform init -backend=false, terraform validate and
79
+ terraform test. These mock checks do not prove real Azure IAM, managed identity,
80
+ storage conditionals or model quality. Obtain explicit authorization for registry
81
+ publication, cloud access, a real account plan and deployment. Production state,
82
+ backup and operating review remain gated; no export proves deployment.
83
+ `;
84
+
85
+ export function gcpPublicFaqTerraform(project,plan,environment='staging'){
86
+ const b=builder(project,plan,environment,'gcp'),{input,add}=b;
87
+ const projectId=input('project_id','Existing reviewed Google project with billing; no project is recreated.','reviewed-project','^[a-z][a-z0-9-]{4,28}[a-z0-9]$');
88
+ const registryLocation=input('registry_location','Location of the existing Artifact Registry Docker repository.','australia-southeast1','^[a-z]+(?:-[a-z]+[0-9])?$');
89
+ const registry=input('registry_repository','Existing Docker repository in this project; preserved.','reviewed-images','^[a-z][a-z0-9-]{1,61}[a-z0-9]$');
90
+ b.data.google_project={destination:{project_id:projectId}};
91
+ for(const [name,service]of Object.entries({run:'run.googleapis.com',model:'aiplatform.googleapis.com',storage:'storage.googleapis.com',registry:'artifactregistry.googleapis.com'}))add('google_project_service','required_'+name,{project:projectId,service,disable_on_destroy:false});
92
+ add('google_project_service_identity','run',{provider:'google-beta',project:projectId,service:'run.googleapis.com',depends_on:['google_project_service.required_run']});
93
+ add('google_artifact_registry_repository_iam_member','image_pull',{project:projectId,location:registryLocation,repository:registry,role:'roles/artifactregistry.reader',member:ref('google_project_service_identity','run','member'),depends_on:['google_project_service.required_registry']});
94
+ const number='${data.google_project.destination.number}';
95
+ for(const {row}of plan.publicFaqPlan.entries){
96
+ const n=row.address,name=input(n+'_name','Unique short Cloud Run/runtime name. The generated deterministic URL is used for this public browser.','reviewed-public-help','^[a-z][a-z0-9-]{3,18}[a-z0-9]$');
97
+ const region=input(n+'_region','Reviewed single-region application, catalog and model location; no global model fallback.','australia-southeast1','^[a-z]+-[a-z]+[0-9]$');
98
+ if(/^[a-z]+-[a-z]+[0-9]$/.test(row.region)){b.variable[n+'_region'].default=row.region;b.examples[n+'_region']=row.region;}
99
+ const repository=input(n+'_image_repository','Path for the emitted image in the existing registry.','architect/public-help','^[a-z0-9]+(?:[._/-][a-z0-9]+)*$');
100
+ const digest=input(n+'_image_digest','Built, scanned, tested and authorized-published emitted image digest.','sha256:'+'0'.repeat(64),'^sha256:[0-9a-f]{64}$');
101
+ const model=input(n+'_model_id','Compatible reviewed regional Gemini model/version with structured JSON output; verify lifecycle, quota, context size and prices.','gemini-reviewed-version','^gemini-[a-z0-9.-]{1,80}$');
102
+ const editor=input(n+'_editor_group','Existing authorized Google editor group email. No users/groups are created.','help-editors@example.test','^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$');
103
+ const review=n+'_policy_review';b.variable[review]={type:'object({ projectId = string, region = string, model = string, abuseLogging = string, approvedBy = string, evidenceSha256 = string, expiresAt = string })',nullable:false,description:'Scoped expiring destination-owner review of actual abuse-monitoring terms/exemption. Operator attestation, not a fabricated approval API; runtime separately reads caching/model logging/sharing settings.'};b.examples[review]={projectId:'reviewed-project',region:b.examples[n+'_region'],model:'gemini-reviewed-version',abuseLogging:'REVIEW_REQUIRED',approvedBy:'REVIEW_REQUIRED',evidenceSha256:'0'.repeat(64),expiresAt:'REPLACE_AFTER_REVIEW'};
104
+ add('google_service_account',n,{project:projectId,account_id:name,display_name:'Public FAQ runtime; no catalog edit permission'});
105
+ const member='serviceAccount:'+ref('google_service_account',n,'email');
106
+ add('google_project_iam_custom_role',n,{project:projectId,role_id:'${replace(var.'+n+'_name, "-", "_")}_model',title:'FAQ model invocation and read-only policy',permissions:['aiplatform.endpoints.predict','aiplatform.cacheConfigs.get','aiplatform.endpoints.fetchPublisherModelConfig'],stage:'GA'});
107
+ add('google_project_iam_member',n,{project:projectId,role:ref('google_project_iam_custom_role',n,'name'),member,depends_on:['google_project_service.required_model']});
108
+ add('google_storage_bucket',n,{project:projectId,name:projectId+'-'+name+'-public',location:region,storage_class:'STANDARD',uniform_bucket_level_access:true,public_access_prevention:'enforced',force_destroy:false,versioning:{enabled:true},soft_delete_policy:{retention_duration_seconds:604800},lifecycle_rule:{action:{type:'Delete'},condition:{days_since_noncurrent_time:7}},lifecycle:{prevent_destroy:true},depends_on:['google_project_service.required_storage']});
109
+ for(const [suffix,permissions]of [['_catalog',['storage.objects.get']],['_editor',['storage.objects.get','storage.objects.create','storage.objects.delete']]])add('google_project_iam_custom_role',n+suffix,{project:projectId,role_id:'${replace(var.'+n+'_name, "-", "_")}'+suffix,title:suffix==='_catalog'?'FAQ current catalog reader':'FAQ conditional catalog editor',permissions,stage:'GA'});
110
+ add('google_storage_bucket_iam_member',n,{bucket:ref('google_storage_bucket',n,'name'),role:ref('google_project_iam_custom_role',n+'_catalog','name'),member});
111
+ add('google_storage_bucket_iam_member',n+'_editor',{bucket:ref('google_storage_bucket',n,'name'),role:ref('google_project_iam_custom_role',n+'_editor','name'),member:'group:'+editor});
112
+ const origin='https://'+name+'-'+number+'.'+region+'.run.app',settings={PROJECT_ID:projectId,REGION:region,MODEL_ID:model,PUBLIC_ORIGIN:origin,MAX_OUTPUT_TOKENS:'1024',CATALOG_BUCKET:ref('google_storage_bucket',n,'name'),POLICY_REVIEW_BASE64:'${base64encode(jsonencode(var.'+review+'))}'};
113
+ add('google_cloud_run_v2_service',n,{project:projectId,name,location:region,deletion_protection:true,ingress:'INGRESS_TRAFFIC_ALL',invoker_iam_disabled:false,iap_enabled:false,labels:{managed_by:'atmem-ai-architect',environment},template:{service_account:ref('google_service_account',n,'email'),timeout:'30s',max_instance_request_concurrency:5,scaling:{min_instance_count:0,max_instance_count:2},containers:{name:'application',image:registryLocation+'-docker.pkg.dev/'+projectId+'/'+registry+'/'+repository+'@'+digest,ports:{container_port:8080},resources:{limits:{cpu:'1',memory:'512Mi'},cpu_idle:true,startup_cpu_boost:true},env:Object.entries(settings).map(([name,value])=>({name,value})),startup_probe:{http_get:{path:'/healthz',port:8080},initial_delay_seconds:0,period_seconds:5,timeout_seconds:2,failure_threshold:12}}},depends_on:['google_project_service.required_run','google_project_service_identity.run','google_artifact_registry_repository_iam_member.image_pull','google_project_iam_member.'+n,'google_storage_bucket_iam_member.'+n]});
114
+ // Anonymous invocation is intentional for this public-only application, never
115
+ // applied to a private module or the bucket itself. Org policy must allow it.
116
+ add('google_cloud_run_v2_service_iam_member',n,{project:projectId,location:region,name:ref('google_cloud_run_v2_service',n,'name'),role:'roles/run.invoker',member:'allUsers'});
117
+ b.output[n+'_url']={value:origin};b.output[n+'_catalog']={value:{bucket:ref('google_storage_bucket',n,'name'),region}};b.source(row);
118
+ b.assertions.push(`run "${n}_public_boundary" {\n command = plan\n assert {\n condition = google_storage_bucket.${n}.public_access_prevention == "enforced" && google_storage_bucket.${n}.uniform_bucket_level_access && !google_storage_bucket.${n}.force_destroy\n error_message = "Only the app is public; the catalog bucket stays private and protected."\n }\n assert {\n condition = google_cloud_run_v2_service_iam_member.${n}.member == "allUsers" && google_cloud_run_v2_service_iam_member.${n}.role == "roles/run.invoker" && !google_cloud_run_v2_service.${n}.iap_enabled\n error_message = "This explicit public-only application has anonymous invocation, not an invented end-user identity."\n }\n assert {\n condition = toset(google_project_iam_custom_role.${n}_catalog.permissions) == toset(["storage.objects.get"]) && google_storage_bucket_iam_member.${n}_editor.member == "group:\${var.${n}_editor_group}"\n error_message = "Runtime read and native editor write authority must remain separate."\n }\n}\nrun "${n}_mutable_image_blocked" {\n command = plan\n variables { ${n}_image_digest = "latest" }\n expect_failures = [var.${n}_image_digest]\n}`);
119
+ }
120
+ const config={terraform:{required_version:'>= 1.17.1, < 2.0.0',required_providers:{google:{source:'hashicorp/google',version:'7.46.2'},'google-beta':{source:'hashicorp/google-beta',version:'7.46.2'}}},provider:{google:{project:projectId},'google-beta':{project:projectId}}};
121
+ return b.finish(config,CLOUD_PROVIDER_LOCKS.gcp+'\n'+CLOUD_PROVIDER_LOCKS.gcpBeta,'mock_provider "google" {\n override_during = plan\n mock_data "google_project" { defaults = { number = "123456789012" } }\n mock_resource "google_service_account" { defaults = { email = "runtime@reviewed-project.iam.gserviceaccount.com" } }\n}\nmock_provider "google-beta" {\n override_during = plan\n mock_resource "google_project_service_identity" { defaults = { email = "service-123456789012@serverless-robot-prod.iam.gserviceaccount.com", member = "serviceAccount:service-123456789012@serverless-robot-prod.iam.gserviceaccount.com" } }\n}\n',GCP_PUBLIC_FAQ_GUIDE);
122
+ }
123
+
124
+ export const GCP_PUBLIC_FAQ_GUIDE=`# Google public-only FAQ composition
125
+
126
+ Only this explicitly selected public Cloud Run browser/API receives anonymous
127
+ run.invoker access. Its catalog bucket remains private with public access
128
+ prevention and uniform IAM. The dedicated runtime has a bucket-scoped custom
129
+ object-reader role; a separate existing company editor group has get/create/delete
130
+ only on that public catalog bucket. There is no HTTP editing route. No private
131
+ source, arbitrary URL fetch, user identity or enterprise authorization is implied.
132
+
133
+ Existing project, registry and editor group are preserved. Required APIs are never
134
+ disabled on destroy. The Cloud Run platform agent, not the application, receives
135
+ reader access on the exact existing image repository. The runtime has narrow
136
+ project-level prediction and read-only cache/model-policy access; no policy writes
137
+ or user-managed key is emitted. Google-beta is used only for the documented service
138
+ identity resource. Reconcile inherited IAM and organization restrictions on public
139
+ invocation; do not disable organization policy to bypass a failure.
140
+
141
+ See applications/*/BUILD.md. Seed genuinely public articles using the authorized
142
+ editor and native generation preconditions; updates/deletes never fall back to
143
+ stale or inaccessible evidence. Versioning, noncurrent-version expiry and seven-day
144
+ soft deletion support recovery and are not an immediate erasure guarantee. Runtime
145
+ never retrieves a historical generation selected by a visitor. No question/answer
146
+ persistence or content-bearing app logs are implemented; review platform logging.
147
+
148
+ The owner policy review is scoped/expiring operator-attested evidence, not an IBM,
149
+ Google or other fabricated provider approval API. Runtime separately requires
150
+ disabled project caching and disabled model request/response logging/sharing.
151
+ The documented global cache-control read sends no question text; review that
152
+ control-plane processing and actual model geography/terms against residency needs.
153
+ Model availability/context/quotas, prices, anonymous abuse controls, budgets and
154
+ real answer/citation/abstention/latency tests remain destination checks. Concurrency,
155
+ token and instance bounds are not an invoice cap or SLA.
156
+
157
+ Use Terraform 1.17.1+; run init -backend=false, validate and test. These native schema
158
+ and mock plans do not establish actual IAM, model or deployed behavior. Build, scan
159
+ and test the exact source/image; obtain authorization before publishing, cloud
160
+ access, real account plan or deployment. Production state/operations remain gated.
161
+ `;
162
+
163
+ export function ibmPublicFaqTerraform(project,plan,environment='staging'){
164
+ const b=builder(project,plan,environment,'ibm'),{input,add}=b;
165
+ const account=input('account_id','Existing destination IBM account; no account is created.','a'.repeat(32),'^[0-9a-f]{32}$');
166
+ const region=input('region','Reviewed regional Code Engine, COS and watsonx model destination.','au-syd','^[a-z]{2}-[a-z]+$');
167
+ const entries=plan.publicFaqPlan.entries;
168
+ if(entries.every(e=>e.row.region===entries[0].row.region)&&/^[a-z]{2}-[a-z]+$/.test(entries[0].row.region)){b.variable.region.default=entries[0].row.region;b.examples.region=entries[0].row.region;}
169
+ b.variable.region.validation=ibmRegistryRegionValidation();
170
+ const ceProject=input('code_engine_project_id','Existing reviewed Code Engine project; never recreate or import it.','11111111-1111-1111-1111-111111111111',UUID);
171
+ const registry=input('registry_namespace','Existing regional IBM Container Registry namespace.','reviewed-namespace','^[a-z0-9]+(?:[-_][a-z0-9]+)*$');
172
+ const pullSecret=input('registry_pull_secret','Existing registry-pull secret NAME in that project; no credential value is exported.','reviewed-registry-pull','^[a-z][a-z0-9-]{1,61}[a-z0-9]$');
173
+ b.data.ibm_code_engine_project={destination:{project_id:ceProject}};
174
+ b.resource.terraform_data.review_gate.lifecycle.precondition.push({condition:'${data.ibm_code_engine_project.destination.account_id == var.account_id && data.ibm_code_engine_project.destination.region == var.region}',error_message:'Existing Code Engine project must match the reviewed account and region.'});
175
+ for(const {row}of entries){
176
+ const n=row.address,name=input(n+'_name','Unique application and trusted-profile name.','reviewed-public-help','^[a-z][a-z0-9-]{2,38}[a-z0-9]$');
177
+ const repository=input(n+'_image_repository','Path for this emitted image in the existing namespace.','architect/public-help','^[a-z0-9]+(?:[._/-][a-z0-9]+)*$');
178
+ const digest=input(n+'_image_digest','Built, scanned, tested and authorized-published image digest.','sha256:'+'0'.repeat(64),'^sha256:[0-9a-f]{64}$');
179
+ const wxProject=input(n+'_watsonx_project_id','Existing watsonx data-platform project. Add the trusted profile as an authorized collaborator and associate the runtime instance.','22222222-2222-2222-2222-222222222222',UUID);
180
+ const instance=input(n+'_runtime_instance_id','Existing associated watsonx Runtime instance GUID.','33333333-3333-3333-3333-333333333333',UUID);
181
+ const model=input(n+'_model_id','Reviewed regional Text Chat JSON-object model; verify lifecycle, quotas and geography.','ibm/reviewed-model','^[a-z0-9][a-z0-9_.-]{0,79}/[a-z0-9][a-z0-9_.-]{0,99}$');
182
+ const editor=input(n+'_editor_access_group_id','Existing authorized company editor access-group ID. No group or user is created.','AccessGroup-44444444-4444-4444-4444-444444444444','^AccessGroup-[0-9a-fA-F-]{36}$');
183
+ const bucket=input(n+'_catalog_bucket','Globally unique regional bucket dedicated to genuinely public article content; the bucket itself remains private.','reviewed-public-catalog-unique','^[a-z][a-z0-9-]{1,61}[a-z0-9]$');
184
+ const review=n+'_policy_review';b.variable[review]={type:'object({ accountId = string, projectId = string, runtimeInstanceId = string, region = string, model = string, retentionReview = string, approvedBy = string, evidenceSha256 = string, expiresAt = string })',nullable:false,description:'Scoped expiring destination-owner review of actual model/provider retention and processing terms. Operator-attested evidence, not a provider approval API.'};b.examples[review]={accountId:b.examples.account_id,projectId:b.examples[n+'_watsonx_project_id'],runtimeInstanceId:b.examples[n+'_runtime_instance_id'],region:b.examples.region,model:b.examples[n+'_model_id'],retentionReview:'REVIEW_REQUIRED',approvedBy:'REVIEW_REQUIRED',evidenceSha256:'0'.repeat(64),expiresAt:'REPLACE_AFTER_REVIEW'};
185
+ add('ibm_resource_instance',n+'_catalog',{name:name+'-public-catalog',service:'cloud-object-storage',plan:'standard',location:'global',resource_group_id:'${data.ibm_code_engine_project.destination.resource_group_id}',lifecycle:{prevent_destroy:true,postcondition:[{condition:'${self.account_id == var.account_id}',error_message:'Catalog instance must belong to the reviewed account.'}]}});
186
+ add('ibm_cos_bucket',n,{bucket_name:bucket,resource_instance_id:ref('ibm_resource_instance',n+'_catalog','id'),region_location:region,storage_class:'standard',endpoint_type:'public',force_delete:false,object_versioning:{enable:true},noncurrent_version_expiration:{enable:true,noncurrent_days:7,prefix:'',rule_id:'expire-old-catalog-versions'},lifecycle:{prevent_destroy:true}});
187
+ add('ibm_iam_trusted_profile',n,{name,description:'Public FAQ compute identity; no catalog write or end-user authority'});
188
+ add('ibm_iam_trusted_profile_link',n,{profile_id:ref('ibm_iam_trusted_profile',n,'profile_id'),cr_type:'CE',link:{crn:'${data.ibm_code_engine_project.destination.crn}',component_name:ref('ibm_code_engine_app',n,'name'),component_type:'app'}});
189
+ add('ibm_iam_trusted_profile_policy',n,{iam_id:ref('ibm_iam_trusted_profile',n,'iam_id'),roles:['Writer'],resources:{service:'pm-20',resource_instance_id:instance,region},description:'Existing watsonx runtime-instance scope. Writer is broader than prediction-only; project membership remains separate.'});
190
+ const catalogScope={service:'cloud-object-storage',resource_instance_id:ref('ibm_resource_instance',n+'_catalog','guid'),resource_type:'bucket',resource:ref('ibm_cos_bucket',n,'bucket_name')};
191
+ add('ibm_iam_trusted_profile_policy',n+'_catalog',{iam_id:ref('ibm_iam_trusted_profile',n,'iam_id'),roles:['Object Reader'],resources:catalogScope});
192
+ // Article deletion rewrites catalog.json; object DELETE is intentionally absent.
193
+ // Object Writer includes object metadata/retention writes; it is not a custom
194
+ // put-only role. It cannot administer this bucket or grant public access.
195
+ add('ibm_iam_access_group_policy',n+'_editor',{access_group_id:editor,roles:['Object Reader','Object Writer'],resources:catalogScope});
196
+ const settings={ACCOUNT_ID:account,WATSONX_PROJECT_ID:wxProject,RUNTIME_INSTANCE_ID:instance,MODEL_REGION:region,MODEL_ID:model,IAM_PROFILE_ID:ref('ibm_iam_trusted_profile',n,'profile_id'),MAX_OUTPUT_TOKENS:'1024',CATALOG_BUCKET:ref('ibm_cos_bucket',n,'bucket_name'),POLICY_REVIEW_BASE64:'${base64encode(jsonencode(var.'+review+'))}'};
197
+ add('ibm_code_engine_app',n,{project_id:ceProject,name,image_reference:ibmRegistryHostExpression()+'/'+registry+'/'+repository+'@'+digest,image_secret:pullSecret,image_port:8080,managed_domain_mappings:'local_public',run_as_user:10001,run_compute_resource_token_enabled:true,scale_cpu_limit:'0.5',scale_memory_limit:'1G',scale_min_instances:0,scale_max_instances:2,scale_concurrency:5,scale_concurrency_target:5,scale_request_timeout:30,run_env_variables:Object.entries(settings).map(([name,value])=>({name,value,type:'literal'})),probe_readiness:{type:'http',path:'/healthz',port:8080,initial_delay:2,interval:5,timeout:2,failure_threshold:12},depends_on:['ibm_iam_trusted_profile_policy.'+n,'ibm_iam_trusted_profile_policy.'+n+'_catalog']});
198
+ b.assertions.push(`run "${n}_sydney_registry" {\n command = plan\n assert {\n condition = var.region != "au-syd" || startswith(ibm_code_engine_app.${n}.image_reference,"au.icr.io/")\n error_message = "Sydney uses au.icr.io; region concatenation cannot select a valid registry."\n }\n}`);
199
+ b.output[n+'_url']={value:ref('ibm_code_engine_app',n,'endpoint')};b.output[n+'_catalog']={value:{bucket,region}};b.output[n+'_trusted_profile_iam_id']={value:ref('ibm_iam_trusted_profile',n,'iam_id')};b.source(row);
200
+ b.assertions.push(`run "${n}_public_boundary" {\n command = plan\n assert {\n condition = ibm_iam_trusted_profile_policy.${n}_catalog.roles == tolist(["Object Reader"]) && ibm_iam_trusted_profile_policy.${n}_catalog.resources[0].resource_type == "bucket" && ibm_iam_trusted_profile_policy.${n}_catalog.resources[0].resource == var.${n}_catalog_bucket\n error_message = "Runtime may read only the dedicated catalog bucket; no write or public-access grant."\n }\n assert {\n condition = toset(ibm_iam_access_group_policy.${n}_editor.roles) == toset(["Object Reader", "Object Writer"]) && ibm_iam_access_group_policy.${n}_editor.resources[0].resource_type == "bucket" && ibm_iam_access_group_policy.${n}_editor.access_group_id == var.${n}_editor_access_group_id\n error_message = "Separate existing editors have bucket-scoped object access, never Manager or bucket Writer."\n }\n assert {\n condition = !ibm_cos_bucket.${n}.force_delete && ibm_cos_bucket.${n}.object_versioning[0].enable && ibm_code_engine_app.${n}.run_compute_resource_token_enabled && ibm_code_engine_app.${n}.run_as_user == 10001\n error_message = "Protect catalog recovery and use nonroot keyless compute identity."\n }\n}\nrun "${n}_mutable_image_blocked" {\n command = plan\n variables { ${n}_image_digest = "latest" }\n expect_failures = [var.${n}_image_digest]\n}`);
201
+ }
202
+ const config={terraform:{required_version:'>= 1.17.1, < 2.0.0',required_providers:{ibm:{source:'IBM-Cloud/ibm',version:'1.89.0'}}},provider:{ibm:{region}}};
203
+ const mocks=`mock_provider "ibm" {\n override_during = plan\n mock_data "ibm_code_engine_project" { defaults = { account_id = "${b.examples.account_id}", region = "${b.examples.region}", resource_group_id = "${'b'.repeat(32)}", crn = "crn:v1:bluemix:public:codeengine:${b.examples.region}:a/${b.examples.account_id}:11111111-1111-1111-1111-111111111111::" } }\n mock_resource "ibm_resource_instance" { defaults = { account_id = "${b.examples.account_id}", id = "crn:v1:bluemix:public:cloud-object-storage:global:a/${b.examples.account_id}:55555555-5555-5555-5555-555555555555::", guid = "55555555-5555-5555-5555-555555555555" } }\n}\n`;
204
+ b.assertions.push(`run "wrong_account_blocked" {\n command = plan\n variables { account_id = "${'c'.repeat(32)}" }\n expect_failures = [terraform_data.review_gate]\n}`);
205
+ return b.finish(config,CLOUD_PROVIDER_LOCKS.ibm,mocks,IBM_PUBLIC_FAQ_GUIDE);
206
+ }
207
+
208
+ export const IBM_PUBLIC_FAQ_GUIDE=`# IBM public-only FAQ composition
209
+
210
+ The anonymous browser/API uses a dedicated Code Engine trusted profile linked only
211
+ to this existing project and this new app. The runtime receives Object Reader on
212
+ the exact private COS bucket; a separate existing company access group receives
213
+ Object Reader and Object Writer on that bucket. Object Writer includes object
214
+ metadata and retention operations, not merely PUT; it does not administer buckets
215
+ or make them public. Article deletion conditionally replaces catalog.json; no
216
+ object DELETE grant or application HTTP editing route is needed. No public-access
217
+ group policy is emitted. Reconcile inherited account/group policies, which can
218
+ override narrower grants. Public endpoint routing does not mean anonymous storage.
219
+
220
+ COS uses a global service instance with a single regional data bucket, encryption
221
+ at rest managed by IBM and TLS. Control-plane geography requires separate review.
222
+ Versioning and seven-day noncurrent expiry aid recovery, not immediate erasure.
223
+ The runtime reads only the current catalog, checks it again before returning an
224
+ answer and withholds stale/unsupported evidence. Questions/answers are not persisted
225
+ or written to application logs. Private networking/customer-managed keys are not
226
+ implemented. This public-only application is not a private knowledge assistant.
227
+
228
+ Existing Code Engine project, namespace/pull-secret, watsonx project and associated
229
+ runtime instance remain intact. The profile gets Writer on that exact pm-20
230
+ instance; this is broader than prediction-only. Add the generated profile as a
231
+ minimum supported project collaborator and verify the association/model separately.
232
+ App creation precedes its compute link to avoid a Terraform cycle; health is
233
+ liveness, not model readiness. No app API key or end-user identity is invented.
234
+
235
+ See applications/*/BUILD.md for editor/build/testing commands. Supply a scoped,
236
+ expiring destination-owner policy review and test real IAM, compute token exchange,
237
+ conditional storage edits, source updates/deletions, model citations/abstention and
238
+ latency. The policy review is operator evidence, not a fabricated provider API.
239
+ Review current model availability, quotas, processing terms, prices, anonymous
240
+ abuse controls and budget policy. Instance/concurrency/token limits are not an
241
+ invoice cap. Protect state/variables. Native schema/mocks and local runtime tests
242
+ do not establish account-plan or deployed behavior. Obtain authorization before
243
+ image publication, cloud access, real plans or deployment; production operating
244
+ and state/backup review remain gated.
245
+
246
+ References:
247
+ - https://cloud.ibm.com/docs/cloud-object-storage?topic=cloud-object-storage-iam-bucket-permissions
248
+ - https://cloud.ibm.com/docs/iam?topic=iam-iam-service-roles-actions
249
+ - https://cloud.ibm.com/docs/cloud-object-storage?topic=cloud-object-storage-upload
250
+ - https://cloud.ibm.com/docs/codeengine?topic=codeengine-trusted-profiles-authentication-file
251
+ `;