@atmem/architect 0.0.0-stage → 0.2.0-alpha.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (498) hide show
  1. package/CONSTITUTION.md +144 -0
  2. package/README.md +33 -2
  3. package/agent-skills/discovery/SKILL.md +48 -0
  4. package/agent-skills/discovery/topics.json +139 -0
  5. package/agent-skills/generation-capabilities.json +760 -0
  6. package/agent-skills/service-lifecycle.json +21 -0
  7. package/agent-skills/specialists/architecture/SKILL.md +15 -0
  8. package/agent-skills/specialists/aws/SKILL.md +17 -0
  9. package/agent-skills/specialists/azure/SKILL.md +7 -0
  10. package/agent-skills/specialists/composition/SKILL.md +17 -0
  11. package/agent-skills/specialists/devops/SKILL.md +10 -0
  12. package/agent-skills/specialists/finops/SKILL.md +7 -0
  13. package/agent-skills/specialists/gcp/SKILL.md +7 -0
  14. package/agent-skills/specialists/ibm/SKILL.md +7 -0
  15. package/agent-skills/specialists/manifest.json +13 -0
  16. package/agent-skills/specialists/pulumi/SKILL.md +7 -0
  17. package/agent-skills/specialists/security/SKILL.md +7 -0
  18. package/agent-skills/specialists/terraform/SKILL.md +14 -0
  19. package/agent-skills/upstream/aws/LICENSE +175 -0
  20. package/agent-skills/upstream/aws/SKILL.md +125 -0
  21. package/agent-skills/upstream/azure/LICENSE +21 -0
  22. package/agent-skills/upstream/azure/SKILL.md +387 -0
  23. package/agent-skills/upstream/gcp/LICENSE +202 -0
  24. package/agent-skills/upstream/gcp/SKILL.md +159 -0
  25. package/agent-skills/upstream/manifest.json +57 -0
  26. package/agent-skills/upstream/pulumi/LICENSE +201 -0
  27. package/agent-skills/upstream/pulumi/SKILL.md +501 -0
  28. package/agent-skills/upstream/terraform/LICENSE +373 -0
  29. package/agent-skills/upstream/terraform/SKILL.md +316 -0
  30. package/agent-skills/workflows/workflows.json +601 -0
  31. package/cli/architect.mjs +3 -0
  32. package/cli/runtime.mjs +115 -0
  33. package/dist/assets/html2canvas.esm-QH1iLAAe.js +22 -0
  34. package/dist/assets/index-B97MkVMs.css +1 -0
  35. package/dist/assets/index-qtCM2D7O.js +21271 -0
  36. package/dist/assets/index.es-C6C0sneB.js +18 -0
  37. package/dist/assets/purify.es-CAi2OJFm.js +3 -0
  38. package/dist/assets/visual-export-DjbjgQbA.js +173 -0
  39. package/dist/favicon.svg +2 -0
  40. package/dist/fonts/DM-Sans-OFL.txt +93 -0
  41. package/dist/fonts/Manrope-OFL.txt +93 -0
  42. package/dist/fonts/NotoSans-Regular.ttf +0 -0
  43. package/dist/fonts/OFL.txt +94 -0
  44. package/dist/fonts/dm-sans-latin-wght-normal.woff2 +0 -0
  45. package/dist/fonts/manrope-latin-wght-normal.woff2 +0 -0
  46. package/dist/index.html +4 -0
  47. package/dist/licenses/aws-architect-LICENSE.txt +17 -0
  48. package/dist/licenses/aws-mcp-LICENSE.txt +175 -0
  49. package/dist/licenses/aws-mcp-NOTICE.txt +1 -0
  50. package/dist/licenses/cloud-emulation-notices.txt +36619 -0
  51. package/dist/licenses/dependency-notices.txt +6379 -0
  52. package/dist/licenses/emulation-notices.txt +717 -0
  53. package/dist/licenses/github-copilot-sdk-LICENSE.txt +21 -0
  54. package/dist/licenses/memory-dependency-notices.txt +3319 -0
  55. package/dist/licenses/openarchflow-LICENSE.txt +21 -0
  56. package/dist/licenses/python-dependency-notices.txt +11951 -0
  57. package/docs/upstream-lock.json +26 -0
  58. package/knowledge/engineering-practices.json +536 -0
  59. package/package.json +30 -4
  60. package/packaging/uv-release-lock.json +54 -0
  61. package/public/licenses/aws-architect-LICENSE.txt +17 -0
  62. package/public/licenses/aws-mcp-LICENSE.txt +175 -0
  63. package/public/licenses/aws-mcp-NOTICE.txt +1 -0
  64. package/public/licenses/cloud-emulation-notices.txt +36619 -0
  65. package/public/licenses/dependency-notices.txt +6379 -0
  66. package/public/licenses/emulation-notices.txt +717 -0
  67. package/public/licenses/github-copilot-sdk-LICENSE.txt +21 -0
  68. package/public/licenses/memory-dependency-notices.txt +3319 -0
  69. package/public/licenses/openarchflow-LICENSE.txt +21 -0
  70. package/public/licenses/python-dependency-notices.txt +11951 -0
  71. package/scripts/terraform-render.mjs +8 -0
  72. package/server/__init__.py +0 -0
  73. package/server/abstraction.py +28 -0
  74. package/server/agent_runtime.py +153 -0
  75. package/server/app.py +257 -0
  76. package/server/architect.py +112 -0
  77. package/server/architecture_activity.py +67 -0
  78. package/server/attachments.py +101 -0
  79. package/server/cloud-emulation-requirements.txt +29 -0
  80. package/server/codex_app_server.py +219 -0
  81. package/server/codex_engineering_backend.py +266 -0
  82. package/server/codex_worker_policy.py +170 -0
  83. package/server/contracts.py +315 -0
  84. package/server/copilot_worker.py +16 -0
  85. package/server/dependency_mirror.py +54 -0
  86. package/server/design_patch.py +43 -0
  87. package/server/emulation-requirements.txt +8 -0
  88. package/server/emulation_adapters.py +20 -0
  89. package/server/emulation_routes.py +98 -0
  90. package/server/emulation_worker.py +351 -0
  91. package/server/engineering_artifacts.py +215 -0
  92. package/server/engineering_assets/application-runtime.json +4372 -0
  93. package/server/engineering_assets/architecture_work.schema.json +79 -0
  94. package/server/engineering_assets/materialize_runtime.py +62 -0
  95. package/server/engineering_assets/prepare_tools.py +96 -0
  96. package/server/engineering_assets/sql_validation.py +59 -0
  97. package/server/engineering_contexts.py +120 -0
  98. package/server/engineering_delivery.py +210 -0
  99. package/server/engineering_finalization.py +210 -0
  100. package/server/engineering_handoff.py +163 -0
  101. package/server/engineering_jobs.py +206 -0
  102. package/server/engineering_knowledge.py +75 -0
  103. package/server/engineering_reconciliation.py +159 -0
  104. package/server/engineering_routes.py +469 -0
  105. package/server/engineering_sessions.py +273 -0
  106. package/server/engineering_tools.py +166 -0
  107. package/server/generation_lint.py +18 -0
  108. package/server/local_providers.py +181 -0
  109. package/server/local_validation.py +236 -0
  110. package/server/memory-requirements.lock +181 -0
  111. package/server/memory-requirements.txt +6 -0
  112. package/server/memory_routes.py +82 -0
  113. package/server/memory_service.py +273 -0
  114. package/server/memory_worker.py +66 -0
  115. package/server/openai_voice.py +80 -0
  116. package/server/packaged_app.py +9 -0
  117. package/server/pricing.py +84 -0
  118. package/server/process_control_observation.py +31 -0
  119. package/server/prompts.py +123 -0
  120. package/server/public_faq_emulation_worker.py +44 -0
  121. package/server/requirements.lock +1618 -0
  122. package/server/requirements.txt +68 -0
  123. package/server/runtime_dependency_locks.py +27 -0
  124. package/server/runtime_evidence.py +93 -0
  125. package/server/settings.py +14 -0
  126. package/server/skills.py +103 -0
  127. package/server/storage_emulation_worker.py +160 -0
  128. package/server/structured_emulation_worker.py +48 -0
  129. package/server/terraform_routes.py +118 -0
  130. package/server/upstream/__init__.py +0 -0
  131. package/server/upstream/agent/__init__.py +1 -0
  132. package/server/upstream/agent/aws_architect.py +600 -0
  133. package/server/upstream/agent/config/__init__.py +1 -0
  134. package/server/upstream/agent/config/agent_config.py +82 -0
  135. package/server/upstream/agent/config/prompts.py +138 -0
  136. package/server/upstream/agent/rate_limiter.py +62 -0
  137. package/server/upstream/utils/__init__.py +1 -0
  138. package/server/upstream/utils/file_writer.py +43 -0
  139. package/server/validation_applicability.py +85 -0
  140. package/server/validation_jobs.py +252 -0
  141. package/server/validation_workers.py +48 -0
  142. package/server/voice_routes.py +91 -0
  143. package/server/voice_worker.py +26 -0
  144. package/specs/028-convergence-evaluation/evidence/20261110-ibm-invoice-native/registry-structured/qualification.json +72 -0
  145. package/specs/028-convergence-evaluation/evidence/20261110-invoice-runtime/durable-current/receipt.json +61 -0
  146. package/specs/029-general-purpose-engine/evidence/20261111-runtime-dependencies/sdk/receipt.json +22 -0
  147. package/src/ArchitectureActivity.jsx +54 -0
  148. package/src/ArchitectureWorkPanel.jsx +46 -0
  149. package/src/ArtifactChecks.jsx +49 -0
  150. package/src/BlockRequirements.jsx +13 -0
  151. package/src/BrainActivity.jsx +11 -0
  152. package/src/ChatMessage.jsx +19 -0
  153. package/src/ChatResizeHandle.jsx +6 -0
  154. package/src/CodePreview.jsx +8 -0
  155. package/src/ComponentReview.jsx +31 -0
  156. package/src/DeliveryViews.jsx +59 -0
  157. package/src/EmulationPanel.jsx +44 -0
  158. package/src/EngagementViews.jsx +385 -0
  159. package/src/EngineeringPanel.jsx +151 -0
  160. package/src/ImplementationDelivery.jsx +55 -0
  161. package/src/JourneyViews.jsx +400 -0
  162. package/src/MemoryPanel.jsx +46 -0
  163. package/src/OpenAIVoicePanel.jsx +65 -0
  164. package/src/OutputsView.jsx +65 -0
  165. package/src/TerraformView.jsx +57 -0
  166. package/src/WorkbenchDialogs.jsx +532 -0
  167. package/src/activity-presentation.mjs +28 -0
  168. package/src/ai-qualification-scenarios.mjs +31 -0
  169. package/src/approval-application-files.mjs +32 -0
  170. package/src/approval-applications.mjs +82 -0
  171. package/src/approval-spec-kit.mjs +30 -0
  172. package/src/architecture-activity.css +28 -0
  173. package/src/architecture-activity.mjs +63 -0
  174. package/src/architecture-work.mjs +176 -0
  175. package/src/artifact-work.mjs +103 -0
  176. package/src/async-documents.mjs +191 -0
  177. package/src/atflow.css +1140 -0
  178. package/src/atforma.css +748 -0
  179. package/src/atmem-tokens.css +79 -0
  180. package/src/aws-preflight.mjs +60 -0
  181. package/src/aws-public-faq.mjs +102 -0
  182. package/src/aws-validation-scenarios.mjs +10 -0
  183. package/src/aws-validation.mjs +48 -0
  184. package/src/azure-plan-mocks.mjs +25 -0
  185. package/src/azure-structured.mjs +133 -0
  186. package/src/bedrock-summary.mjs +152 -0
  187. package/src/bounded-rag.mjs +60 -0
  188. package/src/brand.css +9 -0
  189. package/src/canvas-view.mjs +28 -0
  190. package/src/capability-composition.mjs +44 -0
  191. package/src/chat-attachments.mjs +13 -0
  192. package/src/cloud-provider-locks.mjs +9 -0
  193. package/src/cloud-storage-scenarios.mjs +2 -0
  194. package/src/component-review.mjs +55 -0
  195. package/src/composition-spec-kit.mjs +30 -0
  196. package/src/consultation-context.mjs +15 -0
  197. package/src/consultation.mjs +52 -0
  198. package/src/container-contracts.mjs +5 -0
  199. package/src/container-inspection.mjs +75 -0
  200. package/src/container-runtime.mjs +30 -0
  201. package/src/container-security-inspection.mjs +49 -0
  202. package/src/container-terraform.mjs +109 -0
  203. package/src/conversation.mjs +17 -0
  204. package/src/core.mjs +863 -0
  205. package/src/cross-cloud-storage.mjs +100 -0
  206. package/src/delivery-capabilities.mjs +25 -0
  207. package/src/delivery.mjs +58 -0
  208. package/src/deployment-ownership.mjs +10 -0
  209. package/src/deployment-region.mjs +11 -0
  210. package/src/derive.mjs +31 -0
  211. package/src/design-build-flow.mjs +10 -0
  212. package/src/diagram-attention.mjs +24 -0
  213. package/src/discovery.mjs +359 -0
  214. package/src/document.mjs +170 -0
  215. package/src/emulation-feedback.mjs +61 -0
  216. package/src/emulation-guidance.mjs +37 -0
  217. package/src/engagement.mjs +274 -0
  218. package/src/engineering-client.mjs +73 -0
  219. package/src/engineering-defaults.mjs +17 -0
  220. package/src/engineering.css +31 -0
  221. package/src/enterprise-application.mjs +76 -0
  222. package/src/enterprise-aws-host-infrastructure.mjs +62 -0
  223. package/src/enterprise-aws-host-tests.mjs +15 -0
  224. package/src/enterprise-aws-infrastructure-tests.mjs +38 -0
  225. package/src/enterprise-aws-infrastructure.mjs +138 -0
  226. package/src/enterprise-google-infrastructure.mjs +84 -0
  227. package/src/enterprise-google-tests.mjs +25 -0
  228. package/src/estimate.mjs +188 -0
  229. package/src/existing-references.mjs +18 -0
  230. package/src/external-identities.mjs +17 -0
  231. package/src/faq-lambda-build.mjs +28 -0
  232. package/src/gcp-structured.mjs +104 -0
  233. package/src/generation-provider.mjs +7 -0
  234. package/src/generation-quality.mjs +69 -0
  235. package/src/handoff.mjs +141 -0
  236. package/src/ibm-registry.mjs +12 -0
  237. package/src/ibm-structured.mjs +103 -0
  238. package/src/identifiers.mjs +15 -0
  239. package/src/implementation-map.mjs +14 -0
  240. package/src/implementation-outcome.mjs +8 -0
  241. package/src/incomplete-terraform.mjs +9 -0
  242. package/src/integrations.ts +137 -0
  243. package/src/interface-contracts.mjs +30 -0
  244. package/src/invoice-application.mjs +66 -0
  245. package/src/invoice-aws-operations.mjs +136 -0
  246. package/src/invoice-aws.mjs +143 -0
  247. package/src/invoice-azure-operations.mjs +147 -0
  248. package/src/invoice-azure.mjs +134 -0
  249. package/src/invoice-builder.mjs +35 -0
  250. package/src/invoice-dependencies.mjs +43 -0
  251. package/src/invoice-gcp-operations.mjs +178 -0
  252. package/src/invoice-gcp.mjs +104 -0
  253. package/src/invoice-ibm-operations.mjs +278 -0
  254. package/src/invoice-ibm.mjs +142 -0
  255. package/src/invoice-operations.mjs +143 -0
  256. package/src/invoice-plan.mjs +45 -0
  257. package/src/invoice-region.mjs +6 -0
  258. package/src/invoice-spec-kit.mjs +61 -0
  259. package/src/invoice-state.mjs +7 -0
  260. package/src/invoice-terraform.mjs +29 -0
  261. package/src/invoice-tests.mjs +122 -0
  262. package/src/journey-workspace.css +72 -0
  263. package/src/journey.mjs +87 -0
  264. package/src/levels.mjs +145 -0
  265. package/src/local-agent.mjs +184 -0
  266. package/src/main.jsx +2458 -0
  267. package/src/model-policy-preflight.mjs +34 -0
  268. package/src/openai-voice.mjs +102 -0
  269. package/src/output-bundle.mjs +11 -0
  270. package/src/ownership-inspection.mjs +28 -0
  271. package/src/pack.mjs +201 -0
  272. package/src/pricing.mjs +31 -0
  273. package/src/production-state.mjs +8 -0
  274. package/src/project-copy.mjs +10 -0
  275. package/src/project-file.mjs +160 -0
  276. package/src/project-links.mjs +3 -0
  277. package/src/protected-state.mjs +43 -0
  278. package/src/public-faq-builder.mjs +19 -0
  279. package/src/public-faq-clouds.mjs +251 -0
  280. package/src/public-faq.mjs +122 -0
  281. package/src/pulumi.mjs +123 -0
  282. package/src/python-container.mjs +25 -0
  283. package/src/python-runtime.mjs +50 -0
  284. package/src/rag-handler.mjs +43 -0
  285. package/src/rag-web-assets.mjs +52 -0
  286. package/src/rag-web.mjs +68 -0
  287. package/src/records.mjs +177 -0
  288. package/src/resources.mjs +163 -0
  289. package/src/review.mjs +252 -0
  290. package/src/runtime/EnterpriseDocument.java +89 -0
  291. package/src/runtime/approved_http_destination.py +72 -0
  292. package/src/runtime/aws-lambda-qualification-lock.json +7 -0
  293. package/src/runtime/aws-python-lock.json +82 -0
  294. package/src/runtime/aws-web-python-lock.json +887 -0
  295. package/src/runtime/aws_json_model.py +42 -0
  296. package/src/runtime/azure-python-lock.json +863 -0
  297. package/src/runtime/azure-sources.json +8 -0
  298. package/src/runtime/azure-test-lock.json +23 -0
  299. package/src/runtime/azure_acceptance.py +192 -0
  300. package/src/runtime/azure_structured.py +153 -0
  301. package/src/runtime/bounded_rag.py +126 -0
  302. package/src/runtime/catalog_admin.py +70 -0
  303. package/src/runtime/cloud-sql-proxy-lock.json +8 -0
  304. package/src/runtime/cloud-sql-proxy-security-review.json +30 -0
  305. package/src/runtime/connector_cli.py +50 -0
  306. package/src/runtime/connector_sync.py +70 -0
  307. package/src/runtime/durable-python-lock.json +247 -0
  308. package/src/runtime/durable_workflow.py +325 -0
  309. package/src/runtime/enterprise-application-manifest.json +110 -0
  310. package/src/runtime/enterprise-application-sources.json +266 -0
  311. package/src/runtime/enterprise-auth-python-lock.json +592 -0
  312. package/src/runtime/enterprise-aws-host-bootstrap-source.json +1 -0
  313. package/src/runtime/enterprise-aws-host-probe-source.json +1 -0
  314. package/src/runtime/enterprise-aws-task-template.json +235 -0
  315. package/src/runtime/enterprise-document-lock.json +18 -0
  316. package/src/runtime/enterprise-document.Dockerfile +15 -0
  317. package/src/runtime/enterprise-runtime-aws-python-lock.json +1115 -0
  318. package/src/runtime/enterprise-runtime-azure-python-lock.json +1106 -0
  319. package/src/runtime/enterprise-runtime-gcp-python-lock.json +1060 -0
  320. package/src/runtime/enterprise-runtime-ibm-python-lock.json +1096 -0
  321. package/src/runtime/enterprise-runtime-python-lock.json +1058 -0
  322. package/src/runtime/enterprise-runtime.Dockerfile +15 -0
  323. package/src/runtime/enterprise-web-app.js +1 -0
  324. package/src/runtime/enterprise-web-entry.js +105 -0
  325. package/src/runtime/enterprise-web-lock.json +29 -0
  326. package/src/runtime/enterprise-web-notices.txt +229 -0
  327. package/src/runtime/enterprise-web.css +4 -0
  328. package/src/runtime/enterprise-web.html +8 -0
  329. package/src/runtime/enterprise_audit.py +91 -0
  330. package/src/runtime/enterprise_audit_schema.sql +25 -0
  331. package/src/runtime/enterprise_auth_schema.sql +67 -0
  332. package/src/runtime/enterprise_auth_store.py +241 -0
  333. package/src/runtime/enterprise_aws_host_bootstrap.py +120 -0
  334. package/src/runtime/enterprise_aws_host_probe.py +105 -0
  335. package/src/runtime/enterprise_aws_hosts.py +136 -0
  336. package/src/runtime/enterprise_aws_jobs.py +300 -0
  337. package/src/runtime/enterprise_aws_objects.py +93 -0
  338. package/src/runtime/enterprise_aws_transfer.py +83 -0
  339. package/src/runtime/enterprise_azure_batch_api.py +128 -0
  340. package/src/runtime/enterprise_azure_host.py +599 -0
  341. package/src/runtime/enterprise_azure_jobs.py +294 -0
  342. package/src/runtime/enterprise_azure_objects.py +234 -0
  343. package/src/runtime/enterprise_azure_pool.py +161 -0
  344. package/src/runtime/enterprise_azure_transfer.py +122 -0
  345. package/src/runtime/enterprise_configuration.py +136 -0
  346. package/src/runtime/enterprise_document.py +116 -0
  347. package/src/runtime/enterprise_document_cli.py +32 -0
  348. package/src/runtime/enterprise_document_contract.py +54 -0
  349. package/src/runtime/enterprise_document_job.py +109 -0
  350. package/src/runtime/enterprise_document_jobs.py +122 -0
  351. package/src/runtime/enterprise_document_jobs_schema.sql +23 -0
  352. package/src/runtime/enterprise_extraction_cache.py +186 -0
  353. package/src/runtime/enterprise_extraction_schema.sql +17 -0
  354. package/src/runtime/enterprise_google_jobs.py +275 -0
  355. package/src/runtime/enterprise_google_transfer.py +85 -0
  356. package/src/runtime/enterprise_http.py +212 -0
  357. package/src/runtime/enterprise_identity.py +52 -0
  358. package/src/runtime/enterprise_knowledge.py +152 -0
  359. package/src/runtime/enterprise_models.py +94 -0
  360. package/src/runtime/enterprise_native.py +181 -0
  361. package/src/runtime/enterprise_oauth.py +132 -0
  362. package/src/runtime/enterprise_operator.py +160 -0
  363. package/src/runtime/enterprise_parser_service.py +136 -0
  364. package/src/runtime/enterprise_parser_transport.py +68 -0
  365. package/src/runtime/enterprise_queries.py +255 -0
  366. package/src/runtime/enterprise_queries_schema.sql +27 -0
  367. package/src/runtime/enterprise_query_service.py +111 -0
  368. package/src/runtime/enterprise_secrets.py +110 -0
  369. package/src/runtime/enterprise_sessions.py +95 -0
  370. package/src/runtime/enterprise_sources.py +260 -0
  371. package/src/runtime/enterprise_web.py +39 -0
  372. package/src/runtime/enterprise_worker.py +68 -0
  373. package/src/runtime/export_contract_acceptance.py +18 -0
  374. package/src/runtime/faq-output-contract.json +40 -0
  375. package/src/runtime/faq-web-app.js +41 -0
  376. package/src/runtime/faq-web.css +1 -0
  377. package/src/runtime/faq-web.html +6 -0
  378. package/src/runtime/gcp-sources.json +9 -0
  379. package/src/runtime/gcp_acceptance.py +110 -0
  380. package/src/runtime/gcp_structured.py +150 -0
  381. package/src/runtime/http_acceptance.py +39 -0
  382. package/src/runtime/iap-web-app.js +36 -0
  383. package/src/runtime/iap-web-source.json +1 -0
  384. package/src/runtime/ibm-python-lock.json +856 -0
  385. package/src/runtime/ibm-sources.json +9 -0
  386. package/src/runtime/ibm_acceptance.py +133 -0
  387. package/src/runtime/ibm_structured.py +113 -0
  388. package/src/runtime/invoice-azapi-provider-lock.json +7 -0
  389. package/src/runtime/invoice-ibm-provider-lock.json +7 -0
  390. package/src/runtime/invoice-parser-lock.json +1199 -0
  391. package/src/runtime/invoice-parser-python-lock.json +56 -0
  392. package/src/runtime/invoice-parser.Dockerfile +190 -0
  393. package/src/runtime/invoice-sources.json +58 -0
  394. package/src/runtime/invoice-test-sources.json +24 -0
  395. package/src/runtime/invoice-web.css +2 -0
  396. package/src/runtime/invoice-web.html +12 -0
  397. package/src/runtime/invoice-web.js +112 -0
  398. package/src/runtime/invoice_configuration.py +17 -0
  399. package/src/runtime/invoice_document.py +95 -0
  400. package/src/runtime/invoice_extraction.py +96 -0
  401. package/src/runtime/invoice_http.py +129 -0
  402. package/src/runtime/invoice_identity.py +5 -0
  403. package/src/runtime/invoice_maintenance.py +40 -0
  404. package/src/runtime/invoice_native.py +77 -0
  405. package/src/runtime/invoice_object_store.py +153 -0
  406. package/src/runtime/invoice_operations.py +108 -0
  407. package/src/runtime/invoice_operator.py +79 -0
  408. package/src/runtime/invoice_operator_core.py +39 -0
  409. package/src/runtime/invoice_operator_job.py +147 -0
  410. package/src/runtime/invoice_parser_cli.py +17 -0
  411. package/src/runtime/invoice_parser_identity.py +39 -0
  412. package/src/runtime/invoice_parser_service.py +89 -0
  413. package/src/runtime/invoice_parser_transport.py +89 -0
  414. package/src/runtime/invoice_processing.py +24 -0
  415. package/src/runtime/invoice_retention.py +16 -0
  416. package/src/runtime/invoice_runtime_secrets.py +43 -0
  417. package/src/runtime/invoice_stage.py +80 -0
  418. package/src/runtime/invoice_web.py +39 -0
  419. package/src/runtime/invoice_worker.py +50 -0
  420. package/src/runtime/lambda_faq.py +5 -0
  421. package/src/runtime/parser-requirements.lock +4 -0
  422. package/src/runtime/policy_review.py +18 -0
  423. package/src/runtime/postgres-qualification-lock.json +21 -0
  424. package/src/runtime/public-faq-sources.json +22 -0
  425. package/src/runtime/public_catalog_admin.py +122 -0
  426. package/src/runtime/public_catalog_store.py +125 -0
  427. package/src/runtime/public_faq.py +144 -0
  428. package/src/runtime/public_faq_app.py +49 -0
  429. package/src/runtime/python-container-lock.json +18 -0
  430. package/src/runtime/rag-sources.json +10 -0
  431. package/src/runtime/rag_acceptance.py +60 -0
  432. package/src/runtime/rag_aws_adapter.py +95 -0
  433. package/src/runtime/rds-ca-source.json +9 -0
  434. package/src/runtime/rds-global-ca.pem +2888 -0
  435. package/src/runtime/state-contract-check-source.json +4 -0
  436. package/src/runtime/state_contract_check.py +338 -0
  437. package/src/runtime/structured-source.json +1 -0
  438. package/src/runtime/structured-web-app.js +71 -0
  439. package/src/runtime/structured-web-source.json +1 -0
  440. package/src/runtime/structured_http.py +105 -0
  441. package/src/runtime/structured_output.py +48 -0
  442. package/src/runtime/web-python-lock.json +802 -0
  443. package/src/runtime/web_user_admin.py +44 -0
  444. package/src/runtime/workflow_application.py +62 -0
  445. package/src/runtime/workflow_bindings.py +128 -0
  446. package/src/runtime/workflow_configuration.py +40 -0
  447. package/src/runtime/workflow_connection.py +105 -0
  448. package/src/runtime/workflow_contract.py +54 -0
  449. package/src/runtime/workflow_database.py +94 -0
  450. package/src/runtime/workflow_errors.py +6 -0
  451. package/src/runtime/workflow_http.py +178 -0
  452. package/src/runtime/workflow_identity.py +69 -0
  453. package/src/runtime/workflow_payload.py +118 -0
  454. package/src/runtime/workflow_process_stage.py +88 -0
  455. package/src/runtime/workflow_profile.py +91 -0
  456. package/src/runtime/workflow_review.py +106 -0
  457. package/src/runtime/workflow_role_bootstrap.py +104 -0
  458. package/src/runtime/workflow_schema.sql +72 -0
  459. package/src/runtime/workflow_worker.py +142 -0
  460. package/src/runtime-settings.mjs +15 -0
  461. package/src/s3-access.mjs +14 -0
  462. package/src/source-contracts.mjs +17 -0
  463. package/src/spec-kit.mjs +186 -0
  464. package/src/state-custody.mjs +32 -0
  465. package/src/state-inspection.mjs +45 -0
  466. package/src/state-spec-kit.mjs +13 -0
  467. package/src/storage-tests.mjs +25 -0
  468. package/src/structured-api.mjs +133 -0
  469. package/src/structured-contract.mjs +19 -0
  470. package/src/structured-operation-policy.mjs +2 -0
  471. package/src/structured-web.mjs +17 -0
  472. package/src/style.css +1 -0
  473. package/src/system-description.mjs +26 -0
  474. package/src/terraform-admission.mjs +66 -0
  475. package/src/terraform-composition.mjs +83 -0
  476. package/src/terraform-expressions.mjs +46 -0
  477. package/src/terraform-validation-coverage.mjs +11 -0
  478. package/src/terraform.mjs +128 -0
  479. package/src/text-statistics.mjs +51 -0
  480. package/src/upstream/openarchflow/format-payload.ts +26 -0
  481. package/src/upstream/openarchflow/import/mermaid.ts +205 -0
  482. package/src/upstream/openarchflow/import/sql-ddl.ts +109 -0
  483. package/src/upstream/openarchflow/layout.ts +54 -0
  484. package/src/upstream/openarchflow/providers/aws.ts +196 -0
  485. package/src/upstream/openarchflow/providers/azure.ts +126 -0
  486. package/src/upstream/openarchflow/providers/cloudnative.ts +71 -0
  487. package/src/upstream/openarchflow/providers/generic.ts +227 -0
  488. package/src/upstream/openarchflow/providers/integration.ts +22 -0
  489. package/src/upstream/openarchflow/providers/types.ts +2 -0
  490. package/src/upstream/openarchflow/templates.ts +937 -0
  491. package/src/upstream-catalog.mjs +10 -0
  492. package/src/useChatScroll.jsx +36 -0
  493. package/src/useEmulation.jsx +36 -0
  494. package/src/validation-receipt.mjs +10 -0
  495. package/src/visual-export.mjs +92 -0
  496. package/src/voice-conversation.mjs +117 -0
  497. package/src/work-intake.mjs +24 -0
  498. package/src/workflow-runtime-inventory.mjs +3 -0
@@ -0,0 +1,178 @@
1
+ """Typed approval-workflow HTTP boundary with operator-owned tenant and policy.
2
+
3
+ No domain inference, identity provider, role administration or automatic execution
4
+ is provided here. Trusted bootstrap supplies the verifier, typed store and origin.
5
+ Acceptance means durable enqueue, never completed processing or delivery.
6
+ """
7
+ import asyncio
8
+ import json
9
+ import re
10
+ import threading
11
+ from fastapi import FastAPI, Request
12
+ from fastapi.responses import JSONResponse
13
+ from starlette.concurrency import run_in_threadpool
14
+ from durable_workflow import Principal, Denied, Missing, Conflict, identifier
15
+ from workflow_payload import PayloadContract
16
+ from workflow_configuration import owned_origin
17
+
18
+ MAX_BODY = 66000 # Includes the envelope; typed data itself remains <=64000.
19
+
20
+
21
+ class BodyTooLarge(ValueError): pass
22
+ class UnsupportedBody(ValueError): pass
23
+ class Busy(RuntimeError): pass
24
+
25
+
26
+ def public_operation(row, *, include_source=False):
27
+ result = {'id':str(row['id']), 'state':row['state'], 'revision':row['result_revision'],
28
+ 'result':row['result'], 'receipt':row['receipt'],
29
+ 'createdAt':row['created_at'].isoformat(), 'updatedAt':row['updated_at'].isoformat()}
30
+ if include_source: result['source'] = row['source_ref']
31
+ return result
32
+
33
+
34
+ async def body(request, fields):
35
+ types = request.headers.getlist('content-type')
36
+ if len(types) != 1 or types[0].split(';')[0].lower() != 'application/json':
37
+ raise UnsupportedBody('Use application/json')
38
+ lengths = request.headers.getlist('content-length')
39
+ if len(lengths) > 1 or lengths and not re.fullmatch(r'0|[1-9][0-9]{0,8}',lengths[0]):
40
+ raise ValueError('Use an exact body length')
41
+ expected = int(lengths[0]) if lengths else None
42
+ if expected is not None and expected > MAX_BODY: raise BodyTooLarge()
43
+ raw = bytearray()
44
+ async with asyncio.timeout(5):
45
+ async for chunk in request.stream():
46
+ if len(raw) + len(chunk) > MAX_BODY: raise BodyTooLarge()
47
+ raw.extend(chunk)
48
+ if expected is not None and len(raw) != expected: raise ValueError('Body length differs')
49
+ def unique(pairs):
50
+ result = {}
51
+ for key, value in pairs:
52
+ if key in result: raise ValueError('Duplicate application field')
53
+ result[key] = value
54
+ return result
55
+ def constant(_): raise ValueError('Nonfinite JSON is unsupported')
56
+ value = json.loads(raw.decode('utf-8'),object_pairs_hook=unique,parse_constant=constant)
57
+ if type(value) is not dict or set(value) != set(fields): raise ValueError('Use the exact operation envelope')
58
+ return value
59
+
60
+
61
+ def create_app(verify, store, *, account_id, public_origin, operation_kind='draft', token_header=None):
62
+ identifier(account_id); origin = owned_origin(public_origin)
63
+ if not callable(verify) or type(getattr(store,'payload_contract',None)) is not PayloadContract:
64
+ raise ValueError('Supply an owned verifier and typed application store')
65
+ if type(operation_kind) is not str or operation_kind not in {'document','draft','account_change'}: raise ValueError('Use an owned operation policy')
66
+ if getattr(store,'operation_kind',None) not in {None,operation_kind}: raise ValueError('HTTP and stored operation policies differ')
67
+ if token_header is not None and (type(token_header) is not str or token_header != 'x-goog-iap-jwt-assertion'): raise ValueError('Unsupported native identity transport')
68
+ app = FastAPI(docs_url=None,redoc_url=None,openapi_url=None)
69
+ policy = getattr(store, 'review_policy', None)
70
+ def representation(row): return public_operation(row, include_source=policy is not None)
71
+ slots = threading.BoundedSemaphore(20)
72
+ def error(code,status): return JSONResponse({'error':{'code':code}},status_code=status)
73
+ async def actor(request):
74
+ if token_header:
75
+ headers = request.headers.getlist(token_header)
76
+ token = headers[0] if len(headers) == 1 else ''
77
+ else:
78
+ headers = request.headers.getlist('authorization')
79
+ supplied = headers[0] if len(headers) == 1 else ''
80
+ token = supplied[7:] if supplied.startswith('Bearer ') else ''
81
+ if not token or len(token) > 16384: raise Denied('Verified identity required')
82
+ try: subject = await run_in_threadpool(verify,token)
83
+ except Exception: raise Denied('Verified identity required') from None
84
+ try: principal = Principal(account_id,subject)
85
+ except ValueError: raise Denied('Verified identity required') from None
86
+ await run_in_threadpool(store.authorize,principal)
87
+ return principal
88
+ async def mutation(request,fields):
89
+ user = await actor(request)
90
+ if request.query_params: raise ValueError('Mutations do not accept query configuration')
91
+ value = await body(request,fields)
92
+ if await actor(request) != user: raise Denied('Identity changed while reading input')
93
+ return user,value
94
+ @app.middleware('http')
95
+ async def boundary(request,next_handler):
96
+ acquired = False
97
+ try:
98
+ origins = request.headers.getlist('origin')
99
+ if len(origins) > 1 or origins and origins[0] != origin: raise Denied('Wrong application origin')
100
+ if request.method not in {'GET','HEAD','OPTIONS'}:
101
+ if origins != [origin]: raise Denied('Exact application origin required')
102
+ acquired = slots.acquire(blocking=False)
103
+ if not acquired: raise Busy()
104
+ response = await next_handler(request)
105
+ except Denied: response = error('access_denied',403)
106
+ except Missing: response = error('not_found',404)
107
+ except Conflict: response = error('conflict',409)
108
+ except BodyTooLarge: response = error('body_too_large',413)
109
+ except UnsupportedBody: response = error('unsupported_content_type',415)
110
+ except Busy: response = error('busy',429)
111
+ except TimeoutError: response = error('body_timeout',408)
112
+ except (ValueError,UnicodeError,RecursionError): response = error('invalid_request',400)
113
+ except Exception: response = error('unavailable',503)
114
+ finally:
115
+ if acquired: slots.release()
116
+ response.headers.update({'Cache-Control':'no-store','X-Content-Type-Options':'nosniff',
117
+ 'Referrer-Policy':'no-referrer','Strict-Transport-Security':'max-age=31536000',
118
+ 'Content-Security-Policy':"default-src 'none'; frame-ancestors 'none'; base-uri 'none'"})
119
+ return response
120
+ @app.get('/healthz')
121
+ def health(): return {'status':'running'}
122
+ @app.get('/api/session')
123
+ async def session(request:Request):
124
+ user = await actor(request)
125
+ if request.query_params: raise ValueError('No session overrides are accepted')
126
+ return {'roles':await run_in_threadpool(store.authorize,user),'accountMode':'operator-owned'}
127
+ @app.post('/api/operations',status_code=202)
128
+ async def submit(request:Request):
129
+ user,value = await mutation(request,['source'])
130
+ keys = request.headers.getlist('idempotency-key')
131
+ if len(keys) != 1 or not re.fullmatch(r'[A-Za-z0-9][A-Za-z0-9_.:-]{0,199}',keys[0]):
132
+ raise ValueError('Use a stable bounded operation key')
133
+ operation = await run_in_threadpool(store.submit,user,operation_kind,keys[0],value['source'])
134
+ return {'operation':representation(await run_in_threadpool(store.get,user,operation))}
135
+ @app.get('/api/operations')
136
+ async def listing(request:Request):
137
+ user = await actor(request)
138
+ if set(request.query_params)-{'before'} or len(request.query_params.getlist('before')) > 1:
139
+ raise ValueError('Use the bounded operation cursor')
140
+ rows = await run_in_threadpool(store.list,user,before=request.query_params.get('before'),limit=25)
141
+ return {'operations':[representation(row) for row in rows], 'next':str(rows[-1]['id']) if len(rows)==25 else None}
142
+ @app.get('/api/operations/{operation_id}')
143
+ async def detail(operation_id:str,request:Request):
144
+ user = await actor(request)
145
+ if request.query_params: raise ValueError('No operation overrides are accepted')
146
+ return {'operation':representation(await run_in_threadpool(store.get,user,operation_id))}
147
+ @app.post('/api/operations/{operation_id}/review')
148
+ async def review(operation_id:str,request:Request):
149
+ user,value = await mutation(request,['revision','result'])
150
+ if type(value['revision']) is not int: raise ValueError('Use an exact revision')
151
+ row = await run_in_threadpool(store.edit_result,user,operation_id,value['revision'],value['result'])
152
+ return {'operation':representation(row)}
153
+ if policy is not None:
154
+ @app.post('/api/operations/{operation_id}/inspect')
155
+ async def inspect(operation_id:str,request:Request):
156
+ user,_ = await mutation(request,[])
157
+ row = await run_in_threadpool(store.inspect,user,operation_id)
158
+ return {'operation':representation(row),'payloadSha256':store._fingerprint(row),
159
+ 'destination':row['destination_contract']}
160
+ @app.get('/api/operations/{operation_id}/history')
161
+ async def history(operation_id:str,request:Request):
162
+ user = await actor(request)
163
+ if set(request.query_params)-{'afterRevision'}: raise ValueError('Invalid history cursor')
164
+ cursors = request.query_params.getlist('afterRevision')
165
+ if len(cursors)>1 or cursors and not re.fullmatch(r'0|[1-9][0-9]{0,9}',cursors[0]): raise ValueError('Invalid history cursor')
166
+ rows = await run_in_threadpool(store.result_history,user,operation_id,after_revision=int(cursors[0]) if cursors else 0)
167
+ return {'history':[{'revision':r['revision'],'result':r['result'],'actor':r['actor'],
168
+ 'createdAt':r['created_at'].isoformat()} for r in rows]}
169
+ @app.post('/api/operations/{operation_id}/approve')
170
+ async def approve(operation_id:str,request:Request):
171
+ user,value = await mutation(request,['revision','payloadSha256'] if policy is not None else ['revision'])
172
+ if type(value['revision']) is not int: raise ValueError('Use an exact revision')
173
+ if policy is not None:
174
+ row = await run_in_threadpool(store.approve,user,operation_id,value['revision'],value['payloadSha256'])
175
+ else:
176
+ row = await run_in_threadpool(store.approve,user,operation_id,value['revision'])
177
+ return {'operation':representation(row)}
178
+ return app
@@ -0,0 +1,69 @@
1
+ """Native staff login bindings. Database membership remains authoritative for roles.
2
+
3
+ Configuration is compiler/operator-owned. Never derive a signing-key URL, tenant,
4
+ issuer, OAuth audience or processing role from caller claims or document content.
5
+ JWT validity is bounded by expiry, not a claim of continuous IdP revocation.
6
+ """
7
+ from dataclasses import dataclass
8
+ import re
9
+ import uuid
10
+ import jwt
11
+ from durable_workflow import Denied
12
+
13
+ UUID=r'[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}'
14
+
15
+ class CognitoStaffVerifier:
16
+ def __init__(self,region,pool_id,client_id,scope,*,jwks=None):
17
+ if(not isinstance(region,str)or not re.fullmatch(r'[a-z]{2}-[a-z]+-[0-9]',region)
18
+ or not isinstance(pool_id,str)or not re.fullmatch(re.escape(region)+r'_[A-Za-z0-9]{1,55}',pool_id)
19
+ or not isinstance(client_id,str)or not re.fullmatch(r'[a-z0-9]{1,128}',client_id)
20
+ or not isinstance(scope,str)or not re.fullmatch(r'[A-Za-z0-9_.-]{1,80}/process',scope)):raise ValueError('Use the exact owned Cognito pool/client/scope')
21
+ self.issuer='https://cognito-idp.'+region+'.amazonaws.com/'+pool_id;self.client_id=client_id;self.scope=scope
22
+ self.jwks=jwks or jwt.PyJWKClient(self.issuer+'/.well-known/jwks.json',timeout=2,lifespan=300)
23
+ def __call__(self,token):
24
+ try:
25
+ if not isinstance(token,str)or not 1<=len(token)<=16384:raise Denied('Verified staff identity required')
26
+ key=self.jwks.get_signing_key_from_jwt(token).key
27
+ # Cognito ACCESS tokens bind the app client in client_id, rather than
28
+ # the ID token's aud. Never accept an ID token as an API credential.
29
+ claims=jwt.decode(token,key,algorithms=['RS256'],issuer=self.issuer,options={'verify_aud':False,'require':['iss','sub','exp','iat','client_id','token_use','scope','username']})
30
+ if(claims['token_use']!='access'or claims['client_id']!=self.client_id
31
+ or not isinstance(claims['scope'],str)or self.scope not in claims['scope'].split()
32
+ or not isinstance(claims['sub'],str)or str(uuid.UUID(claims['sub']))!=claims['sub']
33
+ or not isinstance(claims['username'],str)or not claims['username']
34
+ or any(type(claims[name])is not int for name in ['iat','exp'])or not 0<claims['exp']-claims['iat']<=3600):raise Denied('Verified staff identity required')
35
+ return claims['sub']
36
+ except Exception:raise Denied('Verified staff identity required')from None
37
+
38
+ @dataclass(frozen=True)
39
+ class StaffIdentity:
40
+ verify:object
41
+ public_configuration:dict
42
+ token_header:str|None=None
43
+
44
+ def native_staff_identity(provider,settings,*,jwks=None):
45
+ if not isinstance(settings,dict)or any(not isinstance(value,str)for value in settings.values()):raise ValueError('Use owned native staff identity settings')
46
+ patterns={
47
+ 'aws':{'REGION':r'[a-z]{2}-[a-z]+-[0-9]','POOL_ID':r'[a-z]{2}-[a-z]+-[0-9]_[A-Za-z0-9]{1,55}','CLIENT_ID':r'[a-z0-9]{1,128}','AUTH_ORIGIN':r'https://[a-z0-9][a-z0-9-]{0,61}[a-z0-9]\.auth\.[a-z]{2}-[a-z]+-[0-9]\.amazoncognito\.com','AUTH_SCOPE':r'[A-Za-z0-9_.-]{1,80}/process'},
48
+ 'azure':{'TENANT_ID':UUID,'API_CLIENT_ID':UUID,'SPA_CLIENT_ID':UUID},
49
+ 'gcp':{'PROJECT_NUMBER':r'[0-9]{6,20}','REGION':r'[a-z]+-[a-z]+[0-9]','SERVICE_NAME':r'[a-z][a-z0-9-]{4,47}[a-z0-9]'},
50
+ 'ibm':{'APPID_TENANT_ID':UUID,'APPID_CLIENT_ID':UUID,'APPID_ISSUER':r'https://[a-z]{2}-[a-z]+\.appid\.cloud\.ibm\.com/oauth/v4/'+UUID,'AUTH_SCOPE':r'[A-Za-z0-9_.-]{1,80}/process'}}
51
+ if provider not in patterns or set(settings)!=set(patterns[provider])or any(not re.fullmatch(patterns[provider][name],value)for name,value in settings.items()):raise ValueError('Use exact reviewed native staff identity settings')
52
+ c=dict(settings)
53
+ if provider=='aws':
54
+ if not c['AUTH_ORIGIN'].endswith('.auth.'+c['REGION']+'.amazoncognito.com'):raise ValueError('Cognito authorization region differs from the owned pool')
55
+ verify=CognitoStaffVerifier(c['REGION'],c['POOL_ID'],c['CLIENT_ID'],c['AUTH_SCOPE'],jwks=jwks)
56
+ public={'mode':'oauth-pkce','authOrigin':c['AUTH_ORIGIN'],'authorizationEndpoint':c['AUTH_ORIGIN']+'/oauth2/authorize','tokenEndpoint':c['AUTH_ORIGIN']+'/oauth2/token','clientId':c['CLIENT_ID'],'scopes':'openid '+c['AUTH_SCOPE']}
57
+ elif provider=='azure':
58
+ from azure_structured import EntraVerifier
59
+ verify=EntraVerifier(c,jwks);authority='https://login.microsoftonline.com/'+c['TENANT_ID']+'/oauth2/v2.0'
60
+ public={'mode':'oauth-pkce','authOrigin':'https://login.microsoftonline.com','authorizationEndpoint':authority+'/authorize','tokenEndpoint':authority+'/token','clientId':c['SPA_CLIENT_ID'],'scopes':'openid api://'+c['API_CLIENT_ID']+'/access_as_user'}
61
+ elif provider=='gcp':
62
+ from gcp_structured import IapVerifier
63
+ return StaffIdentity(IapVerifier(c,jwks),{'mode':'proxy','loginPath':'/','logoutPath':None},'x-goog-iap-jwt-assertion')
64
+ else:
65
+ from ibm_structured import AppIdVerifier
66
+ if not c['APPID_ISSUER'].endswith('/oauth/v4/'+c['APPID_TENANT_ID']):raise ValueError('App ID issuer tenant differs from the owned tenant')
67
+ verify=AppIdVerifier(c,jwks);issuer=c['APPID_ISSUER'];origin=issuer.split('/oauth/v4/')[0]
68
+ public={'mode':'oauth-pkce','authOrigin':origin,'authorizationEndpoint':issuer+'/authorization','tokenEndpoint':issuer+'/token','clientId':c['APPID_CLIENT_ID'],'scopes':'openid '+c['AUTH_SCOPE']}
69
+ return StaffIdentity(verify,public)
@@ -0,0 +1,118 @@
1
+ """Versioned bounded application data contracts, independent of domain/provider.
2
+
3
+ This is a small closed contract language, not a JSON Schema implementation.
4
+ Operator-selected contracts describe data, never roles, executable validation,
5
+ destinations or transitions. Domain semantic checks remain the adapter's duty.
6
+ """
7
+ from dataclasses import dataclass
8
+ import hashlib
9
+ import json
10
+ import re
11
+
12
+
13
+ def encoded(value):
14
+ def exact(item, depth=0):
15
+ if depth > 32: raise ValueError('Application JSON exceeds its nesting boundary')
16
+ if type(item) is dict:
17
+ if any(type(k) is not str for k in item): raise ValueError('Application object keys must be strings')
18
+ for child in item.values(): exact(child, depth + 1)
19
+ elif type(item) is list:
20
+ for child in item: exact(child, depth + 1)
21
+ elif type(item) not in {str, int, bool, type(None)}:
22
+ raise ValueError('Use exact application JSON types; decimals require an explicit string contract')
23
+ exact(value)
24
+ try:
25
+ raw = json.dumps(value, sort_keys=True, separators=(',', ':'), ensure_ascii=False, allow_nan=False).encode('utf-8')
26
+ except (TypeError, ValueError, UnicodeError, RecursionError):
27
+ raise ValueError('Invalid bounded application JSON') from None
28
+ if len(raw) > 64000:
29
+ raise ValueError('Application JSON exceeds its byte boundary')
30
+ return raw
31
+
32
+
33
+ def schema(value, depth=0, budget=None):
34
+ if budget is None: budget = [256]
35
+ budget[0] -= 1
36
+ if depth > 8 or budget[0] < 0 or type(value) is not dict:
37
+ raise ValueError('Application contract exceeds its structural boundary')
38
+ kind = value.get('type')
39
+ shapes = {'object': {'type', 'properties', 'required'}, 'array': {'type', 'items', 'maxItems'},
40
+ 'string': {'type', 'minBytes', 'maxBytes'}, 'integer': {'type', 'minimum', 'maximum'},
41
+ 'boolean': {'type'}, 'enum': {'type', 'values'}}
42
+ if type(kind) is not str or kind not in shapes or set(value) != shapes[kind]:
43
+ raise ValueError('Use the closed application contract language')
44
+ if kind == 'object':
45
+ properties, required = value['properties'], value['required']
46
+ if (type(properties) is not dict or not 1 <= len(properties) <= 32 or
47
+ any(type(k) is not str or not re.fullmatch(r'[A-Za-z][A-Za-z0-9_]{0,79}', k) for k in properties) or
48
+ type(required) is not list or any(type(k) is not str for k in required) or
49
+ len(required) != len(set(required)) or not set(required) <= set(properties)):
50
+ raise ValueError('Use bounded exact object fields')
51
+ for item in properties.values(): schema(item, depth + 1, budget)
52
+ elif kind == 'array':
53
+ if type(value['maxItems']) is not int or not 1 <= value['maxItems'] <= 64:
54
+ raise ValueError('Use a bounded array')
55
+ schema(value['items'], depth + 1, budget)
56
+ elif kind == 'string':
57
+ if any(type(value[k]) is not int for k in ['minBytes', 'maxBytes']) or not 0 <= value['minBytes'] <= value['maxBytes'] <= 64000:
58
+ raise ValueError('Use exact UTF-8 byte limits')
59
+ elif kind == 'integer':
60
+ if any(type(value[k]) is not int for k in ['minimum', 'maximum']) or not -(2**53 - 1) <= value['minimum'] <= value['maximum'] <= 2**53 - 1:
61
+ raise ValueError('Use exact portable integer limits')
62
+ elif kind == 'enum':
63
+ items = value['values']
64
+ if (type(items) is not list or not 1 <= len(items) <= 64 or
65
+ any(type(item) is not str or not 1 <= len(item.encode('utf-8')) <= 256 for item in items) or len(items) != len(set(items))):
66
+ raise ValueError('Use a bounded distinct string enumeration')
67
+
68
+
69
+ def conforms(rule, value):
70
+ kind = rule['type']
71
+ valid = False
72
+ if kind == 'object':
73
+ valid = (type(value) is dict and set(rule['required']) <= set(value) <= set(rule['properties']))
74
+ if valid:
75
+ for key, item in value.items(): conforms(rule['properties'][key], item)
76
+ elif kind == 'array':
77
+ valid = type(value) is list and len(value) <= rule['maxItems']
78
+ if valid:
79
+ for item in value: conforms(rule['items'], item)
80
+ elif kind == 'string':
81
+ valid = type(value) is str and rule['minBytes'] <= len(value.encode('utf-8')) <= rule['maxBytes']
82
+ elif kind == 'integer': valid = type(value) is int and rule['minimum'] <= value <= rule['maximum']
83
+ elif kind == 'boolean': valid = type(value) is bool
84
+ elif kind == 'enum': valid = type(value) is str and value in rule['values']
85
+ if not valid: raise ValueError('Application payload does not match its owned contract')
86
+
87
+
88
+ @dataclass(frozen=True, init=False)
89
+ class PayloadContract:
90
+ _encoded: bytes
91
+
92
+ def __init__(self, value):
93
+ raw = encoded(value)
94
+ copied = json.loads(raw)
95
+ if (type(copied) is not dict or set(copied) != {'version', 'id', 'source', 'result'} or
96
+ type(copied['version']) is not int or copied['version'] != 1 or
97
+ type(copied['id']) is not str or not re.fullmatch(r'[a-z][a-z0-9-]{0,79}', copied['id'])):
98
+ raise ValueError('Use a versioned owned application payload contract')
99
+ budget = [256]
100
+ for side in ['source', 'result']:
101
+ schema(copied[side], budget=budget)
102
+ if copied[side]['type'] != 'object': raise ValueError('Application boundaries require object payloads')
103
+ object.__setattr__(self, '_encoded', raw)
104
+
105
+ @property
106
+ def sha256(self): return hashlib.sha256(self._encoded).hexdigest()
107
+
108
+ def fields(self, side):
109
+ if side not in {'source', 'result'}: raise ValueError('Use an application input or result boundary')
110
+ return tuple(json.loads(self._encoded)[side]['properties'])
111
+
112
+ def validate(self, side, value):
113
+ if side not in {'source', 'result'}: raise ValueError('Use an application input or result boundary')
114
+ # Round trip before validation: no caller mutation can change the bytes
115
+ # validated for persistence. No clipping, coercion or default insertion.
116
+ copied = json.loads(encoded(value))
117
+ conforms(json.loads(self._encoded)[side], copied)
118
+ return copied
@@ -0,0 +1,88 @@
1
+ """Hard deadlines for trusted processor/destination child processes on Linux.
2
+
3
+ The compiler/operator supplies absolute commands and a minimal environment. No
4
+ shell, model-selected program, inherited account credentials or stderr payloads.
5
+ Input/output are bounded JSON. This is a deadline boundary, not an OS sandbox;
6
+ untrusted PDF parsers still require a separate hardened container boundary.
7
+ """
8
+ import json
9
+ import math
10
+ import os
11
+ from pathlib import Path
12
+ import selectors
13
+ import signal
14
+ import subprocess
15
+ import tempfile
16
+ import time
17
+ from durable_workflow import canonical
18
+ from workflow_errors import TemporaryWork,PermanentWork,ExternalOutcomeUnknown,DestinationNotAttempted,InvalidDispatch
19
+
20
+ class ProcessStage:
21
+ def __init__(self,command,*,kind,timeout_seconds=60,environment=None,cwd=None,idempotency_verified=False):
22
+ if (not isinstance(command,(tuple,list))or not command or any(not isinstance(v,str)or not v or '\0'in v for v in command)
23
+ or not Path(command[0]).is_absolute()or not Path(command[0]).is_file()):raise ValueError('A trusted absolute executable is required')
24
+ if kind not in {'extract','dispatch'}or type(timeout_seconds)not in {int,float}or not math.isfinite(timeout_seconds)or not 0<timeout_seconds<=300:raise ValueError('Invalid bounded stage configuration')
25
+ if type(idempotency_verified)is not bool or(kind=='extract'and idempotency_verified):raise ValueError('Invalid stage replay configuration')
26
+ environment={}if environment is None else environment
27
+ if not isinstance(environment,dict)or any(not isinstance(k,str)or not isinstance(v,str)or not k or '='in k or '\0'in k+v for k,v in environment.items()):raise ValueError('Use an explicit trusted child environment')
28
+ directory=Path(cwd).resolve()if cwd else Path(command[0]).resolve().parent
29
+ if not directory.is_dir():raise ValueError('Use an existing owned working directory')
30
+ self.command=tuple(command);self.kind=kind;self.timeout_seconds=timeout_seconds;self.environment=dict(environment);self.cwd=directory;self.idempotency_verified=idempotency_verified
31
+
32
+ def __call__(self,row,**identity):
33
+ # Deliberately exclude database DSNs, lease tokens and application logins.
34
+ selected={key:row[key]for key in ['kind','source_ref','destination_contract','result','result_revision','approved_by','approved_hash','state']if key in row}
35
+ selected.update({key:str(row[key])for key in ['id','account_id']if key in row})
36
+ if 'created_at'in row:selected['created_at']=row['created_at'].isoformat()if hasattr(row['created_at'],'isoformat')else row['created_at']
37
+ payload=canonical({'operation':selected,'identity':identity},140000)
38
+ failure=TemporaryWork if self.kind=='extract'else ExternalOutcomeUnknown
39
+ process=None
40
+ try:
41
+ # A bounded private temporary input avoids a pipe-write deadlock when
42
+ # a child never reads stdin; no sensitive input appears in argv/env.
43
+ with tempfile.TemporaryFile(mode='w+b')as source,selectors.DefaultSelector()as selector:
44
+ source.write(payload);source.seek(0)
45
+ started=time.monotonic()
46
+ process=subprocess.Popen(self.command,stdin=source,stdout=subprocess.PIPE,stderr=subprocess.DEVNULL,cwd=self.cwd,env=self.environment,start_new_session=True)
47
+ os.set_blocking(process.stdout.fileno(),False);selector.register(process.stdout,selectors.EVENT_READ)
48
+ output=bytearray()
49
+ while selector.get_map():
50
+ remaining=self.timeout_seconds-(time.monotonic()-started)
51
+ if remaining<=0:raise failure('Owned stage exceeded its deadline')
52
+ for key,_ in selector.select(min(remaining,.1)):
53
+ chunk=os.read(key.fd,8192)
54
+ if not chunk:selector.unregister(key.fileobj);continue
55
+ output.extend(chunk)
56
+ if len(output)>70000:raise failure('Owned stage exceeded its output boundary')
57
+ remaining=self.timeout_seconds-(time.monotonic()-started)
58
+ if remaining<=0:raise failure('Owned stage exceeded its deadline')
59
+ try:code=process.wait(timeout=remaining)
60
+ except subprocess.TimeoutExpired:raise failure('Owned stage exceeded its deadline')from None
61
+ if code!=0:raise failure('Owned stage did not confirm completion')
62
+ def unique(pairs):
63
+ value={}
64
+ for key,item in pairs:
65
+ if key in value:raise ValueError('Duplicate stage field')
66
+ value[key]=item
67
+ return value
68
+ try:
69
+ response=json.loads(output,object_pairs_hook=unique,parse_constant=lambda _:(_ for _ in ()).throw(ValueError('Nonfinite stage result')))
70
+ if not isinstance(response,dict)or set(response)!={'status','result'}or not isinstance(response['result'],dict):raise ValueError('Invalid stage result')
71
+ canonical(response['result'],64000)
72
+ except (ValueError,TypeError,UnicodeError,RecursionError):raise failure('Owned stage returned an invalid response')from None
73
+ status=response['status']
74
+ if status=='ok':return response['result']
75
+ if self.kind=='extract'and status=='temporary':raise TemporaryWork('Processing temporarily unavailable')
76
+ if self.kind=='extract'and status=='permanent':raise PermanentWork('Processing requires review')
77
+ if self.kind=='dispatch'and status=='not_attempted':raise DestinationNotAttempted('Destination not attempted')
78
+ if self.kind=='dispatch'and status=='invalid':raise InvalidDispatch('Approved dispatch integrity requires review')
79
+ raise failure('Owned stage did not confirm completion')
80
+ except (TemporaryWork,PermanentWork,ExternalOutcomeUnknown):raise
81
+ except Exception:raise failure('Owned stage did not confirm completion')from None
82
+ finally:
83
+ if process is not None:
84
+ # Kill descendants even if the direct child exited before them.
85
+ try:os.killpg(process.pid,signal.SIGKILL)
86
+ except ProcessLookupError:pass
87
+ process.wait()
88
+ if process.stdout:process.stdout.close()
@@ -0,0 +1,91 @@
1
+ """Pure versioned application declaration, shared by engine and delivered runtime."""
2
+ import base64
3
+ from dataclasses import dataclass
4
+ import hashlib
5
+ import json
6
+ from pathlib import Path
7
+ import uuid
8
+ from urllib.parse import urlsplit
9
+ if __package__:
10
+ from .workflow_payload import PayloadContract,encoded
11
+ from .workflow_contract import bind_payload_contract,bind_application_contract
12
+ else:
13
+ from workflow_payload import PayloadContract,encoded
14
+ from workflow_contract import bind_payload_contract,bind_application_contract
15
+
16
+
17
+ def identifier(value):
18
+ if type(value)is not str or str(uuid.UUID(value))!=value:raise ValueError('Use a canonical account UUID')
19
+ return value
20
+
21
+
22
+ def owned_origin(value):
23
+ try:
24
+ parts = urlsplit(value)
25
+ port = parts.port
26
+ except (TypeError, ValueError): raise ValueError('Use the exact owned application origin') from None
27
+ if (type(value) is not str or not parts.hostname or parts.username or parts.password or
28
+ parts.query or parts.fragment or parts.path or
29
+ (port is not None and not 1 <= port <= 65535) or
30
+ any(ord(c) < 33 or ord(c) > 126 for c in value) or
31
+ (parts.scheme != 'https' and not (parts.scheme == 'http' and parts.hostname in {'localhost','127.0.0.1','::1'}))):
32
+ raise ValueError('Use the exact HTTPS origin or explicit loopback test origin')
33
+ return value
34
+
35
+
36
+ IDENTITY_KEYS={
37
+ 'aws':('REGION','POOL_ID','CLIENT_ID','AUTH_ORIGIN','AUTH_SCOPE'),
38
+ 'azure':('TENANT_ID','API_CLIENT_ID','SPA_CLIENT_ID'),
39
+ 'gcp':('PROJECT_NUMBER','REGION','SERVICE_NAME'),
40
+ 'ibm':('APPID_TENANT_ID','APPID_CLIENT_ID','APPID_ISSUER','AUTH_SCOPE')}
41
+
42
+
43
+ @dataclass(frozen=True,init=False)
44
+ class ApplicationProfile:
45
+ _encoded:bytes
46
+
47
+ def __init__(self,value):
48
+ raw=encoded(value);data=json.loads(raw)
49
+ keys={'format','provider','componentId','environment','accountId','publicOrigin','operationKind','identitySettings','payloadContract','destinationContract'}
50
+ if type(data)is not dict or set(data)!=keys or data['format']!='approval-application-v1':raise ValueError('Use the exact versioned application profile')
51
+ if type(data['provider'])is not str or data['provider']not in IDENTITY_KEYS:raise ValueError('Use the selected application provider')
52
+ if type(data['componentId'])is not str or not 1<=len(data['componentId'].encode('utf-8'))<=512 or any(ord(c)<32 for c in data['componentId']):raise ValueError('Use the complete bounded component identity')
53
+ if type(data['environment'])is not str or data['environment']not in {'staging','production','qualification'}:raise ValueError('Use the reviewed deployment environment')
54
+ identifier(data['accountId']);owned_origin(data['publicOrigin'])
55
+ if type(data['operationKind'])is not str or data['operationKind']not in {'document','draft','account_change'}:raise ValueError('Use an explicit owned operation policy')
56
+ identity=data['identitySettings']
57
+ if type(identity)is not dict or set(identity)!=set(IDENTITY_KEYS[data['provider']])or any(type(v)is not str or not 1<=len(v.encode('utf-8'))<=2000 for v in identity.values()):raise ValueError('Use the complete nonsecret native identity settings')
58
+ if type(data['destinationContract'])is not dict or 'applicationContractSha256'in data['destinationContract']:raise ValueError('Use the reviewed base destination; application binding is generated')
59
+ bind_payload_contract(data['destinationContract'],PayloadContract(data['payloadContract']))
60
+ object.__setattr__(self,'_encoded',raw)
61
+
62
+ @property
63
+ def data(self):return json.loads(self._encoded)
64
+ @property
65
+ def payload(self):return PayloadContract(self.data['payloadContract'])
66
+ @property
67
+ def sha256(self):return hashlib.sha256(self._encoded).hexdigest()
68
+ @property
69
+ def destination(self):return bind_application_contract(bind_payload_contract(self.data['destinationContract'],self.payload),self.sha256)
70
+ @property
71
+ def binding_sha256(self):
72
+ value={key:self.data[key]for key in ['provider','componentId','environment','accountId']}
73
+ return hashlib.sha256(encoded(value)).hexdigest()
74
+ @property
75
+ def namespace(self):
76
+ # Explicit native alias, not truncation of the saved component identity.
77
+ # 88-bit digest encoding fits the existing task/notification constraints.
78
+ return 'w'+base64.b32encode(bytes.fromhex(self.binding_sha256)[:11]).decode().lower().rstrip('=')
79
+
80
+
81
+ def load_profile(path):
82
+ if not isinstance(path,(str,Path))or not Path(path).is_absolute():raise ValueError('Use an owned absolute application profile path')
83
+ with Path(path).open('rb')as stream:raw=stream.read(64001)
84
+ if len(raw)>64000:raise ValueError('Application profile exceeds its byte boundary')
85
+ def unique(pairs):
86
+ result={}
87
+ for key,value in pairs:
88
+ if key in result:raise ValueError('Duplicate application profile field')
89
+ result[key]=value
90
+ return result
91
+ return ApplicationProfile(json.loads(raw.decode('utf-8'),object_pairs_hook=unique))