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
@@ -1,26 +1,16 @@
1
- # A TOOLING-INTERNAL DOMAIN, not a business one — never attached via
2
- # `uses_framework`, never seen by an end-user domain. `bin/project_deploy`
3
- # boots this directory directly (Ports::Loading.bootstrap + load_domain,
4
- # the same pipeline lib/hecks/runtime/loader.rb uses, minus a
5
- # `.world`/`.hecksagon` this domain has no need for) and dispatches one
6
- # command against it before generating anything from a domain's own
7
- # `deployed_to("AwsLambda")` settings.
1
+ # The Deploy chapter: what `deployed_to(...)` may declare, and the commands that generate, check and
2
+ # compare a deploy recipe, project the OIDC manifests and provision a tenant.
8
3
  #
9
- # WHY THIS EXISTS: `world.bluebook`'s `Wiring`/`Setting` is a DELIBERATELY
10
- # open, untyped map — "a verb's schema is not even contained in the file
11
- # being parsed" (syntax.bluebook's own header on this). That's the right
12
- # call for `Wiring` itself (an adapter verb's shape genuinely isn't the
13
- # world language's business), but it leaves `deployed_to`'s ACTUAL shape
14
- # validated nowhere — `bin/project_deploy` used to check it by hand
15
- # (`deploy_settings[:adapter] == "AwsLambda" or abort ...`,
16
- # `fetch(:region) { abort ... }`), the exact raw-Ruby-refusal pattern
17
- # every other kind of bluebook mistake in this codebase does NOT use.
18
- # This closes that gap the same way any other rule gets enforced here:
19
- # as a real command, real invariants, a real corpus-testable refusal —
20
- # not a hand-written abort string discovered only by running the script.
4
+ # `hecks deploy project` and `hecks deploy provision` boot it directly; the Hecks domain attaches it, so
5
+ # each command below is also `hecks deploy <verb>`. The targets validate the `deployed_to` shape
6
+ # that `world.bluebook`'s untyped `Setting` map leaves open. Each run below records that it was
7
+ # requested before its DeployToolchain port is asked, and what came of it after. No command
8
+ # declares a role: the chapter boots standing alone, without Governance to check one against.
21
9
  Hecks.bluebook "Deploy" do
10
+ vision "Generate, check and compare deploy recipes, project OIDC manifests and provision tenants."
11
+
22
12
  aggregate "LambdaTarget" do
23
- description "One domain's validated AWS Lambda deploy target — what deployed_to(\"AwsLambda\") must resolve to before bin/project_deploy generates anything from it."
13
+ description "One domain's validated AWS Lambda deploy target — what deployed_to(\"AwsLambda\") must resolve to before hecks deploy project generates anything from it."
24
14
 
25
15
  identified_by :domain
26
16
 
@@ -41,77 +31,39 @@ Hecks.bluebook "Deploy" do
41
31
  invariant("a region is named") { !value.to_s.empty? }
42
32
  end
43
33
 
44
- # "Postgres" (a plain AWS::RDS::DBInstance, Embryonaut's own live
45
- # choice — bin/project_deploy's Ruby-side default when a domain's
46
- # own deployed_to("AwsLambda") names none, so every domain
47
- # declared before this attribute existed keeps generating the
48
- # identical template it always has) or "Aurora" (Aurora Serverless
49
- # v2, Postgres-compatible — the SAME `Adapters::Postgres`/
50
- # `tokio_postgres` code on both the Ruby and rust/host sides
51
- # either way; this only changes which CloudFormation resource
52
- # bin/project_deploy emits, never a runtime adapter).
53
- # "Shared" — no RDS/VPC of this domain's own at all; it borrows
54
- # another already-deployed domain's instance instead (the
55
- # storehouse), isolated from that domain's own data by a native
56
- # Postgres SCHEMA (this domain's own lowercase name), not a
57
- # separate database. Requires a sibling `owner "OtherDomain"`
58
- # setting inside the SAME deployed_to("AwsLambda") block, naming
59
- # which already-deployed domain owns the shared instance —
60
- # bin/project_deploy checks for that setting itself (Ruby-level,
61
- # the same as `pg_version`/`google_oauth_present` below it), not
62
- # here: which domain owns the instance is a deploy-time fact, not
63
- # a business invariant this validated aggregate's job to hold.
34
+ # "Postgres" (plain RDS, the default when `deployed_to` names none) or "Aurora"
35
+ # (Serverless v2);
36
+ # only the emitted CloudFormation resource differs, never the runtime adapter. "Shared" borrows
37
+ # another domain's instance under its own Postgres schema and needs an `owner` setting, which
38
+ # `hecks deploy project` checks, since the owning domain is a deploy-time fact.
64
39
  value_object "Database" do
65
40
  attribute :value, String, one_of: ["Postgres", "Aurora", "Shared"]
66
41
  end
67
42
 
68
- # "None" (the default — nothing changes for a domain that names
69
- # neither this nor drops a `lambda_handler.rb`, e.g. Banking) or
70
- # "Rust" — the domain's OWN Lambda (rust/host) also serves a public
71
- # web UI in-process (rust/host/src/web.rs), reading HECKS_IR_PATH
72
- # (a plain-JSON sidecar bin/project_wasm writes beside the .wasm
73
- # artifact) and dispatching through the SAME in-process
74
- # dispatch::handle/read the internal {"verb"}/{"read"} path already
75
- # uses — no second Lambda, no VPC Interface Endpoint, no Ruby.
76
- # Deliberately NOT "Ruby" as a third member here: a Ruby WebFunction
77
- # is the pre-existing, SEPARATE `lambda_handler.rb`-file-presence
78
- # mechanism (Embryonaut's own), untouched by this attribute —
79
- # bin/project_deploy refuses generation outright if a domain
80
- # declares `web "Rust"` AND has a `lambda_handler.rb`, rather than
81
- # silently picking one.
43
+ # "None" (default) or "Rust": the domain's own Lambda (rust/host) also serves a public web UI
44
+ # in-process (rust/host/src/web.rs). "Ruby" is not a member: a Ruby WebFunction comes from a
45
+ # `lambda_handler.rb` file, and `hecks deploy project` refuses `web "Rust"` alongside one.
82
46
  value_object "Web" do
83
47
  attribute :value, String, one_of: ["None", "Rust"]
84
48
  end
85
49
 
86
- # 128-10240 MB — AWS Lambda's own real ceiling and floor, not a
87
- # number this domain invented. A typo here used to fail deep inside
88
- # a real `sam deploy`, sometimes minutes in; now it refuses before
89
- # a single file is generated.
50
+ # 128-10240 MB, AWS Lambda's own floor and ceiling.
90
51
  value_object "Memory" do
91
52
  attribute :value, Integer
92
53
  invariant("memory is at least 128 MB") { value >= 128 }
93
54
  invariant("memory is at most 10240 MB") { value <= 10240 }
94
55
  end
95
56
 
96
- # 900s — Lambda's own real ceiling.
57
+ # Lambda's own ceiling of 900s.
97
58
  value_object "Timeout" do
98
59
  attribute :value, Integer
99
60
  invariant("a timeout is positive") { value.positive? }
100
61
  invariant("a timeout fits Lambda's own 900s ceiling") { value <= 900 }
101
62
  end
102
63
 
103
- # ALL FOUR REQUIRED — deliberately, not `optional: true` +
104
- # `default:`. Confirmed directly against CommandInterpreter's own
105
- # `normalize_args`/`coerce_declared_arguments` (interpreting.rb):
106
- # `next unless normalized.key?(attribute.name)` skips coercion
107
- # entirely for an absent key, so a command-level `default:` is
108
- # honored ONLY at the JSON/Rust-codegen boundary (`scalar_from_json_
109
- # expr`'s own domain), never by Ruby's own direct dispatch — a
110
- # `default:` here would be quietly false advertising. "What memory
111
- # defaults to when unspecified" stays exactly where it already
112
- # lived (bin/project_deploy's own `fetch(:memory, 512)`); this
113
- # command validates a FULLY-RESOLVED target, and bin/project_deploy
114
- # resolves the default before ever dispatching.
64
+ # All required, no `default:`: command-level defaults apply only at the JSON/Rust-codegen
65
+ # boundary, not Ruby's direct dispatch (interpreting.rb `normalize_args`). Defaults are
66
+ # resolved by `hecks deploy project` before it dispatches.
115
67
  command "Declare" do
116
68
  goal "Validate one domain's AwsLambda deploy target before anything is generated from it"
117
69
 
@@ -133,13 +85,10 @@ Hecks.bluebook "Deploy" do
133
85
  end
134
86
  end
135
87
 
136
- # A sibling of `LambdaTarget`, not a shared shape with it — value objects
137
- # are not shared across aggregates in this DSL (`Tenant`'s own
138
- # `DomainName`/`Realm`/`Schema` below already make the same point), so
139
- # this aggregate carries its own copies of `DomainName`/`Region`/
140
- # `Database`/`Web` rather than reaching into `LambdaTarget`'s.
88
+ # A sibling of `LambdaTarget` with its own value objects, since value objects are not
89
+ # shared across aggregates.
141
90
  aggregate "FargateTarget" do
142
- description "One domain's validated AWS Fargate deploy target — what deployed_to(\"AwsFargate\") must resolve to before bin/project_deploy generates anything from it."
91
+ description "One domain's validated AWS Fargate deploy target — what deployed_to(\"AwsFargate\") must resolve to before hecks deploy project generates anything from it."
143
92
 
144
93
  identified_by :domain
145
94
 
@@ -161,60 +110,40 @@ Hecks.bluebook "Deploy" do
161
110
  invariant("a region is named") { !value.to_s.empty? }
162
111
  end
163
112
 
164
- # A positive integer, nothing more — AWS's real cpu/memory
165
- # combinations (256 cpu units needs 512-2048 MB of `memory`, say)
166
- # are a pairing `ECS` itself enforces at deploy time; encoding that
167
- # whole table here would duplicate AWS's own rules for no benefit
168
- # this generator needs. This only catches a typo (zero, negative)
169
- # before a single file is generated, the same floor `Memory`/`Port`
170
- # below hold for their own ranges.
113
+ # Positive only: ECS enforces AWS's cpu/memory pairings at deploy time, so this just
114
+ # catches a typo.
171
115
  value_object "Cpu" do
172
116
  attribute :value, Integer
173
117
  invariant("cpu is positive") { value.positive? }
174
118
  end
175
119
 
176
- # Fargate's own valid range, not Lambda's 128-10240 MB —
177
- # `LambdaTarget`'s own `Memory` value object (above) is scoped to
178
- # that aggregate alone, so this is a distinct value object under the
179
- # same name rather than a shared one. A plain sanity floor and
180
- # ceiling, not AWS's own cpu-paired table (see `Cpu`'s own comment).
120
+ # Fargate's own range, not Lambda's 128-10240 MB. A sanity floor and ceiling, not AWS's
121
+ # cpu-paired table (see `Cpu`).
181
122
  value_object "Memory" do
182
123
  attribute :value, Integer
183
124
  invariant("memory is positive") { value.positive? }
184
125
  invariant("memory is at most 122880 MB") { value <= 122880 }
185
126
  end
186
127
 
187
- # Same shape and reasoning as `LambdaTarget`'s own `Database` —
188
- # "Postgres"/"Aurora" provision this domain's own RDS instance;
189
- # "Shared" borrows another already-deployed domain's instance,
190
- # isolated by a native Postgres schema. See that value object's own
191
- # comment for the full reasoning; it applies unchanged here.
128
+ # As `LambdaTarget`'s `Database`.
192
129
  value_object "Database" do
193
130
  attribute :value, String, one_of: ["Postgres", "Aurora", "Shared"]
194
131
  end
195
132
 
196
- # Same shape and reasoning as `LambdaTarget`'s own `Web` — "Rust"
197
- # means the domain's own task also serves its public web UI
198
- # in-process, over the port this aggregate's own `Port` attribute
199
- # declares.
133
+ # As `LambdaTarget`'s `Web`; "Rust" serves the web UI in-process on this aggregate's `Port`.
200
134
  value_object "Web" do
201
135
  attribute :value, String, one_of: ["None", "Rust"]
202
136
  end
203
137
 
204
- # The container port the task listens on and the target group
205
- # routes to — a real TCP port, not an arbitrary integer.
138
+ # The container port the task listens on and the target group routes to.
206
139
  value_object "Port" do
207
140
  attribute :value, Integer
208
141
  invariant("a port is at least 1") { value >= 1 }
209
142
  invariant("a port is at most 65535") { value <= 65535 }
210
143
  end
211
144
 
212
- # All seven required, for the identical reason `LambdaTarget.Declare`
213
- # requires all of its own attributes — see that command's own
214
- # comment on `normalize_args`/`coerce_declared_arguments`. This
215
- # validates a fully-resolved target, after `bin/project_deploy`'s own
216
- # defaulting (`cpu`/`memory`/`port` each fall back to a Ruby-side
217
- # default before this ever dispatches), not instead of it.
145
+ # All seven required for the same reason as `LambdaTarget.Declare`; this validates a
146
+ # target already resolved by `hecks deploy project`'s defaults.
218
147
  command "Declare" do
219
148
  goal "Validate one domain's AwsFargate deploy target before anything is generated from it"
220
149
 
@@ -238,41 +167,27 @@ Hecks.bluebook "Deploy" do
238
167
  end
239
168
  end
240
169
 
241
- # `bin/project_tenant`'S OWN VALIDATED SHAPE — same split LambdaTarget
242
- # draws with `bin/project_deploy`: this aggregate validates, that
243
- # script GENERATES/ACTS (writes `environments/<slug>.world`, ensures
244
- # the Postgres schema, boots once to prove it). Deliberately NOT a
245
- # saga/process manager with durable runtime state — every step
246
- # `bin/project_tenant` takes is already idempotent by construction
247
- # (`CREATE SCHEMA IF NOT EXISTS` — PostgresEra#connect_for's own,
248
- # File.write of the overlay — a plain overwrite, `Hecks.boot` itself),
249
- # the same "generator script, not a business process" shape
250
- # `bin/project_deploy` already is; a saga's own resumability earns
251
- # its cost coordinating a real distributed transaction across
252
- # multiple ports with real failure boundaries (Payments::Payment's
253
- # own PaymentGateway, say) — three local, idempotent, single-process
254
- # steps have no such boundary to resume across. A durable, reactable
255
- # RUNTIME fact ("this tenant exists, is active, is suspended") is a
256
- # different, later, business-facing thing — deliberately not built
257
- # here, and deliberately not named Deploy::Tenant to avoid colliding
258
- # with this validation-only aggregate should it ever land.
170
+ # The validated shape of `hecks deploy provision`, which does the generating and provisioning.
171
+ # Not a saga: each of its steps is idempotent and local, so there is nothing to resume.
259
172
  aggregate "Tenant" do
260
- description "One tenant's validated identity — which realm and Postgres schema `bin/project_tenant` provisions before booting a domain directory under Runtime.boot's own `environment:` overlay for it."
173
+ description "One tenant's validated identity — which realm and Postgres schema `hecks deploy provision` provisions before booting a domain directory under Runtime.boot's own `environment:` overlay for it."
261
174
 
262
175
  identified_by :slug
263
176
 
264
- attribute :slug, Slug
265
- attribute :domain, DomainName
266
- attribute :realm, Realm
267
- attribute :schema, Schema
268
-
269
- # LOWERCASE, NO SPACES — a slug becomes both the `environments/
270
- # <slug>.world` filename and (by convention, not enforced here —
271
- # `schema` is its own, separately-declared field precisely so a
272
- # tenant CAN choose a different schema name than its slug)
273
- # ordinarily the schema name too.
177
+ attribute :slug, Slug
178
+ attribute :domain, DomainName
179
+ attribute :realm, Realm
180
+ attribute :schema, Schema
181
+ attribute :database, DatabaseName, optional: true
182
+ attribute :adapter, AdapterName, optional: true
183
+ attribute :directory, DirectoryPath, optional: true
184
+ attribute :output, Report, optional: true
185
+ attribute :refusal, Report, optional: true
186
+
187
+ # Lowercase, no spaces: a slug becomes the `environments/<slug>.world` filename and, by
188
+ # convention only, the schema name (`schema` is separate so a tenant can differ).
274
189
  value_object "Slug" do
275
- attribute :value, String, pattern: '^[a-z][a-z0-9_]*$'
190
+ attribute :value, String, pattern: '\A[a-z][a-z0-9_]*\z'
276
191
  invariant("a tenant slug is named") { !value.to_s.empty? }
277
192
  end
278
193
 
@@ -286,39 +201,583 @@ Hecks.bluebook "Deploy" do
286
201
  invariant("a tenant realm is named") { !value.to_s.empty? }
287
202
  end
288
203
 
289
- # POSTGRES'S OWN REAL IDENTIFIER RULES, loosely — lowercase (this
290
- # adapter never quotes a mixed-case identifier back out consistently
291
- # once created), letters/digits/underscores, starting with a letter.
292
- # NOT a byte-length ceiling too (Postgres's own real 63-byte
293
- # NAMEDATALEN limit) — the expression grammar invariants compile
294
- # through admits a narrow arithmetic/comparison subset, not
295
- # arbitrary method dispatch (`bytesize` included; found live,
296
- # writing this: `Bluebook::Expression::Evaluator` tries to resolve
297
- # a dotted chain as a FIELD lookup, not a method call, the same
298
- # "admits + but not -, no parentheses" narrowness
299
- # embryonaut_bluebooks/payments' own Refund command already
300
- # documents). Postgres itself refuses a too-long identifier loudly
301
- # on its own; not worth fighting the expression grammar for a
302
- # corner case this rare.
204
+ # Lowercase, letters/digits/underscores, starting with a letter. Postgres's 63-byte
205
+ # identifier limit is not checked: the invariant expression grammar has no `bytesize`, and
206
+ # Postgres refuses a too-long identifier itself.
303
207
  value_object "Schema" do
304
- attribute :value, String, pattern: '^[a-z][a-z0-9_]*$'
208
+ attribute :value, String, pattern: '\A[a-z][a-z0-9_]*\z'
305
209
  invariant("a schema is named") { !value.to_s.empty? }
306
210
  end
307
211
 
308
- command "Declare" do
309
- goal "Validate one tenant's shape before bin/project_tenant provisions its schema and overlay world"
212
+ # A database name or a `postgres://` URL, whichever the overlay's `database` setting takes.
213
+ value_object "DatabaseName" do
214
+ attribute :value, String, pattern: '\A[^\t\n\r]+\z'
215
+ end
216
+
217
+ # The persistence adapter the overlay binds; PostgresEra when a request names none.
218
+ value_object "AdapterName" do
219
+ attribute :value, String, pattern: '\A[A-Z][A-Za-z0-9]*\z'
220
+ end
221
+
222
+ # The domain's own directory on disk, where `environments/<slug>.world` is written.
223
+ value_object "DirectoryPath" do
224
+ attribute :value, String, pattern: '[^\t\n\r]'
225
+ end
310
226
 
311
- attribute :slug, Slug
312
- attribute :domain, DomainName
313
- attribute :realm, Realm
314
- attribute :schema, Schema
227
+ value_object "Report" do
228
+ attribute :value, String
229
+ end
315
230
 
231
+ lifecycle :status, default: "requested" do
232
+ transition "Reprovision" => "requested", from: %w[provisioned refused]
233
+ transition "Complete" => "provisioned", from: "requested"
234
+ transition "Abandon" => "refused", from: "requested"
235
+ end
236
+
237
+ # `hecks deploy provision <directory> slug=s domain= realm= schema= database= [adapter=]`.
238
+ # The only command that creates a tenant: its slug, schema and realm are validated by the value
239
+ # objects' patterns and invariants, then the overlay is written through the TenantProvisioning
240
+ # port; the adapter answers PostgresEra when `adapter` is left out. `dry_run?` on this verb
241
+ # validates a declaration without recording it.
242
+ command "Provision" do
243
+ goal "Validate one tenant, write its environment overlay world, and register it"
244
+
245
+ attribute :directory, DirectoryPath
246
+ attribute :slug, Slug
247
+ attribute :domain, DomainName
248
+ attribute :realm, Realm
249
+ attribute :schema, Schema
250
+ attribute :database, DatabaseName
251
+ attribute :adapter, AdapterName, optional: true
252
+
253
+ sets :directory
316
254
  sets :slug
317
255
  sets :domain
318
256
  sets :realm
319
257
  sets :schema
258
+ sets :database
259
+ sets :adapter
260
+
261
+ emits "TenantProvisionRequested"
262
+ end
263
+
264
+ # A tenant's slug names its record, so provisioning it again is its own command; the overlay
265
+ # is rewritten with the database and adapter given now.
266
+ command "Reprovision" do
267
+ goal "Write a provisioned or refused tenant's environment overlay world again"
268
+
269
+ reference_to Tenant
270
+ attribute :directory, DirectoryPath
271
+ attribute :database, DatabaseName
272
+ attribute :adapter, AdapterName, optional: true
273
+
274
+ sets :directory
275
+ sets :database
276
+ sets :adapter
277
+
278
+ emits "TenantReprovisionRequested"
279
+ end
280
+
281
+ command "Complete" do
282
+ goal "Record that the tenant's overlay was written, and where"
283
+
284
+ reference_to Tenant
285
+ attribute :output, Report
286
+
287
+ sets :output
288
+
289
+ emits "TenantRecorded"
290
+ end
291
+
292
+ command "Abandon" do
293
+ goal "Record that the tenant could not be provisioned, and why"
294
+
295
+ reference_to Tenant
296
+ attribute :refusal, Report
297
+
298
+ sets :refusal
299
+
300
+ emits "ProvisioningAbandoned"
301
+ end
302
+
303
+ query "Provisioning" do
304
+ description "What provisioning one tenant did: its status, and the reason when it was refused."
305
+ attribute :slug, Slug
306
+ where(slug: :slug)
307
+ order_by :slug
308
+ end
309
+
310
+ query "Unprovisioned" do
311
+ description "Every tenant whose provisioning was refused."
312
+ where(status: "refused")
313
+ order_by :slug
314
+ end
315
+ end
316
+
317
+ # `TenantProvisioned` also reaches Tenancy's `RegisterProvisionedTenant` where that chapter is
318
+ # attached, so a provisioned tenant becomes a fact there.
319
+ policy "ProvisionWhenRequested" do
320
+ on "Tenant.TenantProvisionRequested"
321
+ trigger Tenant::TenantProvisioning::WriteOverlay, with: { database: :database, directory: :directory }
322
+ end
323
+
324
+ policy "ReprovisionWhenRequested" do
325
+ on "Tenant.TenantReprovisionRequested"
326
+ trigger Tenant::TenantProvisioning::WriteOverlay, with: { database: :database, directory: :directory }
327
+ end
328
+
329
+ policy "RecordTheTenant" do
330
+ on "Tenant.TenantProvisioned"
331
+ trigger Tenant::Complete, with: { output: :output }
332
+ end
333
+
334
+ policy "RecordTheRefusedTenant" do
335
+ on "Tenant.ProvisioningRefused"
336
+ trigger Tenant::Abandon, with: { refusal: :refusal }
337
+ end
338
+
339
+ aggregate "Recipe" do
340
+ description "One generation of a domain's deploy recipe: the template, scripts and Makefile written from its deployed_to target."
341
+
342
+ attribute :domain, DomainPath
343
+ attribute :run, RunKey
344
+ attribute :tenant, TenantSlug, optional: true
345
+ attribute :schema, SchemaName, optional: true
346
+ attribute :out, Location, optional: true
347
+ attribute :environment, EnvironmentName, optional: true
348
+ attribute :output, Report, optional: true
349
+ attribute :refusal, Report, optional: true
350
+ identified_by :run
351
+
352
+ value_object "RunKey" do
353
+ attribute :value, String, pattern: '[^ \t\n\r]'
354
+
355
+ invariant("a run is named") { !value.to_s.empty? }
356
+ end
357
+
358
+ # A domain directory, whose `bluebook/` holds the `.world` that declares `deployed_to`.
359
+ value_object "DomainPath" do
360
+ attribute :value, String, pattern: '[^\t\n\r]'
361
+
362
+ invariant("a domain is named by its path") { !value.to_s.empty? }
363
+ end
364
+
365
+ # A tenant of a shared-database domain: its stack is the domain's own, suffixed with the slug.
366
+ value_object "TenantSlug" do
367
+ attribute :value, String, pattern: '\A[a-z][a-z0-9_]*\z'
368
+ end
369
+
370
+ value_object "SchemaName" do
371
+ attribute :value, String, pattern: '\A[a-z][a-z0-9_]*\z'
372
+ end
373
+
374
+ # Where the recipe is written, for a domain that lives in a client's repository.
375
+ value_object "Location" do
376
+ attribute :value, String, pattern: '[^\t\n\r]'
377
+ end
378
+
379
+ # An `environments/<name>.world` overlay of the domain, which must exist.
380
+ value_object "EnvironmentName" do
381
+ attribute :value, String, pattern: '\A[A-Za-z][A-Za-z0-9_]*\z'
382
+ end
383
+
384
+ value_object "Report" do
385
+ attribute :value, String
386
+ end
387
+
388
+ lifecycle :status, default: "requested" do
389
+ transition "Complete" => "projected", from: "requested"
390
+ transition "Fault" => "faulted", from: "requested"
391
+ end
392
+
393
+ # `hecks deploy project <domain> [tenant=] [schema=] [out=] [environment=]`. A schema override
394
+ # needs its tenant; the generator says so, and a domain with no `deployed_to` target, or one
395
+ # whose settings conflict, is faulted with the generator's own sentence.
396
+ command "Project" do
397
+ goal "Generate a domain's AWS deploy recipe from its declared deployed_to target"
398
+
399
+ attribute :domain, DomainPath
400
+ attribute :run, RunKey
401
+ attribute :tenant, TenantSlug, optional: true
402
+ attribute :schema, SchemaName, optional: true
403
+ attribute :out, Location, optional: true
404
+ attribute :environment, EnvironmentName, optional: true
405
+
406
+ sets :domain
407
+ sets :run
408
+ sets :tenant
409
+ sets :schema
410
+ sets :out
411
+ sets :environment
412
+
413
+ emits "ProjectionRequested"
414
+ end
415
+
416
+ command "Complete" do
417
+ goal "Record that the recipe was written, and where"
418
+
419
+ reference_to Recipe
420
+ attribute :output, Report
421
+
422
+ sets :output
423
+
424
+ emits "RecipeProjected"
425
+ end
426
+
427
+ command "Fault" do
428
+ goal "Record that the recipe could not be generated, and why"
429
+
430
+ reference_to Recipe
431
+ attribute :refusal, Report
432
+
433
+ sets :refusal
434
+
435
+ emits "RecipeFaulted"
436
+ end
437
+
438
+ query "Outcome" do
439
+ description "What one generation did: its status, and the files written or the reason it stopped."
440
+ attribute :run, RunKey
441
+ where(run: :run)
442
+ order_by :run
443
+ end
444
+
445
+ query "Faulted" do
446
+ description "Every generation that could not write its recipe."
447
+ where(status: "faulted")
448
+ order_by :run
449
+ end
450
+ end
451
+
452
+ policy "GenerateWhenRequested" do
453
+ on "Recipe.ProjectionRequested"
454
+ trigger Recipe::DeployToolchain::Generate, with: { run: :run }
455
+ end
456
+
457
+ policy "RecordTheRecipe" do
458
+ on "Recipe.RecipeAnswered"
459
+ trigger Recipe::Complete, with: { output: :output }
460
+ end
461
+
462
+ policy "RecordTheFaultedRecipe" do
463
+ on "Recipe.RecipeRefused"
464
+ trigger Recipe::Fault, with: { refusal: :refusal }
465
+ end
466
+
467
+ aggregate "MakefileCheck" do
468
+ description "One lint of generated deploy Makefiles for prod-touching recipes that hide failure."
469
+
470
+ attribute :run, RunKey
471
+ attribute :makefiles, PathList, optional: true
472
+ attribute :report, Report, optional: true
473
+ attribute :refusal, Report, optional: true
474
+ identified_by :run
475
+
476
+ value_object "RunKey" do
477
+ attribute :value, String, pattern: '[^ \t\n\r]'
478
+
479
+ invariant("a run is named") { !value.to_s.empty? }
480
+ end
481
+
482
+ # Makefile paths, comma separated; three generated fixture domains when absent.
483
+ value_object "PathList" do
484
+ attribute :value, String, pattern: '[^\t\n\r]'
485
+ end
486
+
487
+ value_object "Report" do
488
+ attribute :value, String
489
+ end
490
+
491
+ lifecycle :status, default: "requested" do
492
+ transition "Pass" => "clean", from: "requested"
493
+ transition "Flag" => "flagged", from: "requested"
494
+ end
495
+
496
+ # A pattern match over Make and shell text, not a static analyzer: the findings are the
497
+ # linter's own sentences, one per violation, and a run that finds any is flagged.
498
+ command "Lint" do
499
+ goal "Lint generated deploy Makefiles for recipes that hide the failure of a command that touches prod"
500
+
501
+ attribute :makefiles, PathList, optional: true
502
+ attribute :run, RunKey
503
+
504
+ sets :makefiles
505
+ sets :run
320
506
 
321
- emits "TenantDeclared"
507
+ emits "LintRequested"
322
508
  end
509
+
510
+ command "Pass" do
511
+ goal "Record that no recipe hides a failure"
512
+
513
+ reference_to MakefileCheck
514
+ attribute :report, Report
515
+
516
+ sets :report
517
+
518
+ emits "LintPassed"
519
+ end
520
+
521
+ command "Flag" do
522
+ goal "Record that a recipe hides a failure, or that the lint could not run, and what it said"
523
+
524
+ reference_to MakefileCheck
525
+ attribute :refusal, Report
526
+
527
+ sets :refusal
528
+
529
+ emits "LintFlagged"
530
+ end
531
+
532
+ query "Verdict" do
533
+ description "What one lint found: its status, and the report or the violations."
534
+ attribute :run, RunKey
535
+ where(run: :run)
536
+ order_by :run
537
+ end
538
+
539
+ query "Flagged" do
540
+ description "Every lint that left a violation or could not run."
541
+ where(status: "flagged")
542
+ order_by :run
543
+ end
544
+ end
545
+
546
+ policy "LintWhenRequested" do
547
+ on "MakefileCheck.LintRequested"
548
+ trigger MakefileCheck::DeployToolchain::Scan, with: { run: :run }
549
+ end
550
+
551
+ policy "RecordTheCleanLint" do
552
+ on "MakefileCheck.LintAnswered"
553
+ trigger MakefileCheck::Pass, with: { report: :report }
554
+ end
555
+
556
+ policy "RecordTheFlaggedLint" do
557
+ on "MakefileCheck.LintRefused"
558
+ trigger MakefileCheck::Flag, with: { refusal: :refusal }
559
+ end
560
+
561
+ aggregate "TemplateComparison" do
562
+ description "One offline comparison of two CloudFormation templates, by logical id."
563
+
564
+ attribute :before, Location
565
+ attribute :after, Location
566
+ attribute :run, RunKey
567
+ attribute :json, Switch, optional: true
568
+ attribute :strict, Switch, optional: true
569
+ attribute :report, Report, optional: true
570
+ attribute :refusal, Report, optional: true
571
+ identified_by :run
572
+
573
+ value_object "RunKey" do
574
+ attribute :value, String, pattern: '[^ \t\n\r]'
575
+
576
+ invariant("a run is named") { !value.to_s.empty? }
577
+ end
578
+
579
+ value_object "Location" do
580
+ attribute :value, String, pattern: '[^\t\n\r]'
581
+
582
+ invariant("a template is named by its path") { !value.to_s.empty? }
583
+ end
584
+
585
+ value_object "Switch" do
586
+ attribute :value, Boolean
587
+ end
588
+
589
+ value_object "Report" do
590
+ attribute :value, String
591
+ end
592
+
593
+ lifecycle :status, default: "requested" do
594
+ transition "Match" => "matching", from: "requested"
595
+ transition "Drift" => "drifted", from: "requested"
596
+ transition "Refuse" => "refused", from: "requested"
597
+ end
598
+
599
+ # `hecks deploy diff <before> after=<template> [--json] [--strict]`. `--strict` also counts
600
+ # cosmetic differences (comments, key order); `--json` writes the report as JSON.
601
+ command "Diff" do
602
+ goal "Compare two CloudFormation templates and report what differs by logical id"
603
+
604
+ attribute :before, Location
605
+ attribute :after, Location
606
+ attribute :run, RunKey
607
+ attribute :json, Switch, optional: true
608
+ attribute :strict, Switch, optional: true
609
+
610
+ sets :before
611
+ sets :after
612
+ sets :run
613
+ sets :json
614
+ sets :strict
615
+
616
+ emits "ComparisonRequested"
617
+ end
618
+
619
+ command "Match" do
620
+ goal "Record that the templates agree"
621
+
622
+ reference_to TemplateComparison
623
+ attribute :report, Report
624
+ attribute :different, Switch
625
+
626
+ given("the templates agree") { !different.value }
627
+
628
+ sets :report
629
+
630
+ emits "TemplatesMatched"
631
+ end
632
+
633
+ command "Drift" do
634
+ goal "Record that the templates differ, and how"
635
+
636
+ reference_to TemplateComparison
637
+ attribute :report, Report
638
+ attribute :different, Switch
639
+
640
+ given("the templates differ") { different.value }
641
+
642
+ sets :report
643
+
644
+ emits "TemplatesDrifted"
645
+ end
646
+
647
+ command "Refuse" do
648
+ goal "Record that a template could not be read, and why"
649
+
650
+ reference_to TemplateComparison
651
+ attribute :refusal, Report
652
+
653
+ sets :refusal
654
+
655
+ emits "ComparisonRefused"
656
+ end
657
+
658
+ query "Verdict" do
659
+ description "What one comparison found: its status, and the report or the reason it could not run."
660
+ attribute :run, RunKey
661
+ where(run: :run)
662
+ order_by :run
663
+ end
664
+
665
+ query "Drifted" do
666
+ description "Every comparison in which the templates differ."
667
+ where(status: "drifted")
668
+ order_by :run
669
+ end
670
+ end
671
+
672
+ policy "CompareWhenRequested" do
673
+ on "TemplateComparison.ComparisonRequested"
674
+ trigger TemplateComparison::DeployToolchain::Compare, with: { run: :run }
675
+ end
676
+
677
+ policy "RecordTheMatch" do
678
+ on "TemplateComparison.ComparisonAnswered"
679
+ trigger TemplateComparison::Match, with: { report: :report, different: :different }
680
+ end
681
+
682
+ policy "RecordTheDrift" do
683
+ on "TemplateComparison.ComparisonAnswered"
684
+ trigger TemplateComparison::Drift, with: { report: :report, different: :different }
685
+ end
686
+
687
+ policy "RecordTheRefusedComparison" do
688
+ on "TemplateComparison.ComparisonUnreadable"
689
+ trigger TemplateComparison::Refuse, with: { refusal: :refusal }
690
+ end
691
+
692
+ aggregate "OidcManifest" do
693
+ description "One projection of each domain's OIDC client and scope manifest into its oidc.json."
694
+
695
+ attribute :run, RunKey
696
+ attribute :domains, DomainList, optional: true
697
+ attribute :output, Report, optional: true
698
+ attribute :refusal, Report, optional: true
699
+ identified_by :run
700
+
701
+ value_object "RunKey" do
702
+ attribute :value, String, pattern: '[^ \t\n\r]'
703
+
704
+ invariant("a run is named") { !value.to_s.empty? }
705
+ end
706
+
707
+ # Domain directories, comma separated; every domain of the checkout when absent.
708
+ value_object "DomainList" do
709
+ attribute :value, String, pattern: '[^\t\n\r]'
710
+ end
711
+
712
+ value_object "Report" do
713
+ attribute :value, String
714
+ end
715
+
716
+ lifecycle :status, default: "requested" do
717
+ transition "Complete" => "projected", from: "requested"
718
+ transition "Fault" => "faulted", from: "requested"
719
+ end
720
+
721
+ command "ProjectOidc" do
722
+ goal "Write each domain's OIDC client and scope manifest beside it as oidc.json"
723
+
724
+ attribute :domains, DomainList, optional: true
725
+ attribute :run, RunKey
726
+
727
+ sets :domains
728
+ sets :run
729
+
730
+ emits "OidcProjectionRequested"
731
+ end
732
+
733
+ command "Complete" do
734
+ goal "Record which manifests were written"
735
+
736
+ reference_to OidcManifest
737
+ attribute :output, Report
738
+
739
+ sets :output
740
+
741
+ emits "OidcProjected"
742
+ end
743
+
744
+ command "Fault" do
745
+ goal "Record that the manifests could not be projected, and why"
746
+
747
+ reference_to OidcManifest
748
+ attribute :refusal, Report
749
+
750
+ sets :refusal
751
+
752
+ emits "OidcFaulted"
753
+ end
754
+
755
+ query "Outcome" do
756
+ description "What one projection did: its status, and the manifests written or the reason it stopped."
757
+ attribute :run, RunKey
758
+ where(run: :run)
759
+ order_by :run
760
+ end
761
+
762
+ query "Faulted" do
763
+ description "Every projection that could not write its manifests."
764
+ where(status: "faulted")
765
+ order_by :run
766
+ end
767
+ end
768
+
769
+ policy "ProjectWhenRequested" do
770
+ on "OidcManifest.OidcProjectionRequested"
771
+ trigger OidcManifest::DeployToolchain::Manifest, with: { run: :run }
772
+ end
773
+
774
+ policy "RecordTheManifests" do
775
+ on "OidcManifest.ManifestAnswered"
776
+ trigger OidcManifest::Complete, with: { output: :output }
777
+ end
778
+
779
+ policy "RecordTheFaultedManifests" do
780
+ on "OidcManifest.ManifestRefused"
781
+ trigger OidcManifest::Fault, with: { refusal: :refusal }
323
782
  end
324
783
  end