@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,191 @@
1
+ import {compileTextStatistics} from './text-statistics.mjs';
2
+ export const ASYNC_INTEGRATIONS=['s3-object-created','sqs-lambda','lambda-s3-read','lambda-dynamodb-write','sqs-redrive'];
3
+ export function asyncPipelinePlan(project,rows){
4
+ const byId=new Map(rows.map(r=>[r.id,r])),nodes=new Map(project.nodes.map(n=>[n.id,n]));
5
+ const edges=(source,type)=>project.edges.filter(e=>e.source===source&&e.integration===type);
6
+ const typed=(id,implementation,service)=>{const n=nodes.get(id),r=byId.get(id);return n?.data.implementation===implementation&&r?.provider==='aws'&&!r.existing&&r.service===service;};
7
+ const candidates=[];
8
+ for(const worker of rows){
9
+ if(!typed(worker.id,'async-word-count','AWS Lambda'))continue;
10
+ const trigger=project.edges.filter(e=>e.target===worker.id&&e.integration==='sqs-lambda');
11
+ const reads=edges(worker.id,'lambda-s3-read'),writes=edges(worker.id,'lambda-dynamodb-write');
12
+ if(trigger.length!==1||reads.length!==1||writes.length!==1)continue;
13
+ const queue=byId.get(trigger[0].source),bucket=byId.get(reads[0].target),table=byId.get(writes[0].target);
14
+ if(!queue||!bucket?.foundation||!table||!typed(queue.id,'sqs-standard','Amazon SQS')||!typed(table.id,'word-count-results','Amazon DynamoDB'))continue;
15
+ const notifications=edges(bucket.id,'s3-object-created').filter(e=>e.target===queue.id),redrives=edges(queue.id,'sqs-redrive');
16
+ if(notifications.length!==1||redrives.length!==1)continue;
17
+ const dlq=byId.get(redrives[0].target);
18
+ if(!dlq||dlq.id===queue.id||!typed(dlq.id,'sqs-dead-letter','Amazon SQS'))continue;
19
+ candidates.push({worker,queue,bucket,table,dlq,edges:[trigger[0],reads[0],writes[0],notifications[0],redrives[0]]});
20
+ }
21
+ // Shared ownership and overlapping S3 notification filters require a separate fan-out contract.
22
+ const counts=new Map();for(const p of candidates)for(const r of [p.worker,p.queue,p.table,p.dlq,p.bucket])counts.set(r.id,(counts.get(r.id)||0)+1);
23
+ const pipelines=candidates.filter(p=>[p.worker,p.queue,p.table,p.dlq,p.bucket].every(r=>counts.get(r.id)===1));
24
+ return {pipelines,componentIds:pipelines.flatMap(p=>[p.worker.id,p.queue.id,p.table.id,p.dlq.id]),edgeIds:pipelines.flatMap(p=>p.edges.map(e=>e.id))};
25
+ }
26
+ export const ASYNC_HANDLER=`"""Version-specific, bounded, idempotent S3 text processing with partial batch failures."""
27
+ import hashlib
28
+ import json
29
+ import logging
30
+ import os
31
+ from urllib.parse import unquote_plus
32
+ import boto3
33
+ from botocore.config import Config
34
+ from botocore.exceptions import ClientError
35
+
36
+ _clients = None
37
+ logger = logging.getLogger(__name__)
38
+
39
+ def clients():
40
+ global _clients
41
+ if _clients is None:
42
+ config=Config(connect_timeout=3,read_timeout=5,retries={"max_attempts":2})
43
+ _clients=(boto3.client("s3",config=config),boto3.client("dynamodb",config=config))
44
+ return _clients
45
+
46
+ def process(body):
47
+ if not isinstance(body,dict):raise ValueError("Invalid storage notification")
48
+ if body.get("Event")=="s3:TestEvent":return
49
+ records=body.get("Records")
50
+ if not isinstance(records,list) or not 1 <= len(records) <= 10:raise ValueError("Invalid notification batch")
51
+ s3,db=clients()
52
+ for record in records:
53
+ if record.get("eventSource")!="aws:s3" or not str(record.get("eventName","")).startswith("ObjectCreated:"):raise ValueError("Unsupported storage event")
54
+ bucket=record["s3"]["bucket"]["name"]
55
+ key=unquote_plus(record["s3"]["object"]["key"])
56
+ version=record["s3"]["object"].get("versionId")
57
+ if bucket!=os.environ["SOURCE_BUCKET"] or not isinstance(version,str) or not version or version=="null":raise ValueError("Wrong bucket or missing exact object version")
58
+ limit=int(os.environ["MAX_INPUT_BYTES"])
59
+ result=s3.get_object(Bucket=bucket,Key=key,VersionId=version,ExpectedBucketOwner=os.environ["EXPECTED_ACCOUNT_ID"])
60
+ stream=result["Body"]
61
+ try:
62
+ if result.get("ContentLength",0)>limit:raise ValueError("Document too large")
63
+ data=stream.read(limit+1)
64
+ finally:stream.close()
65
+ if len(data)>limit:raise ValueError("Document too large")
66
+ text=data.decode("utf-8")
67
+ object_id=hashlib.sha256(json.dumps([bucket,key,version],ensure_ascii=False,separators=(",",":")).encode()).hexdigest()
68
+ item={"objectId":{"S":object_id},"wordCount":{"N":str(len(text.split()))},"characterCount":{"N":str(len(text))},"sourceVersion":{"S":version},"contentSha256":{"S":hashlib.sha256(data).hexdigest()},"processorVersion":{"S":"1"}}
69
+ try:db.put_item(TableName=os.environ["RESULTS_TABLE"],Item=item,ConditionExpression="attribute_not_exists(objectId)")
70
+ except ClientError as error:
71
+ if error.response.get("Error",{}).get("Code")!="ConditionalCheckFailedException":raise
72
+
73
+ def handler(event,context):
74
+ records=event.get("Records") if isinstance(event,dict) else None
75
+ if not isinstance(records,list) or len(records)>10:raise ValueError("Invalid queue batch")
76
+ failures=[]
77
+ for record in records:
78
+ message_id=record.get("messageId")
79
+ if not isinstance(message_id,str) or not message_id:raise ValueError("Queue message ID is missing")
80
+ try:
81
+ if record.get("eventSource")!="aws:sqs" or record.get("eventSourceARN")!=os.environ["QUEUE_ARN"]:raise ValueError("Wrong event source")
82
+ process(json.loads(record["body"]))
83
+ except Exception as error:
84
+ logger.warning(json.dumps({"event":"record_failed","errorType":type(error).__name__}))
85
+ failures.append({"itemIdentifier":message_id})
86
+ return {"batchItemFailures":failures}
87
+ `;
88
+
89
+ export function compileAsyncDocuments(plan,environment='staging'){
90
+ const resources={},variables={},outputs={},files={},preconditions=[],builds=[];
91
+ const add=(type,name,body)=>(resources[type]||={})[name]={...body,depends_on:[...(body.depends_on||[]),'terraform_data.review_gate']};
92
+ const ref=(type,row,field)=>`\u0024{${type}.${row.address}.${field}}`;
93
+ const notifications=new Map();
94
+ for(const pipeline of plan.asyncPlan.pipelines){
95
+ const {worker,queue,bucket,table,dlq}=pipeline,n=worker.address,tags={ManagedBy:'AtMem AI Architect',Environment:environment,Component:n};
96
+ const settings={memoryMb:256,functionTimeoutSeconds:30,concurrency:2,maxInputBytes:1000000,...worker.settings};
97
+ const base=compileTextStatistics({...plan,rows:[{...worker,compute:true,settings}]},environment);
98
+ for(const [type,items]of Object.entries(base.resources))resources[type]={...(resources[type]||{}),...items};
99
+ Object.assign(variables,base.variables);Object.assign(outputs,base.outputs);Object.assign(files,base.files);
100
+ files[`handlers/${n}.py`]=ASYNC_HANDLER;
101
+ files[`app-tests/${n}_test.py`]=asyncHandlerTests(n);
102
+ builds.push({address:n,sdk:true});
103
+ const functionResource=resources.aws_lambda_function[n];
104
+ functionResource.environment.variables={...functionResource.environment.variables,SOURCE_BUCKET:ref('aws_s3_bucket',bucket,'id'),RESULTS_TABLE:ref('aws_dynamodb_table',table,'name'),QUEUE_ARN:ref('aws_sqs_queue',queue,'arn'),EXPECTED_ACCOUNT_ID:'${var.aws_account_id}'};
105
+ variables[`${n}_concurrency`].validation={condition:`\u0024{var.${n}_concurrency >= 2 && var.${n}_concurrency <= 1000 && floor(var.${n}_concurrency) == var.${n}_concurrency}`,error_message:'SQS event source maximum concurrency requires an integer from 2 to 1000.'};
106
+ const window=`${n}_batch_window_seconds`,attempts=`${n}_max_receive_count`,alerts=`${n}_alert_topic_arns`;
107
+ variables[window]={type:'number',default:0,validation:{condition:`\u0024{var.${window} >= 0 && var.${window} <= 300 && floor(var.${window}) == var.${window}}`,error_message:'Batch window must be an integer from 0 to 300 seconds.'}};
108
+ variables[attempts]={type:'number',default:5,validation:{condition:`\u0024{var.${attempts} >= 1 && var.${attempts} <= 20 && floor(var.${attempts}) == var.${attempts}}`,error_message:'Choose 1–20 bounded delivery attempts.'}};
109
+ variables[alerts]={type:'list(string)',default:[],description:'Reviewed existing standard SNS topics for DLQ alarms. Required for production; no notification destination is invented.',validation:{condition:`\u0024{alltrue([for arn in var.${alerts} : can(regex("^arn:aws:sns:[a-z0-9-]+:[0-9]{12}:[A-Za-z0-9_-]+$", arn))])}`,error_message:'Use existing standard SNS topic ARNs.'}};
110
+ if(environment==='production')preconditions.push({condition:`\u0024{length(var.${alerts}) > 0}`,error_message:'Production queue processing requires a reviewed alarm notification topic.'});
111
+ preconditions.push({condition:`\u0024{alltrue([for arn in var.${alerts} : startswith(arn, format("arn:aws:sns:%s:%s:", var.aws_region, var.aws_account_id))])}`,error_message:'Alarm topics must use the selected account and region.'});
112
+ add('aws_sqs_queue',dlq.address,{name_prefix:`atmem-dlq-${dlq.address.slice(0,20)}-`,sqs_managed_sse_enabled:true,message_retention_seconds:1209600,tags});
113
+ add('aws_sqs_queue',queue.address,{name_prefix:`atmem-work-${queue.address.slice(0,20)}-`,sqs_managed_sse_enabled:true,message_retention_seconds:345600,visibility_timeout_seconds:`\u0024{6 * var.${n}_timeout_seconds + var.${window}}`,redrive_policy:`\u0024{jsonencode({deadLetterTargetArn=aws_sqs_queue.${dlq.address}.arn,maxReceiveCount=var.${attempts}})}`,tags});
114
+ add('aws_sqs_queue_policy',dlq.address,{queue_url:ref('aws_sqs_queue',dlq,'id'),policy:JSON.stringify({Version:'2012-10-17',Statement:[{Effect:'Deny',Principal:'*',Action:'sqs:*',Resource:ref('aws_sqs_queue',dlq,'arn'),Condition:{Bool:{'aws:SecureTransport':'false','aws:PrincipalIsAWSService':'false'}}}]})});
115
+ add('aws_sqs_queue_redrive_allow_policy',dlq.address,{queue_url:ref('aws_sqs_queue',dlq,'id'),redrive_allow_policy:`\u0024{jsonencode({redrivePermission="byQueue",sourceQueueArns=[aws_sqs_queue.${queue.address}.arn]})}`});
116
+ add('aws_sqs_queue_policy',queue.address,{queue_url:ref('aws_sqs_queue',queue,'id'),policy:JSON.stringify({Version:'2012-10-17',Statement:[{Effect:'Allow',Principal:{Service:'s3.amazonaws.com'},Action:'sqs:SendMessage',Resource:ref('aws_sqs_queue',queue,'arn'),Condition:{ArnEquals:{'aws:SourceArn':ref('aws_s3_bucket',bucket,'arn')},StringEquals:{'aws:SourceAccount':'${var.aws_account_id}'}}},{Effect:'Deny',Principal:'*',Action:'sqs:*',Resource:ref('aws_sqs_queue',queue,'arn'),Condition:{Bool:{'aws:SecureTransport':'false','aws:PrincipalIsAWSService':'false'}}}]})});
117
+ add('aws_dynamodb_table',table.address,{name:`atmem-results-${ref('aws_iam_role',worker,'name')}`,billing_mode:'PAY_PER_REQUEST',hash_key:'objectId',attribute:[{name:'objectId',type:'S'}],point_in_time_recovery:{enabled:true},server_side_encryption:{enabled:true},deletion_protection_enabled:environment==='production',lifecycle:{prevent_destroy:environment==='production'},tags});
118
+ const policy=JSON.parse(resources.aws_iam_role_policy[n].policy);
119
+ policy.Statement.push({Effect:'Allow',Action:['s3:GetObjectVersion'],Resource:`${ref('aws_s3_bucket',bucket,'arn')}/*`},{Effect:'Allow',Action:['dynamodb:PutItem'],Resource:ref('aws_dynamodb_table',table,'arn')},{Effect:'Allow',Action:['sqs:ReceiveMessage','sqs:DeleteMessage','sqs:GetQueueAttributes'],Resource:ref('aws_sqs_queue',queue,'arn')});
120
+ resources.aws_iam_role_policy[n].policy=JSON.stringify(policy);
121
+ add('aws_lambda_event_source_mapping',n,{event_source_arn:ref('aws_sqs_queue',queue,'arn'),function_name:ref('aws_lambda_alias',worker,'arn'),batch_size:10,maximum_batching_window_in_seconds:`\u0024{var.${window}}`,function_response_types:['ReportBatchItemFailures'],scaling_config:{maximum_concurrency:`\u0024{var.${n}_concurrency}`},depends_on:[`aws_iam_role_policy.${n}`]});
122
+ add('aws_cloudwatch_metric_alarm',dlq.address,{alarm_name:`atmem-dlq-${ref('aws_sqs_queue',dlq,'name')}`,namespace:'AWS/SQS',metric_name:'ApproximateNumberOfMessagesVisible',dimensions:{QueueName:ref('aws_sqs_queue',dlq,'name')},statistic:'Maximum',period:60,evaluation_periods:1,threshold:0,comparison_operator:'GreaterThanThreshold',treat_missing_data:'notBreaching',alarm_actions:`\u0024{var.${alerts}}`,tags});
123
+ const notification=notifications.get(bucket.address)||{bucket,queue:[],policies:[]};notification.queue.push({id:n,queue_arn:ref('aws_sqs_queue',queue,'arn'),events:['s3:ObjectCreated:*']});notification.policies.push(`aws_sqs_queue_policy.${queue.address}`);notifications.set(bucket.address,notification);
124
+ outputs[`${n}_pipeline`]={value:{source_bucket:ref('aws_s3_bucket',bucket,'id'),queue_url:ref('aws_sqs_queue',queue,'id'),dead_letter_queue_url:ref('aws_sqs_queue',dlq,'id'),results_table:ref('aws_dynamodb_table',table,'name')}};
125
+ }
126
+ for(const [address,entry]of notifications)add('aws_s3_bucket_notification',address,{bucket:ref('aws_s3_bucket',entry.bucket,'id'),queue:entry.queue,depends_on:[...entry.policies,`aws_s3_bucket_versioning.${address}`]});
127
+ return {resources,variables,outputs,files,preconditions,builds};
128
+ }
129
+
130
+ function asyncHandlerTests(address){
131
+ return `import importlib.util
132
+ import io
133
+ import json
134
+ import os
135
+ from pathlib import Path
136
+ import sys
137
+ import unittest
138
+ from unittest.mock import MagicMock
139
+ root=Path(__file__).resolve().parents[1]
140
+ sys.path.insert(0,str(root/"build/${address}"))
141
+ from botocore.exceptions import ClientError
142
+ spec=importlib.util.spec_from_file_location("worker",root/"build/${address}/${address}.py")
143
+ module=importlib.util.module_from_spec(spec)
144
+ spec.loader.exec_module(module)
145
+ class WorkerTests(unittest.TestCase):
146
+ def setUp(self):
147
+ os.environ.update(SOURCE_BUCKET="test-bucket",RESULTS_TABLE="results",QUEUE_ARN="arn:aws:sqs:ap-southeast-2:123456789012:queue",EXPECTED_ACCOUNT_ID="123456789012",MAX_INPUT_BYTES="100")
148
+ self.s3=MagicMock();self.db=MagicMock();module._clients=(self.s3,self.db)
149
+ self.s3.get_object.side_effect=lambda **kwargs:{"Body":io.BytesIO(b"one two three"),"ContentLength":13}
150
+ def message(self,version="v1",bucket="test-bucket",message_id="record-1"):
151
+ body={"Records":[{"eventSource":"aws:s3","eventName":"ObjectCreated:Put","s3":{"bucket":{"name":bucket},"object":{"key":"synthetic+text.txt","versionId":version}}}]}
152
+ return {"messageId":message_id,"eventSource":"aws:sqs","eventSourceARN":os.environ["QUEUE_ARN"],"body":json.dumps(body)}
153
+ def test_exact_version_and_conditional_result(self):
154
+ self.assertEqual(module.handler({"Records":[self.message()]},None),{"batchItemFailures":[]})
155
+ self.s3.get_object.assert_called_once_with(Bucket="test-bucket",Key="synthetic text.txt",VersionId="v1",ExpectedBucketOwner="123456789012")
156
+ call=self.db.put_item.call_args.kwargs
157
+ self.assertEqual(call["ConditionExpression"],"attribute_not_exists(objectId)")
158
+ self.assertEqual(call["Item"]["wordCount"],{"N":"3"})
159
+ self.assertEqual(call["Item"]["sourceVersion"],{"S":"v1"})
160
+ def test_duplicate_is_success_without_overwriting(self):
161
+ self.db.put_item.side_effect=[{},ClientError({"Error":{"Code":"ConditionalCheckFailedException"}},"PutItem")]
162
+ event={"Records":[self.message()]}
163
+ self.assertEqual(module.handler(event,None),{"batchItemFailures":[]})
164
+ self.assertEqual(module.handler(event,None),{"batchItemFailures":[]})
165
+ calls=self.db.put_item.call_args_list
166
+ self.assertEqual(calls[0].kwargs["Item"]["objectId"],calls[1].kwargs["Item"]["objectId"])
167
+ self.assertTrue(all(c.kwargs["ConditionExpression"]=="attribute_not_exists(objectId)" for c in calls))
168
+ def test_new_version_has_distinct_result(self):
169
+ module.handler({"Records":[self.message("v1"),self.message("v2",message_id="record-2")]},None)
170
+ calls=self.db.put_item.call_args_list
171
+ self.assertNotEqual(calls[0].kwargs["Item"]["objectId"],calls[1].kwargs["Item"]["objectId"])
172
+ def test_partial_failure_and_redacted_diagnostics(self):
173
+ bad=self.message(bucket="private-secret-title",message_id="bad")
174
+ with self.assertLogs(module.logger,level="WARNING") as logs:
175
+ result=module.handler({"Records":[bad,self.message(message_id="good")]},None)
176
+ self.assertEqual(result,{"batchItemFailures":[{"itemIdentifier":"bad"}]})
177
+ self.assertNotIn("private-secret-title"," ".join(logs.output))
178
+ self.assertEqual(self.db.put_item.call_count,1)
179
+ def test_oversized_document_closes_stream_and_does_not_write(self):
180
+ stream=io.BytesIO(b"x"*101);self.s3.get_object.side_effect=None;self.s3.get_object.return_value={"Body":stream,"ContentLength":101}
181
+ with self.assertLogs(module.logger,level="WARNING"):
182
+ result=module.handler({"Records":[self.message()]},None)
183
+ self.assertEqual(len(result["batchItemFailures"]),1);self.assertTrue(stream.closed);self.db.put_item.assert_not_called()
184
+ def test_storage_test_event_and_retryable_database_failure(self):
185
+ test=self.message();test["body"]=json.dumps({"Event":"s3:TestEvent"})
186
+ self.assertEqual(module.handler({"Records":[test]},None),{"batchItemFailures":[]});self.s3.get_object.assert_not_called()
187
+ self.db.put_item.side_effect=ClientError({"Error":{"Code":"ProvisionedThroughputExceededException"}},"PutItem")
188
+ with self.assertLogs(module.logger,level="WARNING"):
189
+ self.assertEqual(module.handler({"Records":[self.message()]},None),{"batchItemFailures":[{"itemIdentifier":"record-1"}]})
190
+ `;
191
+ }