hecks 3.10.0 → 3.12.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 (542) hide show
  1. checksums.yaml +4 -4
  2. data/examples/pizzas/bluebook/pizzas.bluebook +29 -0
  3. data/examples/pizzas/bluebook/pizzas.hecksagon +7 -0
  4. data/exe/hecks +4 -4
  5. data/lib/hecks/adapters/driven/d1.rb +2 -10
  6. data/lib/hecks/adapters/driven/heki.adapter +1 -1
  7. data/lib/hecks/adapters/driven/heki.rb +2 -12
  8. data/lib/hecks/adapters/driven/lambda.adapter +1 -1
  9. data/lib/hecks/adapters/driven/lambda.rb +3 -18
  10. data/lib/hecks/adapters/driven/postgres.rb +4 -11
  11. data/lib/hecks/adapters/driven/sqlite.adapter +1 -1
  12. data/lib/hecks/adapters/driven/sqlite.rb +2 -10
  13. data/lib/hecks/adapters/driving/admission.rb +46 -0
  14. data/lib/hecks/adapters/driving/cli/nesting.rb +36 -0
  15. data/lib/hecks/adapters/driving/cli/shorthand.rb +88 -0
  16. data/lib/hecks/adapters/driving/cli.rb +127 -0
  17. data/lib/hecks/adapters/driving/cli_runner/answers.rb +160 -0
  18. data/lib/hecks/adapters/driving/cli_runner/resolution.rb +158 -0
  19. data/lib/hecks/adapters/driving/cli_runner/settling.rb +120 -0
  20. data/lib/hecks/adapters/driving/cli_runner/streaming.rb +93 -0
  21. data/lib/hecks/adapters/driving/cli_runner/suggestions.rb +47 -0
  22. data/lib/hecks/adapters/driving/cli_runner.rb +70 -0
  23. data/lib/hecks/adapters/driving/command_request.rb +121 -0
  24. data/lib/hecks/adapters/driving/handle.rb +214 -0
  25. data/lib/hecks/adapters/driving/json.rb +136 -0
  26. data/lib/hecks/adapters/driving/launcher_options.rb +267 -0
  27. data/lib/hecks/adapters/driving/mcp/properties.rb +49 -0
  28. data/lib/hecks/adapters/driving/mcp/tool_calls.rb +116 -0
  29. data/lib/hecks/adapters/driving/mcp/tool_definitions/auditing.rb +53 -0
  30. data/lib/hecks/adapters/driving/mcp/tool_definitions/calling.rb +71 -0
  31. data/lib/hecks/adapters/driving/mcp/tool_definitions/reading.rb +99 -0
  32. data/lib/hecks/adapters/driving/mcp/tool_definitions.rb +18 -0
  33. data/lib/hecks/adapters/driving/mcp.rb +159 -0
  34. data/lib/hecks/adapters/driving/mcp_guide_cache.rb +78 -0
  35. data/lib/hecks/adapters/driving/mcp_scope/argument_policy.rb +97 -0
  36. data/lib/hecks/adapters/driving/mcp_scope/env_problems.rb +69 -0
  37. data/lib/hecks/adapters/driving/mcp_scope/presenter.rb +83 -0
  38. data/lib/hecks/adapters/driving/mcp_scope.rb +213 -0
  39. data/lib/hecks/adapters/driving/newcomer.rb +50 -0
  40. data/lib/hecks/adapters/driving/ruby/aggregate_module.rb +171 -0
  41. data/lib/hecks/adapters/driving/ruby/chapter.rb +91 -0
  42. data/lib/hecks/adapters/driving/ruby.rb +83 -0
  43. data/lib/hecks/adapters/driving/usage_cache.rb +144 -0
  44. data/lib/hecks/{doors.rb → adapters/driving.rb} +10 -6
  45. data/lib/hecks/behaviors/expectations/boot.rb +1 -1
  46. data/lib/hecks/bench/ruby_runner.rb +1 -1
  47. data/lib/hecks/bluebook/ask_resolution.rb +130 -0
  48. data/lib/hecks/bluebook/assembly/aggregate_assembly.rb +8 -2
  49. data/lib/hecks/bluebook/assembly/contracts/read_models.rb +1 -1
  50. data/lib/hecks/bluebook/assembly/contracts/rules.rb +4 -2
  51. data/lib/hecks/bluebook/assembly/contracts/structure.rb +3 -1
  52. data/lib/hecks/bluebook/assembly/marks.rb +4 -15
  53. data/lib/hecks/bluebook/assembly/scalars.rb +39 -0
  54. data/lib/hecks/bluebook/attribute.rb +1 -1
  55. data/lib/hecks/bluebook/behaviour/command.rb +13 -8
  56. data/lib/hecks/bluebook/behaviour/policy.rb +30 -0
  57. data/lib/hecks/bluebook/capabilities/attribute_values.rb +72 -0
  58. data/lib/hecks/bluebook/capabilities.rb +91 -9
  59. data/lib/hecks/bluebook/domain_port.rb +16 -4
  60. data/lib/hecks/bluebook/dsl/adapter_builder.rb +18 -6
  61. data/lib/hecks/bluebook/dsl/binding_proxy.rb +13 -0
  62. data/lib/hecks/bluebook/dsl/bluebook_builder/validation/computed_sources.rb +98 -0
  63. data/lib/hecks/bluebook/dsl/bluebook_builder/validation/fan_out_rows.rb +42 -0
  64. data/lib/hecks/bluebook/dsl/bluebook_builder/validation/projected_fields.rb +14 -2
  65. data/lib/hecks/bluebook/dsl/bluebook_builder/validation/provisions.rb +69 -3
  66. data/lib/hecks/bluebook/dsl/bluebook_builder/validation/with_projections.rb +17 -10
  67. data/lib/hecks/bluebook/dsl/bluebook_builder/validation.rb +5 -0
  68. data/lib/hecks/bluebook/dsl/bootstrap_table.rb +2 -0
  69. data/lib/hecks/bluebook/dsl/command_builder/mutations.rb +8 -1
  70. data/lib/hecks/bluebook/dsl/command_builder/operands.rb +121 -0
  71. data/lib/hecks/bluebook/dsl/command_builder.rb +2 -0
  72. data/lib/hecks/bluebook/dsl/hecksagon_builder.rb +10 -1
  73. data/lib/hecks/bluebook/dsl/lifecycle_builder.rb +45 -2
  74. data/lib/hecks/bluebook/dsl/policy_builder.rb +47 -10
  75. data/lib/hecks/bluebook/dsl/rule_reference.rb +7 -4
  76. data/lib/hecks/bluebook/dsl/world_builder.rb +1 -1
  77. data/lib/hecks/bluebook/expression/ast_json/emitters.rb +6 -0
  78. data/lib/hecks/bluebook/expression/ast_json.rb +9 -6
  79. data/lib/hecks/bluebook/expression/ast_reader.rb +14 -9
  80. data/lib/hecks/bluebook/expression/projection.json +36 -0
  81. data/lib/hecks/bluebook/expression/resolver/operations.rb +31 -0
  82. data/lib/hecks/bluebook/expression/resolver/parsing.rb +38 -5
  83. data/lib/hecks/bluebook/expression/resolver/scanning.rb +22 -5
  84. data/lib/hecks/bluebook/expression/resolver/values.rb +10 -0
  85. data/lib/hecks/bluebook/expression/resolver.rb +20 -1
  86. data/lib/hecks/bluebook/hecksagon.rb +23 -3
  87. data/lib/hecks/bluebook/lifecycle.rb +22 -3
  88. data/lib/hecks/bluebook/meta_validator/adapter_judge.rb +13 -1
  89. data/lib/hecks/bluebook/meta_validator/modes.rb +4 -1
  90. data/lib/hecks/bluebook/meta_validator/readings.rb +24 -1
  91. data/lib/hecks/bluebook/meta_validator/reconstruction/heads.rb +2 -1
  92. data/lib/hecks/bluebook/meta_validator/reconstruction.rb +6 -3
  93. data/lib/hecks/bluebook/meta_validator/shapes.rb +5 -0
  94. data/lib/hecks/bluebook/meta_validator/verdict_cache.rb +1 -1
  95. data/lib/hecks/bluebook/meta_validator.rb +12 -12
  96. data/lib/hecks/bluebook/model_check/ask_checks.rb +71 -0
  97. data/lib/hecks/bluebook/model_check/policy_checks.rb +2 -1
  98. data/lib/hecks/bluebook/model_check/reference_checks.rb +70 -0
  99. data/lib/hecks/bluebook/model_check.rb +8 -2
  100. data/lib/hecks/bluebook/policy.rb +4 -2
  101. data/lib/hecks/bluebook/smoke_test.rb +1 -1
  102. data/lib/hecks/bluebook/synthesizer.rb +2 -0
  103. data/lib/hecks/bluebook.rb +2 -0
  104. data/lib/hecks/cli/command_table.rb +1 -1
  105. data/lib/hecks/cli/console.rb +2 -1
  106. data/lib/hecks/cli/document.rb +1 -1
  107. data/lib/hecks/cli/launcher_words.rb +4 -4
  108. data/lib/hecks/cli/mcp.rb +4 -4
  109. data/lib/hecks/cli/project_cli/launcher_source.rb +2 -2
  110. data/lib/hecks/cli/project_cli/templates.rb +5 -5
  111. data/lib/hecks/cli/project_cli.rb +9 -6
  112. data/lib/hecks/cli/run.rb +2 -2
  113. data/lib/hecks/cli/smoke_http/checks.rb +4 -1
  114. data/lib/hecks/cli/smoke_http/transport.rb +3 -3
  115. data/lib/hecks/cli/smoke_http.rb +3 -0
  116. data/lib/hecks/codemod.rb +5 -2
  117. data/lib/hecks/corpus/routes.rb +7 -0
  118. data/lib/hecks/corpus/rust.rb +3 -2
  119. data/lib/hecks/deploy/bluebook/deploy.bluebook +34 -4
  120. data/lib/hecks/doc/reference/rendering.rb +6 -3
  121. data/lib/hecks/forms/app/commands.rb +8 -7
  122. data/lib/hecks/forms/app/queries.rb +2 -1
  123. data/lib/hecks/forms/app.rb +1 -1
  124. data/lib/hecks/forms/record_renderer.rb +1 -1
  125. data/lib/hecks/framework/bluebook/privacy.bluebook +11 -0
  126. data/lib/hecks/fuzzing/concurrent_dispatch.rb +4 -1
  127. data/lib/hecks/fuzzing/failure_triage.rb +2 -1
  128. data/lib/hecks/fuzzing/mutation/run.rb +11 -4
  129. data/lib/hecks/fuzzing/properties/catalog.rb +6 -4
  130. data/lib/hecks/fuzzing/properties/guaranteed_by_construction.rb +18 -11
  131. data/lib/hecks/fuzzing/properties/guards.rb +1 -1
  132. data/lib/hecks/fuzzing/self_consistency/saga_redelivery.rb +1 -1
  133. data/lib/hecks/fuzzing/self_consistency.rb +6 -2
  134. data/lib/hecks/fuzzing/shrinker.rb +3 -1
  135. data/lib/hecks/fuzzing/value_generator.rb +19 -5
  136. data/lib/hecks/gate/stages.yml +33 -7
  137. data/lib/hecks/grammar/evolve.rb +1 -1
  138. data/lib/hecks/grammar/expression_operators.json +372 -0
  139. data/lib/hecks/grammar/operators.rb +3 -1
  140. data/lib/hecks/hecks/adapters/codebase/corpus_tasks.rb +10 -10
  141. data/lib/hecks/hecks/adapters/codebase/inspection/rubycritic.rb +35 -0
  142. data/lib/hecks/hecks/adapters/codebase/inspection.rb +104 -0
  143. data/lib/hecks/hecks/adapters/codebase/publishing.rb +2 -1
  144. data/lib/hecks/hecks/adapters/codebase/release_facts.rb +12 -2
  145. data/lib/hecks/hecks/adapters/codebase/source_tree.rb +2 -1
  146. data/lib/hecks/hecks/adapters/codebase/test_runner.rb +1 -1
  147. data/lib/hecks/hecks/adapters/cost_explorer.rb +8 -5
  148. data/lib/hecks/hecks/adapters/deploy_toolchain/statuses.rb +2 -1
  149. data/lib/hecks/hecks/adapters/finding_github.rb +13 -6
  150. data/lib/hecks/hecks/adapters/first_admin.rb +2 -2
  151. data/lib/hecks/hecks/adapters/github_rulesets.rb +6 -3
  152. data/lib/hecks/hecks/adapters/in_process_boot.rb +1 -1
  153. data/lib/hecks/hecks/adapters/journal_store/compaction.rb +1 -1
  154. data/lib/hecks/hecks/adapters/journal_store/edge_audit.rb +10 -20
  155. data/lib/hecks/hecks/adapters/journal_store/held_domain.rb +28 -5
  156. data/lib/hecks/hecks/adapters/local_files.rb +2 -2
  157. data/lib/hecks/hecks/adapters/rehearsal/audit_report.rb +107 -0
  158. data/lib/hecks/hecks/adapters/rehearsal/census.rb +71 -0
  159. data/lib/hecks/hecks/adapters/rehearsal/declaration.rb +133 -0
  160. data/lib/hecks/hecks/adapters/rehearsal/environment.rb +83 -0
  161. data/lib/hecks/hecks/adapters/rehearsal/inquiry.rb +142 -0
  162. data/lib/hecks/hecks/adapters/rehearsal/memory_store.rb +96 -0
  163. data/lib/hecks/hecks/adapters/rehearsal/postgres_census.rb +100 -0
  164. data/lib/hecks/hecks/adapters/rehearsal/postgres_reading.rb +69 -0
  165. data/lib/hecks/hecks/adapters/rehearsal/postgres_store.rb +133 -0
  166. data/lib/hecks/hecks/adapters/rehearsal/rows.rb +41 -0
  167. data/lib/hecks/hecks/adapters/rehearsal/rust_audit.rb +83 -0
  168. data/lib/hecks/hecks/adapters/rehearsal/subject.rb +104 -0
  169. data/lib/hecks/hecks/adapters/rehearsal.rb +54 -0
  170. data/lib/hecks/hecks/adapters/rehearsal_store.adapter +7 -0
  171. data/lib/hecks/hecks/adapters/rehearsal_store.rb +81 -0
  172. data/lib/hecks/hecks/adapters/terminal.rb +13 -11
  173. data/lib/hecks/hecks/codebase.behaviors +13 -1
  174. data/lib/hecks/hecks/codebase.bluebook +239 -5
  175. data/lib/hecks/hecks/custodian.behaviors +24 -6
  176. data/lib/hecks/hecks/custodian.bluebook +6 -1227
  177. data/lib/hecks/hecks/deploy.behaviors +1 -1
  178. data/lib/hecks/hecks/deploy.world +1 -3
  179. data/lib/hecks/hecks/hecks.behaviors +1 -1
  180. data/lib/hecks/hecks/hecks.hecksagon +53 -18
  181. data/lib/hecks/hecks/hecks.world +13 -10
  182. data/lib/hecks/hecks/rehearsal.bluebook +477 -0
  183. data/lib/hecks/hecks/site.behaviors +1 -1
  184. data/lib/hecks/hecks/site.world +0 -1
  185. data/lib/hecks/hecks/tooling.bluebook +1238 -0
  186. data/lib/hecks/indifferent_key.rb +20 -0
  187. data/lib/hecks/language/adapter.bluebook +13 -3
  188. data/lib/hecks/language/bluebook/aggregate.bluebook +23 -0
  189. data/lib/hecks/language/bluebook/bluebook.behaviors +23 -0
  190. data/lib/hecks/language/bluebook/bluebook.bluebook +15 -0
  191. data/lib/hecks/language/bluebook/entity.bluebook +18 -0
  192. data/lib/hecks/language/bluebook/policy.behaviors +19 -0
  193. data/lib/hecks/language/bluebook/policy.bluebook +9 -1
  194. data/lib/hecks/language/bluebook/query.bluebook +1 -1
  195. data/lib/hecks/language/bluebook/vocabulary.bluebook +63 -4
  196. data/lib/hecks/language/hecksagon/domain_port.bluebook +1 -1
  197. data/lib/hecks/language/hecksagon/hecksagon.bluebook +22 -0
  198. data/lib/hecks/language/oidc.json +10 -0
  199. data/lib/hecks/language/port.bluebook +4 -4
  200. data/lib/hecks/literal.rb +12 -3
  201. data/lib/hecks/ports/key_vault.rb +7 -2
  202. data/lib/hecks/ports/persistence/plugins/era/era_check.rb +21 -10
  203. data/lib/hecks/ports/persistence/plugins/era/postgres_era/boot.rb +4 -2
  204. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/era_resolver.rb +2 -1
  205. data/lib/hecks/ports/persistence/repository_factory.rb +6 -3
  206. data/lib/hecks/projection_files/expression_tables.rb +7 -2
  207. data/lib/hecks/projections/deploy/box/compose.rb +6 -4
  208. data/lib/hecks/projections/deploy/box/edge.rb +62 -0
  209. data/lib/hecks/projections/deploy/box/logging.rb +99 -0
  210. data/lib/hecks/projections/deploy/box/roll_scripts.rb +16 -8
  211. data/lib/hecks/projections/deploy/box/settings/cdn.rb +40 -0
  212. data/lib/hecks/projections/deploy/box/settings/logs.rb +40 -0
  213. data/lib/hecks/projections/deploy/box/settings/patterns.rb +11 -0
  214. data/lib/hecks/projections/deploy/box/settings/types.rb +16 -1
  215. data/lib/hecks/projections/deploy/box/settings.rb +6 -2
  216. data/lib/hecks/projections/deploy/box/stack_yaml.rb +5 -2
  217. data/lib/hecks/projections/deploy/box/templates/Makefile.tmpl +16 -0
  218. data/lib/hecks/projections/deploy/box/templates/box.yaml.tmpl +8 -4
  219. data/lib/hecks/projections/deploy/box/templates/deploy-box.sh.tmpl +32 -0
  220. data/lib/hecks/projections/deploy/box/templates/deploy-service.sh.tmpl +1 -1
  221. data/lib/hecks/projections/deploy/box/templates/edge.mk.tmpl +17 -0
  222. data/lib/hecks/projections/deploy/box/templates/edge.yaml.tmpl +65 -0
  223. data/lib/hecks/projections/deploy/box/templates/log-group.yaml.tmpl +12 -0
  224. data/lib/hecks/projections/deploy/box/templates/log-policy.yaml.tmpl +7 -0
  225. data/lib/hecks/projections/deploy/box/templates/render-compose-taskdef.sh.tmpl +5 -4
  226. data/lib/hecks/projections/deploy/box/templates/render-compose.sh.tmpl +5 -4
  227. data/lib/hecks/projections/deploy/box.rb +15 -3
  228. data/lib/hecks/projections/deploy/preview/preview.sh.erb +1 -1
  229. data/lib/hecks/projections/deploy/shared.rb +5 -2
  230. data/lib/hecks/projections/model/deviations.rb +2 -2
  231. data/lib/hecks/projections/model.rb +2 -2
  232. data/lib/hecks/projections/oidc.rb +13 -1
  233. data/lib/hecks/projections/shape.rb +5 -2
  234. data/lib/hecks/projections/site/cms_editor/attributes.rb +26 -6
  235. data/lib/hecks/projections/site/cms_editor/blocks.rb +157 -0
  236. data/lib/hecks/projections/site/cms_editor/checks.rb +14 -1
  237. data/lib/hecks/projections/site/cms_editor/clearing.rb +70 -0
  238. data/lib/hecks/projections/site/cms_editor/color.rb +124 -0
  239. data/lib/hecks/projections/site/cms_editor/composition.rb +42 -0
  240. data/lib/hecks/projections/site/cms_editor/destructive.rb +61 -0
  241. data/lib/hecks/projections/site/cms_editor/drafts.rb +102 -0
  242. data/lib/hecks/projections/site/cms_editor/hints.rb +74 -0
  243. data/lib/hecks/projections/site/cms_editor/icons.rb +86 -0
  244. data/lib/hecks/projections/site/cms_editor/key_kinds.rb +31 -0
  245. data/lib/hecks/projections/site/cms_editor/limits.rb +72 -0
  246. data/lib/hecks/projections/site/cms_editor/media.rb +1 -1
  247. data/lib/hecks/projections/site/cms_editor/moment.rb +34 -0
  248. data/lib/hecks/projections/site/cms_editor/palette.rb +115 -0
  249. data/lib/hecks/projections/site/cms_editor/pickers.rb +85 -0
  250. data/lib/hecks/projections/site/cms_editor/preview.rb +91 -0
  251. data/lib/hecks/projections/site/cms_editor/relations.rb +92 -0
  252. data/lib/hecks/projections/site/cms_editor/scale_checks.rb +66 -0
  253. data/lib/hecks/projections/site/cms_editor/scheduling.rb +150 -0
  254. data/lib/hecks/projections/site/cms_editor/schema.rb +96 -19
  255. data/lib/hecks/projections/site/cms_editor/setting.rb +52 -9
  256. data/lib/hecks/projections/site/cms_editor/targets.rb +86 -0
  257. data/lib/hecks/projections/site/cms_editor/templates/package.json.tmpl +18 -1
  258. data/lib/hecks/projections/site/cms_editor/templates/src/app.ts.tmpl +251 -57
  259. data/lib/hecks/projections/site/cms_editor/templates/src/assets.ts.tmpl +98 -0
  260. data/lib/hecks/projections/site/cms_editor/templates/src/auth/membership.ts.tmpl +32 -24
  261. data/lib/hecks/projections/site/cms_editor/templates/src/browser/app.css.tmpl +412 -0
  262. data/lib/hecks/projections/site/cms_editor/templates/src/browser/autosave.js.tmpl +144 -0
  263. data/lib/hecks/projections/site/cms_editor/templates/src/browser/blocks.js.tmpl +500 -0
  264. data/lib/hecks/projections/site/cms_editor/templates/src/browser/body_doc.js.tmpl +175 -0
  265. data/lib/hecks/projections/site/cms_editor/templates/src/browser/body_editor.js.tmpl +418 -0
  266. data/lib/hecks/projections/site/cms_editor/templates/src/browser/epoch.js.tmpl +61 -0
  267. data/lib/hecks/projections/site/cms_editor/templates/src/browser/forms.js.tmpl +210 -0
  268. data/lib/hecks/projections/site/cms_editor/templates/src/browser/lists.js.tmpl +40 -0
  269. data/lib/hecks/projections/site/cms_editor/templates/src/browser/main.js.tmpl +26 -0
  270. data/lib/hecks/projections/site/cms_editor/templates/src/browser/media_picker.js.tmpl +232 -0
  271. data/lib/hecks/projections/site/cms_editor/templates/src/browser/moments.js.tmpl +73 -0
  272. data/lib/hecks/projections/site/cms_editor/templates/src/browser/pickers.js.tmpl +152 -0
  273. data/lib/hecks/projections/site/cms_editor/templates/src/browser/preview.js.tmpl +98 -0
  274. data/lib/hecks/projections/site/cms_editor/templates/src/browser/shell.js.tmpl +140 -0
  275. data/lib/hecks/projections/site/cms_editor/templates/src/browser/toast.js.tmpl +66 -0
  276. data/lib/hecks/projections/site/cms_editor/templates/src/choices.ts.tmpl +99 -0
  277. data/lib/hecks/projections/site/cms_editor/templates/src/commands.ts.tmpl +78 -24
  278. data/lib/hecks/projections/site/cms_editor/templates/src/config.ts.tmpl +6 -0
  279. data/lib/hecks/projections/site/cms_editor/templates/src/flash.ts.tmpl +52 -0
  280. data/lib/hecks/projections/site/cms_editor/templates/src/host.ts.tmpl +19 -2
  281. data/lib/hecks/projections/site/cms_editor/templates/src/media/handler.ts.tmpl +31 -8
  282. data/lib/hecks/projections/site/cms_editor/templates/src/names.ts.tmpl +36 -0
  283. data/lib/hecks/projections/site/cms_editor/templates/src/schema.ts.tmpl +131 -2
  284. data/lib/hecks/projections/site/cms_editor/templates/src/ui/availability.ts.tmpl +15 -0
  285. data/lib/hecks/projections/site/cms_editor/templates/src/ui/block_list.js.tmpl +213 -0
  286. data/lib/hecks/projections/site/cms_editor/templates/src/ui/blocks.ts.tmpl +275 -0
  287. data/lib/hecks/projections/site/cms_editor/templates/src/ui/body_model.js.tmpl +8 -5
  288. data/lib/hecks/projections/site/cms_editor/templates/src/ui/detail.ts.tmpl +88 -0
  289. data/lib/hecks/projections/site/cms_editor/templates/src/ui/dialogs.ts.tmpl +43 -0
  290. data/lib/hecks/projections/site/cms_editor/templates/src/ui/fields.ts.tmpl +229 -34
  291. data/lib/hecks/projections/site/cms_editor/templates/src/ui/html.ts.tmpl +40 -81
  292. data/lib/hecks/projections/site/cms_editor/templates/src/ui/icons.ts.tmpl +15 -0
  293. data/lib/hecks/projections/site/cms_editor/templates/src/ui/input.ts.tmpl +29 -12
  294. data/lib/hecks/projections/site/cms_editor/templates/src/ui/links.ts.tmpl +100 -0
  295. data/lib/hecks/projections/site/cms_editor/templates/src/ui/moments.ts.tmpl +44 -0
  296. data/lib/hecks/projections/site/cms_editor/templates/src/ui/outline.ts.tmpl +53 -17
  297. data/lib/hecks/projections/site/cms_editor/templates/src/ui/pages.ts.tmpl +178 -88
  298. data/lib/hecks/projections/site/cms_editor/templates/src/ui/paging.ts.tmpl +82 -0
  299. data/lib/hecks/projections/site/cms_editor/templates/src/ui/pickers.ts.tmpl +110 -0
  300. data/lib/hecks/projections/site/cms_editor/templates/src/ui/preview.ts.tmpl +87 -0
  301. data/lib/hecks/projections/site/cms_editor/templates/src/ui/related.ts.tmpl +97 -0
  302. data/lib/hecks/projections/site/cms_editor/templates/src/ui/schedule.ts.tmpl +160 -0
  303. data/lib/hecks/projections/site/cms_editor/templates/src/ui/shell.ts.tmpl +211 -0
  304. data/lib/hecks/projections/site/cms_editor/templates/src/ui/table.ts.tmpl +151 -0
  305. data/lib/hecks/projections/site/cms_editor/templates/src/ui/theme.js.tmpl +16 -0
  306. data/lib/hecks/projections/site/cms_editor/templates/src/ui/values.ts.tmpl +69 -0
  307. data/lib/hecks/projections/site/cms_editor/templates/src/ui/words.ts.tmpl +97 -0
  308. data/lib/hecks/projections/site/cms_editor/templates/src/ui/world.ts.tmpl +35 -0
  309. data/lib/hecks/projections/site/cms_editor/templates/tsconfig.json.tmpl +2 -1
  310. data/lib/hecks/projections/site/cms_editor/theme.rb +29 -0
  311. data/lib/hecks/projections/site/cms_editor/theme_checks.rb +57 -0
  312. data/lib/hecks/projections/site/cms_editor.rb +49 -23
  313. data/lib/hecks/projections/site/role_probe.rb +2 -0
  314. data/lib/hecks/projections/site/site_root/workflow.rb +5 -0
  315. data/lib/hecks/projector/cli_audience.rb +22 -1
  316. data/lib/hecks/projector/cli_projector/listing.rb +1 -1
  317. data/lib/hecks/projector/cli_projector/option_specs.rb +1 -1
  318. data/lib/hecks/projector/cli_projector/usage.rb +15 -4
  319. data/lib/hecks/projector/docs_projector/closing.rb +1 -1
  320. data/lib/hecks/projector/docs_projector.rb +1 -1
  321. data/lib/hecks/projector/exporter/bindings.rb +40 -10
  322. data/lib/hecks/projector/exporter/capability_values.rb +55 -0
  323. data/lib/hecks/projector/narrate_projector/reactions.rb +1 -1
  324. data/lib/hecks/projector/target.rb +11 -0
  325. data/lib/hecks/projector.rb +32 -5
  326. data/lib/hecks/quality_control/adapters/github_checks.rb +12 -8
  327. data/lib/hecks/quality_control/adapters/github_issues.rb +8 -4
  328. data/lib/hecks/quality_control/cli/qa_open_pr.rb +2 -2
  329. data/lib/hecks/quality_control/cli/qa_sweep/checks/shrinking.rb +1 -1
  330. data/lib/hecks/quality_control/cli/qa_sweep/finding_report.rb +1 -1
  331. data/lib/hecks/quality_control/cli/qa_sweep.rb +1 -1
  332. data/lib/hecks/quality_control/quality_control.bluebook +6 -2
  333. data/lib/hecks/release/approval.rb +64 -0
  334. data/lib/hecks/router/{door.rb → aggregate_reader.rb} +5 -4
  335. data/lib/hecks/router/namespace_installer.rb +16 -16
  336. data/lib/hecks/router.rb +1 -1
  337. data/lib/hecks/runtime/best_effort.rb +22 -0
  338. data/lib/hecks/runtime/command_interpreter/mutation_applier.rb +12 -2
  339. data/lib/hecks/runtime/command_interpreter.rb +3 -2
  340. data/lib/hecks/runtime/command_rules/emission.rb +1 -1
  341. data/lib/hecks/runtime/dispatcher.rb +4 -4
  342. data/lib/hecks/runtime/entity_element/location.rb +1 -1
  343. data/lib/hecks/runtime/event.rb +5 -0
  344. data/lib/hecks/runtime/identity.rb +7 -6
  345. data/lib/hecks/runtime/interpreting.rb +2 -1
  346. data/lib/hecks/runtime/invocation_builder.rb +1 -1
  347. data/lib/hecks/runtime/loader/boot_steps.rb +8 -5
  348. data/lib/hecks/runtime/loader.rb +10 -10
  349. data/lib/hecks/runtime/policy_interpreter/arguments.rb +7 -4
  350. data/lib/hecks/runtime/policy_interpreter/fan_out.rb +3 -3
  351. data/lib/hecks/runtime/policy_interpreter.rb +6 -6
  352. data/lib/hecks/runtime/port_operation_interpreter.rb +1 -1
  353. data/lib/hecks/runtime/reaction_invocation.rb +1 -1
  354. data/lib/hecks/runtime/rebuild_sweep.rb +11 -1
  355. data/lib/hecks/runtime/registry/ask_verification.rb +35 -0
  356. data/lib/hecks/runtime/registry/hecksagon_rules.rb +10 -0
  357. data/lib/hecks/runtime/registry/merging.rb +1 -1
  358. data/lib/hecks/runtime/registry/providers.rb +16 -0
  359. data/lib/hecks/runtime/registry/read_repository.rb +6 -4
  360. data/lib/hecks/runtime/registry/verification.rb +4 -1
  361. data/lib/hecks/runtime/registry/world_defaults.rb +29 -0
  362. data/lib/hecks/runtime/registry.rb +1 -1
  363. data/lib/hecks/runtime/saga_interpreter/compensation.rb +1 -1
  364. data/lib/hecks/runtime/saga_interpreter/delivery.rb +4 -4
  365. data/lib/hecks/runtime/saga_interpreter/transitions.rb +1 -1
  366. data/lib/hecks/runtime/saga_interpreter.rb +3 -3
  367. data/lib/hecks/runtime/tenant_check.rb +5 -4
  368. data/lib/hecks/runtime/value/coercion.rb +2 -2
  369. data/lib/hecks/runtime/value/validation.rb +16 -4
  370. data/lib/hecks/runtime.rb +9 -9
  371. data/lib/hecks/rust_build/host.rb +11 -4
  372. data/lib/hecks/rust_build/prebuilt_binary.rb +101 -0
  373. data/lib/hecks/rust_build/project_rust/target_ir.rb +1 -1
  374. data/lib/hecks/rust_build/wasm.rb +1 -1
  375. data/lib/hecks/rust_build/wasm_browser.rb +1 -1
  376. data/lib/hecks/rust_build.rb +11 -0
  377. data/lib/hecks/served_options.rb +53 -0
  378. data/lib/hecks/site/bluebook/site.bluebook +1 -0
  379. data/lib/hecks/storehouse/audit.rb +1 -1
  380. data/lib/hecks/storehouse/dispatching.rb +8 -6
  381. data/lib/hecks/storehouse/introspection.rb +2 -2
  382. data/lib/hecks/storehouse/querying.rb +6 -4
  383. data/lib/hecks/storehouse.rb +4 -4
  384. data/lib/hecks/tools/ci_gate_decision.rb +35 -0
  385. data/lib/hecks/tools/ci_gates.rb +20 -1
  386. data/lib/hecks/tools/comment_style/source_file.rb +4 -1
  387. data/lib/hecks/tools/deploy_recipe_lint/fixtures.rb +4 -1
  388. data/lib/hecks/tools/lanes/files.rb +8 -0
  389. data/lib/hecks/tools/lanes/prebuilt_workflow.rb +81 -0
  390. data/lib/hecks/tools/lanes/rows.rb +6 -0
  391. data/lib/hecks/tools/lanes.rb +1 -0
  392. data/lib/hecks/tools/oidc_manifests.rb +4 -5
  393. data/lib/hecks/tools/regeneration_run.rb +11 -4
  394. data/lib/hecks/tools/release_only.rb +111 -0
  395. data/lib/hecks/tools/site_routes/editor_files.rb +12 -5
  396. data/lib/hecks/tools/tenant_provisioning.rb +2 -2
  397. data/lib/hecks/tools/tools_doc.rb +4 -4
  398. data/lib/hecks/version.rb +1 -1
  399. data/lib/hecks/vocabulary.rb +19 -5
  400. data/lib/hecks.rb +15 -15
  401. data/lib/rubocop/cop/hecks/env_dump.rb +69 -0
  402. data/lib/rubocop/cop/hecks/monotonic_duration.rb +53 -0
  403. data/lib/rubocop/cop/hecks/no_wall_clock_in_runtime.rb +34 -0
  404. data/lib/rubocop/cop/hecks/raw_shell_interpolation.rb +79 -0
  405. data/lib/rubocop/cop/hecks/sleep_in_spec.rb +34 -0
  406. data/lib/rubocop/cop/hecks/swallowed_rescue.rb +37 -0
  407. data/lib/rubocop/cop/hecks/symbol_string_key_mix.rb +50 -0
  408. data/lib/rubocop/cop/hecks/untyped_raise.rb +37 -0
  409. data/prebuilt/9ee54e2f0d4d6d3fe046827779b221e02de665fba911a048ae5dd8b8fbfb7d90.marshal +0 -0
  410. data/prebuilt/d74a00e996222c1d8b676d5959092effc46b4dc59e0555f3bf9554ac58e3094a.marshal +0 -0
  411. data/prebuilt/verdicts-df19f35868d3284a70f55e42dcef87ef4e65e6a678e5135f72e1f6cff4c1357b.json +1 -0
  412. data/rust/.gitignore +6 -0
  413. data/rust/Cargo.toml +6 -0
  414. data/rust/build/src/binding_pass.rs +103 -0
  415. data/rust/build/src/cargo_sync.rs +6 -0
  416. data/rust/build/src/lineage_pass.rs +3 -3
  417. data/rust/build/src/main.rs +17 -5
  418. data/rust/build/src/pipeline.rs +48 -5
  419. data/rust/build/src/seams_pass.rs +123 -0
  420. data/rust/build/src/translation_pass.rs +167 -0
  421. data/rust/codegen/src/asks.rs +103 -0
  422. data/rust/codegen/src/commands.rs +13 -8
  423. data/rust/codegen/src/constraints.rs +25 -0
  424. data/rust/codegen/src/domain_generator.rs +2 -0
  425. data/rust/codegen/src/expr_emitter.rs +13 -0
  426. data/rust/codegen/src/json_codec.rs +54 -15
  427. data/rust/codegen/src/main.rs +1 -0
  428. data/rust/codegen/src/mutations.rs +128 -3
  429. data/rust/codegen/src/queries.rs +11 -2
  430. data/rust/codegen/src/reactions.rs +1 -1
  431. data/rust/codegen/src/types.rs +166 -8
  432. data/rust/host/HECKS_RELEASE +1 -1
  433. data/rust/host/src/api.rs +4 -4
  434. data/rust/host/src/bin/validate_harness.rs +43 -0
  435. data/rust/host/src/boundary_fuzz/expr_json.rs +2 -2
  436. data/rust/host/src/boundary_fuzz/ir.rs +1 -0
  437. data/rust/host/src/boundary_fuzz/server.rs +1 -1
  438. data/rust/host/src/checkout.rs +35 -19
  439. data/rust/host/src/commerce_ir.rs +408 -2
  440. data/rust/host/src/expr_json.rs +118 -0
  441. data/rust/host/src/extension.rs +13 -1
  442. data/rust/host/src/lib.rs +1 -0
  443. data/rust/host/src/mint.rs +1 -1
  444. data/rust/host/src/payments/tests.rs +27 -1
  445. data/rust/host/src/payments.rs +12 -4
  446. data/rust/host/src/platform_signin/attack_tests.rs +1100 -0
  447. data/rust/host/src/platform_signin/config.rs +512 -0
  448. data/rust/host/src/platform_signin/cookie.rs +237 -0
  449. data/rust/host/src/platform_signin/extension.rs +190 -0
  450. data/rust/host/src/platform_signin/fetcher.rs +322 -0
  451. data/rust/host/src/platform_signin/handler.rs +251 -0
  452. data/rust/host/src/platform_signin/handler_tests.rs +554 -0
  453. data/rust/host/src/platform_signin/jti.rs +196 -0
  454. data/rust/host/src/platform_signin/jwks.rs +542 -0
  455. data/rust/host/src/platform_signin/jws.rs +249 -0
  456. data/rust/host/src/platform_signin/known_answer_tests.rs +237 -0
  457. data/rust/host/src/platform_signin/mapping_tests.rs +254 -0
  458. data/rust/host/src/platform_signin/mod.rs +75 -0
  459. data/rust/host/src/platform_signin/mode_tests.rs +382 -0
  460. data/rust/host/src/platform_signin/pages.rs +204 -0
  461. data/rust/host/src/platform_signin/query.rs +233 -0
  462. data/rust/host/src/platform_signin/session.rs +151 -0
  463. data/rust/host/src/platform_signin/settings.rs +385 -0
  464. data/rust/host/src/platform_signin/strict_json.rs +351 -0
  465. data/rust/host/src/platform_signin/test_support.rs +235 -0
  466. data/rust/host/src/platform_signin/ttl_tests.rs +94 -0
  467. data/rust/host/src/platform_signin/verify.rs +604 -0
  468. data/rust/host/src/platform_signin/wiring_support.rs +319 -0
  469. data/rust/host/src/query_step.rs +22 -4
  470. data/rust/host/src/reference_validate.rs +653 -108
  471. data/rust/host/src/resend.rs +2 -0
  472. data/rust/host/src/server.rs +19 -6
  473. data/rust/host/src/ui_schema.rs +132 -5
  474. data/rust/host/src/web/newsletter.rs +7 -8
  475. data/rust/host/src/web/newsletter_send.rs +38 -13
  476. data/rust/host/src/web/registrations.rs +229 -26
  477. data/rust/host/src/web.rs +53 -9
  478. data/rust/parser/src/emit.rs +38 -6
  479. data/rust/parser/src/expr/ast_json.rs +7 -1
  480. data/rust/parser/src/expr/resolver.rs +171 -6
  481. data/rust/parser/src/ir.rs +7 -0
  482. data/rust/parser/src/keywords.rs +24 -0
  483. data/rust/parser/src/main.rs +3 -0
  484. data/rust/parser/src/parse/aggregate.rs +2 -1
  485. data/rust/parser/src/parse/chapter.rs +2 -2
  486. data/rust/parser/src/parse/command.rs +2 -0
  487. data/rust/parser/src/parse/hecksagon.rs +5 -2
  488. data/rust/parser/src/parse/lifecycle.rs +81 -0
  489. data/rust/parser/src/parse/mod.rs +15 -1
  490. data/rust/parser/src/parse/policy.rs +13 -2
  491. data/rust/parser/src/parse/value_object.rs +34 -17
  492. data/rust/parser/src/ruby_value.rs +1 -1
  493. data/rust/src/exemplar/commands.rs +4 -4
  494. data/rust/src/exemplar/constraints.rs +1 -1
  495. data/rust/src/exemplar/json.rs +43 -1
  496. data/rust/src/kernel/cli.rs +7 -5
  497. data/rust/src/kernel/dispatch.rs +2 -2
  498. data/rust/src/kernel/dispatch_guard_tests.rs +1 -1
  499. data/rust/src/kernel/expr.rs +66 -3
  500. data/rust/src/kernel/expression_operators/arithmetic.rs +130 -5
  501. data/rust/src/kernel/expression_operators/text.rs +26 -2
  502. data/rust/src/kernel/json.rs +15 -0
  503. data/rust/src/kernel/mod.rs +1 -1
  504. data/rust/src/kernel/orchestrate.rs +54 -5
  505. data/rust/src/kernel/orchestrate_guard_tests.rs +67 -0
  506. data/rust/src/kernel/pattern.rs +60 -0
  507. data/rust/src/kernel/reference_lookup.rs +90 -7
  508. metadata +178 -38
  509. data/lib/hecks/doors/cli_door/nesting.rb +0 -34
  510. data/lib/hecks/doors/cli_door/shorthand.rb +0 -85
  511. data/lib/hecks/doors/cli_door.rb +0 -124
  512. data/lib/hecks/doors/cli_runner/answers.rb +0 -138
  513. data/lib/hecks/doors/cli_runner/resolution.rb +0 -146
  514. data/lib/hecks/doors/cli_runner/settling.rb +0 -115
  515. data/lib/hecks/doors/cli_runner/streaming.rb +0 -90
  516. data/lib/hecks/doors/cli_runner/suggestions.rb +0 -43
  517. data/lib/hecks/doors/cli_runner.rb +0 -66
  518. data/lib/hecks/doors/command_request.rb +0 -119
  519. data/lib/hecks/doors/handle.rb +0 -208
  520. data/lib/hecks/doors/json_door.rb +0 -132
  521. data/lib/hecks/doors/launcher_options.rb +0 -247
  522. data/lib/hecks/doors/mcp_door/properties.rb +0 -47
  523. data/lib/hecks/doors/mcp_door/tool_calls.rb +0 -113
  524. data/lib/hecks/doors/mcp_door/tool_definitions/auditing.rb +0 -51
  525. data/lib/hecks/doors/mcp_door/tool_definitions/calling.rb +0 -69
  526. data/lib/hecks/doors/mcp_door/tool_definitions/reading.rb +0 -97
  527. data/lib/hecks/doors/mcp_door/tool_definitions.rb +0 -15
  528. data/lib/hecks/doors/mcp_door.rb +0 -156
  529. data/lib/hecks/doors/mcp_door_scope/argument_policy.rb +0 -92
  530. data/lib/hecks/doors/mcp_door_scope/env_problems.rb +0 -55
  531. data/lib/hecks/doors/mcp_door_scope/presenter.rb +0 -78
  532. data/lib/hecks/doors/mcp_door_scope.rb +0 -201
  533. data/lib/hecks/doors/mcp_guide_cache.rb +0 -75
  534. data/lib/hecks/doors/ruby_door/aggregate_door.rb +0 -162
  535. data/lib/hecks/doors/ruby_door/chapter.rb +0 -89
  536. data/lib/hecks/doors/ruby_door.rb +0 -80
  537. data/lib/hecks/doors/usage_cache.rb +0 -139
  538. data/lib/hecks/projections/site/cms_editor/templates/src/ui/body_widget.js.tmpl +0 -282
  539. data/lib/hecks/projections/site/cms_editor/templates/src/ui/media_picker.js.tmpl +0 -109
  540. data/prebuilt/c28d6d9db14eea3e17161e9d9c262efee30b256cf97693a7cfd552bce24b2f7f.marshal +0 -0
  541. data/prebuilt/cb375cba61ca0dbe8ddb9739c306510fe05e5f4b7a9b6955caff8224c63ea0e0.marshal +0 -0
  542. data/prebuilt/verdicts-d6d584ad43b5f3cebf88aafbbdbf024c38574acf18e06adffbc555f7786b1c2f.json +0 -1
@@ -0,0 +1,70 @@
1
+ module Hecks
2
+ module Bluebook
3
+ module ModelCheck
4
+ # The checks over how aggregates relate: an attribute that copies another aggregate's
5
+ # identity by value, where `reference_to` would state the link and have it enforced.
6
+ module ReferenceChecks
7
+ # Types that name no aggregate's identity, however many aggregates declare one of them.
8
+ PRIMITIVE_TYPES = %w[String Integer Float Boolean Date DateTime Time Symbol JSON Hash Array].freeze
9
+
10
+ # Flags each scalar attribute whose type is the identity type of another aggregate in
11
+ # this domain and that is not itself a reference: the link exists only by convention.
12
+ #
13
+ # @param bluebook [Bluebook::Chapter] the assembled chapter to check
14
+ # @return [Array<Finding>] one :key_by_value warning per such attribute
15
+ def key_by_value_findings(bluebook)
16
+ owners = identity_type_owners(bluebook)
17
+ bluebook.aggregates.flat_map do |aggregate|
18
+ aggregate.attributes.filter_map { |attribute| key_by_value_finding(aggregate, attribute, owners) }
19
+ end
20
+ end
21
+
22
+ # @return [Hash{String => Array<String>}] each identity attribute's type, to the names
23
+ # of the aggregates whose identity it is
24
+ def identity_type_owners(bluebook)
25
+ bluebook.aggregates.each_with_object(Hash.new { |hash, key| hash[key] = [] }) do |aggregate, owners|
26
+ identity_types(aggregate).each { |type| owners[type] << aggregate.hecks_name }
27
+ end
28
+ end
29
+
30
+ # A composite identity is several facts (a timestamp among them is no key to copy), so
31
+ # only a single-head identity counts.
32
+ #
33
+ # @return [Array<String>] the type of the aggregate's identity attribute, if it has
34
+ # exactly one and it is neither a reference, a list nor a primitive
35
+ def identity_types(aggregate)
36
+ return [] unless aggregate.identity_heads.size == 1
37
+
38
+ attribute = aggregate.attribute(aggregate.identity_heads.first)
39
+ attribute && valued_attribute?(attribute) ? [attribute.type.to_s] : []
40
+ end
41
+
42
+ # @return [Boolean] whether the attribute is one scalar of a named, non-primitive type
43
+ def valued_attribute?(attribute)
44
+ return false if attribute.reference? || attribute.list?
45
+
46
+ !PRIMITIVE_TYPES.include?(attribute.type.to_s)
47
+ end
48
+
49
+ # An owner's single identity attribute is the key itself; being one head of a composite
50
+ # identity is not, since that aggregate still copies the key by value.
51
+ def own_identity?(aggregate, attribute)
52
+ aggregate.identity_heads == [attribute.name.to_sym]
53
+ end
54
+
55
+ def key_by_value_finding(aggregate, attribute, owners)
56
+ return unless valued_attribute?(attribute)
57
+ return if own_identity?(aggregate, attribute)
58
+
59
+ target = (owners.fetch(attribute.type.to_s, []) - [aggregate.hecks_name]).first
60
+ return unless target
61
+
62
+ Finding.new(kind: :key_by_value, severity: :warning,
63
+ subject: "#{aggregate.hecks_name}.#{attribute.name}",
64
+ message: "#{attribute.type} matches #{target}'s identity by value, " \
65
+ "so nothing enforces the link; use reference_to #{target}")
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
@@ -4,6 +4,8 @@ require_relative "model_check/client_profile"
4
4
  require_relative "model_check/lifecycle_checks"
5
5
  require_relative "model_check/saga_checks"
6
6
  require_relative "model_check/policy_checks"
7
+ require_relative "model_check/ask_checks"
8
+ require_relative "model_check/reference_checks"
7
9
  require_relative "model_check/verbs"
8
10
 
9
11
  module Hecks
@@ -32,6 +34,8 @@ module Hecks
32
34
  extend LifecycleChecks
33
35
  extend SagaChecks
34
36
  extend PolicyChecks
37
+ extend AskChecks
38
+ extend ReferenceChecks
35
39
  extend Verbs
36
40
 
37
41
  module_function
@@ -59,15 +63,17 @@ module Hecks
59
63
  findings
60
64
  end
61
65
 
62
- # Lifecycles, sagas and policies: what the model says about itself.
66
+ # Lifecycles, sagas, policies and references: what the model says about itself.
63
67
  def modelled_findings(bluebook, options)
64
68
  [
65
69
  *bluebook.aggregates.flat_map { |aggregate| aggregate_lifecycle_findings(aggregate) },
70
+ *key_by_value_findings(bluebook),
66
71
  *bluebook.process_managers.flat_map { |process_manager| saga_findings(bluebook, process_manager) },
67
72
  *bluebook.policies.flat_map do |policy|
68
73
  policy_findings(bluebook, policy, options[:hecksagon], options[:known_domains],
69
74
  options[:global_emitted_events])
70
- end
75
+ end,
76
+ *unused_ask_findings(bluebook)
71
77
  ]
72
78
  end
73
79
 
@@ -13,6 +13,7 @@ module Hecks
13
13
  name: :name,
14
14
  on_event: :on_event,
15
15
  trigger_command: :trigger_command,
16
+ ask: :ask,
16
17
  target_domain: :target_domain,
17
18
  expect_undelivered: :expect_undelivered,
18
19
  where: :where,
@@ -21,17 +22,18 @@ module Hecks
21
22
  where_ast: -> { where_ast }
22
23
  )
23
24
 
24
- attr_reader :name, :on_event, :trigger_command, :target_domain, :expect_undelivered, :where, :for_each, :with_spec
25
+ attr_reader :name, :on_event, :trigger_command, :ask, :target_domain, :expect_undelivered, :where, :for_each, :with_spec
25
26
 
26
27
  # Aggregate, declared and deliberately off the wire
27
28
  # the wire format is a pinned contract, and it does not carry
28
29
  # where a policy was written before the builder hoisted it
29
30
  attr_accessor :aggregate
30
31
 
31
- def initialize(name:, on_event: nil, trigger_command: nil, target_domain: nil, expect_undelivered: false, where: nil, for_each: nil, with_spec: [], aggregate: nil)
32
+ def initialize(name:, on_event: nil, trigger_command: nil, ask: nil, target_domain: nil, expect_undelivered: false, where: nil, for_each: nil, with_spec: [], aggregate: nil)
32
33
  @name = name.to_s
33
34
  @on_event = on_event
34
35
  @trigger_command = trigger_command
36
+ @ask = ask
35
37
  @target_domain = target_domain
36
38
  @expect_undelivered = expect_undelivered.to_s == "true"
37
39
  @where = where
@@ -27,7 +27,7 @@ module Hecks
27
27
  def call(dir)
28
28
  Dir.mktmpdir("hecks-smoke-") do |scratch|
29
29
  isolate!(dir, scratch)
30
- dispatcher = Hecks.boot(scratch, install_doors: false)
30
+ dispatcher = Hecks.boot(scratch, install_driving: false)
31
31
  domain = dispatcher.registry.bluebooks.keys.first
32
32
  next [] unless domain
33
33
 
@@ -1,3 +1,5 @@
1
+ require_relative "attribute"
2
+
1
3
  module Hecks
2
4
  module Bluebook
3
5
  # Synthesizes one argument per declared attribute from the IR: fixed markers for scalars,
@@ -25,6 +25,7 @@ require_relative "bluebook/read_model"
25
25
  require_relative "bluebook/entity"
26
26
  require_relative "bluebook/domain_port"
27
27
  require_relative "bluebook/policy"
28
+ require_relative "bluebook/ask_resolution"
28
29
  require_relative "bluebook/process_manager"
29
30
  require_relative "bluebook/aggregate"
30
31
  require_relative "bluebook/hecksagon"
@@ -34,6 +35,7 @@ require_relative "bluebook/assembly/contract"
34
35
  require_relative "bluebook/assembly/contracts"
35
36
  require_relative "bluebook/assembly/specializer"
36
37
  require_relative "bluebook/assembly/build"
38
+ require_relative "bluebook/assembly/scalars"
37
39
  require_relative "bluebook/assembly/marks"
38
40
  require_relative "bluebook/assembly/aggregate_assembly"
39
41
  require_relative "bluebook/assembly"
@@ -62,7 +62,7 @@ module Hecks
62
62
  ->(argv, program, _name) { ProjectCli.call(argv, program: program, root: Dir.pwd, remove_stale_bin: false) }
63
63
  ),
64
64
  "mcp" => Command.new(
65
- "Serve the MCP door over stdio (no authentication; stdio only).",
65
+ "Serve the MCP server over stdio (no authentication; stdio only).",
66
66
  "hecks mcp [--stdio]",
67
67
  "cli/mcp",
68
68
  ->(argv, _program, _name) { Mcp.call(argv) }
@@ -7,7 +7,8 @@ require_relative "../ports/persistence/plugins/era"
7
7
  module Hecks
8
8
  module CLI
9
9
  # The command behind `hecks console` and Custodian's `Operation.OpenConsole`: boots a domain
10
- # (pizzas on Memory by default) and drops into IRB with its door installed, for dispatching a
10
+ # (pizzas on Memory by default) and drops into IRB with its Ruby adapter installed, for
11
+ # dispatching a
11
12
  # real command by hand. No argument needs no database (ADR 0073); a domain directory boots as
12
13
  # it is wired, which may bind PostgresEra (examples/directory does).
13
14
  module Console
@@ -44,7 +44,7 @@ module Hecks
44
44
  # @api private
45
45
  def boot_bluebook(path)
46
46
  begin
47
- runtime = Hecks.boot(path, install_doors: false)
47
+ runtime = Hecks.boot(path, install_driving: false)
48
48
  rescue StandardError => e
49
49
  abort "cannot read #{path}: #{e.message.lines.first.strip}"
50
50
  end
@@ -57,7 +57,7 @@ module Hecks
57
57
  def launcher_words(name, rest)
58
58
  return [rest, nil] if UNTOUCHED.include?(name)
59
59
 
60
- require_relative "../doors/cli_door"
60
+ require_relative "../adapters/driving/cli"
61
61
  words = strip_generic(rest)
62
62
  form = LAUNCHER_FORMS[name]
63
63
  return [words, nil] unless form && words.any? { |word| word.match?(NAME_VALUE) }
@@ -133,7 +133,7 @@ module Hecks
133
133
 
134
134
  # @api private
135
135
  def add_flag(key, value, extra)
136
- extra << "--#{key.tr("_", "-")}" if Doors::CliDoor.boolean(value)
136
+ extra << "--#{key.tr("_", "-")}" if Adapters::Driving::Cli.boolean(value)
137
137
  nil
138
138
  end
139
139
 
@@ -153,7 +153,7 @@ module Hecks
153
153
  flag, value = word.split("=", 2)
154
154
  next kept << word unless GENERIC_FLAGS.include?(flag)
155
155
 
156
- Doors::CliDoor.boolean(value || generic_value(queue))
156
+ Adapters::Driving::Cli.boolean(value || generic_value(queue))
157
157
  end
158
158
  kept
159
159
  end
@@ -161,7 +161,7 @@ module Hecks
161
161
  # The Boolean word that follows a generic flag, or "true" when none does.
162
162
  # @api private
163
163
  def generic_value(queue)
164
- Doors::CliDoor::BOOLEAN_WORDS.key?(queue.first.to_s.downcase) ? queue.shift : "true"
164
+ Adapters::Driving::Cli::BOOLEAN_WORDS.key?(queue.first.to_s.downcase) ? queue.shift : "true"
165
165
  end
166
166
  end
167
167
  end
data/lib/hecks/cli/mcp.rb CHANGED
@@ -2,14 +2,14 @@ require_relative "../mcp_stdio_guard"
2
2
 
3
3
  module Hecks
4
4
  module CLI
5
- # The command behind `hecks mcp`: the MCP door onto the
5
+ # The command behind `hecks mcp`: the MCP server onto the
6
6
  # storehouse bus, over stdio only.
7
7
  #
8
8
  # This file loads nothing but `McpStdioGuard`, so the transport check runs
9
9
  # before the framework does.
10
10
  module Mcp
11
11
  # The server name the guard's refusals and warnings carry.
12
- SERVER = "hecks-mcp-door".freeze
12
+ SERVER = "hecks-mcp".freeze
13
13
 
14
14
  module_function
15
15
 
@@ -23,8 +23,8 @@ module Hecks
23
23
  # set up for stdio
24
24
  def call(argv)
25
25
  McpStdioGuard.enforce_stdio!(server: SERVER, argv: argv)
26
- require_relative "../doors/mcp_door"
27
- Doors::McpDoor.serve
26
+ require_relative "../adapters/driving/mcp"
27
+ Adapters::Driving::Mcp.serve
28
28
  end
29
29
  end
30
30
  end
@@ -126,8 +126,8 @@ module Hecks
126
126
  # @api private
127
127
  # @return [String] the opted-in launcher's middle
128
128
  def described_entry(name, boot, shown, quiet: false)
129
- started = "Hecks.boot_described(described, install_doors: false)"
130
- started = "Hecks::Doors::LauncherOptions.quietly(hold: #{RUNS_ON_MEMORY}) { #{started} }" if quiet
129
+ started = "Hecks.boot_described(described, install_driving: false)"
130
+ started = "Hecks::Adapters::Driving::LauncherOptions.quietly(hold: #{RUNS_ON_MEMORY}) { #{started} }" if quiet
131
131
  render(DESCRIBED_ENTRY, boot: boot, shown: shown, name: name, started: started).chomp
132
132
  end
133
133
 
@@ -38,7 +38,7 @@ module Hecks
38
38
  abort "cannot open {{name}}: #{e.message.lines.first.strip}"
39
39
  end
40
40
 
41
- text, status, reason = Hecks::Doors::CliRunner.usage(
41
+ text, status, reason = Hecks::Adapters::Driving::CliRunner.usage(
42
42
  runtime: described, argv: ARGV, program: program
43
43
  )
44
44
  unless text
@@ -48,9 +48,9 @@ module Hecks
48
48
  abort "cannot open {{name}}: #{e.message.lines.first.strip}"
49
49
  end
50
50
  # A question the world lists under `streams`, given `--stream`, tails until interrupted.
51
- streamed = Hecks::Doors::CliRunner.stream(runtime: runtime, argv: ARGV, program: program)
51
+ streamed = Hecks::Adapters::Driving::CliRunner.stream(runtime: runtime, argv: ARGV, program: program)
52
52
  exit streamed unless streamed.nil?
53
- text, status, reason = Hecks::Doors::CliRunner.call(
53
+ text, status, reason = Hecks::Adapters::Driving::CliRunner.call(
54
54
  runtime: runtime, argv: ARGV, program: program
55
55
  )
56
56
  end
@@ -59,12 +59,12 @@ module Hecks
59
59
  # The middle every launcher had before opted-in ones answered usage alone.
60
60
  PLAIN_ENTRY = <<~'RUBY'.freeze
61
61
  runtime = begin
62
- Hecks.boot({{boot}}, install_doors: false)
62
+ Hecks.boot({{boot}}, install_driving: false)
63
63
  rescue StandardError => e
64
64
  abort "cannot open {{name}}: #{e.message.lines.first.strip}"
65
65
  end
66
66
 
67
- text, status = Hecks::Doors::CliRunner.call(
67
+ text, status = Hecks::Adapters::Driving::CliRunner.call(
68
68
  runtime: runtime, argv: ARGV, program: "{{shown}}"
69
69
  )
70
70
  RUBY
@@ -9,12 +9,15 @@ module Hecks
9
9
  # `Hecks.bluebook "QualityControl"` in `qa/` becomes `qa/quality_control`.
10
10
  #
11
11
  # Each launcher is a dozen lines pinning one directory and handing over to
12
- # `Doors::CliRunner`; the surface itself is projected at the moment it runs,
12
+ # `Adapters::Driving::CliRunner`; the surface itself is projected at the moment it runs,
13
13
  # so editing a chapter changes behaviour without regenerating anything.
14
14
  #
15
15
  # A chapter whose world's `launcher` setting names an `executable` gets its launcher
16
16
  # there instead: the Hecks chapter's is the gem's `exe/hecks`.
17
17
  module ProjectCli
18
+ # Raised when the project loads no bluebook.
19
+ class Error < RuntimeError; end
20
+
18
21
  # Build output and other trees under a root that hold no domain a caller means.
19
22
  IGNORED = %r{\A(rust|deploy|tmp|coverage)/}
20
23
 
@@ -34,7 +37,7 @@ module Hecks
34
37
  # @param argv [Array<String>] domain paths under `root`, and optionally `--check`
35
38
  # @param program [String] how the caller was invoked, named in a launcher's header
36
39
  # @param root [String] the directory launchers are written under
37
- # @param remove_stale_bin [Boolean] delete `root/bin/<name>`, a second front door
40
+ # @param remove_stale_bin [Boolean] delete `root/bin/<name>`, a second entry point
38
41
  # @return [void]
39
42
  # @raise [SystemExit] with status 1 for a launcher out of date, an unreadable domain, a
40
43
  # path outside `root` or an unknown flag
@@ -88,9 +91,9 @@ module Hecks
88
91
  # when `check` found it out of date, `:failed` when the domain could not be read or its
89
92
  # launcher could not be made
90
93
  def one(root, path, program, check, remove_stale_bin)
91
- runtime = Hecks.boot(File.join(root, path), install_doors: false)
92
- name = runtime.registry.bluebooks.keys.first or raise "it loads no bluebook"
93
- setting = Doors::LauncherOptions.settings(runtime, name) || {}
94
+ runtime = Hecks.boot(File.join(root, path), install_driving: false)
95
+ name = runtime.registry.bluebooks.keys.first or raise Error, "it loads no bluebook"
96
+ setting = Adapters::Driving::LauncherOptions.settings(runtime, name) || {}
94
97
  settle(launcher_target(name, path, setting, root, program), path, root, check, remove_stale_bin)
95
98
  rescue StandardError, LoadError => e
96
99
  refuse(path, "cannot boot — #{e.message.lines.first.to_s.strip}")
@@ -122,7 +125,7 @@ module Hecks
122
125
  Target.new(name, label, File.join(root, label), text, snake, executable)
123
126
  end
124
127
 
125
- # Writes the launcher, makes it executable, and removes the second front door in `bin/`.
128
+ # Writes the launcher, makes it executable, and removes the second entry point in `bin/`.
126
129
  #
127
130
  # @api private
128
131
  def write_launcher(target, root, remove_stale_bin)
data/lib/hecks/cli/run.rb CHANGED
@@ -68,8 +68,8 @@ module Hecks
68
68
  # near miss deserves the runner's "did you mean" rather than the step-list
69
69
  # form's "no such script".
70
70
  def cli_form(domain, argv, program)
71
- runtime = Hecks.boot(domain, install_doors: false)
72
- text, status = Doors::CliRunner.call(runtime: runtime, argv: argv, program: program)
71
+ runtime = Hecks.boot(domain, install_driving: false)
72
+ text, status = Adapters::Driving::CliRunner.call(runtime: runtime, argv: argv, program: program)
73
73
  status.zero? ? puts(text) : abort(text)
74
74
  exit 0
75
75
  end
@@ -46,7 +46,10 @@ module Hecks
46
46
  before = state
47
47
  expect_success(post(payload, signed_headers))
48
48
  after = state
49
- raise "the state changed on a repeated delivery:\n before #{before}\n after #{after}" unless before == after
49
+ unless before == after
50
+ raise Failure,
51
+ "the state changed on a repeated delivery:\n before #{before}\n after #{after}"
52
+ end
50
53
  end
51
54
  end
52
55
 
@@ -29,15 +29,15 @@ module Hecks
29
29
  end
30
30
 
31
31
  def expect_status(res, code)
32
- raise "expected #{code}, got #{res.code}" unless res.code.to_i == code
32
+ raise Failure, "expected #{code}, got #{res.code}" unless res.code.to_i == code
33
33
  end
34
34
 
35
35
  def expect_success(res)
36
- raise "expected 2xx, got #{res.code}: #{res.body.to_s[0, 200]}" unless res.code.to_i.between?(200, 299)
36
+ raise Failure, "expected 2xx, got #{res.code}: #{res.body.to_s[0, 200]}" unless res.code.to_i.between?(200, 299)
37
37
  end
38
38
 
39
39
  def expect_refused(res)
40
- raise "expected a 4xx refusal, got #{res.code}" unless res.code.to_i.between?(400, 499)
40
+ raise Failure, "expected a 4xx refusal, got #{res.code}" unless res.code.to_i.between?(400, 499)
41
41
  end
42
42
  end
43
43
  end
@@ -12,6 +12,9 @@ module Hecks
12
12
  module CLI
13
13
  # One run of the checks against one service.
14
14
  class SmokeHttp
15
+ # Raised when a smoke check's request gets an answer other than the one it expects.
16
+ class Failure < RuntimeError; end
17
+
15
18
  include Checks
16
19
  include Transport
17
20
  extend Settings
data/lib/hecks/codemod.rb CHANGED
@@ -6,6 +6,9 @@ module Hecks
6
6
  # Shared machinery for a codemod that migrates real `.bluebook` source: boot,
7
7
  # find candidates, edit, then verify by diffing the re-booted IR before keeping it.
8
8
  module Codemod
9
+ # Raised when a shadow cannot be built from the construct.
10
+ class Error < RuntimeError; end
11
+
9
12
  ROOT = File.expand_path("../..", __dir__)
10
13
 
11
14
  EXAMPLE_ROOTS = Corpus.members(:example, root: ROOT).map(&:path)
@@ -155,8 +158,8 @@ module Hecks
155
158
 
156
159
  matches = element_candidates(construct).select { |c| c.hecks_name.to_s == list_attr.type.to_s }
157
160
  if matches.size > 1
158
- raise "#{construct.hecks_name}##{list_field} names #{list_attr.type}, held by both a value " \
159
- "object and an entity — ambiguous, cannot resolve which one the list holds"
161
+ raise Error, "#{construct.hecks_name}##{list_field} names #{list_attr.type}, held by both a value " \
162
+ "object and an entity — ambiguous, cannot resolve which one the list holds"
160
163
  end
161
164
 
162
165
  matches.first
@@ -24,9 +24,16 @@ module Hecks
24
24
  "its filename declares (bump_* / same_*)"),
25
25
  Route.new(%r{\Aspec/fixtures/model_check/}, :named_in, "spec/model_check_spec.rb", :each_file,
26
26
  "domains broken on purpose; each must produce exactly the finding kinds it is built to trigger"),
27
+ Route.new(%r{\Aspec/fixtures/site/editor_chapters/domain/}, :named_in, "spec/site_cms_editor_chapters_spec.rb",
28
+ "site/editor_chapters",
29
+ "two chapters that both declare a Category, so the editor must tell them apart; one SQLite " \
30
+ "file keeps tables by bare aggregate name, which cannot hold both, so the sweep cannot boot it"),
27
31
  # hecks fuzz sweeps it too, once Fuzzing::Replay coerces value-object args
28
32
  # before recomputing givens — today it doesn't, so this given reads as
29
33
  # wrongly admitted.
34
+ Route.new(%r{\Aspec/corpus/asks/}, :named_in, "spec/policy_ask_spec.rb", "spec/corpus/asks",
35
+ "a corpus-owned domain whose ports have no adapter, so an ask is refused; its frozen " \
36
+ "targets are held to the Ruby runtime there and to the Rust policy table in rust/codegen"),
30
37
  Route.new(%r{\Aspec/fixtures/rust_host/}, :named_in, "rust/host/src/web/commerce.rs", "checkout_fixture",
31
38
  "the Rust host's checkout fixture, pinned by its web and /api tests")
32
39
  ].freeze
@@ -184,9 +184,10 @@ module Hecks
184
184
  # domain wins Cargo's `default` is derived, not hand-picked.
185
185
  #
186
186
  # @param root [String] repository root to search under
187
- # @return [Array<RustDomain>] already-generated Rust domains, in regeneration order
187
+ # @return [Array<RustDomain>] every Rust domain with a Cargo feature, in regeneration order:
188
+ # a fresh checkout has no generated output, so the sources, not the output, name them
188
189
  def rust_regen_order(root: ROOT)
189
- rust_domains(root: root).select { |domain| generated?(domain.feature, root: root) }
190
+ rust_domains(root: root)
190
191
  end
191
192
  end
192
193
  end
@@ -212,6 +212,7 @@ Hecks.bluebook "Deploy" do
212
212
  attribute :volume_gb, VolumeGb
213
213
  attribute :database_class, DatabaseClass
214
214
  attribute :storage_gb, StorageGb
215
+ attribute :cdn_aliases, list_of(CdnAlias), optional: true
215
216
 
216
217
  value_object "DomainName" do
217
218
  attribute :value, String
@@ -251,8 +252,19 @@ Hecks.bluebook "Deploy" do
251
252
  invariant("storage is at most 65536 GB") { value <= 65536 }
252
253
  end
253
254
 
254
- # All six required for the same reason as `FargateTarget.Declare`; this validates a target
255
- # already resolved by `hecks deploy project`'s defaults.
255
+ # A host name the CloudFront edge answers on, such as app.example.com. Lowercase labels only:
256
+ # CloudFront refuses a name its certificate does not cover at deploy, which this cannot see.
257
+ value_object "CdnAlias" do
258
+ attribute :value, String
259
+ invariant("a CDN alias is a lowercase host name such as app.example.com") do
260
+ value.to_s.match?(/\A([a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z][a-z0-9-]{0,61}[a-z0-9]\z/)
261
+ end
262
+ invariant("a CDN alias is at most 253 characters") { value.to_s.length <= 253 }
263
+ end
264
+
265
+ # The first six are required for the same reason as `FargateTarget.Declare`; this validates a
266
+ # target already resolved by `hecks deploy project`'s defaults. `cdn_aliases` is the one
267
+ # optional setting: naming at least one asks for the CloudFront edge stack.
256
268
  command "Declare" do
257
269
  goal "Validate one domain's AwsBox deploy target before anything is generated from it"
258
270
 
@@ -262,6 +274,7 @@ Hecks.bluebook "Deploy" do
262
274
  attribute :volume_gb, VolumeGb
263
275
  attribute :database_class, DatabaseClass
264
276
  attribute :storage_gb, StorageGb
277
+ attribute :cdn_aliases, list_of(CdnAlias), optional: true
265
278
 
266
279
  sets :domain
267
280
  sets :region
@@ -269,6 +282,7 @@ Hecks.bluebook "Deploy" do
269
282
  sets :volume_gb
270
283
  sets :database_class
271
284
  sets :storage_gb
285
+ sets :cdn_aliases
272
286
 
273
287
  emits "BoxTargetDeclared"
274
288
  end
@@ -445,6 +459,7 @@ Hecks.bluebook "Deploy" do
445
459
  end
446
460
 
447
461
  lifecycle :status, default: "requested" do
462
+ mark :failure, "refused"
448
463
  transition "Reprovision" => "requested", from: %w[provisioned refused]
449
464
  transition "Complete" => "provisioned", from: "requested"
450
465
  transition "Abandon" => "refused", from: "requested"
@@ -602,6 +617,7 @@ Hecks.bluebook "Deploy" do
602
617
  end
603
618
 
604
619
  lifecycle :status, default: "requested" do
620
+ mark :failure, "faulted"
605
621
  transition "Complete" => "projected", from: "requested"
606
622
  transition "Fault" => "faulted", from: "requested"
607
623
  end
@@ -714,6 +730,7 @@ Hecks.bluebook "Deploy" do
714
730
  end
715
731
 
716
732
  lifecycle :status, default: "requested" do
733
+ mark :failure, "faulted"
717
734
  transition "Complete" => "cleared", from: "requested"
718
735
  transition "Fault" => "faulted", from: "requested"
719
736
  end
@@ -811,6 +828,7 @@ Hecks.bluebook "Deploy" do
811
828
  end
812
829
 
813
830
  lifecycle :status, default: "requested" do
831
+ mark :failure, "flagged"
814
832
  transition "Pass" => "clean", from: "requested"
815
833
  transition "Flag" => "flagged", from: "requested"
816
834
  end
@@ -914,6 +932,7 @@ Hecks.bluebook "Deploy" do
914
932
  end
915
933
 
916
934
  lifecycle :status, default: "requested" do
935
+ mark :failure, "flagged"
917
936
  transition "Pass" => "within_budget", from: "requested"
918
937
  transition "Flag" => "flagged", from: "requested"
919
938
  end
@@ -1031,6 +1050,7 @@ Hecks.bluebook "Deploy" do
1031
1050
  end
1032
1051
 
1033
1052
  lifecycle :status, default: "requested" do
1053
+ mark :failure, "flagged"
1034
1054
  transition "Pass" => "passed", from: "requested"
1035
1055
  transition "Flag" => "flagged", from: "requested"
1036
1056
  end
@@ -1179,6 +1199,7 @@ Hecks.bluebook "Deploy" do
1179
1199
  end
1180
1200
 
1181
1201
  lifecycle :status, default: "requested" do
1202
+ mark :failure, "flagged"
1182
1203
  transition "Complete" => "rolled", from: "requested"
1183
1204
  transition "Flag" => "flagged", from: "requested"
1184
1205
  transition "Verify" => "verified", from: "rolled"
@@ -1361,6 +1382,7 @@ Hecks.bluebook "Deploy" do
1361
1382
  end
1362
1383
 
1363
1384
  lifecycle :status, default: "requested" do
1385
+ mark :failure, "flagged"
1364
1386
  transition "Complete" => "rolled", from: "requested"
1365
1387
  transition "Flag" => "flagged", from: "requested"
1366
1388
  transition "Verify" => "verified", from: "rolled"
@@ -1372,10 +1394,11 @@ Hecks.bluebook "Deploy" do
1372
1394
  # Runs the project's generated `deploy-box.sh`: render the Compose files, push them to the box over
1373
1395
  # SSM, start the containers and check them. A policy then requests a `SmokeRun`, unless
1374
1396
  # `skip_smoke=true`. Exit 1 when flagged, with the script's status (40 no instance, 41 the roll
1375
- # failed, 42 the box unhealthy).
1397
+ # failed, 42 the box unhealthy, 43 no restore anchor). Before the roll the script names the point the
1398
+ # database can be restored to, so the report always carries the way back from a minted era.
1376
1399
 
1377
1400
  command "Run" do
1378
- goal "Roll the app box and record whether it came up healthy (exit 1 when flagged: 40 no instance, 41 roll failed, 42 box unhealthy)"
1401
+ goal "Roll the app box and record whether it came up healthy (exit 1 when flagged: 40 no instance, 41 roll failed, 42 box unhealthy, 43 no restore anchor)"
1379
1402
 
1380
1403
  attribute :project, Location
1381
1404
  attribute :script, Location, optional: true
@@ -1554,6 +1577,7 @@ Hecks.bluebook "Deploy" do
1554
1577
  end
1555
1578
 
1556
1579
  lifecycle :status, default: "requested" do
1580
+ mark :failure, "flagged", "drifted"
1557
1581
  transition "Complete" => "restored", from: "requested"
1558
1582
  transition "Plan" => "planned", from: "requested"
1559
1583
  transition "Flag" => "flagged", from: "requested"
@@ -1835,6 +1859,7 @@ Hecks.bluebook "Deploy" do
1835
1859
  end
1836
1860
 
1837
1861
  lifecycle :status, default: "requested" do
1862
+ mark :failure, "drifted", "flagged"
1838
1863
  transition "Match" => "verified", from: "requested"
1839
1864
  transition "Differ" => "drifted", from: "requested"
1840
1865
  transition "Flag" => "flagged", from: "requested"
@@ -1977,6 +2002,7 @@ Hecks.bluebook "Deploy" do
1977
2002
  # No outcome is a failure: a report that could not be made is `unavailable`, never `flagged`
1978
2003
  # (only a malformed request is), because the era check gates a deploy, not this report.
1979
2004
  lifecycle :status, default: "requested" do
2005
+ mark :failure, "flagged"
1980
2006
  transition "Match" => "unchanged", from: "requested"
1981
2007
  transition "Differ" => "changed", from: "requested"
1982
2008
  transition "Withhold" => "unavailable", from: "requested"
@@ -2140,6 +2166,7 @@ Hecks.bluebook "Deploy" do
2140
2166
  end
2141
2167
 
2142
2168
  lifecycle :status, default: "requested" do
2169
+ mark :failure, "flagged"
2143
2170
  transition "RecordName" => "named", from: "requested"
2144
2171
  transition "RecordUrl" => "located", from: "requested"
2145
2172
  transition "RecordList" => "listed", from: "requested"
@@ -2513,6 +2540,7 @@ Hecks.bluebook "Deploy" do
2513
2540
  end
2514
2541
 
2515
2542
  lifecycle :status, default: "requested" do
2543
+ mark :failure, "flagged"
2516
2544
  transition "Complete" => "rolled", from: "requested"
2517
2545
  transition "Plan" => "planned", from: "requested"
2518
2546
  transition "Flag" => "flagged", from: "requested"
@@ -2648,6 +2676,7 @@ Hecks.bluebook "Deploy" do
2648
2676
  end
2649
2677
 
2650
2678
  lifecycle :status, default: "requested" do
2679
+ mark :failure, "drifted", "refused"
2651
2680
  transition "Match" => "matching", from: "requested"
2652
2681
  transition "Drift" => "drifted", from: "requested"
2653
2682
  transition "Refuse" => "refused", from: "requested"
@@ -2771,6 +2800,7 @@ Hecks.bluebook "Deploy" do
2771
2800
  end
2772
2801
 
2773
2802
  lifecycle :status, default: "requested" do
2803
+ mark :failure, "faulted"
2774
2804
  transition "Complete" => "projected", from: "requested"
2775
2805
  transition "Fault" => "faulted", from: "requested"
2776
2806
  end