hecks 3.14.0 → 4.0.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 (419) hide show
  1. checksums.yaml +4 -4
  2. data/examples/pizzas/adapters/fake_processor.rb +34 -0
  3. data/examples/pizzas/adapters/payment_signature.rb +66 -0
  4. data/examples/pizzas/adapters/payment_webhook.rb +87 -0
  5. data/examples/pizzas/bluebook/pizzas.behaviors +33 -0
  6. data/examples/pizzas/bluebook/pizzas.hecksagon +5 -3
  7. data/examples/pizzas/config.ru +22 -0
  8. data/lib/hecks/adapters/driven/prism.rb +0 -2
  9. data/lib/hecks/adapters/driven.rb +0 -2
  10. data/lib/hecks/adapters/driving/json.rb +1 -7
  11. data/lib/hecks/bluebook/dsl/bootstrap_table.rb +2 -2
  12. data/lib/hecks/bluebook/dsl/derivation_words.rb +58 -0
  13. data/lib/hecks/bluebook/dsl/translation_builder.rb +6 -37
  14. data/lib/hecks/bluebook/expression/ast_json.rb +0 -9
  15. data/lib/hecks/bluebook/hecksagon.rb +1 -1
  16. data/lib/hecks/bluebook/meta_validator/translation_judge/rules.rb +7 -10
  17. data/lib/hecks/bluebook/meta_validator/translation_judge.rb +4 -8
  18. data/lib/hecks/bluebook/meta_validator.rb +0 -11
  19. data/lib/hecks/bluebook/translation.rb +18 -10
  20. data/lib/hecks/bluebook/translation_expression/evaluator.rb +63 -0
  21. data/lib/hecks/bluebook/translation_expression/parser.rb +127 -0
  22. data/lib/hecks/bluebook/translation_expression.rb +39 -0
  23. data/lib/hecks/bluebook/translation_plan.rb +70 -0
  24. data/lib/hecks/bluebook.rb +2 -0
  25. data/lib/hecks/chapters.rb +3 -3
  26. data/lib/hecks/composer/adapters/claude_composer.adapter +3 -0
  27. data/lib/hecks/composer/adapters/claude_composer.rb +83 -0
  28. data/lib/hecks/composer/adapters/fake_agent.adapter +3 -0
  29. data/lib/hecks/composer/adapters/fake_agent.rb +55 -0
  30. data/lib/hecks/composer/adapters/jev.adapter +3 -0
  31. data/lib/hecks/composer/adapters/jev.rb +66 -0
  32. data/lib/hecks/composer/agent.rb +113 -0
  33. data/lib/hecks/composer/assistant.rb +110 -0
  34. data/lib/hecks/composer/behavior_run.rb +53 -0
  35. data/lib/hecks/composer/bluebook/composer.bluebook +178 -0
  36. data/lib/hecks/composer/bluebook/composer.hecksagon +16 -0
  37. data/lib/hecks/composer/board.rb +65 -0
  38. data/lib/hecks/composer/board_edit/command_text.rb +39 -0
  39. data/lib/hecks/composer/board_edit/source.rb +84 -0
  40. data/lib/hecks/composer/board_edit.rb +144 -0
  41. data/lib/hecks/composer/check.rb +89 -0
  42. data/lib/hecks/composer/domains.rb +81 -0
  43. data/lib/hecks/composer/jobs.rb +134 -0
  44. data/lib/hecks/composer/layout.rb +37 -0
  45. data/lib/hecks/composer/live.rb +150 -0
  46. data/lib/hecks/composer/outline.rb +48 -0
  47. data/lib/hecks/composer/page.html +989 -0
  48. data/lib/hecks/composer/panels.rb +142 -0
  49. data/lib/hecks/composer/parse.rb +83 -0
  50. data/lib/hecks/composer/plain.rb +28 -0
  51. data/lib/hecks/composer/ports/composer_agent.port +7 -0
  52. data/lib/hecks/composer/session.rb +141 -0
  53. data/lib/hecks/composer/toolbox.rb +166 -0
  54. data/lib/hecks/composer/web.rb +156 -0
  55. data/lib/hecks/composer/workbench.rb +51 -0
  56. data/lib/hecks/composer/workspace.rb +81 -0
  57. data/lib/hecks/composer.rb +17 -0
  58. data/lib/hecks/corpus/adapters.rb +22 -0
  59. data/lib/hecks/corpus/rust.rb +1 -1
  60. data/lib/hecks/corpus/worlds.rb +19 -0
  61. data/lib/hecks/corpus.rb +5 -0
  62. data/lib/hecks/forms/app/commands.rb +2 -3
  63. data/lib/hecks/forms/app/queries.rb +2 -3
  64. data/lib/hecks/forms/app/records.rb +17 -5
  65. data/lib/hecks/forms/command_form_renderer.rb +42 -16
  66. data/lib/hecks/forms/field_controls.rb +2 -2
  67. data/lib/hecks/forms/field_renderer.rb +1 -1
  68. data/lib/hecks/forms/field_shape.rb +36 -17
  69. data/lib/hecks/forms/index_renderer.rb +2 -1
  70. data/lib/hecks/forms/page.rb +1 -1
  71. data/lib/hecks/forms/params.rb +0 -13
  72. data/lib/hecks/forms/query_form_renderer.rb +7 -6
  73. data/lib/hecks/forms/record_renderer.rb +11 -7
  74. data/lib/hecks/forms/rule_words.rb +100 -0
  75. data/lib/hecks/forms/value_object_shape.rb +2 -1
  76. data/lib/hecks/fuzzing/bounded_exhaustive_expressions.rb +0 -3
  77. data/lib/hecks/fuzzing/isolated_boot/worlds.rb +3 -6
  78. data/lib/hecks/fuzzing/replay/filters.rb +2 -6
  79. data/lib/hecks/gate/stages.yml +25 -0
  80. data/lib/hecks/grammar/evolve/seeds.rb +0 -6
  81. data/lib/hecks/grammar/evolve.rb +0 -3
  82. data/lib/hecks/grammar/translation.bluebook +1 -1
  83. data/lib/hecks/hecks/adapters/codebase/composing.rb +56 -0
  84. data/lib/hecks/hecks/adapters/codebase/source_tree.rb +3 -1
  85. data/lib/hecks/hecks/adapters/journal_store/changes.rb +0 -26
  86. data/lib/hecks/hecks/adapters/journal_store/examination.rb +2 -23
  87. data/lib/hecks/hecks/adapters/journal_store/readings.rb +3 -11
  88. data/lib/hecks/hecks/adapters/journal_store.rb +0 -11
  89. data/lib/hecks/hecks/adapters/rehearsal/inquiry.rb +4 -11
  90. data/lib/hecks/hecks/adapters/rehearsal/memory_store.rb +0 -9
  91. data/lib/hecks/hecks/adapters/rehearsal/postgres_reading.rb +0 -4
  92. data/lib/hecks/hecks/codebase.behaviors +6 -0
  93. data/lib/hecks/hecks/codebase.bluebook +21 -0
  94. data/lib/hecks/hecks/composer.behaviors +68 -0
  95. data/lib/hecks/hecks/context_map.hecksagon +1 -1
  96. data/lib/hecks/hecks/custodian.behaviors +0 -6
  97. data/lib/hecks/hecks/custodian.bluebook +3 -80
  98. data/lib/hecks/hecks/hecks.hecksagon +2 -2
  99. data/lib/hecks/hecks/hecks.world +1 -1
  100. data/lib/hecks/hecks/rehearsal.bluebook +7 -13
  101. data/lib/hecks/kernel_capabilities/templates.rb +4 -4
  102. data/lib/hecks/kernel_capabilities.rb +1 -1
  103. data/lib/hecks/language/bluebook/vocabulary.bluebook +2 -3
  104. data/lib/hecks/language/translation/translation_aggregate.bluebook +21 -24
  105. data/lib/hecks/ports/access_control.rb +2 -2
  106. data/lib/hecks/ports/persistence/plugins/era/era_check.rb +3 -41
  107. data/lib/hecks/ports/persistence/plugins/era/lineage/coverage.rb +7 -7
  108. data/lib/hecks/ports/persistence/plugins/era/lineage/rewrite.rb +25 -2
  109. data/lib/hecks/ports/persistence/plugins/era/lineage/rules.rb +4 -4
  110. data/lib/hecks/ports/persistence/plugins/era/lineage.rb +17 -25
  111. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/base_sql.rb +0 -12
  112. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/domain_rename.rb +1 -1
  113. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/era_store.rb +2 -22
  114. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/provisioning.rb +0 -1
  115. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage.rb +9 -3
  116. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/minter.rb +3 -29
  117. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/refusals.rb +2 -26
  118. data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_two.rb +6 -33
  119. data/lib/hecks/ports/persistence/plugins/era/translation/audit/unfed_report.rb +3 -3
  120. data/lib/hecks/ports/persistence/plugins/era/translation/audit.rb +2 -4
  121. data/lib/hecks/ports/persistence/plugins/era/translation/expression_sql.rb +52 -0
  122. data/lib/hecks/ports/persistence/plugins/era/translation/rule_compiler.rb +23 -29
  123. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold.rb +1 -1
  124. data/lib/hecks/ports/persistence/plugins/era/translation.rb +0 -1
  125. data/lib/hecks/ports/persistence/plugins/era.rb +3 -6
  126. data/lib/hecks/ports.rb +0 -1
  127. data/lib/hecks/projection_files.rb +3 -1
  128. data/lib/hecks/projections/deploy/templates/lambda/nat_comment_oauth.tmpl +1 -1
  129. data/lib/hecks/projections/glossary/entries.rb +10 -4
  130. data/lib/hecks/projections/glossary/groups.rb +42 -0
  131. data/lib/hecks/projections/glossary/html/page.rb +7 -2
  132. data/lib/hecks/projections/glossary/html/parser.rb +1 -1
  133. data/lib/hecks/projections/glossary/html/sections.rb +31 -11
  134. data/lib/hecks/projections/glossary/html.rb +1 -2
  135. data/lib/hecks/projections/glossary/markdown.rb +31 -28
  136. data/lib/hecks/projections/glossary/mermaid.rb +3 -0
  137. data/lib/hecks/projections/glossary/page.css +143 -153
  138. data/lib/hecks/projections/glossary/page.js +63 -3
  139. data/lib/hecks/projections/glossary/sentences/actions.rb +88 -0
  140. data/lib/hecks/projections/glossary/sentences/paths.rb +77 -0
  141. data/lib/hecks/projections/glossary/sentences/queries.rb +90 -0
  142. data/lib/hecks/projections/glossary/sentences/value_objects.rb +32 -5
  143. data/lib/hecks/projections/glossary/sentences.rb +13 -3
  144. data/lib/hecks/projections/glossary/slugs.rb +4 -1
  145. data/lib/hecks/projections/glossary.rb +2 -1
  146. data/lib/hecks/projections/plain_english.rb +97 -0
  147. data/lib/hecks/projections/rust_vocabulary/arguments.rb +2 -2
  148. data/lib/hecks/projections/rust_vocabulary/enum_body.rb +20 -25
  149. data/lib/hecks/projections/rust_vocabulary/tests.rb +2 -2
  150. data/lib/hecks/projections/rust_vocabulary.rb +14 -6
  151. data/lib/hecks/projections/site/cms_editor/color.rb +0 -6
  152. data/lib/hecks/projections/statements/actions.rb +99 -0
  153. data/lib/hecks/projections/statements/relationships.rb +86 -0
  154. data/lib/hecks/projections/statements.rb +15 -24
  155. data/lib/hecks/projector/exporter/adapters.rb +112 -0
  156. data/lib/hecks/projector/exporter/translations.rb +18 -35
  157. data/lib/hecks/projector/exporter/worlds.rb +103 -0
  158. data/lib/hecks/projector/exporter.rb +5 -1
  159. data/lib/hecks/quality_control/adapters/agent.rb +6 -7
  160. data/lib/hecks/quality_control/adapters/agent_profile.rb +16 -114
  161. data/lib/hecks/quality_control/cli/qa_mine_combinations.rb +1 -1
  162. data/lib/hecks/runtime/loader/boot_steps.rb +0 -20
  163. data/lib/hecks/runtime/outbox.rb +2 -9
  164. data/lib/hecks/runtime/port_operation_interpreter.rb +1 -9
  165. data/lib/hecks/runtime/remote_dispatcher.rb +2 -2
  166. data/lib/hecks/runtime/value.rb +13 -0
  167. data/lib/hecks/rust_build/project_rust/target_ir.rb +23 -4
  168. data/lib/hecks/rust_build/wasm.rb +0 -12
  169. data/lib/hecks/rust_build/write_if_changed.rb +12 -12
  170. data/lib/hecks/rust_format.rb +77 -0
  171. data/lib/hecks/tools/fuzz_sweep/findings.rb +3 -9
  172. data/lib/hecks/tools/fuzz_sweep.rb +1 -3
  173. data/lib/hecks/tools/translation_audit/verdicts.rb +3 -28
  174. data/lib/hecks/tools/translation_audit.rb +8 -10
  175. data/lib/hecks/tools/translation_scaffold/reporting.rb +1 -1
  176. data/lib/hecks/version.rb +1 -1
  177. data/lib/hecks/vocabulary.rb +2 -1
  178. data/lib/hecks.rb +3 -0
  179. data/prebuilt/{a883a7e568667aa5ac904c82daff356bdf9e996252a36af6def4a4a43efb967e.marshal → 02c09c73b272c1fb5a9ae6d87bb5e5e529208e00f6b4b597dc2c0fd70a9c0964.marshal} +0 -0
  180. data/prebuilt/{1a6f596be124228be93eba1d86dbc9d2933190fa389b284331241cb9f27115a0.marshal → bb84a835cf6a15136bad5ca03aa5bf93a5b92f5f72444618d3ef2412b987fb32.marshal} +0 -0
  181. data/prebuilt/{verdicts-872993b1aa26d73fe48f28251374b8585fed145d02aab42be0f00de386b6ff80.json → verdicts-f1f10da14c8e8f01b4c9b7e3e2d74be8cd2bf4676364ed17fa16975d2a076d75.json} +1 -1
  182. data/rust/Cargo.toml +40 -0
  183. data/rust/build/Cargo.toml +36 -0
  184. data/rust/build/clippy.toml +4 -0
  185. data/rust/build/src/adapters_pass.rs +196 -0
  186. data/rust/build/src/binding_pass.rs +54 -13
  187. data/rust/build/src/build_artifact.rs +23 -5
  188. data/rust/build/src/cargo_sync.rs +69 -26
  189. data/rust/build/src/lineage_pass.rs +101 -87
  190. data/rust/build/src/main.rs +11 -2
  191. data/rust/build/src/pipeline.rs +80 -19
  192. data/rust/build/src/reserved_names.rs +6 -50
  193. data/rust/build/src/resolve.rs +82 -35
  194. data/rust/build/src/rustfmt.rs +100 -0
  195. data/rust/build/src/seams_pass.rs +85 -16
  196. data/rust/build/src/subprocess.rs +30 -6
  197. data/rust/build/src/tmp.rs +5 -2
  198. data/rust/build/src/translation_pass.rs +72 -22
  199. data/rust/build/src/world_pass.rs +109 -0
  200. data/rust/clippy.toml +4 -0
  201. data/rust/codegen/Cargo.toml +36 -0
  202. data/rust/codegen/clippy.toml +4 -0
  203. data/rust/codegen/src/asks.rs +40 -14
  204. data/rust/codegen/src/attr.rs +2 -2
  205. data/rust/codegen/src/bridging.rs +676 -117
  206. data/rust/codegen/src/commands.rs +979 -373
  207. data/rust/codegen/src/constraints.rs +88 -25
  208. data/rust/codegen/src/dependency_planning.rs +128 -34
  209. data/rust/codegen/src/domain_generator.rs +300 -170
  210. data/rust/codegen/src/exemplar.rs +87 -32
  211. data/rust/codegen/src/expr_emitter.rs +54 -6
  212. data/rust/codegen/src/fielded.rs +193 -41
  213. data/rust/codegen/src/hecks_naming.rs +124 -16
  214. data/rust/codegen/src/hecks_naming_tests.rs +81 -0
  215. data/rust/codegen/src/json.rs +80 -44
  216. data/rust/codegen/src/json_codec.rs +585 -149
  217. data/rust/codegen/src/literal.rs +104 -138
  218. data/rust/codegen/src/main.rs +145 -52
  219. data/rust/codegen/src/manifest.rs +76 -14
  220. data/rust/codegen/src/mutations.rs +1212 -239
  221. data/rust/codegen/src/naming.rs +111 -60
  222. data/rust/codegen/src/optional_pass.rs +90 -28
  223. data/rust/codegen/src/ports.rs +5 -4
  224. data/rust/codegen/src/prelude.rs +139 -49
  225. data/rust/codegen/src/queries.rs +601 -226
  226. data/rust/codegen/src/reactions.rs +268 -74
  227. data/rust/codegen/src/read_models.rs +606 -205
  228. data/rust/codegen/src/reference_specs.rs +16 -3
  229. data/rust/codegen/src/registry.rs +128 -79
  230. data/rust/codegen/src/reserved_names.rs +6 -50
  231. data/rust/codegen/src/shared.rs +71 -22
  232. data/rust/codegen/src/sidecars.rs +15 -5
  233. data/rust/codegen/src/skip_reason.rs +8 -2
  234. data/rust/codegen/src/types.rs +306 -108
  235. data/rust/host/Cargo.lock +1 -0
  236. data/rust/host/Cargo.toml +40 -4
  237. data/rust/host/HECKS_RELEASE +1 -1
  238. data/rust/host/clippy.toml +4 -0
  239. data/rust/host/src/api.rs +698 -218
  240. data/rust/host/src/auth.rs +491 -214
  241. data/rust/host/src/b64.rs +91 -0
  242. data/rust/host/src/bin/expr_harness.rs +6 -2
  243. data/rust/host/src/bin/lineage_harness.rs +47 -11
  244. data/rust/host/src/bin/mint_harness.rs +70 -37
  245. data/rust/host/src/bin/validate_harness.rs +16 -8
  246. data/rust/host/src/boot.rs +144 -68
  247. data/rust/host/src/boundary_fuzz/api.rs +130 -32
  248. data/rust/host/src/boundary_fuzz/auth.rs +108 -23
  249. data/rust/host/src/boundary_fuzz/expr_json.rs +85 -11
  250. data/rust/host/src/boundary_fuzz/ir.rs +164 -12
  251. data/rust/host/src/boundary_fuzz/server.rs +283 -36
  252. data/rust/host/src/boundary_fuzz/web.rs +56 -8
  253. data/rust/host/src/checkout.rs +78 -32
  254. data/rust/host/src/clock.rs +8 -0
  255. data/rust/host/src/commerce_ir.rs +333 -95
  256. data/rust/host/src/crypto.rs +33 -0
  257. data/rust/host/src/dispatch.rs +990 -331
  258. data/rust/host/src/expr_json.rs +1021 -273
  259. data/rust/host/src/extension.rs +24 -4
  260. data/rust/host/src/field_hints.rs +11 -7
  261. data/rust/host/src/fuzz_support.rs +85 -13
  262. data/rust/host/src/host.rs +100 -0
  263. data/rust/host/src/http.rs +22 -0
  264. data/rust/host/src/ir.rs +326 -16
  265. data/rust/host/src/journal.rs +277 -176
  266. data/rust/host/src/lambda_client.rs +219 -53
  267. data/rust/host/src/lib.rs +16 -4
  268. data/rust/host/src/log.rs +62 -11
  269. data/rust/host/src/mint.rs +1153 -326
  270. data/rust/host/src/needs.rs +185 -44
  271. data/rust/host/src/payments/keystore.rs +197 -45
  272. data/rust/host/src/payments/roles.rs +39 -7
  273. data/rust/host/src/payments/tests.rs +1427 -282
  274. data/rust/host/src/payments.rs +391 -112
  275. data/rust/host/src/platform_signin/attack_tests.rs +5 -5
  276. data/rust/host/src/platform_signin/config.rs +11 -11
  277. data/rust/host/src/platform_signin/cookie.rs +2 -2
  278. data/rust/host/src/platform_signin/extension.rs +2 -1
  279. data/rust/host/src/platform_signin/handler.rs +9 -8
  280. data/rust/host/src/platform_signin/jti.rs +4 -2
  281. data/rust/host/src/platform_signin/jwks.rs +2 -1
  282. data/rust/host/src/platform_signin/jws.rs +2 -37
  283. data/rust/host/src/platform_signin/known_answer_tests.rs +5 -1
  284. data/rust/host/src/platform_signin/mode_tests.rs +5 -3
  285. data/rust/host/src/platform_signin/pages.rs +20 -20
  286. data/rust/host/src/platform_signin/session.rs +8 -1
  287. data/rust/host/src/platform_signin/settings.rs +6 -6
  288. data/rust/host/src/platform_signin/strict_json.rs +12 -9
  289. data/rust/host/src/platform_signin/verify.rs +41 -41
  290. data/rust/host/src/platform_signin/wiring_support.rs +13 -18
  291. data/rust/host/src/presentation.rs +207 -63
  292. data/rust/host/src/presentation_write.rs +502 -187
  293. data/rust/host/src/query_step.rs +69 -18
  294. data/rust/host/src/rate_limit.rs +541 -142
  295. data/rust/host/src/reference_transform.rs +77 -25
  296. data/rust/host/src/reference_validate.rs +443 -104
  297. data/rust/host/src/resend.rs +190 -55
  298. data/rust/host/src/secrets.rs +116 -21
  299. data/rust/host/src/server.rs +483 -104
  300. data/rust/host/src/storage_shape.rs +88 -21
  301. data/rust/host/src/test_pg.rs +17 -7
  302. data/rust/host/src/ui_schema.rs +495 -207
  303. data/rust/host/src/wasm_runner.rs +21 -6
  304. data/rust/host/src/web/commerce.rs +101 -23
  305. data/rust/host/src/web/newsletter/cooldown.rs +10 -3
  306. data/rust/host/src/web/newsletter/template.rs +26 -7
  307. data/rust/host/src/web/newsletter/tests.rs +112 -23
  308. data/rust/host/src/web/newsletter.rs +209 -59
  309. data/rust/host/src/web/newsletter_send.rs +251 -79
  310. data/rust/host/src/web/registration_receipt/tests.rs +16 -4
  311. data/rust/host/src/web/registration_receipt.rs +100 -24
  312. data/rust/host/src/web/registrations.rs +1384 -332
  313. data/rust/host/src/web/resend_webhook.rs +138 -80
  314. data/rust/host/src/web.rs +2416 -508
  315. data/rust/lsp/Cargo.toml +36 -0
  316. data/rust/lsp/clippy.toml +4 -0
  317. data/rust/lsp/src/json.rs +29 -22
  318. data/rust/lsp/src/main.rs +81 -31
  319. data/rust/lsp/src/outline.rs +23 -7
  320. data/rust/lsp/src/rpc.rs +17 -4
  321. data/rust/parser/Cargo.toml +36 -0
  322. data/rust/parser/clippy.toml +4 -0
  323. data/rust/parser/src/build/closed_sets.rs +6 -1
  324. data/rust/parser/src/build/identity.rs +4 -3
  325. data/rust/parser/src/build/mod.rs +1 -1
  326. data/rust/parser/src/build/named_pattern.rs +4 -1
  327. data/rust/parser/src/build/naming.rs +2 -80
  328. data/rust/parser/src/build/pattern_subset.rs +6 -8
  329. data/rust/parser/src/build/query_derive.rs +3 -1
  330. data/rust/parser/src/build/query_inference.rs +14 -5
  331. data/rust/parser/src/build/read_model.rs +4 -1
  332. data/rust/parser/src/build/references.rs +4 -3
  333. data/rust/parser/src/canonical.rs +34 -15
  334. data/rust/parser/src/emit.rs +187 -105
  335. data/rust/parser/src/expr/ast_json.rs +134 -42
  336. data/rust/parser/src/expr/evaluator.rs +27 -9
  337. data/rust/parser/src/expr/mod.rs +54 -13
  338. data/rust/parser/src/expr/resolver.rs +299 -92
  339. data/rust/parser/src/ir.rs +35 -3
  340. data/rust/parser/src/keywords.rs +7168 -516
  341. data/rust/parser/src/lex.rs +11 -25
  342. data/rust/parser/src/lib.rs +1 -0
  343. data/rust/parser/src/main.rs +65 -6
  344. data/rust/parser/src/parse/adapter.rs +157 -0
  345. data/rust/parser/src/parse/aggregate.rs +19 -10
  346. data/rust/parser/src/parse/chapter.rs +16 -17
  347. data/rust/parser/src/parse/command.rs +35 -16
  348. data/rust/parser/src/parse/domain_port.rs +4 -7
  349. data/rust/parser/src/parse/entity.rs +21 -11
  350. data/rust/parser/src/parse/hecksagon.rs +10 -4
  351. data/rust/parser/src/parse/lifecycle.rs +9 -5
  352. data/rust/parser/src/parse/mod.rs +22 -91
  353. data/rust/parser/src/parse/needs.rs +21 -12
  354. data/rust/parser/src/parse/policy.rs +2 -2
  355. data/rust/parser/src/parse/process_manager.rs +9 -11
  356. data/rust/parser/src/parse/query.rs +8 -4
  357. data/rust/parser/src/parse/read_model.rs +57 -16
  358. data/rust/parser/src/parse/value_object.rs +7 -2
  359. data/rust/parser/src/parse/world.rs +322 -0
  360. data/rust/parser/src/ruby_value.rs +7 -6
  361. data/rust/src/exemplar/json.rs +4 -4
  362. data/rust/src/exemplar/mutations.rs +18 -0
  363. data/rust/src/exemplar/read_models.rs +1 -10
  364. data/rust/src/kernel/attribute_shapes/composite.rs +54 -14
  365. data/rust/src/kernel/attribute_shapes/list.rs +2 -2
  366. data/rust/src/kernel/attribute_shapes/mod.rs +8 -8
  367. data/rust/src/kernel/attribute_shapes/scalar.rs +2 -2
  368. data/rust/src/kernel/cli.rs +229 -112
  369. data/rust/src/kernel/dispatch.rs +323 -115
  370. data/rust/src/kernel/dispatch_guard_tests.rs +327 -65
  371. data/rust/src/kernel/expr.rs +203 -86
  372. data/rust/src/kernel/expression_operators/arithmetic.rs +138 -25
  373. data/rust/src/kernel/expression_operators/comparison.rs +87 -2
  374. data/rust/src/kernel/expression_operators/enumeration.rs +106 -22
  375. data/rust/src/kernel/expression_operators/logical.rs +9 -3
  376. data/rust/src/kernel/expression_operators/membership.rs +3 -1
  377. data/rust/src/kernel/expression_operators/mod.rs +34 -21
  378. data/rust/src/kernel/expression_operators/pattern_match.rs +46 -11
  379. data/rust/src/kernel/expression_operators/positional.rs +84 -30
  380. data/rust/src/kernel/expression_operators/presence.rs +52 -13
  381. data/rust/src/kernel/expression_operators/sign_test.rs +3 -1
  382. data/rust/src/kernel/expression_operators/sized.rs +24 -8
  383. data/rust/src/kernel/expression_operators/text.rs +120 -27
  384. data/rust/src/kernel/expression_operators/to_string.rs +10 -4
  385. data/rust/src/kernel/json.rs +230 -148
  386. data/rust/src/kernel/mod.rs +46 -33
  387. data/rust/src/kernel/named_query.rs +63 -15
  388. data/rust/src/kernel/needs.rs +112 -25
  389. data/rust/src/kernel/orchestrate.rs +980 -581
  390. data/rust/src/kernel/orchestrate_guard_tests.rs +538 -140
  391. data/rust/src/kernel/pattern.rs +107 -34
  392. data/rust/src/kernel/query_comparators.rs +118 -41
  393. data/rust/src/kernel/query_ordering.rs +13 -5
  394. data/rust/src/kernel/read_model.rs +479 -181
  395. data/rust/src/kernel/reference_lookup.rs +122 -26
  396. data/rust/src/kernel/repository.rs +293 -66
  397. data/rust/src/kernel/routing.rs +58 -42
  398. data/rust/src/kernel/ruby_float.rs +139 -0
  399. data/rust/src/kernel/vocab/aggregate_dispatch_order.rs +57 -57
  400. data/rust/src/kernel/vocab/entity_dispatch_order.rs +54 -54
  401. data/rust/src/kernel/vocab/field_hint.rs +19 -25
  402. data/rust/src/kernel/vocab/mod.rs +6 -6
  403. data/rust/src/kernel/vocab/query_comparator.rs +23 -24
  404. data/rust/src/kernel/vocab/refusal_template.rs +501 -297
  405. data/rust/src/lib.rs +50 -0
  406. data/rust/src/main.rs +4 -1
  407. data/rust/web/Cargo.toml +36 -0
  408. data/rust/web/clippy.toml +4 -0
  409. metadata +82 -15
  410. data/examples/pizzas/bluebook/hecksagon/mock_stripe_payment_adapter.rb +0 -36
  411. data/lib/hecks/adapters/driven/google_authentication.adapter +0 -3
  412. data/lib/hecks/adapters/driven/google_authentication.rb +0 -99
  413. data/lib/hecks/adapters/driven/mock_stripe_adapter.adapter +0 -3
  414. data/lib/hecks/adapters/driven/mock_stripe_adapter.rb +0 -32
  415. data/lib/hecks/ports/authentication.port +0 -6
  416. data/lib/hecks/ports/authentication.rb +0 -67
  417. data/lib/hecks/ports/persistence/plugins/era/translation/approval_file.rb +0 -255
  418. data/lib/hecks/ports/persistence/plugins/era/translation/audit/approval_digest.rb +0 -22
  419. data/rust/host/src/approval.rs +0 -652
@@ -29,6 +29,15 @@ pub struct Ctx<'a> {
29
29
  pub wasm_path: &'a Path,
30
30
  pub config: &'a LineageConfig,
31
31
  pub invoker: &'a dyn LambdaInvoker,
32
+ /// The four above as one value, for the host's own handlers.
33
+ pub host: crate::host::Host<'a>,
34
+ }
35
+
36
+ impl<'a> Ctx<'a> {
37
+ /// The request's journal connection, module, lineage and invoker, as one value.
38
+ pub const fn host(&self) -> crate::host::Host<'a> {
39
+ self.host
40
+ }
32
41
  }
33
42
 
34
43
  /// A public write an extension wants limited per client: `limit_env` names the budget setting.
@@ -83,14 +92,20 @@ pub fn installed() -> &'static [Arc<dyn HostExtension>] {
83
92
  fn default_extensions() -> Vec<Arc<dyn HostExtension>> {
84
93
  let vars = crate::platform_signin::settings::PROCESS_VARIABLES
85
94
  .iter()
86
- .filter_map(|name| std::env::var(name).ok().map(|value| (name.to_string(), value)))
95
+ .filter_map(|name| {
96
+ crate::secrets::var(name)
97
+ .ok()
98
+ .map(|value| (name.to_string(), value))
99
+ })
87
100
  .collect();
88
101
  default_extensions_from(&vars)
89
102
  }
90
103
 
91
104
  /// The default extensions for an explicit set of settings: commerce, plus platform sign-in when
92
105
  /// it is switched on (or its boot refusal when its settings are wrong).
93
- pub(crate) fn default_extensions_from(vars: &HashMap<String, String>) -> Vec<Arc<dyn HostExtension>> {
106
+ pub(crate) fn default_extensions_from(
107
+ vars: &HashMap<String, String>,
108
+ ) -> Vec<Arc<dyn HostExtension>> {
94
109
  let mut extensions: Vec<Arc<dyn HostExtension>> = vec![Arc::new(crate::web::Commerce)];
95
110
  extensions.extend(crate::platform_signin::extension::extensions_for(vars));
96
111
  extensions
@@ -103,10 +118,15 @@ pub fn loaded_ir() -> Option<&'static Value> {
103
118
 
104
119
  /// Every installed extension's rate rules.
105
120
  pub fn rate_rules() -> Vec<RateRule> {
106
- installed().iter().flat_map(|extension| extension.rate_rules()).collect()
121
+ installed()
122
+ .iter()
123
+ .flat_map(|extension| extension.rate_rules())
124
+ .collect()
107
125
  }
108
126
 
109
127
  /// The rule that limits this request, if any.
110
128
  pub fn rate_rule_for(method: &str, path: &str) -> Option<RateRule> {
111
- rate_rules().into_iter().find(|rule| rule.method == method && rule.path == path)
129
+ rate_rules()
130
+ .into_iter()
131
+ .find(|rule| rule.method == method && rule.path == path)
112
132
  }
@@ -27,8 +27,10 @@ pub static EMAIL_HINT: LazyLock<Regex> =
27
27
  /// `(?i)` up front is this crate's spelling
28
28
  /// of Ruby's trailing `/i` — the WHOLE pattern is case-insensitive
29
29
  /// on both sides, never partially.
30
- pub static URL_HINT: LazyLock<Regex> =
31
- LazyLock::new(|| Regex::new(r#"(?i)\b(url|uri|website|link)\b"#).expect("declared field-hint pattern must compile"));
30
+ pub static URL_HINT: LazyLock<Regex> = LazyLock::new(|| {
31
+ Regex::new(r#"(?i)\b(url|uri|website|link)\b"#)
32
+ .expect("declared field-hint pattern must compile")
33
+ });
32
34
 
33
35
  /// Tel hint, resolving to `html_type` on a match —
34
36
  /// Vocabulary::FieldHint's own declared pattern, unmodified (the
@@ -37,8 +39,9 @@ pub static URL_HINT: LazyLock<Regex> =
37
39
  /// `(?i)` up front is this crate's spelling
38
40
  /// of Ruby's trailing `/i` — the WHOLE pattern is case-insensitive
39
41
  /// on both sides, never partially.
40
- pub static TEL_HINT: LazyLock<Regex> =
41
- LazyLock::new(|| Regex::new(r#"(?i)phone|\btel(ephone)?\b"#).expect("declared field-hint pattern must compile"));
42
+ pub static TEL_HINT: LazyLock<Regex> = LazyLock::new(|| {
43
+ Regex::new(r#"(?i)phone|\btel(ephone)?\b"#).expect("declared field-hint pattern must compile")
44
+ });
42
45
 
43
46
  /// Textarea hint, resolving to `kind` on a match —
44
47
  /// Vocabulary::FieldHint's own declared pattern, unmodified (the
@@ -47,6 +50,7 @@ pub static TEL_HINT: LazyLock<Regex> =
47
50
  /// `(?i)` up front is this crate's spelling
48
51
  /// of Ruby's trailing `/i` — the WHOLE pattern is case-insensitive
49
52
  /// on both sides, never partially.
50
- pub static TEXTAREA_HINT: LazyLock<Regex> =
51
- LazyLock::new(|| Regex::new(r#"(?i)\b(text|body|note|notes|description|message|comment)\b"#).expect("declared field-hint pattern must compile"));
52
-
53
+ pub static TEXTAREA_HINT: LazyLock<Regex> = LazyLock::new(|| {
54
+ Regex::new(r#"(?i)\b(text|body|note|notes|description|message|comment)\b"#)
55
+ .expect("declared field-hint pattern must compile")
56
+ });
@@ -13,7 +13,7 @@ pub(crate) struct Rng(u64);
13
13
 
14
14
  impl Rng {
15
15
  pub(crate) fn new(seed: u64) -> Self {
16
- Rng(seed.wrapping_mul(0x9E37_79B9_7F4A_7C15) | 1)
16
+ Self(seed.wrapping_mul(0x9E37_79B9_7F4A_7C15) | 1)
17
17
  }
18
18
 
19
19
  pub(crate) fn next(&mut self) -> u64 {
@@ -38,7 +38,10 @@ impl Rng {
38
38
 
39
39
  /// How many seeds each fuzz test runs.
40
40
  pub(crate) fn seeds() -> u64 {
41
- std::env::var("HOST_FUZZ_SEEDS").ok().and_then(|v| v.parse().ok()).unwrap_or(200)
41
+ std::env::var("HOST_FUZZ_SEEDS")
42
+ .ok()
43
+ .and_then(|v| v.parse().ok())
44
+ .unwrap_or(200)
42
45
  }
43
46
 
44
47
  /// The most a single guarded case may take before it counts as a hang.
@@ -60,10 +63,18 @@ pub(crate) fn guarded<T: Send + 'static>(label: &str, f: impl FnOnce() -> T + Se
60
63
  handle.join().expect("guarded thread joined");
61
64
  value
62
65
  }
63
- Err(mpsc::RecvTimeoutError::Timeout) => panic!("{label}: no answer within {LIMIT:?} (hang)"),
66
+ Err(mpsc::RecvTimeoutError::Timeout) => {
67
+ panic!("{label}: no answer within {LIMIT:?} (hang)")
68
+ }
64
69
  Err(mpsc::RecvTimeoutError::Disconnected) => {
65
- let panic = handle.join().expect_err("a guarded thread that sent nothing must have panicked");
66
- let message = panic.downcast_ref::<String>().cloned().or_else(|| panic.downcast_ref::<&str>().map(|s| s.to_string()));
70
+ let panic = handle
71
+ .join()
72
+ .expect_err("a guarded thread that sent nothing must have panicked");
73
+ let message = panic.downcast_ref::<String>().cloned().or_else(|| {
74
+ panic
75
+ .downcast_ref::<&str>()
76
+ .map(std::string::ToString::to_string)
77
+ });
67
78
  panic!("{label}: panicked: {}", message.unwrap_or_default())
68
79
  }
69
80
  }
@@ -73,9 +84,63 @@ pub(crate) fn guarded<T: Send + 'static>(label: &str, f: impl FnOnce() -> T + Se
73
84
  /// shape that slices through a char boundary), control characters, NUL, bidi marks, astral
74
85
  /// planes, combining marks, percent signs, and every JSON/URL/cookie delimiter.
75
86
  const PIECES: &[&str] = &[
76
- "a", "Z", "0", "9", " ", "\"", "'", "\\", "/", "%", "%4", "%41", "%zz", "%+1", "+", "=", "&", ";", "?", "#", ".", "..", "-", "_", ":", ",", "{", "}", "[", "]",
77
- "\n", "\t", "\r", "\u{0}", "\u{1f}", "\u{7f}", "é", "ü", "日本", "🍕", "\u{10FFFF}", "\u{200B}", "\u{FEFF}", "\u{202E}", "\u{FFFD}", "e\u{301}", "__", "::",
78
- "<script>", "../", "%0d%0a", "id", "name", "value", "sort", "direction", "desc",
87
+ "a",
88
+ "Z",
89
+ "0",
90
+ "9",
91
+ " ",
92
+ "\"",
93
+ "'",
94
+ "\\",
95
+ "/",
96
+ "%",
97
+ "%4",
98
+ "%41",
99
+ "%zz",
100
+ "%+1",
101
+ "+",
102
+ "=",
103
+ "&",
104
+ ";",
105
+ "?",
106
+ "#",
107
+ ".",
108
+ "..",
109
+ "-",
110
+ "_",
111
+ ":",
112
+ ",",
113
+ "{",
114
+ "}",
115
+ "[",
116
+ "]",
117
+ "\n",
118
+ "\t",
119
+ "\r",
120
+ "\u{0}",
121
+ "\u{1f}",
122
+ "\u{7f}",
123
+ "é",
124
+ "ü",
125
+ "日本",
126
+ "🍕",
127
+ "\u{10FFFF}",
128
+ "\u{200B}",
129
+ "\u{FEFF}",
130
+ "\u{202E}",
131
+ "\u{FFFD}",
132
+ "e\u{301}",
133
+ "__",
134
+ "::",
135
+ "<script>",
136
+ "../",
137
+ "%0d%0a",
138
+ "id",
139
+ "name",
140
+ "value",
141
+ "sort",
142
+ "direction",
143
+ "desc",
79
144
  ];
80
145
 
81
146
  pub(crate) fn random_text(rng: &mut Rng) -> String {
@@ -97,8 +162,8 @@ pub(crate) fn edge_number(rng: &mut Rng) -> Value {
97
162
  json!(1e308),
98
163
  json!(-1e308),
99
164
  json!(5e-324),
100
- json!(1.7976931348623157e308),
101
- json!(9007199254740993_i64),
165
+ json!(1.797_693_134_862_315_7e308),
166
+ json!(9_007_199_254_740_993_i64),
102
167
  ];
103
168
  rng.pick(&edges).clone()
104
169
  }
@@ -112,7 +177,11 @@ pub(crate) fn random_value(rng: &mut Rng, depth: usize) -> Value {
112
177
  2 => edge_number(rng),
113
178
  3 | 4 => Value::String(random_text(rng)),
114
179
  5 => json!(rng.next() as i64 >> rng.below(63)),
115
- 6 => Value::Array((0..rng.below(4)).map(|_| random_value(rng, depth + 1)).collect()),
180
+ 6 => Value::Array(
181
+ (0..rng.below(4))
182
+ .map(|_| random_value(rng, depth + 1))
183
+ .collect(),
184
+ ),
116
185
  _ => {
117
186
  let mut map = Map::new();
118
187
  for _ in 0..rng.below(4) {
@@ -125,9 +194,12 @@ pub(crate) fn random_value(rng: &mut Rng, depth: usize) -> Value {
125
194
 
126
195
  /// `text` with a few random edits, on char boundaries.
127
196
  pub(crate) fn mutate_text(rng: &mut Rng, text: &str) -> String {
197
+ const JUNK: &[char] = &[
198
+ '{', '}', '[', ']', '"', '\\', ',', ':', '-', '+', '.', 'e', '0', '9', 'n', 't', ' ',
199
+ '\u{0}', '\n', '%', 'é', '🍕',
200
+ ];
128
201
  let mut chars: Vec<char> = text.chars().collect();
129
- const JUNK: &[char] = &['{', '}', '[', ']', '"', '\\', ',', ':', '-', '+', '.', 'e', '0', '9', 'n', 't', ' ', '\u{0}', '\n', '%', 'é', '🍕'];
130
- for _ in 0..1 + rng.below(3) {
202
+ for _ in 0..=rng.below(3) {
131
203
  if chars.is_empty() {
132
204
  chars.push(*rng.pick(JUNK));
133
205
  continue;
@@ -0,0 +1,100 @@
1
+ //! What a request handler needs to reach the domain, travelling as one value.
2
+
3
+ use crate::journal::LineageConfig;
4
+ use crate::lambda_client::LambdaInvoker;
5
+ use std::path::{Path, PathBuf};
6
+ use std::sync::Arc;
7
+ use tokio::sync::Mutex;
8
+ use tokio_postgres::Client;
9
+
10
+ /// The server's own shared handles, when a host is built from them.
11
+ #[derive(Clone, Copy)]
12
+ struct Shared<'a> {
13
+ client: &'a Arc<Mutex<Client>>,
14
+ wasm_path: &'a Arc<PathBuf>,
15
+ config: &'a Arc<LineageConfig>,
16
+ invoker: &'a Arc<dyn LambdaInvoker>,
17
+ }
18
+
19
+ /// The journal connection, the compiled domain module, the lineage it runs under, and the
20
+ /// invoker that delivers a policy's cross-domain reactions. Borrowed from the server's state (or
21
+ /// a test's fixtures) for the length of one call, so it is `Copy`.
22
+ #[derive(Clone, Copy)]
23
+ pub struct Host<'a> {
24
+ /// The one Postgres connection; its mutex serializes every write onto it.
25
+ pub client: &'a Mutex<Client>,
26
+ pub wasm_path: &'a Path,
27
+ pub config: &'a LineageConfig,
28
+ pub invoker: &'a dyn LambdaInvoker,
29
+ shared: Option<Shared<'a>>,
30
+ }
31
+
32
+ impl<'a> Host<'a> {
33
+ /// A host over borrowed pieces. It cannot outlive the call, so work that must outlast the
34
+ /// response stays inline.
35
+ pub fn new(
36
+ client: &'a Mutex<Client>,
37
+ wasm_path: &'a Path,
38
+ config: &'a LineageConfig,
39
+ invoker: &'a dyn LambdaInvoker,
40
+ ) -> Self {
41
+ Self {
42
+ client,
43
+ wasm_path,
44
+ config,
45
+ invoker,
46
+ shared: None,
47
+ }
48
+ }
49
+
50
+ /// A host over the server's own `Arc`s, from which `detach` can hand work an owned copy.
51
+ pub fn shared(
52
+ client: &'a Arc<Mutex<Client>>,
53
+ wasm_path: &'a Arc<PathBuf>,
54
+ config: &'a Arc<LineageConfig>,
55
+ invoker: &'a Arc<dyn LambdaInvoker>,
56
+ ) -> Self {
57
+ Self {
58
+ client,
59
+ wasm_path,
60
+ config,
61
+ invoker: invoker.as_ref(),
62
+ shared: Some(Shared {
63
+ client,
64
+ wasm_path,
65
+ config,
66
+ invoker,
67
+ }),
68
+ }
69
+ }
70
+
71
+ /// An owned copy for a task that outlives this request, or `None` when the host was built
72
+ /// from borrows and so cannot be detached.
73
+ pub fn detach(&self) -> Option<OwnedHost> {
74
+ self.shared.map(|shared| OwnedHost {
75
+ client: Arc::clone(shared.client),
76
+ wasm_path: Arc::clone(shared.wasm_path),
77
+ config: Arc::clone(shared.config),
78
+ invoker: Arc::clone(shared.invoker),
79
+ })
80
+ }
81
+ }
82
+
83
+ /// A `Host` that owns its handles, for work spawned past the end of a request.
84
+ pub struct OwnedHost {
85
+ client: Arc<Mutex<Client>>,
86
+ wasm_path: Arc<PathBuf>,
87
+ config: Arc<LineageConfig>,
88
+ invoker: Arc<dyn LambdaInvoker>,
89
+ }
90
+
91
+ impl OwnedHost {
92
+ pub fn host(&self) -> Host<'_> {
93
+ Host::new(
94
+ &self.client,
95
+ &self.wasm_path,
96
+ &self.config,
97
+ self.invoker.as_ref(),
98
+ )
99
+ }
100
+ }
@@ -0,0 +1,22 @@
1
+ //! The one HTTP client the host's outbound calls share.
2
+
3
+ use std::sync::LazyLock;
4
+
5
+ /// Built once: the TLS configuration and its root certificates are the costly part of a client.
6
+ ///
7
+ /// It keeps no idle connections. The tests run each case on its own runtime, and a connection
8
+ /// opened under one runtime is dead under the next, so reusing connections would fail them; these
9
+ /// calls (sign-in, checkout, receipts, template fetches) are infrequent and go to different
10
+ /// hosts, so reuse would not pay anyway.
11
+ #[allow(clippy::expect_used)] // reason: a client with default TLS settings always builds
12
+ static CLIENT: LazyLock<reqwest::Client> = LazyLock::new(|| {
13
+ reqwest::Client::builder()
14
+ .pool_max_idle_per_host(0)
15
+ .build()
16
+ .expect("a reqwest client with default settings always builds")
17
+ });
18
+
19
+ /// The shared client. Set a per-call timeout on the request, not on the client.
20
+ pub(crate) fn client() -> &'static reqwest::Client {
21
+ &CLIENT
22
+ }