@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,278 @@
1
+ import{v,r,l,UUID}from'./invoice-builder.mjs';
2
+
3
+ // IBM 2.9 supports JobDefinition, not a Terraform cron subscription resource.
4
+ // Keep job delivery separate from scheduling/alert acceptance under qualification.
5
+ export function ibmInvoiceOperations(b,n,{projectId,pull}){
6
+ const{add}=b;
7
+ b.variable.operations_enabled={type:'bool',default:false,description:'Create the three fixed SQL operating tasks after reviewed immutable image publication. Scheduling and alert acceptance are separate.'};
8
+ b.examples.operations_enabled=false;b.testExpressions.operations_enabled='true';
9
+ b.variable.maintenance_enabled={type:'bool',default:false,description:'Enable operating alerts after bootstrap; separately install the owned cron sources and verify successful runs before application release.'};b.examples.maintenance_enabled=false;b.testExpressions.maintenance_enabled='true';
10
+ const logs=b.input('operator_logs_instance_id','Existing reviewed same-region Cloud Logs instance receiving this region\'s Code Engine platform logs. Existing account routing is preserved.','88888888-8888-4888-8888-888888888888',UUID);
11
+ const webhook=b.input('operator_notification_integration_id','Existing verified Cloud Logs outgoing integration numeric ID; verify intended on-call recipients/delivery without exposing its endpoint or credentials.','12345','^[1-9][0-9]{0,9}$');
12
+ b.variable.operator_notification_integration_id.validation.condition='${can(regex("^[1-9][0-9]{0,9}$",var.operator_notification_integration_id)) && try(tonumber(var.operator_notification_integration_id),0) <= 4294967295}';
13
+ b.resource.terraform_data.review_gate.lifecycle.precondition.push({condition:'${!var.maintenance_enabled || var.operations_enabled}',error_message:'Operating alerts and schedules require fixed operator tasks.'},{condition:'${!var.applications_enabled || (var.operations_enabled && var.maintenance_enabled)}',error_message:'Initialize SQL and verify operating schedules, log routing and notifications before application release.'});
14
+ b.locals.operator_deployment=b.output.operator_deployment.value;
15
+ b.locals.operator_secret_name=l('name')+'-operator-sql';
16
+ const literal=(name,value)=>({name,value,type:'literal'});
17
+ const reference=(name,type,key,reference)=>({name,type,key,reference});
18
+ for(const action of ['initialize','maintain','monitor']){
19
+ const env=[literal('DATABASE_NAME','ibmclouddb'),literal('OPERATOR_DEPLOYMENT_BASE64','${base64encode(jsonencode(local.operator_deployment))}'),...Object.entries({DATABASE_HOST:'host',DATABASE_PORT:'port',DATABASE_CA_PEM:'ca_pem',DATABASE_USER:'operator_user'}).map(([name,key])=>reference(name,'config_map_key_reference',key,l('database_config_name'))),reference('DATABASE_PASSWORD','secret_key_reference','password',l('operator_secret_name'))];
20
+ // Bootstrap needs the two runtime passwords, never the worker's accounting token.
21
+ if(action==='initialize')for(const purpose of ['api','worker'])env.push(reference(purpose.toUpperCase()+'_DATABASE_PASSWORD','secret_key_reference','password',l(purpose==='api'?'api_secret_name':'worker_secret_name')));
22
+ add('ibm_code_engine_job',n+'_operator_'+action,{count:'${var.operations_enabled ? 1 : 0}',project_id:projectId,name:l('name')+'-'+action,image_reference:v('runtime_image'),image_secret:pull,run_commands:['python','-I','/app/invoice_operator_job.py'],run_arguments:[action,'--execute'],run_mode:'task',run_as_user:10001,run_service_account:'none',run_compute_resource_token_enabled:false,scale_array_spec:'0',scale_cpu_limit:'1',scale_memory_limit:'1G',scale_max_execution_time:960,scale_retry_limit:0,run_env_variables:env,depends_on:['ibm_database.'+n]});
23
+ }
24
+ const owned='app:"codeengine" AND codeengine.projectGuid:"'+projectId+'" AND codeengine.region:"'+b.region+'"';
25
+ const query=(action,status)=>owned+' AND codeengine.component:"'+l('name')+'-'+action+'" AND message:"invoice-operator-v1" AND message:"'+status+'"';
26
+ const failures=owned+' AND ('+['initialize','maintain','monitor'].map(action=>'codeengine.component:"'+l('name')+'-'+action+'"').join(' OR ')+') AND ((message:"invoice-operator-v1" AND (message:"failed" OR message:"attention" OR message:"backlog")) OR level:"error" OR level:"fatal")';
27
+ const definitions=[['failed',failures,'more_than_or_unspecified',0,'minutes_5_or_unspecified'],['monitor_missing',query('monitor','ok'),'less_than',1,'hours_2'],['maintenance_missing',query('maintain','ok'),'less_than',1,'hours_36']];
28
+ b.output.operator_log_queries={value:Object.fromEntries(definitions.map(([purpose,filter])=>[purpose,filter]))};
29
+ for(const[purpose,filter,condition,threshold,window]of definitions){
30
+ add('ibm_logs_alert_definition',n+'_'+purpose,{instance_id:logs,region:b.region,name:l('name')+'-'+purpose,description:'Owned SQL operator '+purpose+'. Verify native log samples, alert evaluation and existing on-call delivery before release; no customer invoice data in notifications.',enabled:v('maintenance_enabled'),phantom_mode:false,priority:'p2',type:'logs_threshold',logs_threshold:{condition_type:condition,evaluation_delay_ms:60000,notification_payload_filter:[],logs_filter:{simple_filter:{lucene_query:filter}},rules:[{condition:{threshold,time_window:{logs_time_window_specific_value:window}},override:{priority:'p2'}}],undetected_values_management:{auto_retire_timeframe:'never_or_unspecified',trigger_undetected_values:condition==='less_than'}},notification_group:{webhooks:[{minutes:1,notify_on:'triggered_and_resolved',integration:{integration_id:'${tonumber(var.operator_notification_integration_id)}'}}]},incidents_settings:{minutes:10,notify_on:'triggered_and_resolved'}});
31
+ b.files['monitoring/'+purpose+'.lucene']=filter+'\n';
32
+ }
33
+ b.output.operator_jobs={value:{account:v('account_id'),region:b.region,projectId,maintenanceEnabled:v('maintenance_enabled'),operatorSecret:l('operator_secret_name'),names:Object.fromEntries(['initialize','maintain','monitor'].map(action=>[action,l('name')+'-'+action]))}};
34
+ b.files['scripts/run-operator.py']=IBM_OPERATOR_RUNNER;
35
+ b.files['OPERATING_JOBS.md']=IBM_OPERATING_JOBS;
36
+ b.assertions.push(`run "operator_before_applications" {
37
+ command = plan
38
+ variables {
39
+ applications_enabled = false
40
+ maintenance_enabled = false
41
+ }
42
+ assert {
43
+ condition = length(ibm_code_engine_job.${n}_operator_initialize) == 1 && length(ibm_code_engine_app.${n}_api) == 0 && ibm_code_engine_job.${n}_operator_monitor[0].run_service_account == "none" && !ibm_code_engine_job.${n}_operator_monitor[0].run_compute_resource_token_enabled && ibm_code_engine_job.${n}_operator_monitor[0].scale_retry_limit == 0
44
+ error_message = "Bootstrap is separate, bounded and without application/cloud authority."
45
+ }
46
+ }
47
+ run "operator_mutable_image_rejected" {
48
+ command = plan
49
+ variables {
50
+ applications_enabled = false
51
+ runtime_image = "unreviewed:latest"
52
+ maintenance_enabled = false
53
+ }
54
+ expect_failures = [var.runtime_image]
55
+ }
56
+ run "operating_jobs_required" {
57
+ command = plan
58
+ variables {
59
+ operations_enabled = false
60
+ maintenance_enabled = false
61
+ }
62
+ expect_failures = [terraform_data.review_gate]
63
+ }
64
+ run "maintenance_without_jobs_rejected" {
65
+ command = plan
66
+ variables {
67
+ applications_enabled = false
68
+ operations_enabled = false
69
+ }
70
+ expect_failures = [terraform_data.review_gate]
71
+ }
72
+ run "notification_id_overflow_rejected" {
73
+ command = plan
74
+ variables { operator_notification_integration_id = "4294967296" }
75
+ expect_failures = [var.operator_notification_integration_id]
76
+ }
77
+ `);
78
+ }
79
+
80
+ const IBM_OPERATING_JOBS=`# IBM fixed invoice operating tasks
81
+
82
+ This package delivers initialize/maintain/monitor task definitions, an explicit
83
+ owned cron installer/observer, and Cloud Logs alert definitions. Local tests do not
84
+ prove real native execution, log routing, notification delivery or deployment.
85
+
86
+ Foundation uses applications_enabled=false, operations_enabled=false and
87
+ maintenance_enabled=false. Publish
88
+ the reviewed immutable runtime image into the owned registry only when authorized.
89
+ Set operations_enabled=true with applications still false to create fixed tasks.
90
+ Populate the separate operator SQL secret outside Terraform. databaseConfig also
91
+ needs operator_user: the exact administrative login for this new owned database.
92
+ Only initialize receives the separate API and worker SQL password keys. No task
93
+ receives the accounting token, parser token, model or object-store authority.
94
+
95
+ The destination operator installs/authenticates IBM Cloud CLI and its reviewed Code
96
+ Engine plugin in a dedicated private CLI home. For example, set IBMCLOUD_HOME to
97
+ this package's .local/ibm-operator-cli during login/plugin setup. Keep that directory
98
+ mode 0700 and outside source control. Never copy a user's global CLI credentials.
99
+
100
+ Preview: python3 scripts/run-operator.py initialize
101
+ Authorized execution adds --execute. The helper reads this package's Terraform
102
+ output, explicitly selects its account/region/project in the isolated CLI home,
103
+ then submits the fixed task with --wait. It supplies no image, environment, command
104
+ or service-account overrides. Job-launch permission is privileged; do not grant it
105
+ to the application, worker, model or public user. Retain the actual completed job
106
+ and initialized:true/monitor/maintenance receipt, not merely submit acceptance.
107
+
108
+ After bootstrap, run maintain and monitor once and inspect actual successful
109
+ receipts in the existing Cloud Logs destination. Verify that regional Code Engine
110
+ platform logging is routed to operator_logs_instance_id through the existing
111
+ account routing. Review its region/data custody and the existing outgoing
112
+ notification integration. Do not replace account log routing or expose credentials.
113
+ Read terraform output -json operator_log_queries for resolved queries; monitoring/
114
+ files are readable Terraform expression templates, not resolved instance selectors.
115
+ The Lucene filters use documented app/codeengine.projectGuid/region/component and
116
+ message/level fields, never deprecated label.Namespace/Project/Stream fields.
117
+ Verify the actual native samples match each emitted query before enabling alerts;
118
+ account parsing/routing can change message layout. Missing SQL monitor alerts after
119
+ two hours; missing daily maintenance after 36 hours. Undetected values trigger
120
+ missing-run alerts; native zero-sample evaluation/delivery still need acceptance.
121
+ Notifications exclude payload fields; no invoice/subject/amount is emitted by jobs.
122
+
123
+ Keep applications false, set maintenance_enabled=true, apply reviewed alerts, then
124
+ preview python3 scripts/run-operator.py install-schedules. With authorized --execute,
125
+ the helper uses supported Knative PingSource and IBM JobDefinition APIs in this
126
+ project's isolated KUBECONFIG. Only maintain (02:17 UTC daily) and monitor (hourly at
127
+ minute 7) are scheduled. Initialize is never scheduled. It refuses unrelated source
128
+ ownership and uses native resourceVersion to avoid overwriting concurrent changes.
129
+ Use check-schedules --execute to observe configuration and current Ready generation.
130
+ Ready means reconciled source configuration, not successful SQL work. Retain actual
131
+ successful scheduled task/log/alert delivery evidence before application release.
132
+ Cron sources are explicitly operated resources outside Terraform because IBM 2.9
133
+ has no cron subscription resource; do not hide account writes in a provisioner.
134
+ Before rollback, identify the two exact owned PingSource names/UIDs, verify their
135
+ owner references and remove only those sources with the authorized native operator;
136
+ do not delete the namespace/project. Disable alerts during an approved maintenance
137
+ window. Installed sources persist independently of the Terraform boolean: changing
138
+ maintenance_enabled=false does not pause or delete an installed source.
139
+
140
+ Each task uses one array index, no automatic retries and a 960-second platform
141
+ limit; the application enforces its own 900-second work deadline. Private SQL TLS,
142
+ actual native login privileges, task outcome, schedules and alert delivery still
143
+ need separately authorized destination checks. Provider schema/mocks are not
144
+ deployment, SQL runtime or scheduling evidence.
145
+ `;
146
+
147
+ const IBM_OPERATOR_RUNNER=`"""Preview or explicitly execute a fixed owned IBM Code Engine task."""
148
+ import argparse
149
+ from contextlib import contextmanager
150
+ import copy
151
+ import fcntl
152
+ import json
153
+ import os
154
+ from pathlib import Path
155
+ import re
156
+ import stat
157
+ import subprocess
158
+
159
+ ROOT=Path(__file__).resolve().parents[1]
160
+
161
+ def unique_object(pairs):
162
+ value={}
163
+ for key,child in pairs:
164
+ if key in value:raise ValueError('Duplicate operator output field')
165
+ value[key]=child
166
+ return value
167
+
168
+ def configuration():
169
+ result=subprocess.run(['terraform','output','-json','operator_jobs'],cwd=ROOT,check=True,capture_output=True,text=True,timeout=30)
170
+ value=json.loads(result.stdout,object_pairs_hook=unique_object)
171
+ if not isinstance(value,dict)or set(value)!={'account','region','projectId','maintenanceEnabled','operatorSecret','names'}or type(value['maintenanceEnabled'])is not bool:raise ValueError('Use the owned operator_jobs output')
172
+ if not re.fullmatch(r'[0-9a-f]{32}',value['account'])or not re.fullmatch(r'[a-z]{2}-[a-z]+',value['region'])or not re.fullmatch(r'[0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}',value['projectId']):raise ValueError('Invalid native destination')
173
+ names=value['names']
174
+ if not isinstance(names,dict)or set(names)!={'initialize','maintain','monitor'}:raise ValueError('Use all three fixed jobs')
175
+ prefix=None
176
+ for action,name in names.items():
177
+ if not isinstance(name,str)or not re.fullmatch(r'invoice-[0-9a-f]{12}-'+action,name):raise ValueError('Use a fixed owned task')
178
+ current=name.removesuffix('-'+action)
179
+ if prefix is not None and current!=prefix:raise ValueError('Mixed deployment jobs')
180
+ prefix=current
181
+ return value
182
+
183
+ def commands(value,action):
184
+ return [['ibmcloud','target','-c',value['account'],'-r',value['region']],['ibmcloud','ce','project','select','--id',value['projectId'],'--quiet'],['ibmcloud','ce','jobrun','submit','--job',value['names'][action],'--wait','--wait-timeout','1000']]
185
+
186
+ @contextmanager
187
+ def private_context():
188
+ home=ROOT/'.local/ibm-operator-cli'
189
+ # Pre-existing private CLI authentication is required; do not silently adopt
190
+ # global account context or follow a symlink to somebody else's CLI state.
191
+ metadata=home.lstat()
192
+ if not stat.S_ISDIR(metadata.st_mode)or metadata.st_uid!=os.geteuid()or metadata.st_mode&0o077:raise ValueError('Authenticate in the owned mode-0700 CLI directory first')
193
+ lock=os.open(home/'operator.lock',os.O_CREAT|os.O_RDWR|os.O_NOFOLLOW,0o600)
194
+ with os.fdopen(lock,'w')as stream:
195
+ metadata=os.fstat(stream.fileno())
196
+ if not stat.S_ISREG(metadata.st_mode)or metadata.st_uid!=os.geteuid()or metadata.st_mode&0o077:raise ValueError('Use a private owned operation lock')
197
+ fcntl.flock(stream,fcntl.LOCK_EX|fcntl.LOCK_NB)
198
+ kube=home/'operator-kubeconfig'
199
+ if kube.exists()or kube.is_symlink():
200
+ metadata=kube.lstat()
201
+ if not stat.S_ISREG(metadata.st_mode)or metadata.st_uid!=os.geteuid()or metadata.st_mode&0o077:raise ValueError('Use a private owned kubeconfig')
202
+ env={**os.environ,'IBMCLOUD_HOME':str(home),'IBMCLOUD_TRACE':'false','KUBECONFIG':str(kube)}
203
+ previous=os.umask(0o077)
204
+ try:yield env
205
+ finally:os.umask(previous)
206
+
207
+ def kubectl(env,arguments,body=None):
208
+ result=subprocess.run(['kubectl',*arguments],cwd=ROOT,env=env,check=True,capture_output=True,text=True,input=json.dumps(body)if body is not None else None,timeout=150)
209
+ if len(result.stdout)>1000000:raise ValueError('Unexpected native resource response')
210
+ return result.stdout.strip()
211
+
212
+ def get_resource(env,kind,name,namespace,optional=False):
213
+ raw=kubectl(env,['get',kind,name,'--namespace',namespace,'-o','json',*(['--ignore-not-found']if optional else[])])
214
+ if optional and not raw:return None
215
+ return json.loads(raw,object_pairs_hook=unique_object)
216
+
217
+ def ownership(value,job,namespace,prefix,name):
218
+ metadata=value.get('metadata',{});references=metadata.get('ownerReferences',[])
219
+ expected={'apiVersion':'codeengine.cloud.ibm.com/v1beta1','kind':'JobDefinition','name':job['metadata']['name'],'uid':job['metadata']['uid'],'controller':False,'blockOwnerDeletion':False}
220
+ if value.get('apiVersion')!='sources.knative.dev/v1'or value.get('kind')!='PingSource'or metadata.get('namespace')!=namespace or metadata.get('name')!=name or metadata.get('labels',{}).get('atmem.ai/operator-package')!=prefix or expected not in references:raise ValueError('Refuse unrelated cron source ownership')
221
+ if len(references)!=1 or not metadata.get('uid')or not metadata.get('resourceVersion'):raise ValueError('Ambiguous cron source identity')
222
+
223
+ def schedule_spec(job,action):
224
+ return {'schedule':'17 2 * * *'if action=='maintain'else'7 * * * *','timezone':'UTC','contentType':'application/json','data':'{}','sink':{'ref':{'apiVersion':'codeengine.cloud.ibm.com/v1beta1','kind':'JobDefinition','name':job['metadata']['name']}}}
225
+
226
+ def verify_ready(value,expected):
227
+ spec=value.get('spec',{})
228
+ if any(spec.get(key)!=child for key,child in expected.items()):raise ValueError('Cron configuration differs from the owned task contract')
229
+ status=value.get('status',{});generation=value['metadata'].get('generation')
230
+ if type(generation)is not int or status.get('observedGeneration')!=generation or not any(c.get('type')=='Ready'and c.get('status')=='True'for c in status.get('conditions',[])):raise ValueError('Cron source has not reconciled this generation')
231
+
232
+ def schedules(value,env,install):
233
+ if install and not value['maintenanceEnabled']:raise ValueError('Enable reviewed operating alerts before installing schedules')
234
+ target=commands(value,'monitor')[:2];target[1]=[*target[1],'--kubecfg']
235
+ for command in target:subprocess.run(command,cwd=ROOT,env=env,check=True,timeout=120)
236
+ namespace=kubectl(env,['config','view','--minify','-o','jsonpath={.contexts[0].context.namespace}'])
237
+ if not re.fullmatch(r'[a-z0-9][a-z0-9-]{0,62}',namespace):raise ValueError('Use the selected native project namespace')
238
+ prefix=value['names']['monitor'].removesuffix('-monitor');result=[]
239
+ # Observe both targets and ownership boundaries before making either write.
240
+ pending=[]
241
+ for action in ['maintain','monitor']:
242
+ job=get_resource(env,'jobdefinitions.codeengine.cloud.ibm.com',value['names'][action],namespace)
243
+ metadata=job.get('metadata',{})
244
+ if job.get('apiVersion')!='codeengine.cloud.ibm.com/v1beta1'or job.get('kind')!='JobDefinition'or metadata.get('name')!=value['names'][action]or metadata.get('namespace')!=namespace or not metadata.get('uid'):raise ValueError('Use the actual owned IBM JobDefinition')
245
+ name=value['names'][action]+'-timer';current=get_resource(env,'pingsources.sources.knative.dev',name,namespace,optional=True)
246
+ if current is not None:ownership(current,job,namespace,prefix,name)
247
+ pending.append((action,job,name,current))
248
+ for action,job,name,current in pending:
249
+ spec=schedule_spec(job,action)
250
+ if install:
251
+ if current is None:
252
+ document={'apiVersion':'sources.knative.dev/v1','kind':'PingSource','metadata':{'name':name,'namespace':namespace,'labels':{'atmem.ai/operator-package':prefix},'ownerReferences':[{'apiVersion':'codeengine.cloud.ibm.com/v1beta1','kind':'JobDefinition','name':job['metadata']['name'],'uid':job['metadata']['uid'],'controller':False,'blockOwnerDeletion':False}]},'spec':spec}
253
+ kubectl(env,['create','-f','-','-o','json'],document)
254
+ elif any(current.get('spec',{}).get(key)!=child for key,child in spec.items()):
255
+ # Retain existing metadata/UID and resourceVersion. Native API
256
+ # conflicts fail; never --force, adopt or retry an overwrite.
257
+ document=copy.deepcopy(current);document.pop('status',None);document['spec']=spec
258
+ kubectl(env,['replace','-f','-','-o','json'],document)
259
+ kubectl(env,['wait','--for=condition=Ready','pingsources.sources.knative.dev/'+name,'--namespace',namespace,'--timeout=120s'])
260
+ actual=get_resource(env,'pingsources.sources.knative.dev',name,namespace)
261
+ ownership(actual,job,namespace,prefix,name);verify_ready(actual,spec)
262
+ result.append({'action':action,'name':name,'uid':actual['metadata']['uid'],'generation':actual['metadata']['generation'],'ready':True})
263
+ print(json.dumps({'format':'invoice-ibm-schedules-v1','sources':result,'jobExecutionValidated':False}))
264
+
265
+ def main():
266
+ parser=argparse.ArgumentParser(description=__doc__)
267
+ parser.add_argument('action',choices=['initialize','maintain','monitor','install-schedules','check-schedules']);parser.add_argument('--execute',action='store_true');args=parser.parse_args()
268
+ value=configuration();scheduling=args.action in {'install-schedules','check-schedules'}
269
+ if not args.execute:
270
+ plan=commands(value,'monitor')[:2]if scheduling else commands(value,args.action)
271
+ print(json.dumps({'execute':False,'commands':plan,'cloudOperations':False,'schedules':{action:{'job':value['names'][action],'cron':'17 2 * * *'if action=='maintain'else'7 * * * *','timezone':'UTC'}for action in ['maintain','monitor']}if scheduling else None}));return
272
+ with private_context()as env:
273
+ if scheduling:schedules(value,env,args.action=='install-schedules')
274
+ else:
275
+ for index,command in enumerate(commands(value,args.action)):subprocess.run(command,cwd=ROOT,env=env,check=True,timeout=1100 if index==2 else 120)
276
+
277
+ if __name__=='__main__':main()
278
+ `;
@@ -0,0 +1,142 @@
1
+ import {invoiceBuilder,v,r,l,UUID}from'./invoice-builder.mjs';
2
+ import {ibmRegistryHostExpression,ibmRegistryRegionValidation}from'./ibm-registry.mjs';
3
+ import {ibmInvoiceOperations}from'./invoice-ibm-operations.mjs';
4
+ import providerLock from'./runtime/invoice-ibm-provider-lock.json'with{type:'json'};
5
+
6
+ // Native composition under qualification; no cloud operation is performed here.
7
+ export function ibmInvoiceTerraform(project,row,environment='staging'){
8
+ if(row.provider!=='ibm')throw Error('IBM invoice compilation cannot substitute another cloud');
9
+ const b=invoiceBuilder(project,row,environment),{input,add,region}=b,n=row.address;
10
+ const account=input('account_id','Expected existing IBM Cloud account. No account is created.','a'.repeat(32),'^[0-9a-f]{32}$');
11
+ const group=input('resource_group_name','Existing reviewed destination resource group; never recreated.','reviewed-applications','^[A-Za-z0-9 _.-]{1,128}$');
12
+ const model=input('model_id','Reviewed regional watsonx JSON-object model; verify lifecycle, regional availability and processing terms.','ibm/reviewed-model','^[a-z0-9][a-z0-9_.-]{0,79}/[a-z0-9][a-z0-9_.-]{0,99}$');
13
+ const wxProject=input('watsonx_project_id','Existing watsonx project; authorize only the worker trusted profile and associate its runtime instance.','22222222-2222-2222-2222-222222222222',UUID);
14
+ const instance=input('runtime_instance_id','Existing associated watsonx.ai Runtime instance GUID, not a deployment ID.','33333333-3333-3333-3333-333333333333',UUID);
15
+ const endpoint=input('accounting_endpoint','Existing reviewed accounting HTTPS adapter; never provision a replacement.','https://accounting.example.test/actions','^https://[A-Za-z0-9.-]+(:[0-9]{1,5})?(/[^?#@ ]*)?$');
16
+ const scope=input('accounting_scope','Reviewed accounting scope bound to each approval.','owned-team','^[A-Za-z0-9_.:/-]{1,200}$');
17
+ const pull=input('registry_pull_secret','Name of the separately populated registry-pull secret in the new owned Code Engine project. No credential in Terraform.','registry-pull','^[a-z][a-z0-9-]{1,61}[a-z0-9]$');
18
+ if(!row.region)b.variable.region.validation=ibmRegistryRegionValidation();
19
+ for(const purpose of ['runtime','parser']){
20
+ input(purpose+'_image','Reviewed immutable image in this package-owned regional registry namespace. Empty during foundation.','au.icr.io/reviewed-namespace/'+purpose+'@sha256:'+'a'.repeat(64));b.variable[purpose+'_image'].default='';
21
+ b.variable[purpose+'_image'].validation={condition:'${!(var.applications_enabled'+(purpose==='runtime'?' || var.operations_enabled':'')+') || can(regex("@sha256:[0-9a-f]{64}$",var.'+purpose+'_image))}',error_message:'Use the reviewed immutable image digest before releasing applications.'};
22
+ b.resource.terraform_data.review_gate.lifecycle.precondition.push({condition:'${!(var.applications_enabled'+(purpose==='runtime'?' || var.operations_enabled':'')+') || startswith(var.'+purpose+'_image,format("%s/%s/'+purpose+'@sha256:",'+ibmRegistryHostExpression().slice(2,-1)+',local.name))}',error_message:'Images must use the exact owned regional registry namespace, not an invented hostname or foreign repository.'});
23
+ b.testExpressions[purpose+'_image']='format("au.icr.io/invoice-%s/'+purpose+'@sha256:'+'a'.repeat(64)+'",substr(sha256('+JSON.stringify(b.seed)+'),0,12))';
24
+ }
25
+ b.variable.staff_subjects={type:'set(string)',default:[],description:'Explicit existing admin-enrolled App ID subjects. Application membership/reviewer grants are separately admitted in SQL.',validation:{condition:'${alltrue([for subject in var.staff_subjects : can(regex("^[A-Za-z0-9_.:@-]{1,200}$",subject))])}',error_message:'Use exact verified staff subjects, never public signup or display-name guesses.'}};b.examples.staff_subjects=['44444444-4444-4444-4444-444444444444'];
26
+ b.variable.policy_review_base64={type:'string',default:'',description:'Scoped expiring model privacy/processing-terms review. Empty blocks inference; no approval is fabricated.'};b.examples.policy_review_base64='';
27
+ b.variable.replay_review_base64={type:'string',default:'',description:'Scoped expiring acceptance of actual accounting idempotency. Empty disables automatic uncertain replay.'};b.examples.replay_review_base64='';
28
+ b.data.ibm_resource_group={destination:{name:group}};
29
+ b.resource.terraform_data.review_gate.lifecycle.precondition.push({condition:'${data.ibm_resource_group.destination.account_id == var.account_id && (!var.applications_enabled || length(var.staff_subjects)>0)}',error_message:'Verify the destination account and explicit staff admission before release.'});
30
+ const rg=r('data.ibm_resource_group','destination','id'),projectId=r('ibm_code_engine_project',n,'project_id');
31
+ Object.assign(b.locals,{destination_contract:{id:'normalized-action-v1',endpointSha256:'${sha256(var.accounting_endpoint)}',scope,mappingVersion:1},destination_contract_base64:'${base64encode(jsonencode(local.destination_contract))}',database_config_name:l('name')+'-database',parser_secret_name:l('name')+'-parser',api_secret_name:l('name')+'-api-sql',worker_secret_name:l('name')+'-worker',bucket_name:'${format("%s-%s",local.name,substr(var.account_id,0,8))}'});
32
+ add('ibm_code_engine_project',n,{name:l('name'),resource_group_id:rg,lifecycle:{prevent_destroy:true}});
33
+ add('ibm_cr_namespace',n,{name:l('name'),resource_group_id:rg,lifecycle:{prevent_destroy:true}});
34
+ // Use the maintained Classic private-service endpoint contract, not an assumed
35
+ // direct Code Engine -> VPC/Gen2 route. There is no public SQL fallback.
36
+ add('ibm_database',n,{name:l('name'),service:'databases-for-postgresql',plan:'standard',location:region,resource_group_id:rg,version:'18',service_endpoints:'private',deletion_protection:true,group:{group_id:'member',memory:{allocation_mb:2048},disk:{allocation_mb:20480},members:{allocation_count:2}},configuration:JSON.stringify({log_statement:'none',log_min_error_statement:'panic',log_parameter_max_length_on_error:0}),lifecycle:{prevent_destroy:true}});
37
+ add('ibm_resource_instance',n+'_documents',{name:l('name')+'-documents',service:'cloud-object-storage',plan:'standard',location:'global',resource_group_id:rg,lifecycle:{prevent_destroy:true}});
38
+ add('ibm_cos_bucket',n,{bucket_name:l('bucket_name'),resource_instance_id:r('ibm_resource_instance',n+'_documents','id'),region_location:region,storage_class:'standard',endpoint_type:'public',force_delete:false,object_versioning:{enable:true},lifecycle:{prevent_destroy:true}});
39
+ add('ibm_cos_bucket_lifecycle_configuration',n,{bucket_crn:r('ibm_cos_bucket',n,'crn'),bucket_location:region,endpoint_type:'public',lifecycle_rule:[{rule_id:'invoice-originals-90-days',status:'enable',filter:{prefix:'accounts/'},expiration:{days:90},noncurrent_version_expiration:{noncurrent_days:1}},{rule_id:'unfinished-upload-cleanup',status:'enable',filter:{prefix:'accounts/'},abort_incomplete_multipart_upload:{days_after_initiation:1}}]});
40
+ for(const purpose of ['api','worker']){
41
+ add('ibm_iam_trusted_profile',n+'_'+purpose,{name:l('name')+'-'+purpose,description:'Dedicated invoice '+purpose+'; SQL login and business membership are independent.'});
42
+ add('ibm_iam_trusted_profile_link',n+'_'+purpose,{count:'${var.applications_enabled ? 1 : 0}',profile_id:r('ibm_iam_trusted_profile',n+'_'+purpose,'profile_id'),cr_type:'CE',link:{crn:r('ibm_code_engine_project',n,'crn'),component_name:l('name')+'-'+purpose,component_type:'app'},depends_on:['ibm_code_engine_app.'+n+'_'+purpose]});
43
+ add('ibm_iam_trusted_profile_policy',n+'_'+purpose+'_documents',{iam_id:r('ibm_iam_trusted_profile',n+'_'+purpose,'iam_id'),roles:purpose==='api'?['Object Reader','Object Writer']:['Object Reader'],resources:{service:'cloud-object-storage',resource_instance_id:r('ibm_resource_instance',n+'_documents','guid'),resource_type:'bucket',resource:l('bucket_name')}});
44
+ }
45
+ add('ibm_iam_trusted_profile_policy',n+'_model',{iam_id:r('ibm_iam_trusted_profile',n+'_worker','iam_id'),roles:['Writer'],resources:{service:'pm-20',resource_instance_id:instance,region},description:'Instance-scoped native watsonx role. Writer is broader than prediction-only; separate project collaborator admission remains required.'});
46
+ add('ibm_resource_instance',n+'_identity',{name:l('name')+'-staff',service:'appid',plan:'graduated-tier',location:region,resource_group_id:rg,lifecycle:{prevent_destroy:true}});
47
+ const tenant=r('ibm_resource_instance',n+'_identity','guid'),client=r('ibm_appid_application',n,'client_id');
48
+ add('ibm_appid_application',n,{tenant_id:tenant,name:l('name'),type:'singlepageapp'});
49
+ add('ibm_appid_application_scopes',n,{tenant_id:tenant,client_id:client,scopes:['process']});
50
+ add('ibm_appid_role',n,{tenant_id:tenant,name:'InvoiceStaff',access:[{application_id:client,scopes:['process']}],depends_on:['ibm_appid_application_scopes.'+n]});
51
+ add('ibm_appid_user_roles',n,{for_each:'${var.applications_enabled ? var.staff_subjects : toset([])}',tenant_id:tenant,subject:'${each.value}',role_ids:[r('ibm_appid_role',n,'role_id')]});
52
+ add('ibm_appid_idp_cloud_directory',n,{tenant_id:tenant,is_active:true,signup_enabled:false,self_service_enabled:false,welcome_enabled:false,reset_password_enabled:true,reset_password_notification_enabled:true,identity_field:'email',identity_confirm_access_mode:'FULL',identity_confirm_methods:['email']});
53
+ for(const idp of ['google','facebook','saml'])add('ibm_appid_idp_'+idp,n,{tenant_id:tenant,is_active:false});
54
+ const literal=(name,value)=>({name,value,type:'literal'}),reference=(name,type,key,ref)=>({name,type,key,reference:ref});
55
+ const common={ACCOUNT_ID:l('account_uuid'),REGION:region,WORKFLOW_NAMESPACE:'invoice',DATABASE_NAME:'ibmclouddb',DOCUMENT_BUCKET:l('bucket_name'),DESTINATION_CONTRACT_BASE64:l('destination_contract_base64')};
56
+ for(const purpose of ['api','worker','parser']){
57
+ const settings=purpose==='parser'?{PARSER_AUTH_MODE:'shared-token'}:purpose==='api'?{...common,SERVICE_NAME:l('name')+'-api',PUBLIC_ORIGIN_MODE:'code-engine-default',DATABASE_USER:l('api_db_user'),IAM_PROFILE_ID:r('ibm_iam_trusted_profile',n+'_api','profile_id'),APPID_TENANT_ID:tenant,APPID_CLIENT_ID:client,APPID_ISSUER:r('ibm_appid_application',n,'oauth_server_url'),AUTH_SCOPE:l('name')+'/process'}:{...common,DATABASE_USER:l('worker_db_user'),IAM_PROFILE_ID:r('ibm_iam_trusted_profile',n+'_worker','profile_id'),IBM_ACCOUNT_ID:account,WATSONX_PROJECT_ID:wxProject,RUNTIME_INSTANCE_ID:instance,MODEL_REGION:region,MODEL_ID:model,MAX_OUTPUT_TOKENS:'2048',POLICY_REVIEW_BASE64:v('policy_review_base64'),PARSER_ENDPOINT:r('ibm_code_engine_app',n+'_parser[0]','endpoint')+'/extract',DESTINATION_ENDPOINT:endpoint,DESTINATION_SCOPE:scope,DESTINATION_REPLAY_REVIEW_BASE64:v('replay_review_base64')};
58
+ const env=Object.entries(settings).map(([name,value])=>literal(name,value));
59
+ if(purpose!=='parser')env.push(...[['DATABASE_HOST','host'],['DATABASE_PORT','port'],['DATABASE_CA_PEM','ca_pem']].map(([name,key])=>reference(name,'config_map_key_reference',key,l('database_config_name'))),reference('DATABASE_PASSWORD','secret_key_reference','password',l(purpose==='api'?'api_secret_name':'worker_secret_name')));
60
+ if(purpose==='worker')env.push(reference('DESTINATION_TOKEN','secret_key_reference','accounting_token',l('worker_secret_name')));
61
+ if(purpose!=='api')env.push(reference('PARSER_SHARED_TOKEN','secret_key_reference','token',l('parser_secret_name')));
62
+ add('ibm_code_engine_app',n+'_'+purpose,{count:'${var.applications_enabled ? 1 : 0}',project_id:projectId,name:l('name')+'-'+purpose,image_reference:v(purpose==='parser'?'parser_image':'runtime_image'),image_secret:pull,image_port:8080,managed_domain_mappings:purpose==='api'?'local_public':purpose==='parser'?'local_private':'local',run_as_user:10001,run_service_account:'none',run_compute_resource_token_enabled:purpose!=='parser',scale_cpu_limit:'1',scale_memory_limit:purpose==='parser'?'2G':'1G',scale_min_instances:1,scale_max_instances:1,scale_concurrency:purpose==='api'?32:1,scale_concurrency_target:purpose==='api'?16:1,scale_request_timeout:purpose==='parser'?150:300,run_env_variables:env,...(purpose==='api'?{}:{run_commands:['python','-I','/app/'+(purpose==='worker'?'invoice_worker.py':'invoice_parser_service.py')]}),probe_readiness:{type:'http',path:'/healthz',port:8080,initial_delay:2,interval:5,timeout:2,failure_threshold:12},depends_on:purpose==='parser'?[]:['ibm_iam_trusted_profile_policy.'+n+'_'+purpose+'_documents',...(purpose==='worker'?['ibm_iam_trusted_profile_policy.'+n+'_model']:[])]});
63
+ }
64
+ add('ibm_appid_redirect_urls',n,{count:'${var.applications_enabled ? 1 : 0}',tenant_id:tenant,urls:[r('ibm_code_engine_app',n+'_api[0]','endpoint')+'/']});
65
+ b.output.application_url={value:'${var.applications_enabled ? ibm_code_engine_app.'+n+'_api[0].endpoint : null}'};
66
+ b.output.code_engine_project={value:projectId};b.output.registry={value:ibmRegistryHostExpression()+'/'+l('name')};
67
+ b.output.operator_deployment={value:{provider:'ibm',deploymentId:l('account_uuid'),accountId:l('account_uuid'),namespace:'invoice',tenantId:null,bindings:Object.fromEntries(['api','worker'].map(purpose=>[purpose,{name:l(purpose+'_db_user'),principal:'${uuidv5("url",'+JSON.stringify(b.seed+'/'+purpose+'-sql-credential')+')}'}]))}};
68
+ b.output.database_bootstrap={value:{deploymentCrn:r('ibm_database',n,'id'),database:'ibmclouddb',projectId,databaseConfig:l('database_config_name'),apiSecret:l('api_secret_name'),workerSecret:l('worker_secret_name'),parserSecret:l('parser_secret_name'),registryPullSecret:pull}};
69
+ ibmInvoiceOperations(b,n,{projectId,pull});
70
+ b.files['CODE_ENGINE_INPUTS.md']=IBM_INPUTS;
71
+ b.assertions.push(`run "private_database_and_parser" {\n command = plan\n assert {\n condition = ibm_database.${n}.service_endpoints == "private" && ibm_database.${n}.version == "18" && ibm_database.${n}.deletion_protection\n error_message = "Retain private native PostgreSQL and recovery protection."\n }\n assert {\n condition = ibm_code_engine_app.${n}_parser[0].managed_domain_mappings == "local_private" && !ibm_code_engine_app.${n}_parser[0].run_compute_resource_token_enabled && ibm_code_engine_app.${n}_parser[0].run_service_account == "none"\n error_message = "Untrusted PDF parser has private TLS and no cloud compute/API identity."\n }\n assert {\n condition = startswith(ibm_code_engine_app.${n}_api[0].image_reference,"au.icr.io/") && ibm_code_engine_app.${n}_worker[0].scale_min_instances == 1\n error_message = "Use the actual Sydney registry hostname and retain the background worker."\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(ibm_code_engine_app.${n}_api) == 0 && length(ibm_code_engine_app.${n}_worker) == 0 && length(ibm_code_engine_app.${n}_parser) == 0 && length(ibm_code_engine_job.${n}_operator_initialize) == 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.test/runtime@sha256:${'a'.repeat(64)}" }\n expect_failures = [terraform_data.review_gate]\n}\nrun "empty_staff_rejected" {\n command = plan\n variables { staff_subjects = [] }\n expect_failures = [terraform_data.review_gate]\n}\nrun "wrong_account_rejected" {\n command = plan\n variables { account_id = "${'c'.repeat(32)}" }\n expect_failures = [terraform_data.review_gate]\n}`);
72
+ let mock='mock_provider "ibm" {\n override_during = plan\n mock_data "ibm_resource_group" { defaults = { id="'+ 'b'.repeat(32)+'",account_id="'+'a'.repeat(32)+'" } }\n mock_resource "ibm_code_engine_project" { defaults = { project_id="11111111-1111-4111-8111-111111111111",crn="crn:v1:bluemix:public:codeengine:au-syd:a/'+ 'a'.repeat(32)+':11111111-1111-4111-8111-111111111111::" } }\n mock_resource "ibm_resource_instance" { defaults = { guid="55555555-5555-4555-8555-555555555555",id="crn:v1:bluemix:public:cloud-object-storage:global:a/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:55555555-5555-4555-8555-555555555555::" } }\n mock_resource "ibm_iam_trusted_profile" { defaults = { profile_id="Profile-66666666-6666-4666-8666-666666666666",iam_id="iam-Profile-66666666-6666-4666-8666-666666666666" } }\n mock_resource "ibm_appid_application" { defaults = { client_id="77777777-7777-4777-8777-777777777777",oauth_server_url="https://au-syd.appid.cloud.ibm.com/oauth/v4/55555555-5555-4555-8555-555555555555" } }\n}\n';
73
+ mock+='override_resource {\n override_during = plan\n target = ibm_cos_bucket.'+n+'\n values = { crn = "crn:v1:bluemix:public:cloud-object-storage:global:a/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:55555555-5555-4555-8555-555555555555:bucket:fixture-invoices" }\n}\n';
74
+ for(const [purpose,digit]of [['api','6'],['worker','8']])mock+='override_resource {\n override_during = plan\n target = ibm_iam_trusted_profile.'+n+'_'+purpose+'\n values = '+JSON.stringify({profile_id:'Profile-'+digit.repeat(8)+'-'+digit.repeat(4)+'-4'+digit.repeat(3)+'-8'+digit.repeat(3)+'-'+digit.repeat(12),iam_id:'iam-Profile-'+digit.repeat(8)+'-'+digit.repeat(4)+'-4'+digit.repeat(3)+'-8'+digit.repeat(3)+'-'+digit.repeat(12)})+'\n}\n';
75
+ for(const purpose of ['api','parser'])mock+='override_resource {\n override_during = plan\n target = ibm_code_engine_app.'+n+'_'+purpose+'[0]\n values = { endpoint = format("https://invoice-%s-'+purpose+'.project-fixture.'+(purpose==='parser'?'private.':'')+'au-syd.codeengine.appdomain.cloud",substr(sha256('+JSON.stringify(b.seed)+'),0,12)) }\n}\n';
76
+ return b.finish({ibm:{region}},{ibm:{source:'IBM-Cloud/ibm',version:providerLock.version}},providerLock.lock,mock,IBM_GUIDE);
77
+ }
78
+ const IBM_GUIDE=`# IBM invoice workflow (under qualification)
79
+
80
+ A new owned Code Engine project hosts the public App ID/PKCE staff API, a minimum-one
81
+ background queue worker and a separate private-TLS parser. Only worker/parser hold
82
+ the parser-only 256-bit admission token; it grants no cloud/document/SQL/action
83
+ permission. The parser has neither a compute resource token nor Code Engine API
84
+ service-account authority. API and worker use separate native trusted profiles,
85
+ SQL logins and secret references. Staff authentication is separate from live SQL
86
+ membership and reviewer authority; public self-registration is disabled.
87
+
88
+ The dedicated PostgreSQL 18 Classic instance uses private IBM service endpoints;
89
+ no unimplemented direct VPC/Gen2 route or public SQL fallback is asserted. Exact
90
+ regional service availability, private connectivity, CA verification and inherited
91
+ permissions require authorized destination checks. Documents are private, versioned
92
+ and stored regionally with a 90-day current / one-day noncurrent lifecycle. The
93
+ regional S3 API uses authenticated TLS. Cloud control-plane/log/backup behavior and
94
+ account policy need separate review; no exact erasure deadline is promised.
95
+
96
+ Sydney Container Registry uses au.icr.io, not au-syd.icr.io. The namespace is owned
97
+ by this package. Foundation creates resources with applications_enabled=false.
98
+ CODE_ENGINE_INPUTS.md specifies separately populated config/secret references.
99
+ Publish immutable reviewed images only when authorized, initialize SQL and staff
100
+ membership through the separate operator, then review application release. The
101
+ worker's instance-scoped watsonx Writer role is broader than prediction-only;
102
+ separate project collaborator admission and the scoped model policy review remain
103
+ required. An empty policy review blocks inference and never fabricates approval.
104
+
105
+ Native schemas/mocks and local images do not prove the real account, IBM private
106
+ network, model processing, restore or deployment. Full managed operator/scheduled
107
+ retention delivery, monitoring, state strategy, registry/Spec Kit admission and the
108
+ complete conversation/export checks remain qualification work. No cloud operation
109
+ is performed by generating this package. Preserve the external accounting system.
110
+ `;
111
+ const IBM_INPUTS=`# Code Engine foundation inputs and ownership
112
+
113
+ Use the database_bootstrap and operator_deployment outputs, not guessed identifiers.
114
+ The new database's built-in application database is ibmclouddb; the separate operator
115
+ owns the new workflow schema. Application SQL passwords are distinct strong random
116
+ values created outside Terraform. Native trusted profiles authorize COS/model
117
+ access, not database login: operator bindings use stable owned credential UUIDs,
118
+ not a false claim of native IAM-to-SQL authentication.
119
+
120
+ In the new Code Engine project, an authorized operator creates these references
121
+ from private mode-0600 inputs, without placing secret values in Terraform/state:
122
+ - registry_pull_secret: native registry configuration, private namespace pull only.
123
+ - databaseConfig config map: exact private host, port, native PEM ca_pem and operator_user.
124
+ - operator_jobs.operatorSecret: separate operator SQL password; only operating tasks.
125
+ - apiSecret generic secret: password for the generated API SQL login only.
126
+ - workerSecret generic secret: worker SQL password and existing accounting_token.
127
+ - parserSecret generic secret: token, exactly 64 lowercase hexadecimal characters
128
+ from 32 cryptographically random bytes; only worker and parser reference it.
129
+
130
+ Read native connection/CA metadata for this exact database deployment. Never use a
131
+ public hostname or weaken TLS verification to bypass private connectivity. Supply
132
+ bootstrap's private operator files and create both nonadministrative logins, exact
133
+ schema/grants and memberships. Native CA/token rotation requires an explicit rollout;
134
+ rotate parser/worker together and verify old/missing tokens are denied. The parent
135
+ parser removes the token from its environment and its native tools use a minimal
136
+ explicit environment. This is not an OS sandbox or proof of inherited platform IAM.
137
+
138
+ The API derives its same-origin policy only from documented Code Engine app/domain/
139
+ subdomain/region settings matched to its compiler-owned service name. No request
140
+ Host or Forwarded header chooses a trusted origin. The App ID redirect resource
141
+ references the created API endpoint after creation, avoiding a Terraform cycle.
142
+ `;
@@ -0,0 +1,143 @@
1
+ export const INVOICE_OPERATIONS=`# Invoice workflow operations
2
+
3
+ This is a private staff application. The generated API and worker SQL identities
4
+ cannot create accounts, admit staff, erase audit history or perform operator repairs.
5
+ Keep the schema-owner credential separate. No command below authorizes deployment.
6
+
7
+ ## Bootstrap and staff access
8
+
9
+ Run Terraform foundation with applications_enabled=false. Review the actual account,
10
+ regional availability, costs, private network access and provider identity settings.
11
+ Supply the real accounting endpoint, scope and native secret outside Terraform state.
12
+ Build, scan and publish the emitted API/worker and parser images when authorized;
13
+ pin their exact digests in the emitted repositories before enabling applications.
14
+
15
+ Create a private .local directory (mode 0700), and keep all operator input files mode
16
+ 0600 and outside source control. Run the operator from the emitted application
17
+ directory, using a Python 3.13 environment installed with requirements.lock hashes.
18
+ The operator needs an approved connection path to the private native database.
19
+ Never expose PostgreSQL publicly to make bootstrap easier.
20
+
21
+ operator-connection.json has exactly these fields:
22
+ host, port (integer), dbname, user, passwordFile, caFile.
23
+ The password/token and reviewed native PEM CA are absolute separate file paths.
24
+ There is no inline password, insecure TLS option or arbitrary connection string.
25
+ AWS includes rds-global-ca.pem plus its pinned public-source receipt; verify native
26
+ CA availability for the selected database and update/rebuild before CA expiry.
27
+ IBM supplies its database-specific CA and separately provisioned SQL passwords.
28
+ Azure's operator must be authorized for native Entra mapping in postgres as well as
29
+ schema administration in the application database. Google native IAM SQL users must
30
+ exist before the separate schema/grant step. Short-lived tokens must remain valid
31
+ for the bounded operator action; the tool does not silently acquire extra privilege.
32
+
33
+ operator-deployment.json has exactly: provider, deploymentId (UUID), accountId (UUID),
34
+ namespace (invoice), bindings (api and worker), tenantId (Azure UUID, otherwise null).
35
+ Each binding has name and principal; Google additionally has created_by_package:true.
36
+ Use exact Terraform outputs/native identity subjects, never guessed display names.
37
+ AWS emits the complete nonsecret operator_deployment output. With an approved
38
+ foundation and private connection available, retain that output in the private file.
39
+
40
+ Preview (no database connection or write):
41
+
42
+ python -I invoice_operator.py initialize --connection-file .local/operator-connection.json --deployment-file .local/operator-deployment.json
43
+
44
+ Add --execute only for the reviewed authorized destination. Initialization creates
45
+ owned native login mappings, the exact version-1 schema/queue and restricted grants.
46
+ It refuses to adopt an unrelated role or schema. Re-running the exact owned bootstrap
47
+ is supported; a changed schema requires a reviewed migration, not reinitialization.
48
+ IBM initialization additionally reads --input-file with apiPasswordFile and
49
+ workerPasswordFile pointing to private strong passwords; never rotate existing
50
+ owned passwords implicitly. Roll out credentials explicitly when rotating them.
51
+
52
+ Membership uses --input-file containing subject (verified native login subject),
53
+ roles (explicit array of user/reviewer/supervisor/owner), active (boolean):
54
+
55
+ python -I invoice_operator.py membership --connection-file .local/operator-connection.json --deployment-file .local/operator-deployment.json --input-file .local/member.json --execute
56
+
57
+ Inviting/signing in at the native identity service does not automatically grant
58
+ application membership. Ordinary staff get user; three designated reviewers get
59
+ reviewer. Revocation uses active:false; role replacement is explicit. Native JWT
60
+ expiry and live SQL membership are different boundaries. Test both at the destination.
61
+
62
+ ## Ninety-day retention
63
+
64
+ The invoice API and processing stages refuse payloads whose creation time is outside
65
+ the 90-day retention window, including data recovered from old backups. Private-store
66
+ lifecycles remove original objects separately; version/noncurrent deletion and native
67
+ provider deletion are asynchronous. Backups may retain expired data for the stated
68
+ backup window. This is not an exact physical-deletion deadline or legal-retention SLA.
69
+
70
+ AWS, Azure and Google emit fixed operating jobs/schedules in OPERATING_JOBS.md.
71
+ The IBM native job adapter remains under qualification; do not assume its schedules
72
+ exist. The shared job entrypoint supports preview (without --execute), initialize,
73
+ maintain and monitor using the emitted owned metadata and separate operator identity.
74
+ It is never an API/model endpoint.
75
+
76
+ For the manual CLI maintenance path, pause uploads/API and workers, allow bounded
77
+ work to settle, then run:
78
+
79
+ python -I invoice_operator.py purge-expired --connection-file .local/operator-connection.json --deployment-file .local/operator-deployment.json --execute --confirm-workloads-stopped
80
+
81
+ It removes at most 500 expired operations, their historical suggestions/audit and
82
+ owned queue notifications per transaction. Repeat while moreMayRemain is true.
83
+ Active queue jobs/live leases cause rollback; settle them before retrying. Other
84
+ accounts/namespaces, staff memberships and young records are preserved. Retain the
85
+ count-only maintenance receipt and alert on failure/overdue runs. The fixed
86
+ maintain job additionally bounds a whole execution to twenty 500-record batches,
87
+ reports remaining backlog nonzero and uses the same live-job/lease/ownership guards
88
+ for online expired-only cleanup. Concurrent young submissions are serialized by
89
+ transaction locks and preserved. Restore/reconciliation still require the isolated
90
+ paused boundary. See the provider-specific native job definitions for scheduling;
91
+ a script file alone does not establish that a schedule exists.
92
+
93
+ Deduplication is scoped to the retained operation lifetime. Do not promise unlimited
94
+ historical deduplication after the client-directed 90-day payload/audit deletion.
95
+ Destination operators must independently retain the idempotency identity as required
96
+ by their accounting contract. Do not clear an unknown outcome to resend it.
97
+
98
+ ## Backup, restore and uncertain deliveries
99
+
100
+ Review native managed backup retention, encryption, restore region and current
101
+ provider procedures. Restore to an isolated new database/endpoint with API/workers
102
+ stopped. Do not point running workers at a restored snapshot: the accounting service
103
+ may have accepted deliveries after that snapshot's recovery point.
104
+
105
+ With private operator files explicitly pointing to the isolated restored database:
106
+
107
+ python -I invoice_operator.py quarantine-restore --connection-file .local/restored-connection.json --deployment-file .local/operator-deployment.json --execute --confirm-workloads-stopped
108
+
109
+ Repeat while moreMayRemain is true. The tool fences restored approved/in-flight
110
+ deliveries as unknown, preserves approval hashes and clears stale queue notifications.
111
+ Interrupted extraction leases are fenced back to pending; the normal worker rebuilds
112
+ those notifications after expiry cleanup. This avoids retaining a restored doing
113
+ job forever or restarting an old external delivery. Attempt limits are preserved.
114
+ The stopped-workloads flag is an operator assertion, not proof that cloud workloads
115
+ were stopped. Purge expired restored records before reopening. Reapply reviewed native
116
+ runtime identity grants/membership as appropriate; verify current revocations and
117
+ object versions. Exercise read, denied access, fresh extraction and same-key behavior
118
+ on an isolated synthetic fixture before cutover. Keep old endpoints for rollback;
119
+ never dual-run workers on divergent databases. A local logical restore test does not
120
+ prove native PITR, object recovery, production RPO/RTO or destination availability.
121
+
122
+ For each uncertain delivery, independently query the existing accounting system by
123
+ operation ID and payload digest. If it confirms completion, store a private JSON
124
+ receipt with operation_id, payload_sha256, external_id and accountable operator:
125
+
126
+ python -I invoice_operator.py reconcile-completed --connection-file .local/operator-connection.json --deployment-file .local/operator-deployment.json --input-file .local/verified-receipt.json --execute --confirm-workloads-stopped
127
+
128
+ The tool checks exact ownership/state/approval integrity and records the supplied
129
+ receipt without making an external request. It does not verify the human's accounting
130
+ lookup. A missing receipt is not permission to resend. Automatic same-key replay needs
131
+ the scoped, expiring destination-contract review described in the worker configuration.
132
+ Never rewrite an approved payload, endpoint, account or idempotency key for a retry.
133
+
134
+ ## Monitoring and release checks
135
+
136
+ Alert on stale pending/approved work, dead/unknown outcomes, repeated parser/model
137
+ failures, storage/database growth and failed retention windows. Healthz means process
138
+ alive; it does not establish database/model/destination readiness. Keep payloads,
139
+ credentials and document text out of telemetry. Scale worker/parser capacity together
140
+ after throughput/quota tests. Before production, qualify native sign-in/token expiry,
141
+ workload IAM, private ingress, TLS, native storage versions, actual model quality,
142
+ external accounting idempotency and restore/cutover with authorized destination tests.
143
+ `;