hecks 3.13.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 (440) 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.bluebook +4 -4
  7. data/examples/pizzas/bluebook/pizzas.hecksagon +5 -3
  8. data/examples/pizzas/config.ru +22 -0
  9. data/lib/hecks/adapters/driven/prism.rb +0 -2
  10. data/lib/hecks/adapters/driven.rb +0 -2
  11. data/lib/hecks/adapters/driving/json.rb +1 -7
  12. data/lib/hecks/bluebook/dsl/attribute_collector.rb +15 -5
  13. data/lib/hecks/bluebook/dsl/bootstrap_table.rb +2 -2
  14. data/lib/hecks/bluebook/dsl/derivation_words.rb +58 -0
  15. data/lib/hecks/bluebook/dsl/translation_builder.rb +6 -37
  16. data/lib/hecks/bluebook/expression/ast_json.rb +0 -9
  17. data/lib/hecks/bluebook/hecksagon.rb +1 -1
  18. data/lib/hecks/bluebook/meta_validator/translation_judge/rules.rb +7 -10
  19. data/lib/hecks/bluebook/meta_validator/translation_judge.rb +4 -8
  20. data/lib/hecks/bluebook/meta_validator.rb +0 -11
  21. data/lib/hecks/bluebook/named_pattern.rb +33 -0
  22. data/lib/hecks/bluebook/translation.rb +18 -10
  23. data/lib/hecks/bluebook/translation_expression/evaluator.rb +63 -0
  24. data/lib/hecks/bluebook/translation_expression/parser.rb +127 -0
  25. data/lib/hecks/bluebook/translation_expression.rb +39 -0
  26. data/lib/hecks/bluebook/translation_plan.rb +70 -0
  27. data/lib/hecks/bluebook.rb +3 -0
  28. data/lib/hecks/chapters.rb +3 -3
  29. data/lib/hecks/cli/domain_stub.rb +1 -1
  30. data/lib/hecks/cli/interview_aggregate.rb +4 -4
  31. data/lib/hecks/composer/adapters/claude_composer.adapter +3 -0
  32. data/lib/hecks/composer/adapters/claude_composer.rb +83 -0
  33. data/lib/hecks/composer/adapters/fake_agent.adapter +3 -0
  34. data/lib/hecks/composer/adapters/fake_agent.rb +55 -0
  35. data/lib/hecks/composer/adapters/jev.adapter +3 -0
  36. data/lib/hecks/composer/adapters/jev.rb +66 -0
  37. data/lib/hecks/composer/agent.rb +113 -0
  38. data/lib/hecks/composer/assistant.rb +110 -0
  39. data/lib/hecks/composer/behavior_run.rb +53 -0
  40. data/lib/hecks/composer/bluebook/composer.bluebook +178 -0
  41. data/lib/hecks/composer/bluebook/composer.hecksagon +16 -0
  42. data/lib/hecks/composer/board.rb +65 -0
  43. data/lib/hecks/composer/board_edit/command_text.rb +39 -0
  44. data/lib/hecks/composer/board_edit/source.rb +84 -0
  45. data/lib/hecks/composer/board_edit.rb +144 -0
  46. data/lib/hecks/composer/check.rb +89 -0
  47. data/lib/hecks/composer/domains.rb +81 -0
  48. data/lib/hecks/composer/jobs.rb +134 -0
  49. data/lib/hecks/composer/layout.rb +37 -0
  50. data/lib/hecks/composer/live.rb +150 -0
  51. data/lib/hecks/composer/outline.rb +48 -0
  52. data/lib/hecks/composer/page.html +989 -0
  53. data/lib/hecks/composer/panels.rb +142 -0
  54. data/lib/hecks/composer/parse.rb +83 -0
  55. data/lib/hecks/composer/plain.rb +28 -0
  56. data/lib/hecks/composer/ports/composer_agent.port +7 -0
  57. data/lib/hecks/composer/session.rb +141 -0
  58. data/lib/hecks/composer/toolbox.rb +166 -0
  59. data/lib/hecks/composer/web.rb +156 -0
  60. data/lib/hecks/composer/workbench.rb +51 -0
  61. data/lib/hecks/composer/workspace.rb +81 -0
  62. data/lib/hecks/composer.rb +17 -0
  63. data/lib/hecks/corpus/adapters.rb +22 -0
  64. data/lib/hecks/corpus/rust.rb +1 -1
  65. data/lib/hecks/corpus/worlds.rb +19 -0
  66. data/lib/hecks/corpus.rb +5 -0
  67. data/lib/hecks/deploy/bluebook/deploy.bluebook +34 -34
  68. data/lib/hecks/forms/app/commands.rb +2 -3
  69. data/lib/hecks/forms/app/queries.rb +2 -3
  70. data/lib/hecks/forms/app/records.rb +17 -5
  71. data/lib/hecks/forms/command_form_renderer.rb +42 -16
  72. data/lib/hecks/forms/field_controls.rb +2 -2
  73. data/lib/hecks/forms/field_renderer.rb +1 -1
  74. data/lib/hecks/forms/field_shape.rb +36 -17
  75. data/lib/hecks/forms/index_renderer.rb +2 -1
  76. data/lib/hecks/forms/page.rb +1 -1
  77. data/lib/hecks/forms/params.rb +0 -13
  78. data/lib/hecks/forms/query_form_renderer.rb +7 -6
  79. data/lib/hecks/forms/record_renderer.rb +11 -7
  80. data/lib/hecks/forms/rule_words.rb +100 -0
  81. data/lib/hecks/forms/value_object_shape.rb +2 -1
  82. data/lib/hecks/framework/bluebook/change.bluebook +2 -2
  83. data/lib/hecks/fuzzing/bounded_exhaustive_expressions.rb +0 -3
  84. data/lib/hecks/fuzzing/domain_generator/block_rendering.rb +1 -1
  85. data/lib/hecks/fuzzing/isolated_boot/worlds.rb +3 -6
  86. data/lib/hecks/fuzzing/replay/filters.rb +2 -6
  87. data/lib/hecks/gate/stages.yml +25 -0
  88. data/lib/hecks/grammar/evolve/seeds.rb +0 -6
  89. data/lib/hecks/grammar/evolve.rb +0 -3
  90. data/lib/hecks/grammar/translation.bluebook +1 -1
  91. data/lib/hecks/hecks/adapters/codebase/composing.rb +56 -0
  92. data/lib/hecks/hecks/adapters/codebase/source_tree.rb +3 -1
  93. data/lib/hecks/hecks/adapters/journal_store/changes.rb +0 -26
  94. data/lib/hecks/hecks/adapters/journal_store/examination.rb +2 -23
  95. data/lib/hecks/hecks/adapters/journal_store/readings.rb +3 -11
  96. data/lib/hecks/hecks/adapters/journal_store.rb +0 -11
  97. data/lib/hecks/hecks/adapters/rehearsal/inquiry.rb +4 -11
  98. data/lib/hecks/hecks/adapters/rehearsal/memory_store.rb +0 -9
  99. data/lib/hecks/hecks/adapters/rehearsal/postgres_reading.rb +0 -4
  100. data/lib/hecks/hecks/codebase.behaviors +6 -0
  101. data/lib/hecks/hecks/codebase.bluebook +58 -37
  102. data/lib/hecks/hecks/composer.behaviors +68 -0
  103. data/lib/hecks/hecks/context_map.hecksagon +1 -1
  104. data/lib/hecks/hecks/custodian.behaviors +0 -6
  105. data/lib/hecks/hecks/custodian.bluebook +15 -92
  106. data/lib/hecks/hecks/hecks.bluebook +2 -2
  107. data/lib/hecks/hecks/hecks.hecksagon +2 -2
  108. data/lib/hecks/hecks/hecks.world +1 -1
  109. data/lib/hecks/hecks/rehearsal.bluebook +10 -16
  110. data/lib/hecks/hecks/tooling.bluebook +22 -22
  111. data/lib/hecks/kernel_capabilities/templates.rb +4 -4
  112. data/lib/hecks/kernel_capabilities.rb +1 -1
  113. data/lib/hecks/language/bluebook/aggregate.bluebook +1 -0
  114. data/lib/hecks/language/bluebook/command.bluebook +1 -0
  115. data/lib/hecks/language/bluebook/entity.bluebook +1 -0
  116. data/lib/hecks/language/bluebook/query.bluebook +1 -0
  117. data/lib/hecks/language/bluebook/shape.bluebook +8 -7
  118. data/lib/hecks/language/bluebook/vocabulary.bluebook +2 -3
  119. data/lib/hecks/language/hecksagon/port_operation.bluebook +1 -0
  120. data/lib/hecks/language/translation/translation_aggregate.bluebook +21 -24
  121. data/lib/hecks/ports/access_control.rb +2 -2
  122. data/lib/hecks/ports/persistence/plugins/era/era_check.rb +3 -41
  123. data/lib/hecks/ports/persistence/plugins/era/lineage/coverage.rb +7 -7
  124. data/lib/hecks/ports/persistence/plugins/era/lineage/rewrite.rb +25 -2
  125. data/lib/hecks/ports/persistence/plugins/era/lineage/rules.rb +4 -4
  126. data/lib/hecks/ports/persistence/plugins/era/lineage.rb +17 -25
  127. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/base_sql.rb +0 -12
  128. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/domain_rename.rb +1 -1
  129. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/era_store.rb +2 -22
  130. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/provisioning.rb +0 -1
  131. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage.rb +9 -3
  132. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/minter.rb +3 -29
  133. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/refusals.rb +2 -26
  134. data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_two.rb +6 -33
  135. data/lib/hecks/ports/persistence/plugins/era/translation/audit/unfed_report.rb +3 -3
  136. data/lib/hecks/ports/persistence/plugins/era/translation/audit.rb +2 -4
  137. data/lib/hecks/ports/persistence/plugins/era/translation/expression_sql.rb +52 -0
  138. data/lib/hecks/ports/persistence/plugins/era/translation/rule_compiler.rb +23 -29
  139. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold.rb +1 -1
  140. data/lib/hecks/ports/persistence/plugins/era/translation.rb +0 -1
  141. data/lib/hecks/ports/persistence/plugins/era.rb +3 -6
  142. data/lib/hecks/ports.rb +0 -1
  143. data/lib/hecks/projection_files.rb +3 -1
  144. data/lib/hecks/projections/deploy/templates/lambda/nat_comment_oauth.tmpl +1 -1
  145. data/lib/hecks/projections/glossary/entries.rb +10 -4
  146. data/lib/hecks/projections/glossary/groups.rb +42 -0
  147. data/lib/hecks/projections/glossary/html/page.rb +7 -2
  148. data/lib/hecks/projections/glossary/html/parser.rb +1 -1
  149. data/lib/hecks/projections/glossary/html/sections.rb +31 -11
  150. data/lib/hecks/projections/glossary/html.rb +1 -2
  151. data/lib/hecks/projections/glossary/markdown.rb +31 -28
  152. data/lib/hecks/projections/glossary/mermaid.rb +3 -0
  153. data/lib/hecks/projections/glossary/page.css +143 -153
  154. data/lib/hecks/projections/glossary/page.js +63 -3
  155. data/lib/hecks/projections/glossary/sentences/actions.rb +88 -0
  156. data/lib/hecks/projections/glossary/sentences/paths.rb +77 -0
  157. data/lib/hecks/projections/glossary/sentences/queries.rb +90 -0
  158. data/lib/hecks/projections/glossary/sentences/value_objects.rb +32 -5
  159. data/lib/hecks/projections/glossary/sentences.rb +13 -3
  160. data/lib/hecks/projections/glossary/slugs.rb +4 -1
  161. data/lib/hecks/projections/glossary.rb +2 -1
  162. data/lib/hecks/projections/plain_english.rb +97 -0
  163. data/lib/hecks/projections/rust_vocabulary/arguments.rb +2 -2
  164. data/lib/hecks/projections/rust_vocabulary/enum_body.rb +20 -25
  165. data/lib/hecks/projections/rust_vocabulary/tests.rb +2 -2
  166. data/lib/hecks/projections/rust_vocabulary.rb +14 -6
  167. data/lib/hecks/projections/site/cms_editor/color.rb +0 -6
  168. data/lib/hecks/projections/statements/actions.rb +99 -0
  169. data/lib/hecks/projections/statements/relationships.rb +86 -0
  170. data/lib/hecks/projections/statements.rb +15 -24
  171. data/lib/hecks/projector/exporter/adapters.rb +112 -0
  172. data/lib/hecks/projector/exporter/translations.rb +18 -35
  173. data/lib/hecks/projector/exporter/worlds.rb +103 -0
  174. data/lib/hecks/projector/exporter.rb +5 -1
  175. data/lib/hecks/quality_control/adapters/agent.rb +6 -7
  176. data/lib/hecks/quality_control/adapters/agent_profile.rb +16 -114
  177. data/lib/hecks/quality_control/cli/qa_mine_combinations.rb +1 -1
  178. data/lib/hecks/quality_control/quality_control.bluebook +51 -51
  179. data/lib/hecks/runtime/loader/boot_steps.rb +0 -20
  180. data/lib/hecks/runtime/outbox.rb +2 -9
  181. data/lib/hecks/runtime/port_operation_interpreter.rb +1 -9
  182. data/lib/hecks/runtime/remote_dispatcher.rb +2 -2
  183. data/lib/hecks/runtime/value.rb +13 -0
  184. data/lib/hecks/rust_build/project_rust/target_ir.rb +23 -4
  185. data/lib/hecks/rust_build/wasm.rb +0 -12
  186. data/lib/hecks/rust_build/write_if_changed.rb +12 -12
  187. data/lib/hecks/rust_format.rb +77 -0
  188. data/lib/hecks/site/bluebook/site.bluebook +5 -5
  189. data/lib/hecks/sme/bluebook/sme.bluebook +12 -12
  190. data/lib/hecks/tickets/bluebook/tickets.bluebook +3 -3
  191. data/lib/hecks/tools/fuzz_sweep/findings.rb +3 -9
  192. data/lib/hecks/tools/fuzz_sweep.rb +1 -3
  193. data/lib/hecks/tools/translation_audit/verdicts.rb +3 -28
  194. data/lib/hecks/tools/translation_audit.rb +8 -10
  195. data/lib/hecks/tools/translation_scaffold/reporting.rb +1 -1
  196. data/lib/hecks/version.rb +1 -1
  197. data/lib/hecks/vocabulary.rb +2 -1
  198. data/lib/hecks.rb +3 -0
  199. data/prebuilt/{58208399bada10b0db99928c48e38789288fc58f7b71a72b21bfa386680e32ed.marshal → 02c09c73b272c1fb5a9ae6d87bb5e5e529208e00f6b4b597dc2c0fd70a9c0964.marshal} +0 -0
  200. data/prebuilt/{2b59737fbdbd5f44edda0fddce2611f45d76087b3a7c782d1f1a17ea58c77948.marshal → bb84a835cf6a15136bad5ca03aa5bf93a5b92f5f72444618d3ef2412b987fb32.marshal} +0 -0
  201. data/prebuilt/verdicts-f1f10da14c8e8f01b4c9b7e3e2d74be8cd2bf4676364ed17fa16975d2a076d75.json +1 -0
  202. data/rust/Cargo.toml +40 -0
  203. data/rust/build/Cargo.toml +36 -0
  204. data/rust/build/clippy.toml +4 -0
  205. data/rust/build/src/adapters_pass.rs +196 -0
  206. data/rust/build/src/binding_pass.rs +54 -13
  207. data/rust/build/src/build_artifact.rs +23 -5
  208. data/rust/build/src/cargo_sync.rs +69 -26
  209. data/rust/build/src/lineage_pass.rs +101 -87
  210. data/rust/build/src/main.rs +11 -2
  211. data/rust/build/src/pipeline.rs +80 -19
  212. data/rust/build/src/reserved_names.rs +6 -50
  213. data/rust/build/src/resolve.rs +82 -35
  214. data/rust/build/src/rustfmt.rs +100 -0
  215. data/rust/build/src/seams_pass.rs +85 -16
  216. data/rust/build/src/subprocess.rs +30 -6
  217. data/rust/build/src/tmp.rs +5 -2
  218. data/rust/build/src/translation_pass.rs +72 -22
  219. data/rust/build/src/world_pass.rs +109 -0
  220. data/rust/clippy.toml +4 -0
  221. data/rust/codegen/Cargo.toml +36 -0
  222. data/rust/codegen/clippy.toml +4 -0
  223. data/rust/codegen/src/asks.rs +40 -14
  224. data/rust/codegen/src/attr.rs +2 -2
  225. data/rust/codegen/src/bridging.rs +676 -117
  226. data/rust/codegen/src/commands.rs +979 -373
  227. data/rust/codegen/src/constraints.rs +88 -25
  228. data/rust/codegen/src/dependency_planning.rs +128 -34
  229. data/rust/codegen/src/domain_generator.rs +300 -170
  230. data/rust/codegen/src/exemplar.rs +87 -32
  231. data/rust/codegen/src/expr_emitter.rs +54 -6
  232. data/rust/codegen/src/fielded.rs +193 -41
  233. data/rust/codegen/src/hecks_naming.rs +124 -16
  234. data/rust/codegen/src/hecks_naming_tests.rs +81 -0
  235. data/rust/codegen/src/json.rs +80 -44
  236. data/rust/codegen/src/json_codec.rs +585 -149
  237. data/rust/codegen/src/literal.rs +104 -138
  238. data/rust/codegen/src/main.rs +145 -52
  239. data/rust/codegen/src/manifest.rs +76 -14
  240. data/rust/codegen/src/mutations.rs +1212 -239
  241. data/rust/codegen/src/naming.rs +111 -60
  242. data/rust/codegen/src/optional_pass.rs +90 -28
  243. data/rust/codegen/src/ports.rs +5 -4
  244. data/rust/codegen/src/prelude.rs +139 -49
  245. data/rust/codegen/src/queries.rs +601 -226
  246. data/rust/codegen/src/reactions.rs +268 -74
  247. data/rust/codegen/src/read_models.rs +606 -205
  248. data/rust/codegen/src/reference_specs.rs +16 -3
  249. data/rust/codegen/src/registry.rs +128 -79
  250. data/rust/codegen/src/reserved_names.rs +6 -50
  251. data/rust/codegen/src/shared.rs +71 -22
  252. data/rust/codegen/src/sidecars.rs +15 -5
  253. data/rust/codegen/src/skip_reason.rs +8 -2
  254. data/rust/codegen/src/types.rs +306 -108
  255. data/rust/host/Cargo.lock +1 -0
  256. data/rust/host/Cargo.toml +40 -4
  257. data/rust/host/HECKS_RELEASE +1 -1
  258. data/rust/host/clippy.toml +4 -0
  259. data/rust/host/src/api.rs +698 -218
  260. data/rust/host/src/auth.rs +491 -214
  261. data/rust/host/src/b64.rs +91 -0
  262. data/rust/host/src/bin/expr_harness.rs +6 -2
  263. data/rust/host/src/bin/lineage_harness.rs +47 -11
  264. data/rust/host/src/bin/mint_harness.rs +70 -37
  265. data/rust/host/src/bin/validate_harness.rs +16 -8
  266. data/rust/host/src/boot.rs +144 -68
  267. data/rust/host/src/boundary_fuzz/api.rs +130 -32
  268. data/rust/host/src/boundary_fuzz/auth.rs +108 -23
  269. data/rust/host/src/boundary_fuzz/expr_json.rs +85 -11
  270. data/rust/host/src/boundary_fuzz/ir.rs +164 -12
  271. data/rust/host/src/boundary_fuzz/server.rs +283 -36
  272. data/rust/host/src/boundary_fuzz/web.rs +56 -8
  273. data/rust/host/src/checkout.rs +78 -32
  274. data/rust/host/src/clock.rs +8 -0
  275. data/rust/host/src/commerce_ir.rs +333 -95
  276. data/rust/host/src/crypto.rs +33 -0
  277. data/rust/host/src/dispatch.rs +990 -331
  278. data/rust/host/src/expr_json.rs +1021 -273
  279. data/rust/host/src/extension.rs +24 -4
  280. data/rust/host/src/field_hints.rs +11 -7
  281. data/rust/host/src/fuzz_support.rs +85 -13
  282. data/rust/host/src/host.rs +100 -0
  283. data/rust/host/src/http.rs +22 -0
  284. data/rust/host/src/ir.rs +326 -16
  285. data/rust/host/src/journal.rs +277 -176
  286. data/rust/host/src/lambda_client.rs +219 -53
  287. data/rust/host/src/lib.rs +16 -4
  288. data/rust/host/src/log.rs +62 -11
  289. data/rust/host/src/mint.rs +1153 -326
  290. data/rust/host/src/needs.rs +185 -44
  291. data/rust/host/src/payments/keystore.rs +197 -45
  292. data/rust/host/src/payments/roles.rs +191 -0
  293. data/rust/host/src/payments/tests.rs +1445 -275
  294. data/rust/host/src/payments.rs +409 -121
  295. data/rust/host/src/platform_signin/attack_tests.rs +5 -5
  296. data/rust/host/src/platform_signin/config.rs +11 -11
  297. data/rust/host/src/platform_signin/cookie.rs +2 -2
  298. data/rust/host/src/platform_signin/extension.rs +2 -1
  299. data/rust/host/src/platform_signin/handler.rs +9 -8
  300. data/rust/host/src/platform_signin/jti.rs +4 -2
  301. data/rust/host/src/platform_signin/jwks.rs +2 -1
  302. data/rust/host/src/platform_signin/jws.rs +2 -37
  303. data/rust/host/src/platform_signin/known_answer_tests.rs +5 -1
  304. data/rust/host/src/platform_signin/mode_tests.rs +5 -3
  305. data/rust/host/src/platform_signin/pages.rs +20 -20
  306. data/rust/host/src/platform_signin/session.rs +8 -1
  307. data/rust/host/src/platform_signin/settings.rs +6 -6
  308. data/rust/host/src/platform_signin/strict_json.rs +12 -9
  309. data/rust/host/src/platform_signin/verify.rs +41 -41
  310. data/rust/host/src/platform_signin/wiring_support.rs +13 -18
  311. data/rust/host/src/presentation.rs +207 -63
  312. data/rust/host/src/presentation_write.rs +502 -187
  313. data/rust/host/src/query_step.rs +69 -18
  314. data/rust/host/src/rate_limit.rs +541 -142
  315. data/rust/host/src/reference_transform.rs +77 -25
  316. data/rust/host/src/reference_validate.rs +443 -104
  317. data/rust/host/src/resend.rs +190 -55
  318. data/rust/host/src/secrets.rs +116 -21
  319. data/rust/host/src/server.rs +483 -104
  320. data/rust/host/src/storage_shape.rs +88 -21
  321. data/rust/host/src/test_pg.rs +17 -7
  322. data/rust/host/src/ui_schema.rs +495 -207
  323. data/rust/host/src/wasm_runner.rs +21 -6
  324. data/rust/host/src/web/commerce.rs +101 -23
  325. data/rust/host/src/web/newsletter/cooldown.rs +10 -3
  326. data/rust/host/src/web/newsletter/template.rs +26 -7
  327. data/rust/host/src/web/newsletter/tests.rs +112 -23
  328. data/rust/host/src/web/newsletter.rs +209 -59
  329. data/rust/host/src/web/newsletter_send.rs +251 -79
  330. data/rust/host/src/web/registration_receipt/tests.rs +16 -4
  331. data/rust/host/src/web/registration_receipt.rs +100 -24
  332. data/rust/host/src/web/registrations.rs +1384 -332
  333. data/rust/host/src/web/resend_webhook.rs +138 -80
  334. data/rust/host/src/web.rs +2416 -508
  335. data/rust/lsp/Cargo.toml +36 -0
  336. data/rust/lsp/clippy.toml +4 -0
  337. data/rust/lsp/src/json.rs +29 -22
  338. data/rust/lsp/src/main.rs +81 -31
  339. data/rust/lsp/src/outline.rs +23 -7
  340. data/rust/lsp/src/rpc.rs +17 -4
  341. data/rust/parser/Cargo.toml +36 -0
  342. data/rust/parser/clippy.toml +4 -0
  343. data/rust/parser/src/build/closed_sets.rs +6 -1
  344. data/rust/parser/src/build/identity.rs +4 -3
  345. data/rust/parser/src/build/mod.rs +1 -0
  346. data/rust/parser/src/build/named_pattern.rs +26 -0
  347. data/rust/parser/src/build/naming.rs +2 -80
  348. data/rust/parser/src/build/pattern_subset.rs +6 -8
  349. data/rust/parser/src/build/query_derive.rs +3 -1
  350. data/rust/parser/src/build/query_inference.rs +14 -5
  351. data/rust/parser/src/build/read_model.rs +4 -1
  352. data/rust/parser/src/build/references.rs +4 -3
  353. data/rust/parser/src/canonical.rs +34 -15
  354. data/rust/parser/src/emit.rs +187 -105
  355. data/rust/parser/src/expr/ast_json.rs +134 -42
  356. data/rust/parser/src/expr/evaluator.rs +27 -9
  357. data/rust/parser/src/expr/mod.rs +54 -13
  358. data/rust/parser/src/expr/resolver.rs +299 -92
  359. data/rust/parser/src/ir.rs +35 -3
  360. data/rust/parser/src/keywords.rs +7168 -510
  361. data/rust/parser/src/lex.rs +11 -25
  362. data/rust/parser/src/lib.rs +1 -0
  363. data/rust/parser/src/main.rs +65 -6
  364. data/rust/parser/src/parse/adapter.rs +157 -0
  365. data/rust/parser/src/parse/aggregate.rs +19 -10
  366. data/rust/parser/src/parse/chapter.rs +16 -17
  367. data/rust/parser/src/parse/command.rs +35 -16
  368. data/rust/parser/src/parse/domain_port.rs +4 -7
  369. data/rust/parser/src/parse/entity.rs +21 -11
  370. data/rust/parser/src/parse/hecksagon.rs +10 -4
  371. data/rust/parser/src/parse/lifecycle.rs +9 -5
  372. data/rust/parser/src/parse/mod.rs +43 -91
  373. data/rust/parser/src/parse/needs.rs +21 -12
  374. data/rust/parser/src/parse/policy.rs +2 -2
  375. data/rust/parser/src/parse/process_manager.rs +9 -11
  376. data/rust/parser/src/parse/query.rs +8 -4
  377. data/rust/parser/src/parse/read_model.rs +57 -16
  378. data/rust/parser/src/parse/value_object.rs +7 -2
  379. data/rust/parser/src/parse/world.rs +322 -0
  380. data/rust/parser/src/ruby_value.rs +7 -6
  381. data/rust/src/exemplar/json.rs +4 -4
  382. data/rust/src/exemplar/mutations.rs +18 -0
  383. data/rust/src/exemplar/read_models.rs +1 -10
  384. data/rust/src/kernel/attribute_shapes/composite.rs +54 -14
  385. data/rust/src/kernel/attribute_shapes/list.rs +2 -2
  386. data/rust/src/kernel/attribute_shapes/mod.rs +8 -8
  387. data/rust/src/kernel/attribute_shapes/scalar.rs +2 -2
  388. data/rust/src/kernel/cli.rs +229 -112
  389. data/rust/src/kernel/dispatch.rs +323 -115
  390. data/rust/src/kernel/dispatch_guard_tests.rs +327 -65
  391. data/rust/src/kernel/expr.rs +203 -86
  392. data/rust/src/kernel/expression_operators/arithmetic.rs +138 -25
  393. data/rust/src/kernel/expression_operators/comparison.rs +87 -2
  394. data/rust/src/kernel/expression_operators/enumeration.rs +106 -22
  395. data/rust/src/kernel/expression_operators/logical.rs +9 -3
  396. data/rust/src/kernel/expression_operators/membership.rs +3 -1
  397. data/rust/src/kernel/expression_operators/mod.rs +34 -21
  398. data/rust/src/kernel/expression_operators/pattern_match.rs +46 -11
  399. data/rust/src/kernel/expression_operators/positional.rs +84 -30
  400. data/rust/src/kernel/expression_operators/presence.rs +52 -13
  401. data/rust/src/kernel/expression_operators/sign_test.rs +3 -1
  402. data/rust/src/kernel/expression_operators/sized.rs +24 -8
  403. data/rust/src/kernel/expression_operators/text.rs +120 -27
  404. data/rust/src/kernel/expression_operators/to_string.rs +10 -4
  405. data/rust/src/kernel/json.rs +230 -148
  406. data/rust/src/kernel/mod.rs +46 -33
  407. data/rust/src/kernel/named_query.rs +63 -15
  408. data/rust/src/kernel/needs.rs +112 -25
  409. data/rust/src/kernel/orchestrate.rs +980 -581
  410. data/rust/src/kernel/orchestrate_guard_tests.rs +538 -140
  411. data/rust/src/kernel/pattern.rs +107 -34
  412. data/rust/src/kernel/query_comparators.rs +118 -41
  413. data/rust/src/kernel/query_ordering.rs +13 -5
  414. data/rust/src/kernel/read_model.rs +479 -181
  415. data/rust/src/kernel/reference_lookup.rs +122 -26
  416. data/rust/src/kernel/repository.rs +293 -66
  417. data/rust/src/kernel/routing.rs +58 -42
  418. data/rust/src/kernel/ruby_float.rs +139 -0
  419. data/rust/src/kernel/vocab/aggregate_dispatch_order.rs +57 -57
  420. data/rust/src/kernel/vocab/entity_dispatch_order.rs +54 -54
  421. data/rust/src/kernel/vocab/field_hint.rs +19 -25
  422. data/rust/src/kernel/vocab/mod.rs +6 -6
  423. data/rust/src/kernel/vocab/query_comparator.rs +23 -24
  424. data/rust/src/kernel/vocab/refusal_template.rs +501 -297
  425. data/rust/src/lib.rs +50 -0
  426. data/rust/src/main.rs +4 -1
  427. data/rust/web/Cargo.toml +36 -0
  428. data/rust/web/clippy.toml +4 -0
  429. metadata +85 -15
  430. data/examples/pizzas/bluebook/hecksagon/mock_stripe_payment_adapter.rb +0 -36
  431. data/lib/hecks/adapters/driven/google_authentication.adapter +0 -3
  432. data/lib/hecks/adapters/driven/google_authentication.rb +0 -99
  433. data/lib/hecks/adapters/driven/mock_stripe_adapter.adapter +0 -3
  434. data/lib/hecks/adapters/driven/mock_stripe_adapter.rb +0 -32
  435. data/lib/hecks/ports/authentication.port +0 -6
  436. data/lib/hecks/ports/authentication.rb +0 -67
  437. data/lib/hecks/ports/persistence/plugins/era/translation/approval_file.rb +0 -255
  438. data/lib/hecks/ports/persistence/plugins/era/translation/audit/approval_digest.rb +0 -22
  439. data/prebuilt/verdicts-48318ca172edd21443b1ad02801c697fff100b746e828f09db987647641a5df2.json +0 -1
  440. data/rust/host/src/approval.rs +0 -652
@@ -1,67 +0,0 @@
1
- require_relative "../runtime/registry"
2
-
3
- module Hecks
4
- module Ports
5
- # The OIDC handshake: builds the provider URL and turns the returned code into verified claims.
6
- # One adapter registry-wide answers it; it never touches the registry's Identity data.
7
- module Authentication
8
- NAME = "authentication".freeze
9
-
10
- # A sign-in that could not be verified (state mismatch, failed code exchange, bad ID token).
11
- class ValidationError < StandardError
12
- end
13
-
14
- module_function
15
-
16
- # Builds the provider URL that starts a sign-in, with the CSRF state minted for it.
17
- #
18
- # The caller keeps the state and hands it back to `verify` as `expected_state`.
19
- #
20
- # @param registry [Runtime::Registry] the booted registry to resolve the adapter against
21
- # @return [Array(String, String)] the URL to send the browser to, then the fresh
22
- # `state` value embedded in it
23
- # @raise [Runtime::WiringError] if this port does not resolve to exactly one adapter
24
- # @raise [KeyError] if the adapter's required configuration is unset
25
- def authorization_url(registry)
26
- adapter(registry).authorization_url
27
- end
28
-
29
- # Exchanges the authorization code a provider sent back for a Hash of verified claims.
30
- #
31
- # @param registry [Runtime::Registry] the booted registry to resolve the adapter against
32
- # @param code [String] the authorization code the provider sent back
33
- # @param state [String, nil] the state parameter the provider returned; nil is refused
34
- # @param expected_state [String, nil] the state `authorization_url` returned; nil is refused
35
- # @return [Hash{Symbol => Object}] the verified claims: `issuer:`, `subject:`, `email:`
36
- # (nil if the token carries none) and `email_verified:` -- never the raw token
37
- # @raise [Ports::Authentication::ValidationError] if a state is nil or they differ, the
38
- # code exchange fails, or the ID token is missing or does not verify
39
- # @raise [Runtime::WiringError] if this port does not resolve to exactly one adapter
40
- # @raise [KeyError] if required configuration is unset, or the token lacks `iss`/`sub`
41
- def verify(registry, code:, state:, expected_state:)
42
- adapter(registry).verify(code: code, state: state, expected_state: expected_state)
43
- end
44
-
45
- # Finds the single adapter bound to this port.
46
- #
47
- # @raise [Runtime::WiringError] if none, or more than one, implements this port
48
- def adapter(registry)
49
- implementations = registry.adapters.values.select { |a| a.port == NAME }
50
- return registry.adapter_class(implementations.first.name) if implementations.size == 1
51
-
52
- raise Runtime::WiringError, wiring_refusal(implementations)
53
- end
54
-
55
- # Words the refusal for a port that resolves to no adapter or to several.
56
- #
57
- # @param implementations [Array] the adapters bound to this port
58
- # @return [String] the error message
59
- def wiring_refusal(implementations)
60
- return "no adapter implements the #{NAME} port — nothing can authenticate a sign-in" if implementations.empty?
61
-
62
- names = implementations.map(&:name).sort.join(", ")
63
- "#{implementations.size} adapters implement the #{NAME} port (#{names}) — the runtime will not choose for you"
64
- end
65
- end
66
- end
67
- end
@@ -1,255 +0,0 @@
1
- require "json"
2
- require "date"
3
- require "fileutils"
4
- require_relative "audit/approval_digest"
5
- require_relative "../../../../../version"
6
-
7
- module Hecks
8
- module Translation
9
- # The committed form of an edge's approval: `translations/<edge>.approval`, a JSON file beside
10
- # the edge that a reviewer sees in the same diff.
11
- #
12
- # It binds to the edge's content digest and not to the journal's tip, so a production journal
13
- # that keeps writing between the commit and the deploy does not void it. An edge with a compute
14
- # or rekey rule also carries the rehearsal a person ran against real data, since the audit's
15
- # samples are that edge's only other verification.
16
- module ApprovalFile
17
- EXTENSION = ".approval".freeze
18
-
19
- # The keys of a rehearsal block; every one is required when the block is required.
20
- #
21
- # `host_version` is the Hecks release the rehearsal ran on, and the gate checks it: a
22
- # rehearsal counts only on a host whose release shares its `major.minor` (see
23
- # `host_compatible?`).
24
- REHEARSAL_KEYS = %w[snapshot host_version result at].freeze
25
-
26
- # How a `host_version` reads: `major.minor`, an optional patch, an optional pre-release or
27
- # build suffix. Only the first two numbers take part in the comparison.
28
- HOST_LINE = /\A(\d+)\.(\d+)(?:\.\d+)?(?:[-+][0-9A-Za-z.+-]+)?\z/
29
-
30
- # The release the running host reports: the Hecks release this code was built for. The Rust
31
- # host embeds the same string from `rust/host/HECKS_RELEASE`, and a spec fails when the two
32
- # drift.
33
- HOST_RELEASE = Hecks::VERSION
34
-
35
- # An ISO 8601 time: `2026-09-28T12:30:00Z`, with optional fraction and `+HH:MM` offset. The
36
- # host's approval.rs accepts the same shape.
37
- TIMESTAMP = /\A(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})\z/
38
-
39
- extend Audit::ApprovalDigest
40
-
41
- module_function
42
-
43
- # Names an edge by the labels it joins; labels are hex, so the dash cannot be part of one.
44
- #
45
- # @param edge [Bluebook::Translation] the parsed translation edge
46
- # @return [String] `<from>-<to>`
47
- def edge_name(edge) = "#{edge.from}-#{edge.to}"
48
-
49
- # Where an edge's approval lives.
50
- #
51
- # @param directory [String] the domain's bluebook directory
52
- # @param edge [Bluebook::Translation] the parsed translation edge
53
- # @return [String] `<directory>/translations/<edge>.approval`
54
- def path_for(directory, edge) = File.join(directory, "translations", "#{edge_name(edge)}#{EXTENSION}")
55
-
56
- # Whether the edge carries a rule whose only verification is a human's review of samples.
57
- #
58
- # @param edge [Bluebook::Translation] the parsed translation edge
59
- # @return [Boolean] true when any aggregate declares a compute or a rekey
60
- def needs_rehearsal?(edge)
61
- edge.aggregates.any? { |declared| !declared.computes.empty? || !declared.rekeys.empty? }
62
- end
63
-
64
- # Whether a rehearsal block records a run that passed, with every field named.
65
- #
66
- # @param rehearsal [Hash, nil] the block, string-keyed as it reads from JSON
67
- # @return [Boolean] true when all of `REHEARSAL_KEYS` are non-empty Strings and `result` is
68
- # `pass`
69
- def rehearsed?(rehearsal)
70
- return false unless rehearsal.is_a?(Hash)
71
-
72
- REHEARSAL_KEYS.all? { |key| named?(rehearsal[key]) } && rehearsal["result"] == "pass"
73
- end
74
-
75
- # The `major.minor` a version names.
76
- #
77
- # @param version [Object] a `host_version` as it reads from JSON
78
- # @return [Array<Integer>, nil] `[major, minor]`, or nil when it is not a version
79
- def release_line(version)
80
- match = HOST_LINE.match(version) if version.is_a?(String)
81
- match && [match[1].to_i, match[2].to_i]
82
- end
83
-
84
- # Whether a rehearsal ran on a host compatible with the running one.
85
- #
86
- # The rule is the smallest sound one: equal `major.minor`. A patch release does not change
87
- # what a mint does, so a rehearsal survives it; a minor or major release may, so a rehearsal
88
- # from an older host (or a newer one, which proves nothing about this one) does not.
89
- #
90
- # @param rehearsal [Hash] a rehearsal block, string-keyed
91
- # @param host_version [String] the running host's release
92
- # @return [Boolean] true when both versions parse and share `major.minor`
93
- def host_compatible?(rehearsal, host_version = HOST_RELEASE)
94
- line = release_line(rehearsal["host_version"])
95
- !line.nil? && line == release_line(host_version)
96
- end
97
-
98
- # The refusal for a rehearsal that ran on another host line; rust/host words it the same.
99
- #
100
- # @param rehearsal [Hash] a rehearsal block, string-keyed
101
- # @param host_version [String] the running host's release
102
- # @return [String] names both versions
103
- def host_refusal(rehearsal, host_version = HOST_RELEASE)
104
- line = release_line(host_version)&.join(".")
105
- "the rehearsal ran on Hecks #{rehearsal["host_version"]}, but this host is Hecks #{host_version}; " \
106
- "a rehearsal counts only on a host of the same major.minor (#{line}.x) — " \
107
- "re-run the rehearsal on this host and approve again"
108
- end
109
-
110
- # Whether a value is a String with something in it; a number or nil names nothing.
111
- #
112
- # @param value [Object] a field as it reads from JSON
113
- # @return [Boolean] true for a String that is not blank
114
- def named?(value) = value.is_a?(String) && !value.strip.empty?
115
-
116
- # Whether a value is an ISO 8601 time that exists on the calendar.
117
- #
118
- # @param value [Object] a field as it reads from JSON
119
- # @return [Boolean] true for a String of the `TIMESTAMP` shape with a real date and clock time
120
- def timestamp?(value)
121
- return false unless value.is_a?(String) && (match = TIMESTAMP.match(value))
122
-
123
- year, month, day, hour, minute, second = match.captures.map(&:to_i)
124
- Date.valid_date?(year, month, day) && hour < 24 && minute < 60 && second < 60
125
- end
126
-
127
- # Whether an approval names who approved it and when, the two things a reviewer signs.
128
- #
129
- # @param approval [Hash] the file, string-keyed as it reads from JSON
130
- # @return [Boolean] true when `approved_by` is a non-empty String and `approved_at` a time
131
- def attributed?(approval)
132
- named?(approval["approved_by"]) && timestamp?(approval["approved_at"])
133
- end
134
-
135
- # Builds the JSON document of one approval.
136
- #
137
- # @param edge [Bluebook::Translation] the parsed translation edge
138
- # @param approved_by [String] who approved it, from their git identity
139
- # @param approved_at [String] when, as an ISO 8601 UTC time
140
- # @param rehearsal [Hash{String => String}, nil] the block; required for a compute or rekey
141
- # @return [Hash{String => Object}] `edge`, `edge_digest`, `approved_by`, `approved_at`, and
142
- # `rehearsal` when one was given
143
- # @raise [ArgumentError] if `approved_by` is blank or `approved_at` is not a time, or if the
144
- # edge needs a rehearsal and none that passed was given
145
- def build(edge:, approved_by:, approved_at:, rehearsal: nil)
146
- refuse_unattributed!(approved_by, approved_at)
147
- refuse_unrehearsed!(edge, rehearsal)
148
-
149
- document = { "edge" => edge_name(edge), "edge_digest" => edge_digest(edge),
150
- "approved_by" => approved_by, "approved_at" => approved_at }
151
- document["rehearsal"] = rehearsal.slice(*REHEARSAL_KEYS) if rehearsal
152
- document
153
- end
154
-
155
- # Refuses an approval that does not say who approved it and when.
156
- #
157
- # @param approved_by [String] who approved it
158
- # @param approved_at [String] when, as an ISO 8601 UTC time
159
- # @return [void]
160
- # @raise [ArgumentError] if either is blank or malformed
161
- def refuse_unattributed!(approved_by, approved_at)
162
- return if attributed?("approved_by" => approved_by, "approved_at" => approved_at)
163
-
164
- raise ArgumentError, "an approval names who approved it (approved_by, your git identity) " \
165
- "and when (approved_at, an ISO 8601 time)"
166
- end
167
-
168
- # Refuses the approval of a compute or rekey edge that carries no passing rehearsal.
169
- #
170
- # @param edge [Bluebook::Translation] the parsed translation edge
171
- # @param rehearsal [Hash{String => String}, nil] the rehearsal block
172
- # @return [void]
173
- # @raise [ArgumentError] if the edge needs a rehearsal and none that passed was given
174
- def refuse_unrehearsed!(edge, rehearsal)
175
- return unless needs_rehearsal?(edge) && !rehearsed?(rehearsal)
176
-
177
- raise ArgumentError, "an edge with a compute or rekey rule is approved on a rehearsal that passed: " \
178
- "name the snapshot, the host version, the result (pass) and when it ran"
179
- end
180
-
181
- # Writes an edge's approval file, replacing an earlier approval of the same edge.
182
- #
183
- # @param directory [String] the domain's bluebook directory
184
- # @param edge [Bluebook::Translation] the parsed translation edge
185
- # @param document [Hash{String => Object}] what `build` answered
186
- # @return [String] the path written
187
- def write!(directory, edge, document)
188
- path = path_for(directory, edge)
189
- FileUtils.mkdir_p(File.dirname(path))
190
- File.write(path, "#{JSON.pretty_generate(document)}\n")
191
- path
192
- end
193
-
194
- # Reads every committed approval of a domain.
195
- #
196
- # @param directory [String] the domain's bluebook directory
197
- # @return [Array<Hash{String => Object}>] each parsed file; one that is not JSON is skipped,
198
- # since a file that cannot be read approves nothing
199
- def read_all(directory)
200
- Dir[File.join(directory, "translations", "*#{EXTENSION}")].filter_map do |path|
201
- parsed = JSON.parse(File.read(path))
202
- parsed if parsed.is_a?(Hash)
203
- rescue JSON::ParserError
204
- nil
205
- end
206
- end
207
-
208
- # The committed approval that lets an edge mint, if there is one.
209
- #
210
- # @param directory [String, nil] the domain's bluebook directory
211
- # @param edge [Bluebook::Translation] the parsed translation edge
212
- # @param host_version [String] the running host's release
213
- # @return [Hash{String => Object}, nil] an approval whose digest is the edge's, that names
214
- # who approved it and when, and whose rehearsal passed on a compatible host when the edge
215
- # needs one; nil when none applies
216
- def applicable(directory, edge, host_version: HOST_RELEASE)
217
- return unless directory
218
-
219
- digest = edge_digest(edge)
220
- read_all(directory).find do |approval|
221
- approval["edge_digest"] == digest && attributed?(approval) &&
222
- (!needs_rehearsal?(edge) ||
223
- (rehearsed?(approval["rehearsal"]) && host_compatible?(approval["rehearsal"], host_version)))
224
- end
225
- end
226
-
227
- # Why a committed approval that covers the edge was still not applied, when the only thing
228
- # wrong is the host it was rehearsed on.
229
- #
230
- # @param directory [String, nil] the domain's bluebook directory
231
- # @param edge [Bluebook::Translation] the parsed translation edge
232
- # @param host_version [String] the running host's release
233
- # @return [String, nil] `host_refusal`'s text, or nil when no such approval exists
234
- def host_mismatch(directory, edge, host_version: HOST_RELEASE)
235
- return unless directory && needs_rehearsal?(edge)
236
-
237
- digest = edge_digest(edge)
238
- stale = read_all(directory).find do |approval|
239
- approval["edge_digest"] == digest && stale_host?(approval, host_version)
240
- end
241
- host_refusal(stale["rehearsal"], host_version) if stale
242
- end
243
-
244
- # Whether an attributed approval's passing rehearsal ran on an incompatible host.
245
- #
246
- # @param approval [Hash{String => Object}] one parsed approval
247
- # @param host_version [String] the running host's release
248
- # @return [Boolean]
249
- def stale_host?(approval, host_version)
250
- attributed?(approval) && rehearsed?(approval["rehearsal"]) &&
251
- !host_compatible?(approval["rehearsal"], host_version)
252
- end
253
- end
254
- end
255
- end
@@ -1,22 +0,0 @@
1
- require "digest"
2
- require_relative "../../../../../../projector/exporter"
3
-
4
- module Hecks
5
- module Translation
6
- module Audit
7
- # The human gate: a compute edge cannot mint until `hecks audit_translation --approve`
8
- # binds an approval to the edge's content digest and the journal's ordinal at review.
9
- module ApprovalDigest
10
- # Fingerprints a parsed translation edge, so an approval lapses when the edge's
11
- # meaning changes but not when only a comment does.
12
- #
13
- # @param edge [Bluebook::Translation] the parsed translation edge
14
- # @return [String] 64 lowercase hex characters: the SHA-256 of the edge's exported
15
- # JSON (`Projector::Exporter.translation_hash`)
16
- def edge_digest(edge)
17
- Digest::SHA256.hexdigest(JSON.generate(Projector::Exporter.translation_hash(edge)))
18
- end
19
- end
20
- end
21
- end
22
- end