hecks 2.8.0 → 3.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 (886) hide show
  1. checksums.yaml +4 -4
  2. data/exe/hecks +50 -7
  3. data/lib/hecks/adapters/driven/claude_code.rb +4 -104
  4. data/lib/hecks/adapters/driven/d1.rb +44 -237
  5. data/lib/hecks/adapters/driven/folder.rb +17 -76
  6. data/lib/hecks/adapters/driven/google_authentication.rb +15 -49
  7. data/lib/hecks/adapters/driven/governance_authorization.rb +23 -70
  8. data/lib/hecks/adapters/driven/heki/journal.rb +8 -41
  9. data/lib/hecks/adapters/driven/heki/saga_store.rb +12 -54
  10. data/lib/hecks/adapters/driven/heki/snapshot.rb +4 -12
  11. data/lib/hecks/adapters/driven/heki.rb +13 -42
  12. data/lib/hecks/adapters/driven/identity_registry.rb +3 -14
  13. data/lib/hecks/adapters/driven/in_memory_ordering.rb +9 -26
  14. data/lib/hecks/adapters/driven/in_process_key_vault.rb +2 -14
  15. data/lib/hecks/adapters/driven/lambda/client.rb +10 -51
  16. data/lib/hecks/adapters/driven/lambda.rb +10 -84
  17. data/lib/hecks/adapters/driven/local_storage.rb +5 -40
  18. data/lib/hecks/adapters/driven/memory.rb +32 -100
  19. data/lib/hecks/adapters/driven/mock_stripe_adapter.rb +5 -21
  20. data/lib/hecks/adapters/driven/postgres/codec.rb +6 -28
  21. data/lib/hecks/adapters/driven/postgres/outbox.rb +3 -12
  22. data/lib/hecks/adapters/driven/postgres/reconnect.rb +10 -32
  23. data/lib/hecks/adapters/driven/postgres/schema_builder.rb +34 -108
  24. data/lib/hecks/adapters/driven/postgres/shared_connection.rb +180 -0
  25. data/lib/hecks/adapters/driven/postgres.rb +149 -136
  26. data/lib/hecks/adapters/driven/postgres_era.adapter +4 -15
  27. data/lib/hecks/adapters/driven/prism.rb +48 -38
  28. data/lib/hecks/adapters/driven/sql_query_builder.rb +21 -121
  29. data/lib/hecks/adapters/driven/sqlite/codec.rb +8 -40
  30. data/lib/hecks/adapters/driven/sqlite/projection.rb +26 -82
  31. data/lib/hecks/adapters/driven/sqlite/schema_builder.rb +40 -84
  32. data/lib/hecks/adapters/driven/sqlite.rb +128 -65
  33. data/lib/hecks/adapters/driven/tenant_provisioner.rb +76 -62
  34. data/lib/hecks/adapters/driven.rb +5 -36
  35. data/lib/hecks/adapters/driving/github_webhook.rb +8 -76
  36. data/lib/hecks/behaviors/dsl.rb +7 -25
  37. data/lib/hecks/behaviors/expectations.rb +32 -142
  38. data/lib/hecks/behaviors/ir.rb +7 -20
  39. data/lib/hecks/behaviors/rspec.rb +6 -17
  40. data/lib/hecks/behaviors/runner.rb +10 -34
  41. data/lib/hecks/behaviors.rb +4 -8
  42. data/lib/hecks/bench/cli.rb +62 -0
  43. data/lib/hecks/bench/environment.rb +71 -0
  44. data/lib/hecks/bench/postgres_probe.rb +30 -0
  45. data/lib/hecks/bench/report.rb +76 -0
  46. data/lib/hecks/bench/ruby_runner.rb +93 -0
  47. data/lib/hecks/bench/run.rb +55 -0
  48. data/lib/hecks/bench/rust_runner.rb +101 -0
  49. data/lib/hecks/bench/stats.rb +46 -0
  50. data/lib/hecks/bench/suite.rb +98 -0
  51. data/lib/hecks/bench/workload.rb +89 -0
  52. data/lib/hecks/bench.rb +17 -0
  53. data/lib/hecks/bluebook/aggregate.rb +9 -75
  54. data/lib/hecks/bluebook/assembly/aggregate_assembly.rb +9 -38
  55. data/lib/hecks/bluebook/assembly/build.rb +4 -15
  56. data/lib/hecks/bluebook/assembly/contract.rb +15 -136
  57. data/lib/hecks/bluebook/assembly/contracts.rb +56 -174
  58. data/lib/hecks/bluebook/assembly/marks.rb +31 -223
  59. data/lib/hecks/bluebook/assembly/specializer.rb +6 -52
  60. data/lib/hecks/bluebook/assembly.rb +6 -45
  61. data/lib/hecks/bluebook/attribute.rb +12 -61
  62. data/lib/hecks/bluebook/behaviour/aggregate.rb +39 -39
  63. data/lib/hecks/bluebook/behaviour/attribute.rb +3 -14
  64. data/lib/hecks/bluebook/behaviour/chapter.rb +14 -42
  65. data/lib/hecks/bluebook/behaviour/command.rb +14 -66
  66. data/lib/hecks/bluebook/behaviour/domain_port.rb +11 -20
  67. data/lib/hecks/bluebook/behaviour/entity.rb +7 -27
  68. data/lib/hecks/bluebook/behaviour/hexagon.rb +23 -41
  69. data/lib/hecks/bluebook/behaviour/lifecycle.rb +15 -40
  70. data/lib/hecks/bluebook/behaviour/policy.rb +23 -52
  71. data/lib/hecks/bluebook/behaviour/process_manager.rb +30 -57
  72. data/lib/hecks/bluebook/behaviour/read_model.rb +25 -31
  73. data/lib/hecks/bluebook/behaviour/traits.rb +27 -64
  74. data/lib/hecks/bluebook/behaviour/value_object.rb +5 -24
  75. data/lib/hecks/bluebook/capabilities.rb +17 -49
  76. data/lib/hecks/bluebook/chapter.rb +16 -50
  77. data/lib/hecks/bluebook/command.rb +23 -81
  78. data/lib/hecks/bluebook/domain_port.rb +49 -67
  79. data/lib/hecks/bluebook/dsl/aggregate_builder/sealing.rb +50 -229
  80. data/lib/hecks/bluebook/dsl/aggregate_builder.rb +50 -377
  81. data/lib/hecks/bluebook/dsl/attribute_collector.rb +33 -204
  82. data/lib/hecks/bluebook/dsl/binding_proxy.rb +16 -69
  83. data/lib/hecks/bluebook/dsl/bluebook_builder/validation.rb +96 -708
  84. data/lib/hecks/bluebook/dsl/bluebook_builder.rb +63 -169
  85. data/lib/hecks/bluebook/dsl/bootstrap_table.rb +3 -1
  86. data/lib/hecks/bluebook/dsl/command_builder.rb +74 -546
  87. data/lib/hecks/bluebook/dsl/const_shim.rb +8 -41
  88. data/lib/hecks/bluebook/dsl/domain_port_builder.rb +42 -89
  89. data/lib/hecks/bluebook/dsl/entity_builder.rb +44 -330
  90. data/lib/hecks/bluebook/dsl/generic_dispatch.rb +20 -269
  91. data/lib/hecks/bluebook/dsl/hecksagon_builder.rb +148 -197
  92. data/lib/hecks/bluebook/dsl/identity_declaration.rb +13 -88
  93. data/lib/hecks/bluebook/dsl/lifecycle_builder.rb +6 -20
  94. data/lib/hecks/bluebook/dsl/policy_builder.rb +16 -88
  95. data/lib/hecks/bluebook/dsl/port_builder.rb +2 -6
  96. data/lib/hecks/bluebook/dsl/port_operation_builder.rb +22 -96
  97. data/lib/hecks/bluebook/dsl/process_manager_builder.rb +31 -184
  98. data/lib/hecks/bluebook/dsl/query_builder.rb +38 -43
  99. data/lib/hecks/bluebook/dsl/read_model_builder.rb +75 -201
  100. data/lib/hecks/bluebook/dsl/rule_reference.rb +22 -163
  101. data/lib/hecks/bluebook/dsl/translation_builder.rb +28 -114
  102. data/lib/hecks/bluebook/dsl/value_object_builder.rb +10 -124
  103. data/lib/hecks/bluebook/dsl/word_gate.rb +16 -162
  104. data/lib/hecks/bluebook/dsl/world_builder.rb +46 -111
  105. data/lib/hecks/bluebook/entity.rb +13 -71
  106. data/lib/hecks/bluebook/expression/ast_json.rb +24 -190
  107. data/lib/hecks/bluebook/expression/ast_reader.rb +12 -54
  108. data/lib/hecks/bluebook/expression/canonical_form.rb +11 -88
  109. data/lib/hecks/bluebook/expression/evaluator.rb +47 -295
  110. data/lib/hecks/bluebook/expression/resolver/block_predicates.rb +30 -147
  111. data/lib/hecks/bluebook/expression/resolver.rb +39 -661
  112. data/lib/hecks/bluebook/hexagon.rb +18 -33
  113. data/lib/hecks/bluebook/lifecycle.rb +5 -16
  114. data/lib/hecks/bluebook/meta_validator/adapter_judge.rb +1 -7
  115. data/lib/hecks/bluebook/meta_validator/judge.rb +111 -361
  116. data/lib/hecks/bluebook/meta_validator/plan.rb +33 -162
  117. data/lib/hecks/bluebook/meta_validator/port_judge.rb +2 -7
  118. data/lib/hecks/bluebook/meta_validator/readings.rb +56 -342
  119. data/lib/hecks/bluebook/meta_validator/reconstruction.rb +25 -176
  120. data/lib/hecks/bluebook/meta_validator/shapes.rb +53 -267
  121. data/lib/hecks/bluebook/meta_validator/syntax_boot.rb +47 -306
  122. data/lib/hecks/bluebook/meta_validator/translation_judge.rb +7 -43
  123. data/lib/hecks/bluebook/meta_validator/verdict_cache.rb +246 -0
  124. data/lib/hecks/bluebook/meta_validator/world_judge.rb +6 -18
  125. data/lib/hecks/bluebook/meta_validator.rb +87 -352
  126. data/lib/hecks/bluebook/model_check/client_profile.rb +6 -21
  127. data/lib/hecks/bluebook/model_check.rb +122 -596
  128. data/lib/hecks/bluebook/pattern_subset.rb +49 -69
  129. data/lib/hecks/bluebook/process_manager.rb +13 -83
  130. data/lib/hecks/bluebook/project_loader.rb +3 -39
  131. data/lib/hecks/bluebook/project_register.rb +12 -60
  132. data/lib/hecks/bluebook/query.rb +27 -51
  133. data/lib/hecks/bluebook/read_model.rb +57 -81
  134. data/lib/hecks/bluebook/reference.rb +7 -41
  135. data/lib/hecks/bluebook/smoke_test.rb +9 -99
  136. data/lib/hecks/bluebook/synthesizer.rb +13 -62
  137. data/lib/hecks/bluebook/translation.rb +26 -62
  138. data/lib/hecks/bluebook/value_object.rb +11 -36
  139. data/lib/hecks/bluebook.rb +5 -22
  140. data/lib/hecks/cache_dir.rb +4 -23
  141. data/lib/hecks/canonical_json.rb +30 -0
  142. data/lib/hecks/chapters.rb +102 -0
  143. data/lib/hecks/cli/behaviors.rb +61 -0
  144. data/lib/hecks/cli/canonicalise.rb +25 -0
  145. data/lib/hecks/cli/check_engine_agreement.rb +32 -0
  146. data/lib/hecks/cli/check_era.rb +88 -0
  147. data/lib/hecks/cli/console.rb +66 -0
  148. data/lib/hecks/cli/deploy_template_diff.rb +40 -0
  149. data/lib/hecks/cli/doc_coverage.rb +32 -0
  150. data/lib/hecks/cli/document.rb +5 -23
  151. data/lib/hecks/cli/expression_projection.rb +41 -0
  152. data/lib/hecks/cli/follow.rb +88 -0
  153. data/lib/hecks/cli/history.rb +44 -0
  154. data/lib/hecks/cli/ir.rb +4 -6
  155. data/lib/hecks/cli/mcp.rb +5 -6
  156. data/lib/hecks/cli/model_check.rb +24 -88
  157. data/lib/hecks/cli/pattern_cases.rb +47 -0
  158. data/lib/hecks/cli/present.rb +39 -0
  159. data/lib/hecks/cli/project_cli.rb +223 -64
  160. data/lib/hecks/cli/project_diagrams.rb +4 -10
  161. data/lib/hecks/cli/project_glossary.rb +44 -0
  162. data/lib/hecks/cli/reference.rb +46 -0
  163. data/lib/hecks/cli/refresh_projections.rb +44 -0
  164. data/lib/hecks/cli/refresh_rspec_runtime_baseline.rb +150 -0
  165. data/lib/hecks/cli/release.rb +70 -0
  166. data/lib/hecks/cli/release_gem.rb +59 -0
  167. data/lib/hecks/cli/rspec_io_parallel_files.rb +137 -0
  168. data/lib/hecks/cli/rspec_shard_files.rb +66 -0
  169. data/lib/hecks/cli/run.rb +15 -61
  170. data/lib/hecks/cli/seed_semantics_corpus.rb +71 -0
  171. data/lib/hecks/cli/serve_query_ir_mcp.rb +30 -0
  172. data/lib/hecks/cli/shape.rb +70 -0
  173. data/lib/hecks/cli/smoke_http.rb +230 -0
  174. data/lib/hecks/cli/smoke_test.rb +7 -19
  175. data/lib/hecks/cli/spec_example.rb +27 -0
  176. data/lib/hecks/cli/statements.rb +32 -0
  177. data/lib/hecks/cli/stores.rb +4 -6
  178. data/lib/hecks/cli/stress_concurrency_specs.rb +177 -0
  179. data/lib/hecks/cli.rb +216 -73
  180. data/lib/hecks/codemod.rb +324 -0
  181. data/lib/hecks/construct.rb +8 -34
  182. data/lib/hecks/corpus.rb +423 -0
  183. data/lib/hecks/deploy/bluebook/deploy.bluebook +617 -158
  184. data/lib/hecks/deploy/bluebook/deploy.hecksagon +41 -11
  185. data/lib/hecks/deploy/oidc.json +82 -2
  186. data/lib/hecks/doc/reference.rb +351 -0
  187. data/lib/hecks/doors/cli_door.rb +196 -0
  188. data/lib/hecks/doors/cli_runner.rb +297 -0
  189. data/lib/hecks/{facade → doors}/command_request.rb +14 -34
  190. data/lib/hecks/doors/handle.rb +206 -0
  191. data/lib/hecks/doors/json_door.rb +132 -0
  192. data/lib/hecks/doors/launcher_options.rb +129 -0
  193. data/lib/hecks/{cli → doors}/mcp_door.rb +25 -120
  194. data/lib/hecks/doors/mcp_door_scope.rb +97 -0
  195. data/lib/hecks/doors/ruby_door/aggregate_door.rb +162 -0
  196. data/lib/hecks/doors/ruby_door/chapter.rb +72 -0
  197. data/lib/hecks/doors/ruby_door.rb +77 -0
  198. data/lib/hecks/doors.rb +61 -0
  199. data/lib/hecks/embryonaut_bluebook/lock.rb +3 -35
  200. data/lib/hecks/embryonaut_bluebook/shape.rb +1 -17
  201. data/lib/hecks/embryonaut_bluebook/vendor.rb +8 -53
  202. data/lib/hecks/embryonaut_bluebook/vendor_cli.rb +4 -19
  203. data/lib/hecks/embryonaut_bluebook.rb +5 -72
  204. data/lib/hecks/engine_agreement.rb +156 -0
  205. data/lib/hecks/facade.rb +23 -51
  206. data/lib/hecks/forms/app.rb +21 -76
  207. data/lib/hecks/forms/banking_presentation.rb +50 -0
  208. data/lib/hecks/forms/command_form_renderer.rb +10 -29
  209. data/lib/hecks/forms/field_renderer.rb +17 -156
  210. data/lib/hecks/forms/field_shape.rb +31 -222
  211. data/lib/hecks/forms/html.rb +12 -47
  212. data/lib/hecks/forms/index_renderer.rb +1 -4
  213. data/lib/hecks/forms/page.rb +3 -9
  214. data/lib/hecks/forms/params.rb +14 -60
  215. data/lib/hecks/forms/port_argument.rb +2 -19
  216. data/lib/hecks/forms/query_form_renderer.rb +4 -79
  217. data/lib/hecks/forms/record_renderer.rb +8 -75
  218. data/lib/hecks/forms/record_table.rb +7 -50
  219. data/lib/hecks/forms/reference_options.rb +3 -30
  220. data/lib/hecks/forms/value_object_shape.rb +8 -35
  221. data/lib/hecks/forms.rb +5 -33
  222. data/lib/hecks/fqn.rb +5 -12
  223. data/lib/hecks/framework/bluebook/compliance.bluebook +16 -65
  224. data/lib/hecks/framework/bluebook/console_settings.bluebook +47 -134
  225. data/lib/hecks/framework/bluebook/framework.hecksagon +5 -14
  226. data/lib/hecks/framework/bluebook/governance.bluebook +13 -34
  227. data/lib/hecks/framework/bluebook/identity.bluebook +11 -26
  228. data/lib/hecks/framework/bluebook/privacy.bluebook +8 -33
  229. data/lib/hecks/framework.rb +11 -80
  230. data/lib/hecks/freezer.rb +5 -39
  231. data/lib/hecks/fuzzing/bounded_exhaustive_expressions.rb +393 -0
  232. data/lib/hecks/fuzzing/combination_miner.rb +86 -0
  233. data/lib/hecks/fuzzing/concurrent_dispatch.rb +214 -0
  234. data/lib/hecks/fuzzing/coverage_campaign.rb +143 -0
  235. data/lib/hecks/fuzzing/differential.rb +156 -0
  236. data/lib/hecks/fuzzing/domain_generator.rb +615 -0
  237. data/lib/hecks/fuzzing/era_boundary.rb +71 -0
  238. data/lib/hecks/fuzzing/form_census.rb +136 -0
  239. data/lib/hecks/fuzzing/generated_domain_check.rb +93 -0
  240. data/lib/hecks/fuzzing/invalid_value_generator.rb +64 -0
  241. data/lib/hecks/fuzzing/isolated_boot.rb +301 -0
  242. data/lib/hecks/fuzzing/nondeterministic.rb +51 -0
  243. data/lib/hecks/fuzzing/outside_world.rb +45 -0
  244. data/lib/hecks/fuzzing/persistence_parity.rb +102 -0
  245. data/lib/hecks/fuzzing/properties/corrections.rb +88 -0
  246. data/lib/hecks/fuzzing/properties/dispatch_and_mutations.rb +314 -0
  247. data/lib/hecks/fuzzing/properties/guards.rb +190 -0
  248. data/lib/hecks/fuzzing/properties/invariants_and_aggregation.rb +300 -0
  249. data/lib/hecks/fuzzing/properties/lifecycle_and_replay.rb +93 -0
  250. data/lib/hecks/fuzzing/properties/outbox.rb +89 -0
  251. data/lib/hecks/fuzzing/properties/querying.rb +175 -0
  252. data/lib/hecks/fuzzing/properties.rb +162 -0
  253. data/lib/hecks/fuzzing/qa_settings.rb +123 -0
  254. data/lib/hecks/fuzzing/replay.rb +505 -0
  255. data/lib/hecks/fuzzing/rotation_priority.rb +48 -0
  256. data/lib/hecks/fuzzing/rust_gap_manifest.rb +108 -0
  257. data/lib/hecks/fuzzing/self_consistency.rb +339 -0
  258. data/lib/hecks/fuzzing/sequence_generator/adversary.rb +385 -0
  259. data/lib/hecks/fuzzing/sequence_generator/catalog.rb +132 -0
  260. data/lib/hecks/fuzzing/sequence_generator/outcome_tracker.rb +95 -0
  261. data/lib/hecks/fuzzing/sequence_generator/picker.rb +77 -0
  262. data/lib/hecks/fuzzing/sequence_generator/query_binding.rb +109 -0
  263. data/lib/hecks/fuzzing/sequence_generator/step_builder.rb +237 -0
  264. data/lib/hecks/fuzzing/sequence_generator.rb +189 -0
  265. data/lib/hecks/fuzzing/shrinker.rb +166 -0
  266. data/lib/hecks/fuzzing/structural_skips.rb +33 -0
  267. data/lib/hecks/fuzzing/sweep_depth.rb +43 -0
  268. data/lib/hecks/fuzzing/target_capabilities.rb +163 -0
  269. data/lib/hecks/fuzzing/value_generator.rb +216 -0
  270. data/lib/hecks/fuzzing.rb +23 -0
  271. data/lib/hecks/grammar/evolve.rb +336 -0
  272. data/lib/hecks/grammar/expression.bluebook +15 -40
  273. data/lib/hecks/grammar/translation.bluebook +3 -6
  274. data/lib/hecks/grammar.rb +16 -41
  275. data/lib/hecks/hecks/adapters/codebase/codemods.rb +45 -0
  276. data/lib/hecks/hecks/adapters/codebase/conformance.rb +71 -0
  277. data/lib/hecks/hecks/adapters/codebase/corpus_tasks.rb +202 -0
  278. data/lib/hecks/hecks/adapters/codebase/gem_registry.rb +80 -0
  279. data/lib/hecks/hecks/adapters/codebase/kernel_tables.rb +54 -0
  280. data/lib/hecks/hecks/adapters/codebase/language.rb +240 -0
  281. data/lib/hecks/hecks/adapters/codebase/npm_registry.rb +102 -0
  282. data/lib/hecks/hecks/adapters/codebase/publishing.rb +142 -0
  283. data/lib/hecks/hecks/adapters/codebase/regeneration.rb +67 -0
  284. data/lib/hecks/hecks/adapters/codebase/release_facts.rb +90 -0
  285. data/lib/hecks/hecks/adapters/codebase/ruby_child.rb +83 -0
  286. data/lib/hecks/hecks/adapters/codebase/secret_vault.rb +36 -0
  287. data/lib/hecks/hecks/adapters/codebase/source_tree.adapter +7 -0
  288. data/lib/hecks/hecks/adapters/codebase/source_tree.rb +189 -0
  289. data/lib/hecks/hecks/adapters/codebase/sqlite_fixture.rb +71 -0
  290. data/lib/hecks/hecks/adapters/codebase/style.rb +171 -0
  291. data/lib/hecks/hecks/adapters/codebase/test_runner.rb +55 -0
  292. data/lib/hecks/hecks/adapters/codebase/test_suite.rb +165 -0
  293. data/lib/hecks/hecks/adapters/codebase/tree.rb +111 -0
  294. data/lib/hecks/hecks/adapters/console_capture.rb +79 -0
  295. data/lib/hecks/hecks/adapters/deploy_toolchain.adapter +7 -0
  296. data/lib/hecks/hecks/adapters/deploy_toolchain.rb +108 -0
  297. data/lib/hecks/hecks/adapters/git.adapter +7 -0
  298. data/lib/hecks/hecks/adapters/git.rb +102 -0
  299. data/lib/hecks/hecks/adapters/host_http.adapter +7 -0
  300. data/lib/hecks/hecks/adapters/host_http.rb +65 -0
  301. data/lib/hecks/hecks/adapters/in_process_boot.adapter +7 -0
  302. data/lib/hecks/hecks/adapters/in_process_boot.rb +197 -0
  303. data/lib/hecks/hecks/adapters/in_process_operations.rb +202 -0
  304. data/lib/hecks/hecks/adapters/journal_store/changes.rb +143 -0
  305. data/lib/hecks/hecks/adapters/journal_store/compaction.rb +145 -0
  306. data/lib/hecks/hecks/adapters/journal_store/edge_audit.rb +132 -0
  307. data/lib/hecks/hecks/adapters/journal_store/examination.rb +135 -0
  308. data/lib/hecks/hecks/adapters/journal_store/held_domain.rb +163 -0
  309. data/lib/hecks/hecks/adapters/journal_store/readings.rb +187 -0
  310. data/lib/hecks/hecks/adapters/journal_store.adapter +7 -0
  311. data/lib/hecks/hecks/adapters/journal_store.rb +64 -0
  312. data/lib/hecks/hecks/adapters/local_files.adapter +7 -0
  313. data/lib/hecks/hecks/adapters/local_files.rb +46 -0
  314. data/lib/hecks/hecks/adapters/pg_admin.adapter +7 -0
  315. data/lib/hecks/hecks/adapters/pg_admin.rb +245 -0
  316. data/lib/hecks/hecks/adapters/process_pool.adapter +7 -0
  317. data/lib/hecks/hecks/adapters/process_pool.rb +119 -0
  318. data/lib/hecks/hecks/adapters/rust_toolchain.adapter +7 -0
  319. data/lib/hecks/hecks/adapters/rust_toolchain.rb +179 -0
  320. data/lib/hecks/hecks/adapters/rust_workspace.rb +150 -0
  321. data/lib/hecks/hecks/adapters/shell.adapter +7 -0
  322. data/lib/hecks/hecks/adapters/shell.rb +49 -0
  323. data/lib/hecks/hecks/adapters/terminal.adapter +7 -0
  324. data/lib/hecks/hecks/adapters/terminal.rb +74 -0
  325. data/lib/hecks/hecks/codebase.behaviors +172 -0
  326. data/lib/hecks/hecks/codebase.bluebook +2453 -0
  327. data/lib/hecks/hecks/context_map.hecksagon +13 -0
  328. data/lib/hecks/hecks/custodian.behaviors +179 -0
  329. data/lib/hecks/hecks/custodian.bluebook +1847 -0
  330. data/lib/hecks/hecks/deploy.behaviors +74 -0
  331. data/lib/hecks/hecks/deploy.world +12 -0
  332. data/lib/hecks/hecks/environments/memory.world +10 -0
  333. data/lib/hecks/hecks/governance.world +7 -0
  334. data/lib/hecks/hecks/hecks.behaviors +62 -0
  335. data/lib/hecks/hecks/hecks.bluebook +124 -0
  336. data/lib/hecks/hecks/hecks.hecksagon +390 -0
  337. data/lib/hecks/hecks/hecks.world +42 -0
  338. data/lib/hecks/ir.rb +14 -83
  339. data/lib/hecks/kernel_capabilities.rb +194 -0
  340. data/lib/hecks/language/adapter.bluebook +2 -7
  341. data/lib/hecks/language/bluebook/aggregate.bluebook +56 -221
  342. data/lib/hecks/language/bluebook/attaches/paging.bluebook +6 -15
  343. data/lib/hecks/language/bluebook/bluebook.bluebook +26 -83
  344. data/lib/hecks/language/bluebook/bluebook.hecksagon +3 -15
  345. data/lib/hecks/language/bluebook/command.bluebook +27 -144
  346. data/lib/hecks/language/bluebook/entity.bluebook +24 -97
  347. data/lib/hecks/language/bluebook/policy.bluebook +16 -67
  348. data/lib/hecks/language/bluebook/process_manager.bluebook +28 -151
  349. data/lib/hecks/language/bluebook/projection.bluebook +126 -60
  350. data/lib/hecks/language/bluebook/query.bluebook +19 -43
  351. data/lib/hecks/language/bluebook/shape.bluebook +23 -73
  352. data/lib/hecks/language/bluebook/syntax.bluebook +51 -262
  353. data/lib/hecks/language/bluebook/vocabulary.bluebook +83 -198
  354. data/lib/hecks/language/hecksagon/adapter_binding.bluebook +3 -10
  355. data/lib/hecks/language/hecksagon/domain_port.bluebook +14 -19
  356. data/lib/hecks/language/hecksagon/hecksagon.bluebook +26 -25
  357. data/lib/hecks/language/hecksagon/port_operation.bluebook +3 -14
  358. data/lib/hecks/language/oidc.json +35 -0
  359. data/lib/hecks/language/port.bluebook +4 -17
  360. data/lib/hecks/language/translation/translation.bluebook +3 -9
  361. data/lib/hecks/language/translation/translation_aggregate.bluebook +5 -24
  362. data/lib/hecks/language/world/wiring.bluebook +1 -3
  363. data/lib/hecks/language/world/world.bluebook +5 -7
  364. data/lib/hecks/literal.rb +8 -50
  365. data/lib/hecks/mcp_stdio_guard.rb +4 -41
  366. data/lib/hecks/naming.rb +29 -137
  367. data/lib/hecks/persistence_legacy_fixture/regenerate.rb +161 -0
  368. data/lib/hecks/persistence_legacy_fixture.rb +113 -0
  369. data/lib/hecks/ports/access_control.rb +7 -23
  370. data/lib/hecks/ports/agent/answers.rb +5 -23
  371. data/lib/hecks/ports/agent.rb +47 -172
  372. data/lib/hecks/ports/authentication.rb +12 -39
  373. data/lib/hecks/ports/authorization.rb +16 -43
  374. data/lib/hecks/ports/clock.rb +5 -45
  375. data/lib/hecks/ports/extraction.rb +7 -12
  376. data/lib/hecks/ports/identity_assignment.rb +8 -29
  377. data/lib/hecks/ports/identity_generation.rb +6 -29
  378. data/lib/hecks/ports/identity_resolution.rb +2 -10
  379. data/lib/hecks/ports/key_vault.rb +9 -45
  380. data/lib/hecks/ports/persistence/append_only.rb +61 -64
  381. data/lib/hecks/ports/persistence/binding_policy.rb +4 -14
  382. data/lib/hecks/ports/persistence/codec_boundary.rb +20 -80
  383. data/lib/hecks/ports/persistence/null_saga_store.rb +4 -20
  384. data/lib/hecks/ports/persistence/plugin.rb +13 -42
  385. data/lib/hecks/ports/persistence/plugins/era/era_check.rb +44 -144
  386. data/lib/hecks/ports/persistence/plugins/era/era_guard/shape_diff.rb +15 -115
  387. data/lib/hecks/ports/persistence/plugins/era/era_guard.rb +20 -85
  388. data/lib/hecks/ports/persistence/plugins/era/era_tamper.rb +6 -25
  389. data/lib/hecks/ports/persistence/plugins/era/expected_era.rb +18 -24
  390. data/lib/hecks/ports/persistence/plugins/era/lineage.rb +55 -181
  391. data/lib/hecks/ports/persistence/plugins/era/postgres_era/events.rb +77 -0
  392. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/era_store.rb +12 -122
  393. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/field_cache.rb +28 -128
  394. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/head_compiler.rb +73 -474
  395. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/mint_transaction.rb +31 -124
  396. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/provisioning.rb +45 -219
  397. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/resumable_backfill.rb +13 -108
  398. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/tail_merge.rb +19 -76
  399. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/transform_installer.rb +9 -49
  400. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage.rb +6 -123
  401. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/coverage_check.rb +23 -55
  402. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/era_resolver.rb +14 -72
  403. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/merge_coordinator.rb +7 -16
  404. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/minter.rb +43 -127
  405. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager.rb +13 -45
  406. data/lib/hecks/ports/persistence/plugins/era/postgres_era.rb +131 -555
  407. data/lib/hecks/ports/persistence/plugins/era/storage_shape.rb +13 -63
  408. data/lib/hecks/ports/persistence/plugins/era/translation/approval_file.rb +227 -0
  409. data/lib/hecks/ports/persistence/plugins/era/translation/audit/approval_digest.rb +2 -17
  410. data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_one.rb +3 -14
  411. data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_two.rb +13 -58
  412. data/lib/hecks/ports/persistence/plugins/era/translation/audit/unfed_report.rb +3 -17
  413. data/lib/hecks/ports/persistence/plugins/era/translation/audit.rb +9 -26
  414. data/lib/hecks/ports/persistence/plugins/era/translation/reattest.rb +50 -47
  415. data/lib/hecks/ports/persistence/plugins/era/translation/rule_compiler.rb +18 -124
  416. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/differ.rb +34 -123
  417. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/renderer.rb +5 -12
  418. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/writer.rb +3 -9
  419. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold.rb +2 -14
  420. data/lib/hecks/ports/persistence/plugins/era/translation.rb +1 -0
  421. data/lib/hecks/ports/persistence/plugins/era.rb +4 -23
  422. data/lib/hecks/ports/persistence/postgres_dump/connection.rb +7 -23
  423. data/lib/hecks/ports/persistence/postgres_dump.rb +4 -35
  424. data/lib/hecks/ports/persistence/remote_runtime.rb +2 -24
  425. data/lib/hecks/ports/persistence/repository_factory.rb +8 -27
  426. data/lib/hecks/ports/persistence/state_codec.rb +47 -108
  427. data/lib/hecks/ports/persistence.rb +7 -14
  428. data/lib/hecks/ports/projection.rb +42 -84
  429. data/lib/hecks/ports/query/in_memory.rb +10 -58
  430. data/lib/hecks/ports/query/ordering.rb +11 -32
  431. data/lib/hecks/ports/query.rb +14 -37
  432. data/lib/hecks/ports.rb +2 -8
  433. data/lib/hecks/projection_files.rb +285 -0
  434. data/lib/hecks/projections/bootstrap_table.rb +12 -44
  435. data/lib/hecks/projections/deploy/fargate/assembly.rb +2 -15
  436. data/lib/hecks/projections/deploy/fargate/cdn.rb +1 -48
  437. data/lib/hecks/projections/deploy/fargate/cdn_default.rb +2 -11
  438. data/lib/hecks/projections/deploy/fargate/check.rb +5 -14
  439. data/lib/hecks/projections/deploy/fargate/containers.rb +3 -78
  440. data/lib/hecks/projections/deploy/fargate/extras.rb +3 -44
  441. data/lib/hecks/projections/deploy/fargate/monitoring.rb +0 -44
  442. data/lib/hecks/projections/deploy/fargate/settings.rb +2 -54
  443. data/lib/hecks/projections/deploy/fargate/yaml.rb +13 -58
  444. data/lib/hecks/projections/deploy/fargate.rb +40 -207
  445. data/lib/hecks/projections/deploy/lambda.rb +191 -708
  446. data/lib/hecks/projections/deploy/preview/access_yaml.rb +1 -33
  447. data/lib/hecks/projections/deploy/preview/containers.rb +6 -111
  448. data/lib/hecks/projections/deploy/preview/preview.sh.erb +1 -1
  449. data/lib/hecks/projections/deploy/preview/routing_yaml.rb +4 -56
  450. data/lib/hecks/projections/deploy/preview/script.rb +2 -14
  451. data/lib/hecks/projections/deploy/preview/settings.rb +3 -33
  452. data/lib/hecks/projections/deploy/preview/task_yaml.rb +2 -38
  453. data/lib/hecks/projections/deploy/preview/template.rb +3 -59
  454. data/lib/hecks/projections/deploy/preview.rb +2 -67
  455. data/lib/hecks/projections/deploy/scripts/deploy-service.sh.tmpl +1 -1
  456. data/lib/hecks/projections/deploy/scripts/expected-era.header +1 -1
  457. data/lib/hecks/projections/deploy/scripts/hosting.mk.tmpl +3 -3
  458. data/lib/hecks/projections/deploy/scripts/settings.rb +3 -25
  459. data/lib/hecks/projections/deploy/scripts/smoke-after-deploy.sh.tmpl +1 -1
  460. data/lib/hecks/projections/deploy/scripts.rb +4 -57
  461. data/lib/hecks/projections/deploy/shared.rb +48 -147
  462. data/lib/hecks/projections/deploy/smoke.rb +4 -61
  463. data/lib/hecks/projections/deploy/template_diff/comparer.rb +3 -25
  464. data/lib/hecks/projections/deploy/template_diff/loader.rb +2 -11
  465. data/lib/hecks/projections/deploy/template_diff.rb +5 -57
  466. data/lib/hecks/projections/diagrams.rb +22 -584
  467. data/lib/hecks/projections/glossary/html.rb +14 -130
  468. data/lib/hecks/projections/glossary/markdown.rb +8 -69
  469. data/lib/hecks/projections/glossary/mermaid.rb +9 -66
  470. data/lib/hecks/projections/glossary/sensitivity.rb +5 -34
  471. data/lib/hecks/projections/glossary/sentences.rb +14 -159
  472. data/lib/hecks/projections/glossary.rb +30 -222
  473. data/lib/hecks/projections/ir.rb +3 -10
  474. data/lib/hecks/projections/model/deviations.rb +16 -43
  475. data/lib/hecks/projections/model.rb +12 -51
  476. data/lib/hecks/projections/oidc.rb +12 -56
  477. data/lib/hecks/projections/parser_table.rb +13 -32
  478. data/lib/hecks/projections/reference.rb +4 -18
  479. data/lib/hecks/projections/rust_vocabulary.rb +13 -251
  480. data/lib/hecks/projections/shape.rb +3 -29
  481. data/lib/hecks/projections/statements.rb +7 -86
  482. data/lib/hecks/projections/vocabulary.rb +6 -22
  483. data/lib/hecks/projections.rb +2 -16
  484. data/lib/hecks/projector/cli_projector.rb +154 -400
  485. data/lib/hecks/projector/docs_projector.rb +10 -201
  486. data/lib/hecks/projector/exporter.rb +42 -134
  487. data/lib/hecks/projector/ir_projector.rb +2 -9
  488. data/lib/hecks/projector/narrate_projector.rb +15 -189
  489. data/lib/hecks/projector/target.rb +13 -76
  490. data/lib/hecks/projector.rb +30 -121
  491. data/lib/hecks/quality_control/adapters/agent.adapter +7 -0
  492. data/lib/hecks/quality_control/adapters/agent.rb +58 -0
  493. data/lib/hecks/quality_control/adapters/angle_tools.adapter +7 -0
  494. data/lib/hecks/quality_control/adapters/angle_tools.rb +15 -0
  495. data/lib/hecks/quality_control/adapters/clearance_recorder.rb +36 -0
  496. data/lib/hecks/quality_control/adapters/clearance_tools.adapter +7 -0
  497. data/lib/hecks/quality_control/adapters/clearance_tools.rb +17 -0
  498. data/lib/hecks/quality_control/adapters/git_pr.adapter +7 -0
  499. data/lib/hecks/quality_control/adapters/git_pr.rb +226 -0
  500. data/lib/hecks/quality_control/adapters/github_checks.adapter +9 -0
  501. data/lib/hecks/quality_control/adapters/github_checks.rb +83 -0
  502. data/lib/hecks/quality_control/adapters/github_ci_webhook.rb +56 -0
  503. data/lib/hecks/quality_control/adapters/github_issues.adapter +7 -0
  504. data/lib/hecks/quality_control/adapters/github_issues.rb +49 -0
  505. data/lib/hecks/quality_control/adapters/qa_tool.rb +59 -0
  506. data/lib/hecks/quality_control/adapters/sweep_tools.adapter +7 -0
  507. data/lib/hecks/quality_control/adapters/sweep_tools.rb +51 -0
  508. data/lib/hecks/quality_control/adapters/target_tools.adapter +7 -0
  509. data/lib/hecks/quality_control/adapters/target_tools.rb +43 -0
  510. data/lib/hecks/quality_control/cli/child.rb +45 -0
  511. data/lib/hecks/quality_control/cli/qa_concurrency_racer.rb +45 -0
  512. data/lib/hecks/quality_control/cli/qa_discover_external_domains.rb +248 -0
  513. data/lib/hecks/quality_control/cli/qa_domain_novelty.rb +163 -0
  514. data/lib/hecks/quality_control/cli/qa_generated_domains.rb +450 -0
  515. data/lib/hecks/quality_control/cli/qa_log_bug.rb +195 -0
  516. data/lib/hecks/quality_control/cli/qa_mine_combinations.rb +220 -0
  517. data/lib/hecks/quality_control/cli/qa_open_pr.rb +305 -0
  518. data/lib/hecks/quality_control/cli/qa_postgres_migrate.rb +154 -0
  519. data/lib/hecks/quality_control/cli/qa_postgres_role.rb +159 -0
  520. data/lib/hecks/quality_control/cli/qa_pr_check.rb +232 -0
  521. data/lib/hecks/quality_control/cli/qa_seed_angles.rb +142 -0
  522. data/lib/hecks/quality_control/cli/qa_seed_targets.rb +69 -0
  523. data/lib/hecks/quality_control/cli/qa_sweep/all_mode.rb +280 -0
  524. data/lib/hecks/quality_control/cli/qa_sweep/checks.rb +329 -0
  525. data/lib/hecks/quality_control/cli/qa_sweep/dials.rb +92 -0
  526. data/lib/hecks/quality_control/cli/qa_sweep/finding_report.rb +117 -0
  527. data/lib/hecks/quality_control/cli/qa_sweep/parsing.rb +175 -0
  528. data/lib/hecks/quality_control/cli/qa_sweep/release_mode.rb +60 -0
  529. data/lib/hecks/quality_control/cli/qa_sweep.rb +611 -0
  530. data/lib/hecks/quality_control/cli/qa_tick.rb +274 -0
  531. data/lib/hecks/quality_control/quality_control.bluebook +2224 -0
  532. data/lib/hecks/quality_control/quality_control.hecksagon +13 -0
  533. data/lib/hecks/quality_control/quality_control.ports.hecksagon +54 -0
  534. data/lib/hecks/query_ir.rb +346 -0
  535. data/lib/hecks/query_ir_mcp.rb +198 -0
  536. data/lib/hecks/query_specification/common/comparators.rb +5 -26
  537. data/lib/hecks/query_specification/common/comparison.rb +35 -143
  538. data/lib/hecks/query_specification/common/dsl.rb +8 -24
  539. data/lib/hecks/query_specification/common/null_policy.rb +20 -70
  540. data/lib/hecks/query_specification/common/options.rb +2 -6
  541. data/lib/hecks/query_specification/common/where_clause.rb +2 -10
  542. data/lib/hecks/query_specification/field_path.rb +37 -77
  543. data/lib/hecks/query_specification/hop_path.rb +12 -76
  544. data/lib/hecks/release/gem_pin.rb +2 -26
  545. data/lib/hecks/release/runner/ci_publisher.rb +5 -8
  546. data/lib/hecks/release/runner/clean_tree.rb +42 -0
  547. data/lib/hecks/release/runner/commands.rb +2 -4
  548. data/lib/hecks/release/runner/console.rb +6 -0
  549. data/lib/hecks/release/runner/gem_publisher.rb +15 -9
  550. data/lib/hecks/release/runner/npm_publisher.rb +9 -53
  551. data/lib/hecks/release/runner/preflight.rb +29 -20
  552. data/lib/hecks/release/runner/published.rb +8 -26
  553. data/lib/hecks/release/runner/tagger.rb +31 -23
  554. data/lib/hecks/release/runner.rb +60 -38
  555. data/lib/hecks/rendering.rb +4 -26
  556. data/lib/hecks/router/namespace_installer.rb +15 -39
  557. data/lib/hecks/router.rb +4 -8
  558. data/lib/hecks/runtime/adapter_lookup.rb +124 -0
  559. data/lib/hecks/runtime/aggregate_lock.rb +8 -33
  560. data/lib/hecks/runtime/boot_gates.rb +3 -18
  561. data/lib/hecks/runtime/caller.rb +19 -59
  562. data/lib/hecks/runtime/capability_graph.rb +5 -21
  563. data/lib/hecks/runtime/command_interpreter/argument_gate.rb +16 -78
  564. data/lib/hecks/runtime/command_interpreter/mutation_applier.rb +27 -160
  565. data/lib/hecks/runtime/command_interpreter.rb +124 -306
  566. data/lib/hecks/runtime/command_rules/admissibility.rb +95 -366
  567. data/lib/hecks/runtime/command_rules/arithmetic.rb +66 -196
  568. data/lib/hecks/runtime/command_rules/authorization.rb +13 -45
  569. data/lib/hecks/runtime/command_rules/emission.rb +8 -21
  570. data/lib/hecks/runtime/command_rules/references.rb +23 -202
  571. data/lib/hecks/runtime/dependency_planning.rb +50 -104
  572. data/lib/hecks/runtime/dispatcher.rb +134 -243
  573. data/lib/hecks/runtime/entity_element.rb +40 -462
  574. data/lib/hecks/runtime/entity_interpreter.rb +64 -219
  575. data/lib/hecks/runtime/errors.rb +32 -115
  576. data/lib/hecks/runtime/event.rb +3 -25
  577. data/lib/hecks/runtime/identity.rb +18 -154
  578. data/lib/hecks/runtime/instance.rb +18 -150
  579. data/lib/hecks/runtime/interpreting.rb +14 -70
  580. data/lib/hecks/runtime/invocation.rb +28 -164
  581. data/lib/hecks/runtime/loader.rb +109 -194
  582. data/lib/hecks/runtime/outbox.rb +39 -262
  583. data/lib/hecks/runtime/policy_interpreter.rb +43 -202
  584. data/lib/hecks/runtime/port_operation_interpreter.rb +28 -97
  585. data/lib/hecks/runtime/query_interpreter.rb +122 -187
  586. data/lib/hecks/runtime/reaction_invocation.rb +36 -138
  587. data/lib/hecks/runtime/reaction_outcome.rb +89 -0
  588. data/lib/hecks/runtime/read_model_interpreter.rb +117 -208
  589. data/lib/hecks/runtime/rebuild_sweep.rb +8 -54
  590. data/lib/hecks/runtime/reference_hop.rb +8 -81
  591. data/lib/hecks/runtime/refusal_wording.rb +28 -87
  592. data/lib/hecks/runtime/registry/saga_persistence.rb +10 -102
  593. data/lib/hecks/runtime/registry/verification.rb +213 -227
  594. data/lib/hecks/runtime/registry/world_defaults.rb +4 -53
  595. data/lib/hecks/runtime/registry.rb +156 -247
  596. data/lib/hecks/runtime/remote_dispatcher.rb +68 -154
  597. data/lib/hecks/runtime/routing.rb +4 -15
  598. data/lib/hecks/runtime/saga_interpreter/correlation.rb +14 -61
  599. data/lib/hecks/runtime/saga_interpreter.rb +79 -263
  600. data/lib/hecks/runtime/saga_pending_dispatch.rb +2 -43
  601. data/lib/hecks/runtime/tenant_check.rb +6 -68
  602. data/lib/hecks/runtime/tenant_scope.rb +3 -28
  603. data/lib/hecks/runtime/value/admission.rb +16 -67
  604. data/lib/hecks/runtime/value/coercion.rb +162 -760
  605. data/lib/hecks/runtime/value/entity_list_coercion.rb +26 -219
  606. data/lib/hecks/runtime/value/field_checks.rb +172 -0
  607. data/lib/hecks/runtime/value.rb +15 -84
  608. data/lib/hecks/runtime.rb +35 -69
  609. data/lib/hecks/rust_build/conformance.rb +158 -0
  610. data/lib/hecks/rust_build/conformance_fuzz.rb +71 -0
  611. data/lib/hecks/rust_build/coverage.rb +218 -0
  612. data/lib/hecks/rust_build/native_build.rb +124 -0
  613. data/lib/hecks/rust_build/project_rust/root_mod.rb +120 -0
  614. data/lib/hecks/rust_build/project_rust.rb +332 -0
  615. data/lib/hecks/rust_build/wasm.rb +105 -0
  616. data/lib/hecks/rust_build/wasm_browser.rb +113 -0
  617. data/lib/hecks/rust_build.rb +144 -0
  618. data/lib/hecks/storehouse.rb +155 -582
  619. data/lib/hecks/tenancy/bluebook/tenancy.bluebook +10 -34
  620. data/lib/hecks/tenancy/bluebook/tenancy.hecksagon +6 -23
  621. data/lib/hecks/three_zero/forms.yml +127 -0
  622. data/lib/hecks/three_zero.rb +12 -0
  623. data/lib/hecks/tools/argument_gate_matrix.rb +316 -0
  624. data/lib/hecks/tools/comment_style.rb +1070 -0
  625. data/lib/hecks/tools/corpus_report.rb +87 -0
  626. data/lib/hecks/tools/deploy_recipe.rb +255 -0
  627. data/lib/hecks/tools/deploy_recipe_lint.rb +282 -0
  628. data/lib/hecks/tools/drop_implicit_append_fields.rb +95 -0
  629. data/lib/hecks/tools/era_projection_backfill.rb +94 -0
  630. data/lib/hecks/tools/era_reattest.rb +146 -0
  631. data/lib/hecks/tools/evolve_run.rb +189 -0
  632. data/lib/hecks/tools/fuzz_sweep.rb +373 -0
  633. data/lib/hecks/tools/heki_compaction.rb +100 -0
  634. data/lib/hecks/tools/hoist_local_givens.rb +246 -0
  635. data/lib/hecks/tools/journal_compaction.rb +89 -0
  636. data/lib/hecks/tools/oidc_manifests.rb +70 -0
  637. data/lib/hecks/tools/query_ir_run.rb +81 -0
  638. data/lib/hecks/tools/regeneration_run.rb +166 -0
  639. data/lib/hecks/tools/rust_comment_style.rb +642 -0
  640. data/lib/hecks/tools/sequence_script.rb +62 -0
  641. data/lib/hecks/tools/tail_merge.rb +117 -0
  642. data/lib/hecks/tools/tenant_provisioning.rb +142 -0
  643. data/lib/hecks/tools/translation_audit.rb +208 -0
  644. data/lib/hecks/tools/translation_scaffold.rb +131 -0
  645. data/lib/hecks/tools.rb +86 -0
  646. data/lib/hecks/vendoring/git_environment.rb +2 -8
  647. data/lib/hecks/vendoring/git_source.rb +4 -10
  648. data/lib/hecks/vendoring.rb +7 -46
  649. data/lib/hecks/version.rb +3 -14
  650. data/lib/hecks.rb +52 -90
  651. data/lib/rubocop/cop/hecks/fallback_hash_lookup.rb +8 -46
  652. data/lib/rubocop/cop/hecks/sequential_hash_rename_in_loop.rb +11 -80
  653. data/lib/rubocop/cop/hecks/thread_shared_ivar_mutation.rb +10 -99
  654. data/qa/settings.yml +66 -0
  655. data/rust/.cargo/config.toml +6 -0
  656. data/rust/.gitignore +2 -0
  657. data/rust/Cargo.lock +54 -0
  658. data/rust/Cargo.toml +61 -0
  659. data/rust/build/.cargo/config.toml +3 -0
  660. data/rust/build/.gitignore +1 -0
  661. data/rust/build/Cargo.lock +7 -0
  662. data/rust/build/Cargo.toml +19 -0
  663. data/rust/build/src/build_artifact.rs +47 -0
  664. data/rust/build/src/cargo_sync.rs +248 -0
  665. data/rust/build/src/json.rs +421 -0
  666. data/rust/build/src/lineage_pass.rs +285 -0
  667. data/rust/build/src/main.rs +51 -0
  668. data/rust/build/src/optional_pass.rs +150 -0
  669. data/rust/build/src/pipeline.rs +264 -0
  670. data/rust/build/src/reserved_names.rs +76 -0
  671. data/rust/build/src/resolve.rs +124 -0
  672. data/rust/build/src/root.rs +25 -0
  673. data/rust/build/src/sidecars.rs +73 -0
  674. data/rust/build/src/subprocess.rs +51 -0
  675. data/rust/build/src/tmp.rs +31 -0
  676. data/rust/codegen/.cargo/config.toml +3 -0
  677. data/rust/codegen/.gitignore +1 -0
  678. data/rust/codegen/Cargo.lock +7 -0
  679. data/rust/codegen/Cargo.toml +20 -0
  680. data/rust/codegen/src/attr.rs +32 -0
  681. data/rust/codegen/src/bridging.rs +481 -0
  682. data/rust/codegen/src/commands.rs +1226 -0
  683. data/rust/codegen/src/constraints.rs +109 -0
  684. data/rust/codegen/src/dependency_planning.rs +209 -0
  685. data/rust/codegen/src/domain_generator.rs +1288 -0
  686. data/rust/codegen/src/exemplar.rs +230 -0
  687. data/rust/codegen/src/expr_emitter.rs +87 -0
  688. data/rust/codegen/src/fielded.rs +192 -0
  689. data/rust/codegen/src/hecks_naming.rs +33 -0
  690. data/rust/codegen/src/json.rs +335 -0
  691. data/rust/codegen/src/json_codec.rs +697 -0
  692. data/rust/codegen/src/literal.rs +207 -0
  693. data/rust/codegen/src/main.rs +290 -0
  694. data/rust/codegen/src/manifest.rs +227 -0
  695. data/rust/codegen/src/mutations.rs +784 -0
  696. data/rust/codegen/src/naming.rs +286 -0
  697. data/rust/codegen/src/ports.rs +208 -0
  698. data/rust/codegen/src/prelude.rs +116 -0
  699. data/rust/codegen/src/queries.rs +786 -0
  700. data/rust/codegen/src/reactions.rs +532 -0
  701. data/rust/codegen/src/read_models.rs +697 -0
  702. data/rust/codegen/src/reference_specs.rs +40 -0
  703. data/rust/codegen/src/registry.rs +966 -0
  704. data/rust/codegen/src/reserved_names.rs +76 -0
  705. data/rust/codegen/src/shared.rs +93 -0
  706. data/rust/codegen/src/skip_reason.rs +25 -0
  707. data/rust/codegen/src/types.rs +362 -0
  708. data/rust/host/.cargo/config.toml +3 -0
  709. data/rust/host/.gitignore +1 -0
  710. data/rust/host/Cargo.lock +4297 -0
  711. data/rust/host/Cargo.toml +61 -0
  712. data/rust/host/HECKS_RELEASE +1 -0
  713. data/rust/host/rds-ca-bundle.pem +2736 -0
  714. data/rust/host/src/api.rs +1596 -0
  715. data/rust/host/src/approval.rs +652 -0
  716. data/rust/host/src/auth.rs +1287 -0
  717. data/rust/host/src/bin/expr_harness.rs +46 -0
  718. data/rust/host/src/bin/lineage_harness.rs +119 -0
  719. data/rust/host/src/bin/mint_harness.rs +135 -0
  720. data/rust/host/src/checkout.rs +265 -0
  721. data/rust/host/src/dispatch.rs +1443 -0
  722. data/rust/host/src/expr_json.rs +1117 -0
  723. data/rust/host/src/field_hints.rs +52 -0
  724. data/rust/host/src/ir.rs +733 -0
  725. data/rust/host/src/journal.rs +874 -0
  726. data/rust/host/src/lambda_client.rs +378 -0
  727. data/rust/host/src/log.rs +147 -0
  728. data/rust/host/src/main.rs +474 -0
  729. data/rust/host/src/mint.rs +1865 -0
  730. data/rust/host/src/payments/keystore.rs +330 -0
  731. data/rust/host/src/payments/tests.rs +1400 -0
  732. data/rust/host/src/payments.rs +767 -0
  733. data/rust/host/src/presentation.rs +698 -0
  734. data/rust/host/src/presentation_write.rs +1431 -0
  735. data/rust/host/src/query_step.rs +149 -0
  736. data/rust/host/src/rate_limit.rs +904 -0
  737. data/rust/host/src/reference_transform.rs +241 -0
  738. data/rust/host/src/reference_validate.rs +338 -0
  739. data/rust/host/src/resend.rs +296 -0
  740. data/rust/host/src/secrets.rs +106 -0
  741. data/rust/host/src/server.rs +663 -0
  742. data/rust/host/src/storage_shape.rs +175 -0
  743. data/rust/host/src/test_pg.rs +40 -0
  744. data/rust/host/src/ui_schema.rs +1351 -0
  745. data/rust/host/src/wasm_runner.rs +191 -0
  746. data/rust/host/src/web/newsletter/cooldown.rs +126 -0
  747. data/rust/host/src/web/newsletter/tests.rs +104 -0
  748. data/rust/host/src/web/newsletter.rs +310 -0
  749. data/rust/host/src/web/newsletter_send.rs +357 -0
  750. data/rust/host/src/web/registrations.rs +1505 -0
  751. data/rust/host/src/web.rs +2937 -0
  752. data/rust/lsp/.gitignore +1 -0
  753. data/rust/lsp/Cargo.lock +7 -0
  754. data/rust/lsp/Cargo.toml +16 -0
  755. data/rust/lsp/README.md +133 -0
  756. data/rust/lsp/src/diagnostics.rs +165 -0
  757. data/rust/lsp/src/json.rs +385 -0
  758. data/rust/lsp/src/main.rs +399 -0
  759. data/rust/lsp/src/outline.rs +177 -0
  760. data/rust/lsp/src/rpc.rs +67 -0
  761. data/rust/parser/.cargo/config.toml +5 -0
  762. data/rust/parser/.gitignore +1 -0
  763. data/rust/parser/Cargo.lock +7 -0
  764. data/rust/parser/Cargo.toml +21 -0
  765. data/rust/parser/src/build/closed_sets.rs +27 -0
  766. data/rust/parser/src/build/identity.rs +276 -0
  767. data/rust/parser/src/build/mod.rs +12 -0
  768. data/rust/parser/src/build/naming.rs +141 -0
  769. data/rust/parser/src/build/pattern_subset.rs +161 -0
  770. data/rust/parser/src/build/query_derive.rs +72 -0
  771. data/rust/parser/src/build/query_inference.rs +269 -0
  772. data/rust/parser/src/build/query_options.rs +100 -0
  773. data/rust/parser/src/build/read_model.rs +94 -0
  774. data/rust/parser/src/build/references.rs +32 -0
  775. data/rust/parser/src/canonical.rs +114 -0
  776. data/rust/parser/src/diag.rs +55 -0
  777. data/rust/parser/src/emit.rs +953 -0
  778. data/rust/parser/src/expr/ast_json.rs +147 -0
  779. data/rust/parser/src/expr/evaluator.rs +81 -0
  780. data/rust/parser/src/expr/mod.rs +84 -0
  781. data/rust/parser/src/expr/resolver.rs +497 -0
  782. data/rust/parser/src/ir.rs +387 -0
  783. data/rust/parser/src/keywords.rs +585 -0
  784. data/rust/parser/src/lex.rs +662 -0
  785. data/rust/parser/src/main.rs +252 -0
  786. data/rust/parser/src/parse/aggregate.rs +612 -0
  787. data/rust/parser/src/parse/chapter.rs +517 -0
  788. data/rust/parser/src/parse/command.rs +637 -0
  789. data/rust/parser/src/parse/domain_port.rs +127 -0
  790. data/rust/parser/src/parse/entity.rs +527 -0
  791. data/rust/parser/src/parse/file.rs +67 -0
  792. data/rust/parser/src/parse/hecksagon.rs +231 -0
  793. data/rust/parser/src/parse/lifecycle.rs +162 -0
  794. data/rust/parser/src/parse/mod.rs +1262 -0
  795. data/rust/parser/src/parse/policy.rs +87 -0
  796. data/rust/parser/src/parse/process_manager.rs +305 -0
  797. data/rust/parser/src/parse/query.rs +100 -0
  798. data/rust/parser/src/parse/read_model.rs +214 -0
  799. data/rust/parser/src/parse/value_object.rs +250 -0
  800. data/rust/parser/src/ruby_value.rs +422 -0
  801. data/rust/project/bridging.rb +257 -0
  802. data/rust/project/commands.rb +877 -0
  803. data/rust/project/constraints.rb +86 -0
  804. data/rust/project/dependency_planning.rb +178 -0
  805. data/rust/project/domain_generator.rb +980 -0
  806. data/rust/project/exemplar.rb +148 -0
  807. data/rust/project/expr_emitter.rb +72 -0
  808. data/rust/project/fielded.rb +141 -0
  809. data/rust/project/json_codec.rb +641 -0
  810. data/rust/project/mutations.rb +721 -0
  811. data/rust/project/naming.rb +205 -0
  812. data/rust/project/ports.rb +65 -0
  813. data/rust/project/queries.rb +493 -0
  814. data/rust/project/reactions.rb +317 -0
  815. data/rust/project/read_models.rb +690 -0
  816. data/rust/project/reference_specs.rb +27 -0
  817. data/rust/project/registry.rb +396 -0
  818. data/rust/project/skip_reason.rb +29 -0
  819. data/rust/project/types.rb +225 -0
  820. data/rust/project/write_if_changed.rb +83 -0
  821. data/rust/project.rb +30 -0
  822. data/rust/project_rust_pipeline.rb +383 -0
  823. data/rust/src/exemplar/commands.rs +279 -0
  824. data/rust/src/exemplar/constraints.rs +18 -0
  825. data/rust/src/exemplar/fielded.rs +280 -0
  826. data/rust/src/exemplar/json.rs +277 -0
  827. data/rust/src/exemplar/mod.rs +17 -0
  828. data/rust/src/exemplar/mutations.rs +80 -0
  829. data/rust/src/exemplar/queries.rs +33 -0
  830. data/rust/src/exemplar/reactions.rs +88 -0
  831. data/rust/src/exemplar/read_models.rs +48 -0
  832. data/rust/src/exemplar/registry.rs +166 -0
  833. data/rust/src/exemplar/types.rs +44 -0
  834. data/rust/src/kernel/attribute_shapes/composite.rs +88 -0
  835. data/rust/src/kernel/attribute_shapes/list.rs +18 -0
  836. data/rust/src/kernel/attribute_shapes/mod.rs +44 -0
  837. data/rust/src/kernel/attribute_shapes/optional.rs +9 -0
  838. data/rust/src/kernel/attribute_shapes/scalar.rs +39 -0
  839. data/rust/src/kernel/cli.rs +585 -0
  840. data/rust/src/kernel/dispatch.rs +1090 -0
  841. data/rust/src/kernel/expr.rs +458 -0
  842. data/rust/src/kernel/expression_operators/arithmetic.rs +128 -0
  843. data/rust/src/kernel/expression_operators/comparison.rs +48 -0
  844. data/rust/src/kernel/expression_operators/enumeration.rs +232 -0
  845. data/rust/src/kernel/expression_operators/logical.rs +13 -0
  846. data/rust/src/kernel/expression_operators/membership.rs +18 -0
  847. data/rust/src/kernel/expression_operators/mod.rs +68 -0
  848. data/rust/src/kernel/expression_operators/pattern_match.rs +73 -0
  849. data/rust/src/kernel/expression_operators/positional.rs +126 -0
  850. data/rust/src/kernel/expression_operators/presence.rs +101 -0
  851. data/rust/src/kernel/expression_operators/sign_test.rs +16 -0
  852. data/rust/src/kernel/expression_operators/sized.rs +35 -0
  853. data/rust/src/kernel/expression_operators/text.rs +79 -0
  854. data/rust/src/kernel/expression_operators/to_string.rs +18 -0
  855. data/rust/src/kernel/json.rs +779 -0
  856. data/rust/src/kernel/mod.rs +133 -0
  857. data/rust/src/kernel/named_query.rs +219 -0
  858. data/rust/src/kernel/orchestrate.rs +1810 -0
  859. data/rust/src/kernel/pattern.rs +307 -0
  860. data/rust/src/kernel/query_comparators.rs +206 -0
  861. data/rust/src/kernel/query_ordering.rs +103 -0
  862. data/rust/src/kernel/read_model.rs +914 -0
  863. data/rust/src/kernel/reference_lookup.rs +149 -0
  864. data/rust/src/kernel/repository.rs +468 -0
  865. data/rust/src/kernel/routing.rs +612 -0
  866. data/rust/src/kernel/vocab/aggregate_dispatch_order.rs +118 -0
  867. data/rust/src/kernel/vocab/entity_dispatch_order.rs +114 -0
  868. data/rust/src/kernel/vocab/field_hint.rs +70 -0
  869. data/rust/src/kernel/vocab/mod.rs +20 -0
  870. data/rust/src/kernel/vocab/query_comparator.rs +65 -0
  871. data/rust/src/kernel/vocab/refusal_template.rs +1592 -0
  872. data/rust/src/lib.rs +8 -0
  873. data/rust/src/main.rs +16 -0
  874. data/rust/web/.gitignore +1 -0
  875. data/rust/web/Cargo.lock +119 -0
  876. data/rust/web/Cargo.toml +18 -0
  877. data/rust/web/src/lib.rs +8 -0
  878. metadata +478 -12
  879. data/lib/hecks/facade/cli_door.rb +0 -178
  880. data/lib/hecks/facade/cli_runner.rb +0 -271
  881. data/lib/hecks/facade/handle.rb +0 -293
  882. data/lib/hecks/facade/json_door.rb +0 -247
  883. data/lib/hecks/facade/surface/aggregate_door.rb +0 -222
  884. data/lib/hecks/facade/surface/chapter.rb +0 -116
  885. data/lib/hecks/facade/surface.rb +0 -61
  886. data/lib/hecks/mcp_door_scope.rb +0 -176
@@ -4,31 +4,14 @@ require_relative "../../ports/authentication"
4
4
 
5
5
  module Hecks
6
6
  module Adapters
7
- # **Google's own OIDC handshake** — the `authentication` port's one real
8
- # implementation today. Consolidates what was hand-rolled per-app
9
- # (a console app's `google_auth.rb` did this on its own) into
10
- # one adapter, so any hecks-based app gets Google sign-in for free, the
11
- # same "one adapter, reusable everywhere" value every other adapter
12
- # in this directory already has.
7
+ # Google's OIDC handshake — the `authentication` port's adapter for Google
8
+ # sign-in, via `oauth2` (code exchange) and `google-id-token` (verification).
13
9
  #
14
- # `oauth2` does only the authorization-code exchange (no Rack
15
- # middleware, no Omniauth strategy indirection) ; `google-id-token`
16
- # does only ID-token verification (signature checked against
17
- # Google's real, rotating JWKS — real, maintained code, never
18
- # hand-rolled here). Neither library decides what a verified
19
- # (issuer, subject) means — that's `Ports::IdentityResolution`'s
20
- # job, called by whoever consumes this port's `verify`.
10
+ # `oauth2`/`google-id-token` load lazily, inside the methods that use
11
+ # them, so a domain that never binds this adapter never needs them installed.
21
12
  #
22
- # Lazy requires, same reasoning `Postgres.connect_for` already
23
- # holds itself to for `pg`: a domain that never binds
24
- # `authentication` to this adapter should never need these gems
25
- # installed. This file loads in every boot (driven.rb's own
26
- # unconditional require_relative list) ; the gems load only where
27
- # a real handshake actually happens.
28
- #
29
- # `GOOGLE_CLIENT_ID`/`GOOGLE_CLIENT_SECRET`/`GOOGLE_REDIRECT_URI` —
30
- # no defaults, on purpose: a login mechanism silently
31
- # half-configured is worse than one that refuses to boot at all.
13
+ # `GOOGLE_CLIENT_ID`/`GOOGLE_CLIENT_SECRET`/`GOOGLE_REDIRECT_URI` have no
14
+ # defaults, on purpose: a half-configured login should refuse to boot.
32
15
  module GoogleAuthentication
33
16
  ISSUER = "https://accounts.google.com".freeze
34
17
 
@@ -48,9 +31,8 @@ module Hecks
48
31
  )
49
32
  end
50
33
 
51
- # The URL to send a browser to, carrying a fresh CSRF `state` the
52
- # caller is responsible for stashing (a session, typically) and
53
- # checking again in `verify`.
34
+ # The URL to send a browser to, carrying a fresh CSRF `state` the caller
35
+ # must stash (typically in a session) and check again in `verify`.
54
36
  #
55
37
  # @return [Array(String, String)] the URL to send the browser to, and the fresh CSRF
56
38
  # `state` embedded in it
@@ -66,38 +48,22 @@ module Hecks
66
48
  [url, state]
67
49
  end
68
50
 
69
- # Exchanges `code` for tokens, verifies the returned ID token's
70
- # signature and claims against Google's own JWKS, and confirms
71
- # `state` matches what `authorization_url` handed out — a
72
- # mismatch (or any failure in the exchange/verification itself)
73
- # is a Ports::Authentication::ValidationError, never a
74
- # silently-empty result. Returns
75
- # {issuer:, subject:, email:, email_verified:} on success — never
76
- # the raw token, never anything a caller would need to re-verify
77
- # itself. `email_verified` rides along because a caller granting
78
- # access off this email needs to know Google actually checked it.
79
- #
51
+ # Exchanges `code` for tokens and verifies the ID token against Google's
52
+ # JWKS; `email_verified` tells a caller if Google actually checked the email.
80
53
  # @param code [String] the authorization code the provider sent back
81
54
  # @param state [String, nil] the state parameter the provider returned; nil is refused
82
55
  # @param expected_state [String, nil] the state `authorization_url` handed out before
83
56
  # the redirect; nil is refused
84
57
  # @return [Hash{Symbol => Object}] `issuer:` and `subject:` (String), `email:` (String,
85
58
  # or nil if the token carries none), `email_verified:` (Boolean)
86
- # @raise [Ports::Authentication::ValidationError] if either state is nil or the two
87
- # differ, the code exchange fails, the response has no ID token, or the ID token does
88
- # not verify
59
+ # @raise [Ports::Authentication::ValidationError] if the state check, code exchange, or
60
+ # ID token verification fails
89
61
  # @raise [KeyError] if `GOOGLE_CLIENT_ID` or `GOOGLE_REDIRECT_URI` is unset, or a
90
62
  # verified token lacks an `iss` or `sub` claim
91
63
  def verify(code:, state:, expected_state:)
92
- # **Both gems, before anything else** — not staggered further down
93
- # this method: the rescue clause below names GoogleIDToken
94
- # ::ValidationError, and Ruby resolves that constant reference
95
- # at the moment an exception is being matched, not at parse
96
- # time. An OAuth2::Error raised before a later `require
97
- # "google-id-token"` line ran would make the rescue clause
98
- # itself blow up on an undefined constant, masking the real
99
- # error. Requiring both up front means whichever one raises
100
- # first, the constant is already there to catch it.
64
+ # Both requires happen up front: the rescue below matches
65
+ # GoogleIDToken::ValidationError, resolved only when caught, so
66
+ # requiring it lazily after an OAuth2::Error would mask the real failure.
101
67
  require "oauth2"
102
68
  require "google-id-token"
103
69
 
@@ -2,45 +2,23 @@ require "time"
2
2
 
3
3
  module Hecks
4
4
  module Adapters
5
- # **The `authorization` port, fulfilled by governance** — same registry,
6
- # same boot, so "ask Governance" is a dispatch against records
7
- # already sitting in the store this adapter is handed, not a bridge
8
- # to a second runtime. `Runtime::Dispatcher.new(registry)` is cheap
9
- # to build fresh per call (`Registry#capability_graph`'s own
10
- # neighbor, `#repository`, does the same kind of on-demand build) —
11
- # nothing here holds one across calls, so there is no boot-order
12
- # dependency on when Governance's bluebook loads relative to this
13
- # adapter, only that it has by the time `holds_role?` is called.
14
- #
15
- # An active assignment, not merely a past one — `RoleAssignment`
16
- # answers with every assignment an actor has ever held, current or
17
- # past (`AssignmentsForActor`'s own description covers both), and
18
- # leaves `ends_at` for the caller to read, the same deferral
19
- # `Governance::RoleTransition.Allowed` makes for the same reason.
20
- # This is that caller.
5
+ # The `authorization` port, answered by dispatching queries against Governance's records
6
+ # in the same registry. Only assignments with no `ends_at` count as live.
21
7
  module GovernanceAuthorization
22
8
  module_function
23
9
 
24
- # `as_of` and `scope` are both optional, same opt-in shape
25
- # `refuse_role_mismatch` already gives `actor_id` itself — an
26
- # unbound `as_of` skips the `starts_at` check and an unbound
27
- # `scope` skips the `scope` check, exactly the behavior before
28
- # either existed. Neither is fetched here: `as_of` arrives already
29
- # resolved from `Ports::Clock.now`, called by the caller at the
30
- # door, never by this adapter — see `Ports::Clock`'s own header
31
- # for why the dispatch path must not consult the clock itself.
10
+ # Reports whether `actor_id` holds a live grant of `role`.
32
11
  #
33
- # @param registry [Runtime::Registry] the booted registry, to resolve the authorization
34
- # provider's verb
35
- # @param actor_id [String] the actor whose grants are checked, compared as a String
36
- # @param role [String, Symbol] the role name to look for, compared as a String
37
- # @param as_of [Integer, nil] Unix epoch seconds; a grant whose `starts_at` is later, or
38
- # does not parse as a time, does not count. nil skips the `starts_at` check
12
+ # `as_of` and `scope` are opt-in: nil skips the matching check. `as_of` comes from the
13
+ # caller, since the dispatch path must not read the clock (see `Ports::Clock`).
14
+ #
15
+ # @param registry [Runtime::Registry] the booted registry
16
+ # @param actor_id [String] the actor whose grants are checked
17
+ # @param role [String, Symbol] the role name to look for
18
+ # @param as_of [Integer, nil] Unix epoch seconds; a later (or unparseable) `starts_at` fails
39
19
  # @param scope [String, nil] the scope the caller acts in; nil skips the scope check
40
- # @return [Boolean] true if at least one live grant of `role` to `actor_id` passes the
41
- # `as_of` and `scope` checks
42
- # @raise [Runtime::WiringError] if the loaded chapters providing `"authorization"` are
43
- # not exactly one (see `provided_verb`)
20
+ # @return [Boolean] true if a live grant of `role` to `actor_id` passes both checks
21
+ # @raise [Runtime::WiringError] unless exactly one chapter provides `"authorization"`
44
22
  def holds_role?(registry, actor_id:, role:, as_of: nil, scope: nil)
45
23
  rows = Runtime::Dispatcher.new(registry).query(
46
24
  provided_verb(registry, :assignments),
@@ -55,11 +33,7 @@ module Hecks
55
33
  end
56
34
  end
57
35
 
58
- # `scope` unchecked when not stated, same as every other opt-in
59
- # field here — a caller that never says which scope it is acting
60
- # in gets the pre-scope behavior: any live assignment for the role
61
- # authorizes, everywhere. A caller that does state one only
62
- # authorizes against an assignment granted for that scope.
36
+ # Without a `scope`, any live assignment for the role authorizes everywhere.
63
37
  #
64
38
  # @param row [Hash{Symbol => Object}] one `RoleAssignment` row as
65
39
  # `Runtime::Dispatcher#query` returns it; `:scope` holds a `{value: String}` Hash
@@ -69,13 +43,8 @@ module Hecks
69
43
  scope.nil? || row[:scope][:value] == scope.to_s
70
44
  end
71
45
 
72
- # `starts_at` is a free-text string in the bluebook (`Timestamp`'s
73
- # only invariant is "present", not any particular format) — parsed
74
- # here with `Time.parse` rather than compared lexically, since
75
- # nothing guarantees every caller writes it zero-padded ISO 8601.
76
- # Fails closed : a `starts_at` that does not parse is treated as
77
- # not-yet-started rather than silently ignored, the same direction
78
- # every other check in this method already fails.
46
+ # `starts_at` is free text, so it is parsed with `Time.parse` rather than compared
47
+ # lexically. Fails closed: an unparseable value counts as not yet started.
79
48
  #
80
49
  # @param row [Hash{Symbol => Object}] one `RoleAssignment` row as
81
50
  # `Runtime::Dispatcher#query` returns it; `:starts_at` holds a `{value: String}` Hash
@@ -92,21 +61,13 @@ module Hecks
92
61
 
93
62
  # Answers whether one role may act as another.
94
63
  #
95
- # **The other half** — may role X act as role Y. `RoleTransition.Allowed`
96
- # is identified by the exact pair, so at most one row ever comes
97
- # back ; still read as `.any?` rather than trusting that structurally,
98
- # the same defensiveness `holds_role?` already has to have anyway
99
- # since `AssignmentsForActor` can return several.
64
+ # Read with `.any?` rather than trusting that the exact-pair lookup returns one row.
100
65
  #
101
- # @param registry [Runtime::Registry] the booted registry, to resolve the authorization
102
- # provider's verb
66
+ # @param registry [Runtime::Registry] the booted registry
103
67
  # @param from_role [String, Symbol] the role the caller holds, compared as a String
104
- # @param to_role [String, Symbol] the role the caller wants to act as, compared as a
105
- # String
106
- # @return [Boolean] true if a live (not ended) allowance lets `from_role` act as
107
- # `to_role`
108
- # @raise [Runtime::WiringError] if the loaded chapters providing `"authorization"` are
109
- # not exactly one (see `provided_verb`)
68
+ # @param to_role [String, Symbol] the role the caller wants to act as, compared as a String
69
+ # @return [Boolean] true if a live allowance lets `from_role` act as `to_role`
70
+ # @raise [Runtime::WiringError] unless exactly one chapter provides `"authorization"`
110
71
  def authorized_as?(registry, from_role:, to_role:)
111
72
  rows = Runtime::Dispatcher.new(registry).query(
112
73
  provided_verb(registry, :transitions),
@@ -116,12 +77,7 @@ module Hecks
116
77
  rows.any? { |row| row[:ends_at].nil? }
117
78
  end
118
79
 
119
- # The role itself, not just a yes/no about one — the same
120
- # `AssignmentsForActor` query `holds_role?` runs, just returning
121
- # the live (non-revoked) row's `role_name` instead of comparing it
122
- # against a caller-supplied guess. `nil` for no live assignment at
123
- # all — the caller's own fallback (an aggregate's own role field,
124
- # a default) is domain-specific and does not belong here.
80
+ # Returns the actor's live role name, or nil; any fallback is the caller's.
125
81
  #
126
82
  # @param registry [Runtime::Registry] the booted registry, to resolve the authorization
127
83
  # provider's verb
@@ -140,11 +96,8 @@ module Hecks
140
96
  live && live[:role_name][:value]
141
97
  end
142
98
 
143
- # The verb, read from the provider's own declaration — `provides
144
- # "authorization", assignments: ..., transitions: ...` on whichever
145
- # loaded chapter declares it (Governance's, in every boot today).
146
- # Exactly one provider, the same "the runtime will not choose for
147
- # you" rule `Ports::Authorization.adapter` applies to adapters.
99
+ # Reads a verb from the one chapter that `provides "authorization"`; the runtime will
100
+ # not choose between several (as in `Ports::Authorization.adapter`).
148
101
  #
149
102
  # @param registry [Runtime::Registry] the booted registry to search for the
150
103
  # `"authorization"` provider
@@ -22,35 +22,13 @@ module Hecks
22
22
  end
23
23
  end
24
24
 
25
- # An explicit, opt-in maintenance operation — never run
26
- # automatically after an ordinary save/delete. Heki's journal is
27
- # not a disposable write-ahead log: it is this adapter's own
28
- # answer to `entries`, and `entries` is a real port contract
29
- # (`Ports::Persistence::AppendOnly`'s own required-methods list)
30
- # read in full, forever, by `Ports::Projection::Worker#catch_up!`
31
- # and `Registry#projection_current?` to catch a projection up to
32
- # its authoritative source, and by `bin/history` to show "every
33
- # journal entry a domain's append-only adapters hold" — the same
34
- # contract Postgres/Sqlite/D1 uphold by way of a journal table
35
- # that is never pruned. A real example (`examples/banking`,
36
- # `persisted_by("Heki")` + `projected_by("SqliteProjection")`)
37
- # depends on this today. Compacting throws that full history away
38
- # for whatever happened before the call — correct only for an
39
- # aggregate nothing ever projects from; callers (`bin/
40
- # heki_compact`) are responsible for confirming that first.
25
+ # Folds the journal into the snapshot and truncates it. Opt-in; never run after a save.
41
26
  #
42
- # Crash-safety ordering: `write` below is the exact same
43
- # temp-file, fsync, atomic-rename sequence `save`/`delete`
44
- # already use — the snapshot it produces is confirmed durably on
45
- # disk before this method ever touches the journal. Only once
46
- # that succeeds does `truncate_journal!` run. A crash between the
47
- # two leaves old (now fully redundant) journal lines in place;
48
- # replaying them again over the fresh snapshot on the next boot
49
- # is idempotent — the same value gets set again, never a wrong
50
- # one — so nothing is lost, just a little wasted replay work
51
- # once. A crash before `write` completes leaves the journal
52
- # fully intact and the prior snapshot untouched, exactly today's
53
- # existing crash-recovery guarantee.
27
+ # This discards the history `entries` returns, which projections and `hecks history`
28
+ # read in full, so use it only on an aggregate nothing projects from.
29
+ #
30
+ # The snapshot is written durably before the journal is truncated; a crash between
31
+ # the two leaves redundant lines whose replay is idempotent.
54
32
  #
55
33
  # @return [void]
56
34
  # @raise [Malformed] if the snapshot or journal file is corrupt
@@ -68,15 +46,7 @@ module Hecks
68
46
  def truncate_journal!
69
47
  return unless File.exist?(@journal_path)
70
48
 
71
- # A single `truncate(0)` syscall on an already-open file
72
- # descriptor — the file's length changes atomically at the
73
- # filesystem level, so there is no "half truncated" state to
74
- # observe even under a crash mid-call. `fsync` below makes
75
- # that change durable before this method returns; without it
76
- # a crash could still leave the old (harmless-to-replay)
77
- # content on disk after a normal return, which is fine per
78
- # the crash-safety note above, but the durable case is the
79
- # one actually worth returning success for.
49
+ # `truncate(0)` is atomic; the fsync makes it durable before returning.
80
50
  File.open(@journal_path, "r+b") do |file|
81
51
  file.truncate(0)
82
52
  file.flush
@@ -106,10 +76,7 @@ module Hecks
106
76
  encoded = Ports::Persistence::StateCodec.encode(@aggregate, state)
107
77
  line = "#{JSON.generate(operation: operation, id: id.to_s, state: encoded, mirrors: @entry_mirrors)}\n"
108
78
 
109
- # One write, not JSON-then-newline as two: two concurrent
110
- # appends can only interleave *between* writes, never inside
111
- # one, so this line can't come out split by another process's
112
- # line landing in the middle of it.
79
+ # One write, so a concurrent append cannot land in the middle of this line.
113
80
  File.open(@journal_path, "ab") do |journal|
114
81
  journal.write(line)
115
82
  journal.flush
@@ -4,46 +4,11 @@ require_relative "journal"
4
4
  module Hecks
5
5
  module Adapters
6
6
  class Heki
7
- # The optional saga-persistence capability (§2)'s Heki-specific store — a sibling
8
- # snapshot+journal file pair, keyed by (domain, process manager, correlation).
7
+ # Saga checkpoints in a sibling snapshot+journal file pair, keyed by
8
+ # (domain, process manager, correlation).
9
9
  #
10
- # ## Why a sibling file pair, not a table
11
- #
12
- # Built the exact same way an aggregate's own persistence already
13
- # is: `Snapshot`/`Journal` (heki/snapshot.rb, heki/journal.rb)
14
- # operate generically on `@path`/`@journal_path`/`@entry_mirrors`
15
- # and never touch `@aggregate`, so this reuses them unchanged
16
- # rather than re-deriving the same binary framing and
17
- # crash-recovery replay.
18
- #
19
- # ## Where the file lives
20
- #
21
- # Reserved file name (`hecks_saga_instances.heki`, matching the
22
- # `hecks_`-prefix convention every other new saga table in this
23
- # work uses) avoids colliding with any real aggregate's own
24
- # `storage_name`. Lives in the same directory an aggregate's own
25
- # `.heki` file would (`File.dirname(@path)`, `Heki`'s own call
26
- # below) — which, since Heki's `resolve_path` has no per-domain
27
- # component at all, is typically shared across every domain
28
- # booted from the same `root`. `domain` is therefore carried
29
- # inside each record and filtered on read, the same reason
30
- # Postgres's own `hecks_saga_instances` keeps an explicit `domain`
31
- # column under schema isolation (§3).
32
- #
33
- # ## Record shape
34
- #
35
- # One flat records hash, keyed by a composite string (Heki's own
36
- # snapshot format is id-keyed, not tuple-keyed) — never exposed
37
- # outside this class; `each_saga` yields the five real fields a
38
- # caller actually wants, not the internal key shape.
39
- #
40
- # ## Locking
41
- #
42
- # Locked the same way an aggregate's own store is: `with_lock`
43
- # (`Snapshot`, shared) serializes each save/delete's read-modify-
44
- # write against `@path`'s own lock file — a saga gets exactly the
45
- # durability and concurrency-safety this adapter already gives its
46
- # aggregates, no better, no worse.
10
+ # The file is shared by every domain booted from the same directory, so `domain`
11
+ # is stored in each record and filtered on read.
47
12
  class SagaStore
48
13
  include Snapshot
49
14
  include Journal
@@ -59,16 +24,13 @@ module Hecks
59
24
  # Upserts one saga instance's checkpoint, keyed by domain, process manager and
60
25
  # correlation, under the file lock.
61
26
  #
62
- # @param domain [String] the owning domain, carried in the record and filtered on
63
- # read
27
+ # @param domain [String] the owning domain, carried in the record and filtered on read
64
28
  # @param process_manager [String] the process manager's name
65
29
  # @param correlation [String] the instance's correlation value
66
30
  # @param state [String] the saga's current state name
67
31
  # @param memory [Hash] the saga's working memory to persist
68
- # @param completed_compensations [Array] the ledger of completed compensable legs;
69
- # `[]` when none
70
- # @return [Hash{String => Hash}] the store's full internal records Hash after the
71
- # write; callers ignore it
32
+ # @param completed_compensations [Array] completed compensable legs; `[]` when none
33
+ # @return [Hash{String => Hash}] the full records Hash after the write; callers ignore it
72
34
  def save_saga(domain, process_manager, correlation, state, memory, completed_compensations = [])
73
35
  key = key_for(domain, process_manager, correlation)
74
36
  record = { "domain" => domain, "process_manager" => process_manager,
@@ -104,8 +66,7 @@ module Hecks
104
66
  end
105
67
  end
106
68
 
107
- # Yields every checkpointed saga instance of `domain`, for `Registry
108
- # #rehydrate_sagas!` to restore at boot.
69
+ # Yields every checkpointed saga instance of `domain`, for boot-time rehydration.
109
70
  #
110
71
  # @param domain [String] the owning domain to filter records to
111
72
  # @yieldparam process_manager [String] the process manager's name
@@ -113,10 +74,8 @@ module Hecks
113
74
  # @yieldparam state [String] the saga's state name
114
75
  # @yieldparam memory [Hash{Symbol => Object}] the saga's memory, Symbol keys at every
115
76
  # depth
116
- # @yieldparam completed_compensations [Array] the completed-compensation ledger, `[]`
117
- # when the record carries none
118
- # @return [Enumerator, Hash{String => Hash}] an enumerator over the same five values
119
- # when no block is given; otherwise the store's full internal records Hash
77
+ # @yieldparam completed_compensations [Array] the completed-compensation ledger
78
+ # @return [Enumerator, Hash{String => Hash}] an enumerator when no block is given
120
79
  def each_saga(domain)
121
80
  return enum_for(:each_saga, domain) unless block_given?
122
81
 
@@ -135,9 +94,8 @@ module Hecks
135
94
  @store ||= replay_journal(read_snapshot)
136
95
  end
137
96
 
138
- # A plain space-joined key, not anything fancier — a correlation value is real
139
- # business data (an order id, a customer reference) and nothing
140
- # here should assume it never contains a space.
97
+ # Space-joined; the key is opaque and never parsed back, so spaces in a
98
+ # correlation value are harmless.
141
99
  def key_for(domain, process_manager, correlation) = [domain, process_manager, correlation].join(" ")
142
100
  end
143
101
  end
@@ -23,11 +23,7 @@ module Hecks
23
23
  raise Malformed, "#{@path}: json error: #{e.message}"
24
24
  end
25
25
 
26
- # Temp-file-plus-rename, fsynced ahead of the `File.rename` call: a reader can
27
- # only ever see the last complete snapshot or the one before it,
28
- # never a truncated or partial one — `File.binwrite`'s old
29
- # truncate-then-write left a window, proportional to the whole
30
- # dataset, where the file on disk was neither.
26
+ # Temp file, fsync, then rename, so a reader never sees a partial snapshot.
31
27
  def write(records)
32
28
  sorted = records.sort_by { |id, _| id }.to_h
33
29
  json = JSON.generate(sorted)
@@ -42,13 +38,9 @@ module Hecks
42
38
  File.rename(tmp, @path)
43
39
  end
44
40
 
45
- # Serializes the read-modify-write each save/delete does against
46
- # the snapshot (and the journal append that precedes it) across
47
- # processes — `flock` is per-process advisory, so every writer
48
- # has to go through this to matter, which `with_lock`'s only two
49
- # callers (`Heki#save`/`#delete`, `SagaStore#save_saga`/
50
- # `#delete_saga`) both do. The lock file is separate from
51
- # `@path` so a held lock never blocks `write`'s own rename.
41
+ # Serializes each save/delete's read-modify-write across processes; `flock` is
42
+ # advisory, so every writer must use it. The lock file is separate from `@path`
43
+ # so a held lock never blocks `write`'s rename.
52
44
  def with_lock
53
45
  File.open(lock_path, File::CREAT | File::RDWR, 0o644) do |lock|
54
46
  lock.flock(File::LOCK_EX)
@@ -35,12 +35,9 @@ module Hecks
35
35
  @aggregate = aggregate
36
36
  @path = resolve_path(settings, root)
37
37
  @journal_path = "#{@path}.journal"
38
- @events = []
39
- # The optional saga-persistence capability's own scoping (§2/§4)
40
- # — falls back to the aggregate's own name for a directly-
41
- # instantiated adapter (specs), same fallback shape Postgres's
42
- # own @domain already uses.
43
- @domain = (
38
+ @events = []
39
+ # Saga scope; falls back to the aggregate's name for a directly built adapter.
40
+ @domain = (
44
41
  if settings.key?(:domain)
45
42
  settings[:domain]
46
43
  elsif settings.key?("domain")
@@ -81,13 +78,7 @@ module Hecks
81
78
 
82
79
  # Answers a declared query specification against the projected records.
83
80
  #
84
- # `registry: context[:registry]` — Memory's own `query` already
85
- # threads this through; Heki's own never did, which made
86
- # `none_in_state?` (Ports::Query::InMemory) unconditionally
87
- # return `true` (its own graceful "no registry, no way to look
88
- # the target up" default) for every `none_in_state` where-clause
89
- # against a Heki-backed aggregate — silently excluding nothing,
90
- # always, no matter the actual target state.
81
+ # The registry is passed through so `none_in_state` clauses can look up their target.
91
82
  #
92
83
  # @param specification [QuerySpecification::Common::Options,
93
84
  # Bluebook::Behaviour::ReadModel::FilteredOptions] the declared query specification
@@ -113,17 +104,11 @@ module Hecks
113
104
 
114
105
  # Applies one journaled entry to the current-state snapshot.
115
106
  #
116
- # Reads fresh rather than trusting the memoized `store` — under
117
- # `with_lock`, another process may have projected a snapshot since
118
- # this one last read it, and mutating *its* stale copy would
119
- # overwrite that write on disk rather than layer on top of it.
107
+ # Reads fresh, not the memoized `store`: another process may have projected since,
108
+ # and a stale copy would overwrite that write.
120
109
  #
121
- # On a delete, though, the record `current.delete` finds is already
122
- # gone: every caller (`#delete` above, `AppendOnly#delete`) appends
123
- # before it projects, so the fresh read above has already replayed
124
- # this very entry off the journal. What the memoized `store` last
125
- # held — from before this call — is read up front, for the return
126
- # value only; it plays no part in what gets written.
110
+ # On a delete the fresh read has already replayed the entry, so the returned record
111
+ # comes from the memoized `store`, read up front.
127
112
  #
128
113
  # @param entry [Persistence::Entry] the save or delete to materialize
129
114
  # @return [Runtime::Instance, nil] on a save, the newly stored record; on a delete, the
@@ -178,10 +163,7 @@ module Hecks
178
163
  # @return [Array<Runtime::Event>] the adapter's in-memory event log, including `event`
179
164
  def record_event(event) = @events << event
180
165
 
181
- # ── the optional saga-persistence capability (§2) — Heki's own
182
- # shape (a sibling snapshot+journal file pair, `SagaStore`,
183
- # heki/saga_store.rb) rather than a table in a store this adapter
184
- # doesn't have.
166
+ # Checkpoints one saga instance in a sibling file pair (`SagaStore`).
185
167
  #
186
168
  # @param process_manager [String, Symbol] the process manager's name, compared as
187
169
  # `.to_s`
@@ -209,18 +191,15 @@ module Hecks
209
191
  saga_store.delete_saga(@domain, process_manager.to_s, correlation.to_s)
210
192
  end
211
193
 
212
- # Yields every checkpointed saga instance of this domain, for `Registry
213
- # #rehydrate_sagas!` to restore at boot.
194
+ # Yields every checkpointed saga instance of this domain, for boot-time rehydration.
214
195
  #
215
196
  # @yieldparam process_manager [String] the process manager's name
216
197
  # @yieldparam correlation [String] the instance's correlation value
217
198
  # @yieldparam state [String] the saga's state name
218
199
  # @yieldparam memory [Hash{Symbol => Object}] the saga's memory, Symbol keys at every
219
200
  # depth
220
- # @yieldparam completed_compensations [Array] the completed-compensation ledger, `[]`
221
- # when none was recorded
222
- # @return [Enumerator, Hash{String => Hash}] an enumerator over the same five values
223
- # when no block is given; otherwise `SagaStore`'s internal records Hash
201
+ # @yieldparam completed_compensations [Array] the completed-compensation ledger
202
+ # @return [Enumerator, Hash{String => Hash}] an enumerator when no block is given
224
203
  def each_saga(&) = saga_store.each_saga(@domain, &)
225
204
 
226
205
  private
@@ -229,8 +208,6 @@ module Hecks
229
208
  @saga_store ||= SagaStore.new(File.dirname(@path))
230
209
  end
231
210
 
232
- # `record` is the snapshot/journal's own string-keyed JSON — decoded
233
- # deep through the state codec, never symbolized one level by hand.
234
211
  def instance(id, record)
235
212
  Runtime::Instance.new(
236
213
  aggregate: @aggregate,
@@ -248,13 +225,7 @@ module Hecks
248
225
  replay_journal(snapshot)
249
226
  end
250
227
 
251
- # `dir: :default` — a bare Symbol, the framework's own convention
252
- # for "a declared value that resolves by convention, never a silent
253
- # fallback" — would otherwise crash `File.join` outright
254
- # (`TypeError: no implicit conversion of Symbol into String`):
255
- # `resolve_path` only ever checked for a missing `dir` setting,
256
- # never a Symbol one. Treated the same as no setting at all — falls
257
- # back to the existing "data" default, not a new special case.
228
+ # `dir: :default` means no setting; a Symbol would make `File.join` raise TypeError.
258
229
  def resolve_path(settings, root)
259
230
  declared =
260
231
  if settings.key?(:dir)
@@ -1,22 +1,13 @@
1
1
  module Hecks
2
2
  module Adapters
3
- # The `identity_resolution` port, fulfilled by the Identity framework
4
- # bluebook — same registry, same boot, so this is a dispatch against
5
- # records already sitting in the store this adapter is handed, not a
6
- # bridge to a second runtime. Same reasoning `GovernanceAuthorization`
7
- # gives for itself, one port over.
3
+ # The `identity_resolution` port, fulfilled by the Identity framework bluebook
4
+ # through a dispatch on the same registry.
8
5
  module IdentityRegistry
9
6
  module_function
10
7
 
11
8
  # Looks up the id of the identity an authenticated (issuer, subject) pair is linked to,
12
9
  # querying the Identity framework bluebook's own `ResolvedBy`.
13
10
  #
14
- # `nil` for a pair nothing has linked, the first match otherwise —
15
- # `ResolvedBy` is a lookup by the exact (issuer, subject) an
16
- # authenticated token carries, not a listing, so more than one row
17
- # would mean two links share a pair, which `Link`'s own natural
18
- # key already prevents by construction.
19
- #
20
11
  # @param registry [Runtime::Registry] the booted registry, queried for the linked
21
12
  # identity's id
22
13
  # @param issuer [String] the OIDC issuer that authenticated the caller, compared as a
@@ -24,9 +15,7 @@ module Hecks
24
15
  # @param subject [String] the OIDC subject the issuer vouches for, compared as a String
25
16
  # @return [String, nil] the linked identity's id, or nil if nothing has linked this pair
26
17
  def resolve(registry, issuer:, subject:)
27
- # The resolve verb this registry's declared identity provider names
28
- # (`provides "identity", resolve:`), never a hard-coded chapter —
29
- # same declared-not-named shape GovernanceAuthorization already holds.
18
+ # The verb comes from the declared identity provider (`provides "identity", resolve:`).
30
19
  provider = registry.bluebooks.values.find { |chapter| chapter.provides?(::Hecks::Bluebook::Capabilities::IDENTITY) }
31
20
  verb = provider&.provided_verb(::Hecks::Bluebook::Capabilities::IDENTITY, :resolve) ||
32
21
  "Identity::ExternalIdentifier.ResolvedBy"