hecks 3.4.2 → 3.6.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 (1099) hide show
  1. checksums.yaml +4 -4
  2. data/examples/pizzas/bluebook/hecksagon/mock_stripe_payment_adapter.rb +1 -1
  3. data/lib/hecks/adapters/driven/claude_code.rb +11 -7
  4. data/lib/hecks/adapters/driven/d1/connection.rb +90 -0
  5. data/lib/hecks/adapters/driven/d1.rb +48 -314
  6. data/lib/hecks/adapters/driven/folder.rb +20 -10
  7. data/lib/hecks/adapters/driven/google_authentication.rb +18 -4
  8. data/lib/hecks/adapters/driven/governance_authorization.rb +2 -2
  9. data/lib/hecks/adapters/driven/heki/journal.rb +11 -10
  10. data/lib/hecks/adapters/driven/heki/saga_store.rb +4 -6
  11. data/lib/hecks/adapters/driven/heki/sagas.rb +55 -0
  12. data/lib/hecks/adapters/driven/heki.rb +21 -66
  13. data/lib/hecks/adapters/driven/in_memory_ordering.rb +37 -12
  14. data/lib/hecks/adapters/driven/lambda/client.rb +1 -1
  15. data/lib/hecks/adapters/driven/lambda.rb +1 -8
  16. data/lib/hecks/adapters/driven/memory/outbox_rows.rb +76 -0
  17. data/lib/hecks/adapters/driven/memory/shared_elements/values.rb +117 -0
  18. data/lib/hecks/adapters/driven/memory/shared_elements.rb +10 -97
  19. data/lib/hecks/adapters/driven/memory.rb +3 -65
  20. data/lib/hecks/adapters/driven/postgres/codec.rb +29 -26
  21. data/lib/hecks/adapters/driven/postgres/ddl.rb +50 -0
  22. data/lib/hecks/adapters/driven/postgres/dialect.rb +93 -0
  23. data/lib/hecks/adapters/driven/postgres/events.rb +57 -0
  24. data/lib/hecks/adapters/driven/postgres/journal.rb +127 -0
  25. data/lib/hecks/adapters/driven/postgres/outbox.rb +39 -31
  26. data/lib/hecks/adapters/driven/postgres/repository.rb +190 -0
  27. data/lib/hecks/adapters/driven/postgres/sagas.rb +72 -0
  28. data/lib/hecks/adapters/driven/postgres/schema_builder.rb +13 -41
  29. data/lib/hecks/adapters/driven/postgres.rb +61 -528
  30. data/lib/hecks/adapters/driven/prism.rb +1 -1
  31. data/lib/hecks/adapters/driven/sql_query_builder.rb +45 -53
  32. data/lib/hecks/adapters/driven/sql_value_members.rb +57 -0
  33. data/lib/hecks/adapters/driven/sqlite/codec.rb +32 -29
  34. data/lib/hecks/adapters/driven/sqlite/ddl.rb +68 -0
  35. data/lib/hecks/adapters/driven/sqlite/dialect.rb +55 -0
  36. data/lib/hecks/adapters/driven/sqlite/events.rb +61 -0
  37. data/lib/hecks/adapters/driven/sqlite/journal.rb +125 -0
  38. data/lib/hecks/adapters/driven/sqlite/outbox.rb +98 -0
  39. data/lib/hecks/adapters/driven/sqlite/projection.rb +82 -63
  40. data/lib/hecks/adapters/driven/sqlite/repository.rb +146 -0
  41. data/lib/hecks/adapters/driven/sqlite/sagas.rb +69 -0
  42. data/lib/hecks/adapters/driven/sqlite/schema_builder.rb +8 -55
  43. data/lib/hecks/adapters/driven/sqlite.rb +36 -513
  44. data/lib/hecks/adapters/driven/tenant_provisioner.rb +13 -7
  45. data/lib/hecks/adapters/driving/github_webhook.rb +11 -8
  46. data/lib/hecks/behaviors/dsl.rb +17 -12
  47. data/lib/hecks/behaviors/expectations/boot.rb +81 -0
  48. data/lib/hecks/behaviors/expectations/checks.rb +178 -0
  49. data/lib/hecks/behaviors/expectations/dispatching.rb +93 -0
  50. data/lib/hecks/behaviors/expectations/qualify.rb +81 -0
  51. data/lib/hecks/behaviors/expectations.rb +39 -355
  52. data/lib/hecks/behaviors/rspec.rb +12 -12
  53. data/lib/hecks/behaviors/runner.rb +20 -11
  54. data/lib/hecks/bench/cli.rb +16 -13
  55. data/lib/hecks/bench/environment.rb +1 -1
  56. data/lib/hecks/bench/report.rb +11 -7
  57. data/lib/hecks/bench/ruby_runner.rb +13 -8
  58. data/lib/hecks/bench/rust_runner.rb +19 -11
  59. data/lib/hecks/bench/suite.rb +48 -20
  60. data/lib/hecks/bench/workload.rb +42 -31
  61. data/lib/hecks/bluebook/aggregate.rb +15 -21
  62. data/lib/hecks/bluebook/assembly/aggregate_assembly.rb +18 -21
  63. data/lib/hecks/bluebook/assembly/build.rb +12 -7
  64. data/lib/hecks/bluebook/assembly/contracts/read_models.rb +70 -0
  65. data/lib/hecks/bluebook/assembly/contracts/rules.rb +84 -0
  66. data/lib/hecks/bluebook/assembly/contracts/sagas.rb +109 -0
  67. data/lib/hecks/bluebook/assembly/contracts/structure.rb +91 -0
  68. data/lib/hecks/bluebook/assembly/contracts.rb +9 -319
  69. data/lib/hecks/bluebook/assembly/marks.rb +9 -8
  70. data/lib/hecks/bluebook/attribute.rb +13 -10
  71. data/lib/hecks/bluebook/behaviour/aggregate.rb +10 -3
  72. data/lib/hecks/bluebook/behaviour/read_model.rb +26 -13
  73. data/lib/hecks/bluebook/chapter.rb +22 -14
  74. data/lib/hecks/bluebook/command.rb +14 -18
  75. data/lib/hecks/bluebook/domain_port.rb +11 -8
  76. data/lib/hecks/bluebook/dsl/aggregate_builder/correction_sealing.rb +78 -0
  77. data/lib/hecks/bluebook/dsl/aggregate_builder/draining.rb +74 -0
  78. data/lib/hecks/bluebook/dsl/aggregate_builder/query_field_sealing.rb +105 -0
  79. data/lib/hecks/bluebook/dsl/aggregate_builder/query_sealing.rb +121 -0
  80. data/lib/hecks/bluebook/dsl/aggregate_builder/relationships.rb +128 -0
  81. data/lib/hecks/bluebook/dsl/aggregate_builder/rules.rb +84 -0
  82. data/lib/hecks/bluebook/dsl/aggregate_builder/sealing.rb +61 -249
  83. data/lib/hecks/bluebook/dsl/aggregate_builder.rb +51 -285
  84. data/lib/hecks/bluebook/dsl/attribute_collector/identity_resolution.rb +113 -0
  85. data/lib/hecks/bluebook/dsl/attribute_collector.rb +58 -117
  86. data/lib/hecks/bluebook/dsl/binding_proxy.rb +24 -19
  87. data/lib/hecks/bluebook/dsl/bluebook_builder/pending_givens.rb +109 -0
  88. data/lib/hecks/bluebook/dsl/bluebook_builder/validation/correlation_keys.rb +105 -0
  89. data/lib/hecks/bluebook/dsl/bluebook_builder/validation/event_shapes.rb +126 -0
  90. data/lib/hecks/bluebook/dsl/bluebook_builder/validation/hop_tails.rb +79 -0
  91. data/lib/hecks/bluebook/dsl/bluebook_builder/validation/projected_fields.rb +76 -0
  92. data/lib/hecks/bluebook/dsl/bluebook_builder/validation/provisions.rb +65 -0
  93. data/lib/hecks/bluebook/dsl/bluebook_builder/validation/query_hops.rb +123 -0
  94. data/lib/hecks/bluebook/dsl/bluebook_builder/validation/references.rb +112 -0
  95. data/lib/hecks/bluebook/dsl/bluebook_builder/validation/with_projections.rb +126 -0
  96. data/lib/hecks/bluebook/dsl/bluebook_builder/validation.rb +34 -595
  97. data/lib/hecks/bluebook/dsl/bluebook_builder.rb +18 -107
  98. data/lib/hecks/bluebook/dsl/command_builder/implicit_attributes.rb +132 -0
  99. data/lib/hecks/bluebook/dsl/command_builder/mutations.rb +190 -0
  100. data/lib/hecks/bluebook/dsl/command_builder/owner.rb +22 -0
  101. data/lib/hecks/bluebook/dsl/command_builder/rules.rb +57 -0
  102. data/lib/hecks/bluebook/dsl/command_builder.rb +60 -360
  103. data/lib/hecks/bluebook/dsl/domain_port_builder.rb +19 -13
  104. data/lib/hecks/bluebook/dsl/entity_builder/rules.rb +96 -0
  105. data/lib/hecks/bluebook/dsl/entity_builder/scope.rb +25 -0
  106. data/lib/hecks/bluebook/dsl/entity_builder/sealing.rb +94 -0
  107. data/lib/hecks/bluebook/dsl/entity_builder.rb +35 -169
  108. data/lib/hecks/bluebook/dsl/generic_dispatch.rb +53 -24
  109. data/lib/hecks/bluebook/dsl/hecksagon_builder/chapter_scope.rb +133 -0
  110. data/lib/hecks/bluebook/dsl/hecksagon_builder.rb +3 -97
  111. data/lib/hecks/bluebook/dsl/identity_declaration.rb +73 -73
  112. data/lib/hecks/bluebook/dsl/lifecycle_builder.rb +7 -3
  113. data/lib/hecks/bluebook/dsl/need_word.rb +1 -1
  114. data/lib/hecks/bluebook/dsl/port_operation_builder.rb +34 -29
  115. data/lib/hecks/bluebook/dsl/process_manager_builder.rb +57 -41
  116. data/lib/hecks/bluebook/dsl/query_builder.rb +12 -15
  117. data/lib/hecks/bluebook/dsl/read_model_builder/sealing.rb +116 -0
  118. data/lib/hecks/bluebook/dsl/read_model_builder.rb +25 -102
  119. data/lib/hecks/bluebook/dsl/rule_reference.rb +26 -12
  120. data/lib/hecks/bluebook/dsl/translation_builder.rb +24 -14
  121. data/lib/hecks/bluebook/dsl/value_object_builder.rb +29 -19
  122. data/lib/hecks/bluebook/dsl/word_gate.rb +34 -27
  123. data/lib/hecks/bluebook/entity.rb +13 -17
  124. data/lib/hecks/bluebook/expression/ast_json/emitters.rb +93 -0
  125. data/lib/hecks/bluebook/expression/ast_json/emitters.rb-e +88 -0
  126. data/lib/hecks/bluebook/expression/ast_json.rb +49 -76
  127. data/lib/hecks/bluebook/expression/ast_reader.rb +95 -28
  128. data/lib/hecks/bluebook/expression/canonical_form.rb +6 -26
  129. data/lib/hecks/bluebook/expression/evaluator/parser.rb +62 -0
  130. data/lib/hecks/bluebook/expression/evaluator/scanning.rb +122 -0
  131. data/lib/hecks/bluebook/expression/evaluator.rb +11 -111
  132. data/lib/hecks/bluebook/expression/resolver/block_predicates.rb +28 -44
  133. data/lib/hecks/bluebook/expression/resolver/lookups.rb +77 -0
  134. data/lib/hecks/bluebook/expression/resolver/operations.rb +78 -0
  135. data/lib/hecks/bluebook/expression/resolver/parsing.rb +110 -0
  136. data/lib/hecks/bluebook/expression/resolver/scanning.rb +139 -0
  137. data/lib/hecks/bluebook/expression/resolver/values.rb +115 -0
  138. data/lib/hecks/bluebook/expression/resolver.rb +16 -414
  139. data/lib/hecks/bluebook/{hexagon.rb → hecksagon.rb} +22 -14
  140. data/lib/hecks/bluebook/keyword_fields.rb +42 -0
  141. data/lib/hecks/bluebook/meta_validator/adapter_judge.rb +7 -6
  142. data/lib/hecks/bluebook/meta_validator/judge/cells.rb +99 -0
  143. data/lib/hecks/bluebook/meta_validator/judge/dispatching.rb +111 -0
  144. data/lib/hecks/bluebook/meta_validator/judge/identity.rb +108 -0
  145. data/lib/hecks/bluebook/meta_validator/judge/walking.rb +141 -0
  146. data/lib/hecks/bluebook/meta_validator/judge.rb +31 -376
  147. data/lib/hecks/bluebook/meta_validator/modes.rb +137 -0
  148. data/lib/hecks/bluebook/meta_validator/plan/category.rb +44 -0
  149. data/lib/hecks/bluebook/meta_validator/plan/verbs.rb +73 -0
  150. data/lib/hecks/bluebook/meta_validator/plan.rb +38 -122
  151. data/lib/hecks/bluebook/meta_validator/readings/fields.rb +100 -0
  152. data/lib/hecks/bluebook/meta_validator/readings.rb +10 -95
  153. data/lib/hecks/bluebook/meta_validator/reconstruction/heads.rb +89 -0
  154. data/lib/hecks/bluebook/meta_validator/reconstruction/reading.rb +96 -0
  155. data/lib/hecks/bluebook/meta_validator/reconstruction.rb +25 -151
  156. data/lib/hecks/bluebook/meta_validator/shapes/helpers.rb +83 -0
  157. data/lib/hecks/bluebook/meta_validator/shapes.rb +8 -75
  158. data/lib/hecks/bluebook/meta_validator/syntax_boot/disk_cache.rb +77 -0
  159. data/lib/hecks/bluebook/meta_validator/syntax_boot.rb +31 -95
  160. data/lib/hecks/bluebook/meta_validator/translation_judge/rules.rb +74 -0
  161. data/lib/hecks/bluebook/meta_validator/translation_judge.rb +15 -65
  162. data/lib/hecks/bluebook/meta_validator/verdict_cache/tagging.rb +63 -0
  163. data/lib/hecks/bluebook/meta_validator/verdict_cache.rb +22 -43
  164. data/lib/hecks/bluebook/meta_validator/world_judge.rb +8 -4
  165. data/lib/hecks/bluebook/meta_validator.rb +59 -175
  166. data/lib/hecks/bluebook/model_check/lifecycle_checks.rb +122 -0
  167. data/lib/hecks/bluebook/model_check/policy_checks.rb +129 -0
  168. data/lib/hecks/bluebook/model_check/saga_checks.rb +134 -0
  169. data/lib/hecks/bluebook/model_check/verbs.rb +69 -0
  170. data/lib/hecks/bluebook/model_check.rb +73 -413
  171. data/lib/hecks/bluebook/pattern_subset/refusals.rb +54 -0
  172. data/lib/hecks/bluebook/pattern_subset/scan.rb +58 -0
  173. data/lib/hecks/bluebook/pattern_subset.rb +93 -134
  174. data/lib/hecks/bluebook/process_manager.rb +10 -9
  175. data/lib/hecks/bluebook/project_discovery.rb +10 -7
  176. data/lib/hecks/bluebook/project_register.rb +42 -41
  177. data/lib/hecks/bluebook/query.rb +19 -12
  178. data/lib/hecks/bluebook/read_model.rb +41 -39
  179. data/lib/hecks/bluebook/smoke_test.rb +51 -36
  180. data/lib/hecks/bluebook/synthesizer.rb +13 -5
  181. data/lib/hecks/bluebook/translation.rb +12 -12
  182. data/lib/hecks/bluebook.rb +1 -1
  183. data/lib/hecks/chapters.rb +32 -16
  184. data/lib/hecks/cli/behaviors.rb +22 -15
  185. data/lib/hecks/cli/check_era.rb +2 -2
  186. data/lib/hecks/cli/command_table.rb +72 -0
  187. data/lib/hecks/cli/console.rb +10 -7
  188. data/lib/hecks/cli/deploy_template_diff.rb +22 -9
  189. data/lib/hecks/cli/document.rb +14 -10
  190. data/lib/hecks/cli/domain_stub.rb +1 -1
  191. data/lib/hecks/cli/domain_writer.rb +1 -1
  192. data/lib/hecks/cli/expression_projection.rb +8 -6
  193. data/lib/hecks/cli/follow.rb +10 -4
  194. data/lib/hecks/cli/interview_aggregate.rb +132 -0
  195. data/lib/hecks/cli/interview_draft.rb +16 -200
  196. data/lib/hecks/cli/interview_record.rb +130 -0
  197. data/lib/hecks/cli/interview_run.rb +19 -8
  198. data/lib/hecks/cli/interview_session/agent_state.rb +70 -0
  199. data/lib/hecks/cli/interview_session/catalog.rb +76 -0
  200. data/lib/hecks/cli/interview_session/manual_findings.rb +48 -0
  201. data/lib/hecks/cli/interview_session/proposals.rb +90 -0
  202. data/lib/hecks/cli/interview_session.rb +8 -205
  203. data/lib/hecks/cli/interview_shape.rb +13 -6
  204. data/lib/hecks/cli/ir.rb +8 -11
  205. data/lib/hecks/cli/launcher_words.rb +168 -0
  206. data/lib/hecks/cli/model_check/examination.rb +93 -0
  207. data/lib/hecks/cli/model_check/sources.rb +57 -0
  208. data/lib/hecks/cli/model_check.rb +28 -134
  209. data/lib/hecks/cli/project_cli/launcher_source.rb +177 -0
  210. data/lib/hecks/cli/project_cli/templates.rb +106 -0
  211. data/lib/hecks/cli/project_cli.rb +57 -236
  212. data/lib/hecks/cli/project_diagrams.rb +26 -4
  213. data/lib/hecks/cli/project_glossary.rb +19 -9
  214. data/lib/hecks/cli/refresh_rspec_runtime_baseline.rb +29 -13
  215. data/lib/hecks/cli/release.rb +29 -22
  216. data/lib/hecks/cli/release_gem.rb +12 -6
  217. data/lib/hecks/cli/rspec_io_parallel_files.rb +87 -30
  218. data/lib/hecks/cli/rspec_shard_files.rb +24 -9
  219. data/lib/hecks/cli/run.rb +25 -44
  220. data/lib/hecks/cli/run_expectations.rb +63 -0
  221. data/lib/hecks/cli/seed_semantics_corpus.rb +37 -17
  222. data/lib/hecks/cli/smoke_http/checks.rb +66 -0
  223. data/lib/hecks/cli/smoke_http/settings.rb +63 -0
  224. data/lib/hecks/cli/smoke_http/transport.rb +45 -0
  225. data/lib/hecks/cli/smoke_http.rb +8 -142
  226. data/lib/hecks/cli/smoke_test.rb +18 -4
  227. data/lib/hecks/cli/stores.rb +7 -4
  228. data/lib/hecks/cli/stress_concurrency_specs/reporting.rb +44 -0
  229. data/lib/hecks/cli/stress_concurrency_specs/usage.rb +28 -0
  230. data/lib/hecks/cli/stress_concurrency_specs.rb +82 -80
  231. data/lib/hecks/cli.rb +32 -208
  232. data/lib/hecks/codemod/runner.rb +92 -0
  233. data/lib/hecks/codemod/sweep.rb +94 -0
  234. data/lib/hecks/codemod.rb +22 -165
  235. data/lib/hecks/corpus/routes.rb +34 -0
  236. data/lib/hecks/corpus/rust.rb +193 -0
  237. data/lib/hecks/corpus/sources.rb +46 -0
  238. data/lib/hecks/corpus.rb +28 -265
  239. data/lib/hecks/deploy/bluebook/deploy.bluebook +1510 -3
  240. data/lib/hecks/deploy/bluebook/deploy.hecksagon +57 -0
  241. data/lib/hecks/deploy/oidc.json +225 -0
  242. data/lib/hecks/doc/reference/coverage.rb +70 -0
  243. data/lib/hecks/doc/reference/harvester.rb +55 -0
  244. data/lib/hecks/doc/reference/readme.rb +89 -0
  245. data/lib/hecks/doc/reference/rendering.rb +149 -0
  246. data/lib/hecks/doc/reference.rb +14 -273
  247. data/lib/hecks/doors/cli_door/nesting.rb +34 -0
  248. data/lib/hecks/doors/cli_door/shorthand.rb +85 -0
  249. data/lib/hecks/doors/cli_door.rb +23 -95
  250. data/lib/hecks/doors/cli_runner/answers.rb +138 -0
  251. data/lib/hecks/doors/cli_runner/resolution.rb +146 -0
  252. data/lib/hecks/doors/cli_runner/settling.rb +115 -0
  253. data/lib/hecks/doors/cli_runner/streaming.rb +90 -0
  254. data/lib/hecks/doors/cli_runner/suggestions.rb +43 -0
  255. data/lib/hecks/doors/cli_runner.rb +12 -336
  256. data/lib/hecks/doors/command_request.rb +42 -31
  257. data/lib/hecks/doors/handle.rb +32 -30
  258. data/lib/hecks/doors/launcher_options.rb +62 -7
  259. data/lib/hecks/doors/mcp_door/properties.rb +47 -0
  260. data/lib/hecks/doors/mcp_door/tool_calls.rb +113 -0
  261. data/lib/hecks/doors/mcp_door/tool_definitions/auditing.rb +51 -0
  262. data/lib/hecks/doors/mcp_door/tool_definitions/calling.rb +69 -0
  263. data/lib/hecks/doors/mcp_door/tool_definitions/reading.rb +97 -0
  264. data/lib/hecks/doors/mcp_door/tool_definitions.rb +15 -0
  265. data/lib/hecks/doors/mcp_door.rb +55 -301
  266. data/lib/hecks/doors/mcp_door_scope/argument_policy.rb +92 -0
  267. data/lib/hecks/doors/mcp_door_scope/env_problems.rb +55 -0
  268. data/lib/hecks/doors/mcp_door_scope/presenter.rb +78 -0
  269. data/lib/hecks/doors/mcp_door_scope.rb +16 -172
  270. data/lib/hecks/doors/ruby_door/aggregate_door.rb +1 -1
  271. data/lib/hecks/doors/ruby_door/chapter.rb +33 -16
  272. data/lib/hecks/doors/ruby_door.rb +14 -11
  273. data/lib/hecks/doors/usage_cache.rb +14 -8
  274. data/lib/hecks/doors.rb +10 -4
  275. data/lib/hecks/embryonaut_bluebook/manifest.rb +11 -3
  276. data/lib/hecks/embryonaut_bluebook/registry/changelog.rb +26 -0
  277. data/lib/hecks/embryonaut_bluebook/registry/versions.rb +27 -0
  278. data/lib/hecks/embryonaut_bluebook/registry.rb +27 -37
  279. data/lib/hecks/embryonaut_bluebook/vendor/acceptance.rb +37 -0
  280. data/lib/hecks/embryonaut_bluebook/vendor.rb +22 -36
  281. data/lib/hecks/embryonaut_bluebook/vendor_cli.rb +9 -6
  282. data/lib/hecks/embryonaut_bluebook.rb +16 -11
  283. data/lib/hecks/engine_agreement.rb +24 -17
  284. data/lib/hecks/forms/app/commands.rb +98 -0
  285. data/lib/hecks/forms/app/queries.rb +62 -0
  286. data/lib/hecks/forms/app/records.rb +67 -0
  287. data/lib/hecks/forms/app/responses.rb +46 -0
  288. data/lib/hecks/forms/app.rb +33 -221
  289. data/lib/hecks/forms/banking_presentation.rb +5 -0
  290. data/lib/hecks/forms/command_form_renderer.rb +55 -14
  291. data/lib/hecks/forms/field_controls.rb +95 -0
  292. data/lib/hecks/forms/field_renderer.rb +34 -88
  293. data/lib/hecks/forms/field_shape.rb +9 -34
  294. data/lib/hecks/forms/html.rb +1 -1
  295. data/lib/hecks/forms/index_renderer.rb +14 -9
  296. data/lib/hecks/forms/page.rb +2 -106
  297. data/lib/hecks/forms/page_assets.rb +88 -0
  298. data/lib/hecks/forms/page_script.rb +28 -0
  299. data/lib/hecks/forms/params.rb +17 -8
  300. data/lib/hecks/forms/query_form_renderer.rb +11 -7
  301. data/lib/hecks/forms/record_renderer.rb +28 -19
  302. data/lib/hecks/forms/reference_options.rb +1 -1
  303. data/lib/hecks/forms/text_shape.rb +40 -0
  304. data/lib/hecks/fqn.rb +64 -32
  305. data/lib/hecks/framework.rb +10 -3
  306. data/lib/hecks/freezer.rb +10 -1
  307. data/lib/hecks/fuzzing/bounded_exhaustive_expressions/fragments.rb +61 -0
  308. data/lib/hecks/fuzzing/bounded_exhaustive_expressions/productions.rb +217 -0
  309. data/lib/hecks/fuzzing/bounded_exhaustive_expressions.rb +5 -194
  310. data/lib/hecks/fuzzing/combination_miner.rb +23 -12
  311. data/lib/hecks/fuzzing/concurrent_dispatch/racing.rb +64 -0
  312. data/lib/hecks/fuzzing/concurrent_dispatch/world_copy.rb +66 -0
  313. data/lib/hecks/fuzzing/concurrent_dispatch.rb +31 -107
  314. data/lib/hecks/fuzzing/coverage_campaign.rb +7 -7
  315. data/lib/hecks/fuzzing/differential/wire_comparison.rb +74 -0
  316. data/lib/hecks/fuzzing/differential.rb +59 -84
  317. data/lib/hecks/fuzzing/domain_generator/block_rendering.rb +70 -0
  318. data/lib/hecks/fuzzing/domain_generator/builder/attribute_shapes.rb +105 -0
  319. data/lib/hecks/fuzzing/domain_generator/builder/shapes.rb +97 -0
  320. data/lib/hecks/fuzzing/domain_generator/builder/wiring.rb +128 -0
  321. data/lib/hecks/fuzzing/domain_generator/builder.rb +105 -0
  322. data/lib/hecks/fuzzing/domain_generator/pruning.rb +90 -0
  323. data/lib/hecks/fuzzing/domain_generator/removals.rb +62 -0
  324. data/lib/hecks/fuzzing/domain_generator/rendering.rb +94 -0
  325. data/lib/hecks/fuzzing/domain_generator/tokens.rb +38 -0
  326. data/lib/hecks/fuzzing/domain_generator.rb +7 -555
  327. data/lib/hecks/fuzzing/era_boundary.rb +34 -24
  328. data/lib/hecks/fuzzing/form_census.rb +18 -8
  329. data/lib/hecks/fuzzing/generated_domain_check.rb +23 -11
  330. data/lib/hecks/fuzzing/isolated_boot/copying.rb +62 -0
  331. data/lib/hecks/fuzzing/isolated_boot/postgres_scratch.rb +133 -0
  332. data/lib/hecks/fuzzing/isolated_boot/worlds.rb +102 -0
  333. data/lib/hecks/fuzzing/isolated_boot.rb +25 -252
  334. data/lib/hecks/fuzzing/persistence_parity.rb +5 -5
  335. data/lib/hecks/fuzzing/properties/aggregation_recompute.rb +121 -0
  336. data/lib/hecks/fuzzing/properties/catalog.rb +138 -0
  337. data/lib/hecks/fuzzing/properties/corrections.rb +23 -20
  338. data/lib/hecks/fuzzing/properties/dispatch_and_mutations.rb +64 -185
  339. data/lib/hecks/fuzzing/properties/group_by_recompute.rb +69 -0
  340. data/lib/hecks/fuzzing/properties/guards.rb +76 -108
  341. data/lib/hecks/fuzzing/properties/invariants_and_aggregation.rb +66 -227
  342. data/lib/hecks/fuzzing/properties/lifecycle_and_replay.rb +46 -35
  343. data/lib/hecks/fuzzing/properties/mutation_recompute.rb +162 -0
  344. data/lib/hecks/fuzzing/properties/outbox.rb +41 -24
  345. data/lib/hecks/fuzzing/properties/piece_invariants.rb +61 -0
  346. data/lib/hecks/fuzzing/properties/policy_wiring.rb +140 -0
  347. data/lib/hecks/fuzzing/properties/query_rows.rb +67 -0
  348. data/lib/hecks/fuzzing/properties/querying.rb +69 -90
  349. data/lib/hecks/fuzzing/properties/references.rb +100 -0
  350. data/lib/hecks/fuzzing/properties/tenant_scope.rb +84 -0
  351. data/lib/hecks/fuzzing/properties.rb +6 -119
  352. data/lib/hecks/fuzzing/qa_settings.rb +23 -17
  353. data/lib/hecks/fuzzing/replay/fan_out.rb +78 -0
  354. data/lib/hecks/fuzzing/replay/filters.rb +72 -0
  355. data/lib/hecks/fuzzing/replay/guard_check.rb +88 -0
  356. data/lib/hecks/fuzzing/replay/mutation_trace.rb +117 -0
  357. data/lib/hecks/fuzzing/replay/observation.rb +60 -0
  358. data/lib/hecks/fuzzing/replay/read_only_steps.rb +84 -0
  359. data/lib/hecks/fuzzing/replay/session.rb +151 -0
  360. data/lib/hecks/fuzzing/replay.rb +35 -442
  361. data/lib/hecks/fuzzing/rust_gap_manifest.rb +3 -4
  362. data/lib/hecks/fuzzing/self_consistency/saga_redelivery.rb +133 -0
  363. data/lib/hecks/fuzzing/self_consistency/sagas.rb +93 -0
  364. data/lib/hecks/fuzzing/self_consistency/value_objects.rb +87 -0
  365. data/lib/hecks/fuzzing/self_consistency.rb +8 -213
  366. data/lib/hecks/fuzzing/sequence_generator/adversary/argument_mutations.rb +116 -0
  367. data/lib/hecks/fuzzing/sequence_generator/adversary/caller_draw.rb +68 -0
  368. data/lib/hecks/fuzzing/sequence_generator/adversary/identity_mutations.rb +62 -0
  369. data/lib/hecks/fuzzing/sequence_generator/adversary/precedence_mutations.rb +126 -0
  370. data/lib/hecks/fuzzing/sequence_generator/adversary.rb +23 -283
  371. data/lib/hecks/fuzzing/sequence_generator/argument_drawing.rb +78 -0
  372. data/lib/hecks/fuzzing/sequence_generator/catalog.rb +69 -53
  373. data/lib/hecks/fuzzing/sequence_generator/identity_shaping.rb +85 -0
  374. data/lib/hecks/fuzzing/sequence_generator/outcome_tracker.rb +20 -16
  375. data/lib/hecks/fuzzing/sequence_generator/picker.rb +12 -6
  376. data/lib/hecks/fuzzing/sequence_generator/prefixing.rb +45 -0
  377. data/lib/hecks/fuzzing/sequence_generator/query_binding.rb +19 -8
  378. data/lib/hecks/fuzzing/sequence_generator/step_builder.rb +43 -144
  379. data/lib/hecks/fuzzing/sequence_generator.rb +65 -63
  380. data/lib/hecks/fuzzing/shrinker.rb +33 -29
  381. data/lib/hecks/fuzzing/target_capabilities.rb +10 -4
  382. data/lib/hecks/fuzzing/value_generator.rb +27 -17
  383. data/lib/hecks/gate/stages.yml +10 -0
  384. data/lib/hecks/grammar/evolve/arguments.rb +90 -0
  385. data/lib/hecks/grammar/evolve/keywords.rb +81 -0
  386. data/lib/hecks/grammar/evolve/seeds.rb +172 -0
  387. data/lib/hecks/grammar/evolve.rb +22 -263
  388. data/lib/hecks/grammar/operators.rb +111 -0
  389. data/lib/hecks/grammar.rb +53 -126
  390. data/lib/hecks/hecks/adapters/bluebook_report.rb +91 -0
  391. data/lib/hecks/hecks/adapters/codebase/codemods.rb +1 -1
  392. data/lib/hecks/hecks/adapters/codebase/corpus_tasks.rb +23 -9
  393. data/lib/hecks/hecks/adapters/codebase/language/edits.rb +75 -0
  394. data/lib/hecks/hecks/adapters/codebase/language.rb +30 -72
  395. data/lib/hecks/hecks/adapters/codebase/promotion/candidates.rb +54 -0
  396. data/lib/hecks/hecks/adapters/codebase/promotion/gate.rb +50 -0
  397. data/lib/hecks/hecks/adapters/codebase/promotion/move.rb +70 -0
  398. data/lib/hecks/hecks/adapters/codebase/promotion/standing.rb +88 -0
  399. data/lib/hecks/hecks/adapters/codebase/promotion/watch.rb +83 -0
  400. data/lib/hecks/hecks/adapters/codebase/promotion.rb +115 -0
  401. data/lib/hecks/hecks/adapters/codebase/publishing.rb +31 -12
  402. data/lib/hecks/hecks/adapters/codebase/regeneration.rb +43 -6
  403. data/lib/hecks/hecks/adapters/codebase/release_facts.rb +16 -5
  404. data/lib/hecks/hecks/adapters/codebase/source_tree.rb +9 -1
  405. data/lib/hecks/hecks/adapters/codebase/sqlite_fixture.rb +1 -1
  406. data/lib/hecks/hecks/adapters/codebase/style.rb +1 -1
  407. data/lib/hecks/hecks/adapters/codebase/test_runner.rb +11 -5
  408. data/lib/hecks/hecks/adapters/codebase/test_suite.rb +27 -8
  409. data/lib/hecks/hecks/adapters/console_capture.rb +21 -17
  410. data/lib/hecks/hecks/adapters/cost_explorer.rb +11 -6
  411. data/lib/hecks/hecks/adapters/deploy_plans.rb +49 -0
  412. data/lib/hecks/hecks/adapters/deploy_toolchain/answers.rb +141 -0
  413. data/lib/hecks/hecks/adapters/deploy_toolchain/scripts.rb +95 -0
  414. data/lib/hecks/hecks/adapters/deploy_toolchain/statuses.rb +74 -0
  415. data/lib/hecks/hecks/adapters/deploy_toolchain.rb +122 -59
  416. data/lib/hecks/hecks/adapters/finding_github.rb +2 -2
  417. data/lib/hecks/hecks/adapters/first_admin.rb +22 -8
  418. data/lib/hecks/hecks/adapters/git.rb +18 -5
  419. data/lib/hecks/hecks/adapters/git_refs.rb +144 -0
  420. data/lib/hecks/hecks/adapters/github_rulesets.rb +126 -0
  421. data/lib/hecks/hecks/adapters/host_http.rb +16 -6
  422. data/lib/hecks/hecks/adapters/in_process_boot.rb +9 -5
  423. data/lib/hecks/hecks/adapters/in_process_operations/tailing.rb +61 -0
  424. data/lib/hecks/hecks/adapters/in_process_operations.rb +39 -37
  425. data/lib/hecks/hecks/adapters/journal_store/changes.rb +21 -15
  426. data/lib/hecks/hecks/adapters/journal_store/edge_audit.rb +29 -12
  427. data/lib/hecks/hecks/adapters/journal_store/readings/attestation.rb +52 -0
  428. data/lib/hecks/hecks/adapters/journal_store/readings/scaffolding.rb +52 -0
  429. data/lib/hecks/hecks/adapters/journal_store/readings.rb +5 -62
  430. data/lib/hecks/hecks/adapters/local_files.rb +27 -10
  431. data/lib/hecks/hecks/adapters/pg_admin/ownership.rb +115 -0
  432. data/lib/hecks/hecks/adapters/pg_admin.rb +14 -87
  433. data/lib/hecks/hecks/adapters/process_pool.rb +54 -22
  434. data/lib/hecks/hecks/adapters/rust_toolchain.rb +12 -4
  435. data/lib/hecks/hecks/adapters/site_toolchain.rb +19 -10
  436. data/lib/hecks/hecks/adapters/terminal.rb +13 -9
  437. data/lib/hecks/hecks/codebase.bluebook +322 -5
  438. data/lib/hecks/hecks/custodian.bluebook +12 -2
  439. data/lib/hecks/hecks/hecks.hecksagon +73 -0
  440. data/lib/hecks/hecks/hecks.world +15 -3
  441. data/lib/hecks/kernel_capabilities/templates.rb +92 -0
  442. data/lib/hecks/kernel_capabilities.rb +18 -85
  443. data/lib/hecks/language/bluebook/vocabulary.bluebook +43 -1
  444. data/lib/hecks/literal/item_splitter.rb +50 -0
  445. data/lib/hecks/literal.rb +29 -38
  446. data/lib/hecks/mcp_stdio_guard.rb +8 -8
  447. data/lib/hecks/naming.rb +9 -3
  448. data/lib/hecks/persistence_legacy_fixture/postgres_stores.rb +81 -0
  449. data/lib/hecks/persistence_legacy_fixture/regenerate.rb +26 -66
  450. data/lib/hecks/persistence_legacy_fixture.rb +13 -10
  451. data/lib/hecks/ports/access_control.rb +13 -10
  452. data/lib/hecks/ports/agent/answers.rb +2 -2
  453. data/lib/hecks/ports/agent.rb +13 -10
  454. data/lib/hecks/ports/authentication.rb +13 -10
  455. data/lib/hecks/ports/authorization.rb +13 -10
  456. data/lib/hecks/ports/clock.rb +13 -10
  457. data/lib/hecks/ports/extraction.rb +13 -12
  458. data/lib/hecks/ports/identity_assignment.rb +13 -10
  459. data/lib/hecks/ports/identity_generation.rb +13 -10
  460. data/lib/hecks/ports/identity_resolution.rb +13 -10
  461. data/lib/hecks/ports/key_vault.rb +13 -10
  462. data/lib/hecks/ports/persistence/append_only.rb +5 -5
  463. data/lib/hecks/ports/persistence/binding_policy.rb +33 -9
  464. data/lib/hecks/ports/persistence/codec_boundary.rb +22 -11
  465. data/lib/hecks/ports/persistence/constants.rb +10 -0
  466. data/lib/hecks/ports/persistence/plugins/era/era_check.rb +18 -16
  467. data/lib/hecks/ports/persistence/plugins/era/era_guard/shape_diff.rb +27 -18
  468. data/lib/hecks/ports/persistence/plugins/era/era_guard.rb +52 -23
  469. data/lib/hecks/ports/persistence/plugins/era/era_tamper.rb +14 -8
  470. data/lib/hecks/ports/persistence/plugins/era/expected_era.rb +17 -6
  471. data/lib/hecks/ports/persistence/plugins/era/lineage/coverage.rb +58 -0
  472. data/lib/hecks/ports/persistence/plugins/era/lineage/rewrite.rb +130 -0
  473. data/lib/hecks/ports/persistence/plugins/era/lineage/rules.rb +25 -0
  474. data/lib/hecks/ports/persistence/plugins/era/lineage.rb +20 -180
  475. data/lib/hecks/ports/persistence/plugins/era/postgres_era/boot.rb +41 -0
  476. data/lib/hecks/ports/persistence/plugins/era/postgres_era/class_methods.rb +105 -0
  477. data/lib/hecks/ports/persistence/plugins/era/postgres_era/dialect.rb +137 -0
  478. data/lib/hecks/ports/persistence/plugins/era/postgres_era/events.rb +25 -28
  479. data/lib/hecks/ports/persistence/plugins/era/postgres_era/head_writes.rb +62 -0
  480. data/lib/hecks/ports/persistence/plugins/era/postgres_era/journal.rb +128 -0
  481. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/base_sql.rb +74 -0
  482. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/chain_sql.rb +169 -0
  483. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/domain_rename.rb +91 -0
  484. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/era_integrity.rb +99 -0
  485. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/era_store.rb +0 -73
  486. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/field_cache.rb +55 -39
  487. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/head_compiler.rb +51 -222
  488. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/merge_writes.rb +120 -0
  489. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/mint_transaction.rb +85 -60
  490. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/provisioning.rb +97 -181
  491. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/resumable_backfill.rb +19 -19
  492. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/sql_templates.rb +88 -0
  493. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/tail_merge.rb +77 -118
  494. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/transform_installer.rb +3 -117
  495. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/transform_sql.rb +116 -0
  496. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage.rb +3 -1
  497. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/context.rb +38 -0
  498. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/coverage_check.rb +43 -25
  499. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/era_resolver.rb +62 -38
  500. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/merge_coordinator.rb +21 -16
  501. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/minter.rb +66 -86
  502. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/refusals.rb +75 -0
  503. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager.rb +27 -9
  504. data/lib/hecks/ports/persistence/plugins/era/postgres_era/query_phases.rb +63 -0
  505. data/lib/hecks/ports/persistence/plugins/era/postgres_era/sagas.rb +78 -0
  506. data/lib/hecks/ports/persistence/plugins/era/postgres_era.rb +28 -482
  507. data/lib/hecks/ports/persistence/plugins/era/translation/approval_file.rb +40 -12
  508. data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_one.rb +22 -15
  509. data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_two.rb +39 -19
  510. data/lib/hecks/ports/persistence/plugins/era/translation/audit/unfed_report.rb +16 -16
  511. data/lib/hecks/ports/persistence/plugins/era/translation/rule_compiler.rb +48 -25
  512. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/differ.rb +60 -99
  513. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/path_diff.rb +57 -0
  514. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/renderer.rb +21 -11
  515. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/writer.rb +13 -4
  516. data/lib/hecks/ports/persistence/postgres_dump/connection.rb +4 -2
  517. data/lib/hecks/ports/persistence/postgres_dump.rb +13 -7
  518. data/lib/hecks/ports/persistence/repository_factory.rb +35 -11
  519. data/lib/hecks/ports/persistence/state_codec.rb +10 -0
  520. data/lib/hecks/ports/persistence.rb +1 -10
  521. data/lib/hecks/ports/projection.rb +34 -21
  522. data/lib/hecks/ports/query/in_memory.rb +16 -8
  523. data/lib/hecks/projection_files/expression_tables.rb +64 -0
  524. data/lib/hecks/projection_files/texts.rb +67 -0
  525. data/lib/hecks/projection_files.rb +19 -103
  526. data/lib/hecks/projections/bootstrap_table.rb +43 -29
  527. data/lib/hecks/projections/deploy/bastion_lines.rb +32 -0
  528. data/lib/hecks/projections/deploy/box/access.rb +73 -0
  529. data/lib/hecks/projections/deploy/box/caddy.rb +87 -0
  530. data/lib/hecks/projections/deploy/box/compose.rb +70 -0
  531. data/lib/hecks/projections/deploy/box/hosting.rb +16 -108
  532. data/lib/hecks/projections/deploy/box/hosting_parts.rb +97 -0
  533. data/lib/hecks/projections/deploy/box/hosting_settings.rb +1 -1
  534. data/lib/hecks/projections/deploy/box/roll_recipe.rb +62 -0
  535. data/lib/hecks/projections/deploy/box/roll_scripts.rb +135 -0
  536. data/lib/hecks/projections/deploy/box/settings/checks.rb +38 -0
  537. data/lib/hecks/projections/deploy/box/settings/containers.rb +123 -0
  538. data/lib/hecks/projections/deploy/box/settings/origin.rb +56 -0
  539. data/lib/hecks/projections/deploy/box/settings/patterns.rb +43 -0
  540. data/lib/hecks/projections/deploy/box/settings/types.rb +72 -0
  541. data/lib/hecks/projections/deploy/box/settings.rb +58 -263
  542. data/lib/hecks/projections/deploy/box/stack_yaml.rb +107 -0
  543. data/lib/hecks/projections/deploy/box/templates/MIGRATION.md.tmpl +39 -0
  544. data/lib/hecks/projections/deploy/box/templates/Makefile.tmpl +24 -0
  545. data/lib/hecks/projections/deploy/box/templates/deploy-box.sh.tmpl +51 -4
  546. data/lib/hecks/projections/deploy/box/templates/deploy-service.services-roll.part +4 -3
  547. data/lib/hecks/projections/deploy/box/templates/deploy-service.sh.tmpl +16 -4
  548. data/lib/hecks/projections/deploy/box/templates/deploy-service.taskdef-roll.part +8 -7
  549. data/lib/hecks/projections/deploy/box/templates/deploy-service.taskdef.part +1 -1
  550. data/lib/hecks/projections/deploy/box/templates/deploy-usage-services.tmpl +4 -0
  551. data/lib/hecks/projections/deploy/box/templates/deploy-usage-taskdef.tmpl +5 -0
  552. data/lib/hecks/projections/deploy/box/templates/ecr-repository.yaml.tmpl +9 -0
  553. data/lib/hecks/projections/deploy/box/templates/hosting.mk.tmpl +6 -3
  554. data/lib/hecks/projections/deploy/box/templates/mode-summary-services.tmpl +2 -0
  555. data/lib/hecks/projections/deploy/box/templates/mode-summary-taskdef.tmpl +4 -0
  556. data/lib/hecks/projections/deploy/box/templates/restore-to-rds.sh.tmpl +8 -3
  557. data/lib/hecks/projections/deploy/box/templates/services-block.tmpl +9 -0
  558. data/lib/hecks/projections/deploy/box/templates/tunnel-egress.yaml.tmpl +11 -0
  559. data/lib/hecks/projections/deploy/box/templates/verify-copy.sh.tmpl +2 -2
  560. data/lib/hecks/projections/deploy/box/templates/writable-secrets.yaml.tmpl +7 -0
  561. data/lib/hecks/projections/deploy/box.rb +37 -503
  562. data/lib/hecks/projections/deploy/fargate/assembly.rb +13 -142
  563. data/lib/hecks/projections/deploy/fargate/cdn/behaviors.rb +76 -0
  564. data/lib/hecks/projections/deploy/fargate/cdn/lines.rb +112 -0
  565. data/lib/hecks/projections/deploy/fargate/cdn/options.rb +85 -0
  566. data/lib/hecks/projections/deploy/fargate/cdn.rb +23 -215
  567. data/lib/hecks/projections/deploy/fargate/check.rb +16 -6
  568. data/lib/hecks/projections/deploy/fargate/containers/definition_lines.rb +61 -0
  569. data/lib/hecks/projections/deploy/fargate/containers/reading.rb +86 -0
  570. data/lib/hecks/projections/deploy/fargate/containers/rendering.rb +132 -0
  571. data/lib/hecks/projections/deploy/fargate/containers/routing.rb +93 -0
  572. data/lib/hecks/projections/deploy/fargate/containers.rb +10 -286
  573. data/lib/hecks/projections/deploy/fargate/extras/reading.rb +90 -0
  574. data/lib/hecks/projections/deploy/fargate/extras/rendering.rb +81 -0
  575. data/lib/hecks/projections/deploy/fargate/extras.rb +9 -158
  576. data/lib/hecks/projections/deploy/fargate/monitoring/alarms.rb +115 -0
  577. data/lib/hecks/projections/deploy/fargate/monitoring/reading.rb +84 -0
  578. data/lib/hecks/projections/deploy/fargate/monitoring/topic.rb +59 -0
  579. data/lib/hecks/projections/deploy/fargate/monitoring/warmer.rb +90 -0
  580. data/lib/hecks/projections/deploy/fargate/monitoring/warmer_roles.rb +76 -0
  581. data/lib/hecks/projections/deploy/fargate/monitoring.rb +14 -348
  582. data/lib/hecks/projections/deploy/fargate/sections.rb +115 -0
  583. data/lib/hecks/projections/deploy/fargate/settings/ids.rb +55 -0
  584. data/lib/hecks/projections/deploy/fargate/settings/tuning.rb +77 -0
  585. data/lib/hecks/projections/deploy/fargate/settings.rb +17 -104
  586. data/lib/hecks/projections/deploy/fargate/stack/blocks.rb +91 -0
  587. data/lib/hecks/projections/deploy/fargate/stack/readers.rb +87 -0
  588. data/lib/hecks/projections/deploy/fargate/stack/recipes.rb +106 -0
  589. data/lib/hecks/projections/deploy/fargate/stack.rb +146 -0
  590. data/lib/hecks/projections/deploy/fargate/task_sections.rb +56 -0
  591. data/lib/hecks/projections/deploy/fargate/yaml.rb +1 -1
  592. data/lib/hecks/projections/deploy/fargate.rb +51 -756
  593. data/lib/hecks/projections/deploy/lambda/pii.rb +49 -0
  594. data/lib/hecks/projections/deploy/lambda/stack/blocks.rb +118 -0
  595. data/lib/hecks/projections/deploy/lambda/stack/checks.rb +64 -0
  596. data/lib/hecks/projections/deploy/lambda/stack/deploy_chain.rb +119 -0
  597. data/lib/hecks/projections/deploy/lambda/stack/readers.rb +62 -0
  598. data/lib/hecks/projections/deploy/lambda/stack/reading.rb +170 -0
  599. data/lib/hecks/projections/deploy/lambda/stack/reading_web.rb +53 -0
  600. data/lib/hecks/projections/deploy/lambda/stack/recipes.rb +112 -0
  601. data/lib/hecks/projections/deploy/lambda/stack/web.rb +57 -0
  602. data/lib/hecks/projections/deploy/lambda/stack.rb +54 -0
  603. data/lib/hecks/projections/deploy/lambda.rb +77 -1885
  604. data/lib/hecks/projections/deploy/preview/access_yaml.rb +8 -74
  605. data/lib/hecks/projections/deploy/preview/containers.rb +18 -7
  606. data/lib/hecks/projections/deploy/preview/routing_yaml.rb +15 -87
  607. data/lib/hecks/projections/deploy/preview/settings.rb +7 -4
  608. data/lib/hecks/projections/deploy/preview/task_yaml.rb +42 -106
  609. data/lib/hecks/projections/deploy/preview/template.rb +11 -106
  610. data/lib/hecks/projections/deploy/preview/yaml_text.rb +1 -1
  611. data/lib/hecks/projections/deploy/scripts/hosting.mk.tmpl +1 -1
  612. data/lib/hecks/projections/deploy/scripts/settings.rb +14 -6
  613. data/lib/hecks/projections/deploy/scripts.rb +11 -9
  614. data/lib/hecks/projections/deploy/shared/rows.rb +48 -0
  615. data/lib/hecks/projections/deploy/shared.rb +89 -449
  616. data/lib/hecks/projections/deploy/smoke.rb +15 -10
  617. data/lib/hecks/projections/deploy/template_diff/comparer.rb +21 -147
  618. data/lib/hecks/projections/deploy/template_diff/normalizer.rb +60 -0
  619. data/lib/hecks/projections/deploy/template_diff/value_diff.rb +136 -0
  620. data/lib/hecks/projections/deploy/template_diff.rb +8 -3
  621. data/lib/hecks/projections/deploy/templates/fargate/Dockerfile.tmpl +28 -0
  622. data/lib/hecks/projections/deploy/templates/fargate/Makefile.tmpl +63 -0
  623. data/lib/hecks/projections/deploy/templates/fargate/always_params.tmpl +4 -0
  624. data/lib/hecks/projections/deploy/templates/fargate/deploy_plain.tmpl +1 -0
  625. data/lib/hecks/projections/deploy/templates/fargate/deploy_shared.tmpl +11 -0
  626. data/lib/hecks/projections/deploy/templates/fargate/mint_era_own.tmpl +44 -0
  627. data/lib/hecks/projections/deploy/templates/fargate/mint_era_shared.tmpl +8 -0
  628. data/lib/hecks/projections/deploy/templates/fargate/missing_owner.tmpl +9 -0
  629. data/lib/hecks/projections/deploy/templates/fargate/oauth_params.tmpl +7 -0
  630. data/lib/hecks/projections/deploy/templates/fargate/oauth_task_env.tmpl +4 -0
  631. data/lib/hecks/projections/deploy/templates/fargate/oauth_task_policy.tmpl +7 -0
  632. data/lib/hecks/projections/deploy/templates/fargate/owning_params.tmpl +33 -0
  633. data/lib/hecks/projections/deploy/templates/fargate/template.yaml.tmpl +281 -0
  634. data/lib/hecks/projections/deploy/templates/lambda/Makefile.tmpl +218 -0
  635. data/lib/hecks/projections/deploy/templates/lambda/aurora_depends.tmpl +18 -0
  636. data/lib/hecks/projections/deploy/templates/lambda/build_dispatch_none.tmpl +10 -0
  637. data/lib/hecks/projections/deploy/templates/lambda/build_pg.tmpl +15 -0
  638. data/lib/hecks/projections/deploy/templates/lambda/build_plain.tmpl +2 -0
  639. data/lib/hecks/projections/deploy/templates/lambda/build_web.tmpl +11 -0
  640. data/lib/hecks/projections/deploy/templates/lambda/env_blind_guard.tmpl +4 -0
  641. data/lib/hecks/projections/deploy/templates/lambda/mint_era_own.tmpl +122 -0
  642. data/lib/hecks/projections/deploy/templates/lambda/mint_era_shared.tmpl +47 -0
  643. data/lib/hecks/projections/deploy/templates/lambda/missing_owner.tmpl +9 -0
  644. data/lib/hecks/projections/deploy/templates/lambda/nat_comment_oauth.tmpl +14 -0
  645. data/lib/hecks/projections/deploy/templates/lambda/nat_comment_plain.tmpl +3 -0
  646. data/lib/hecks/projections/deploy/templates/lambda/oauth_note.tmpl +8 -0
  647. data/lib/hecks/projections/deploy/templates/lambda/params_oauth.tmpl +13 -0
  648. data/lib/hecks/projections/deploy/templates/lambda/params_shared.tmpl +33 -0
  649. data/lib/hecks/projections/deploy/templates/lambda/pg_native.tmpl +71 -0
  650. data/lib/hecks/projections/deploy/templates/lambda/pii_oac.tmpl +8 -0
  651. data/lib/hecks/projections/deploy/templates/lambda/pii_permission.tmpl +8 -0
  652. data/lib/hecks/projections/deploy/templates/lambda/pii_resources.tmpl +116 -0
  653. data/lib/hecks/projections/deploy/templates/lambda/predeploy_bridge.tmpl +30 -0
  654. data/lib/hecks/projections/deploy/templates/lambda/predeploy_bridge_oauth.tmpl +12 -0
  655. data/lib/hecks/projections/deploy/templates/lambda/predeploy_bridge_plain.tmpl +7 -0
  656. data/lib/hecks/projections/deploy/templates/lambda/rename_schema_own.tmpl +93 -0
  657. data/lib/hecks/projections/deploy/templates/lambda/rename_schema_shared.tmpl +7 -0
  658. data/lib/hecks/projections/deploy/templates/lambda/rust_oauth_env.tmpl +17 -0
  659. data/lib/hecks/projections/deploy/templates/lambda/rust_oauth_policy.tmpl +16 -0
  660. data/lib/hecks/projections/deploy/templates/lambda/rust_session_secret.tmpl +13 -0
  661. data/lib/hecks/projections/deploy/templates/lambda/samconfig.toml.tmpl +12 -0
  662. data/lib/hecks/projections/deploy/templates/lambda/shared_note.tmpl +6 -0
  663. data/lib/hecks/projections/deploy/templates/lambda/sync_oauth.tmpl +23 -0
  664. data/lib/hecks/projections/deploy/templates/lambda/template.yaml.tmpl +187 -0
  665. data/lib/hecks/projections/deploy/templates/lambda/translation_own.tmpl +46 -0
  666. data/lib/hecks/projections/deploy/templates/lambda/translation_shared.tmpl +2 -0
  667. data/lib/hecks/projections/deploy/templates/lambda/web_function.tmpl +207 -0
  668. data/lib/hecks/projections/deploy/templates/lambda/web_google_oauth_env.tmpl +12 -0
  669. data/lib/hecks/projections/deploy/templates/lambda/web_no_oauth_env.tmpl +7 -0
  670. data/lib/hecks/projections/deploy/templates/lambda/web_oauth_policy.tmpl +4 -0
  671. data/lib/hecks/projections/deploy/templates/lambda/webhook_secret_resource.tmpl +20 -0
  672. data/lib/hecks/projections/deploy/templates/preview/alb.tmpl +8 -0
  673. data/lib/hecks/projections/deploy/templates/preview/alb_security_group.tmpl +11 -0
  674. data/lib/hecks/projections/deploy/templates/preview/assume_role.tmpl +6 -0
  675. data/lib/hecks/projections/deploy/templates/preview/base_parameters.tmpl +24 -0
  676. data/lib/hecks/projections/deploy/templates/preview/cluster.tmpl +4 -0
  677. data/lib/hecks/projections/deploy/templates/preview/container_secret.tmpl +9 -0
  678. data/lib/hecks/projections/deploy/templates/preview/db_init_script.sh.tmpl +23 -0
  679. data/lib/hecks/projections/deploy/templates/preview/db_init_secrets.tmpl +5 -0
  680. data/lib/hecks/projections/deploy/templates/preview/db_init_task.tmpl +39 -0
  681. data/lib/hecks/projections/deploy/templates/preview/desired_count.tmpl +5 -0
  682. data/lib/hecks/projections/deploy/templates/preview/distribution.tmpl +24 -0
  683. data/lib/hecks/projections/deploy/templates/preview/execution_role.tmpl +16 -0
  684. data/lib/hecks/projections/deploy/templates/preview/header.tmpl +16 -0
  685. data/lib/hecks/projections/deploy/templates/preview/ingress.tmpl +8 -0
  686. data/lib/hecks/projections/deploy/templates/preview/listener.tmpl +9 -0
  687. data/lib/hecks/projections/deploy/templates/preview/listener_rule.tmpl +11 -0
  688. data/lib/hecks/projections/deploy/templates/preview/log_group.tmpl +5 -0
  689. data/lib/hecks/projections/deploy/templates/preview/log_options.tmpl +5 -0
  690. data/lib/hecks/projections/deploy/templates/preview/outputs.tmpl +14 -0
  691. data/lib/hecks/projections/deploy/templates/preview/service.tmpl +17 -0
  692. data/lib/hecks/projections/deploy/templates/preview/session_secret.tmpl +11 -0
  693. data/lib/hecks/projections/deploy/templates/preview/target_group.tmpl +9 -0
  694. data/lib/hecks/projections/deploy/templates/preview/task_definition.tmpl +15 -0
  695. data/lib/hecks/projections/deploy/templates/preview/task_role.tmpl +22 -0
  696. data/lib/hecks/projections/deploy/templates/shared/aurora_db.tmpl +52 -0
  697. data/lib/hecks/projections/deploy/templates/shared/bastion.tmpl +74 -0
  698. data/lib/hecks/projections/deploy/templates/shared/bastion_own_public.tmpl +41 -0
  699. data/lib/hecks/projections/deploy/templates/shared/bastion_reuse_public.tmpl +10 -0
  700. data/lib/hecks/projections/deploy/templates/shared/nat_gateway.tmpl +102 -0
  701. data/lib/hecks/projections/deploy/templates/shared/oauth_egress.tmpl +17 -0
  702. data/lib/hecks/projections/deploy/templates/shared/plain_db.tmpl +16 -0
  703. data/lib/hecks/projections/deploy/templates/shared/vpc_and_database.tmpl +67 -0
  704. data/lib/hecks/projections/deploy/text_template.rb +35 -0
  705. data/lib/hecks/projections/diagrams/dispatch.rb +114 -0
  706. data/lib/hecks/projections/diagrams/statecharts.rb +59 -0
  707. data/lib/hecks/projections/diagrams/structure.rb +114 -0
  708. data/lib/hecks/projections/diagrams.rb +33 -256
  709. data/lib/hecks/projections/glossary/entries.rb +140 -0
  710. data/lib/hecks/projections/glossary/html/page.rb +96 -0
  711. data/lib/hecks/projections/glossary/html/parser.rb +66 -0
  712. data/lib/hecks/projections/glossary/html/sections.rb +78 -0
  713. data/lib/hecks/projections/glossary/html.rb +7 -179
  714. data/lib/hecks/projections/glossary/index.rb +45 -0
  715. data/lib/hecks/projections/glossary/markdown.rb +22 -11
  716. data/lib/hecks/projections/glossary/mermaid.rb +44 -31
  717. data/lib/hecks/projections/glossary/sensitivity.rb +7 -4
  718. data/lib/hecks/projections/glossary/sentences/value_objects.rb +77 -0
  719. data/lib/hecks/projections/glossary/sentences.rb +42 -81
  720. data/lib/hecks/projections/glossary/slugs.rb +33 -0
  721. data/lib/hecks/projections/glossary.rb +22 -190
  722. data/lib/hecks/projections/model.rb +20 -14
  723. data/lib/hecks/projections/rust_vocabulary/arguments/support.rb +33 -0
  724. data/lib/hecks/projections/rust_vocabulary/arguments.rb +171 -0
  725. data/lib/hecks/projections/rust_vocabulary/enum_body.rb +114 -0
  726. data/lib/hecks/projections/rust_vocabulary/tests.rb +144 -0
  727. data/lib/hecks/projections/rust_vocabulary.rb +24 -293
  728. data/lib/hecks/projections/site/admin.rb +146 -0
  729. data/lib/hecks/projections/site/admin_cms/templates/membership.rb +115 -0
  730. data/lib/hecks/projections/site/admin_cms/templates/session_strategy.rb +90 -0
  731. data/lib/hecks/projections/site/admin_cms/templates/sso.rb +101 -0
  732. data/lib/hecks/projections/site/admin_cms/templates/sso_tail.rb +54 -0
  733. data/lib/hecks/projections/site/admin_cms/templates/users.rb +83 -0
  734. data/lib/hecks/projections/site/admin_cms/templates.rb +33 -0
  735. data/lib/hecks/projections/site/admin_cms.rb +78 -0
  736. data/lib/hecks/projections/site/edge/behaviours.rb +10 -6
  737. data/lib/hecks/projections/site/edge/checks.rb +30 -80
  738. data/lib/hecks/projections/site/edge/findings.rb +28 -0
  739. data/lib/hecks/projections/site/edge/route_checks.rb +110 -0
  740. data/lib/hecks/projections/site/edge/row_reader.rb +52 -0
  741. data/lib/hecks/projections/site/edge/rules.rb +28 -26
  742. data/lib/hecks/projections/site/edge.rb +20 -31
  743. data/lib/hecks/projections/site/live_edge.rb +9 -7
  744. data/lib/hecks/projections/site/payload/fields/definitions.rb +90 -0
  745. data/lib/hecks/projections/site/payload/fields/readers.rb +69 -0
  746. data/lib/hecks/projections/site/payload/fields.rb +137 -0
  747. data/lib/hecks/projections/site/payload/lifecycle/text.rb +84 -0
  748. data/lib/hecks/projections/site/payload/lifecycle/text_tail.rb +106 -0
  749. data/lib/hecks/projections/site/payload/lifecycle.rb +33 -0
  750. data/lib/hecks/projections/site/payload/model.rb +128 -0
  751. data/lib/hecks/projections/site/payload/specs/wire.rb +69 -0
  752. data/lib/hecks/projections/site/payload/specs.rb +135 -0
  753. data/lib/hecks/projections/site/payload_driver.rb +95 -0
  754. data/lib/hecks/projections/site/root_rows.rb +67 -0
  755. data/lib/hecks/projections/site/routes_ts/helpers.rb +79 -0
  756. data/lib/hecks/projections/site/routes_ts/listings.rb +75 -0
  757. data/lib/hecks/projections/site/routes_ts/navigation.rb +79 -0
  758. data/lib/hecks/projections/site/routes_ts.rb +27 -175
  759. data/lib/hecks/projections/site/site_admin/access.rb +104 -0
  760. data/lib/hecks/projections/site/site_admin/session.rb +127 -0
  761. data/lib/hecks/projections/site/site_admin.rb +85 -0
  762. data/lib/hecks/projections/site/site_cdn.rb +12 -7
  763. data/lib/hecks/projections/site/site_host/dockerfile.rb +75 -0
  764. data/lib/hecks/projections/site/site_host/templates.rb +109 -0
  765. data/lib/hecks/projections/site/site_host.rb +58 -0
  766. data/lib/hecks/projections/site/site_root/workflow.rb +65 -0
  767. data/lib/hecks/projections/site/site_root.rb +128 -0
  768. data/lib/hecks/projections/site/table/checks.rb +28 -57
  769. data/lib/hecks/projections/site/table/link_builder.rb +14 -5
  770. data/lib/hecks/projections/site/table/navigation_checks.rb +75 -0
  771. data/lib/hecks/projections/site/table/row_builder.rb +31 -53
  772. data/lib/hecks/projections/site/table/row_defaults.rb +65 -0
  773. data/lib/hecks/projections/site/table.rb +9 -5
  774. data/lib/hecks/projections/vocabulary.rb +34 -31
  775. data/lib/hecks/projector/cli_audience.rb +42 -0
  776. data/lib/hecks/projector/cli_projector/claims.rb +149 -0
  777. data/lib/hecks/projector/cli_projector/command_help.rb +65 -0
  778. data/lib/hecks/projector/cli_projector/command_specs.rb +133 -0
  779. data/lib/hecks/projector/cli_projector/listing.rb +100 -0
  780. data/lib/hecks/projector/cli_projector/option_specs.rb +116 -0
  781. data/lib/hecks/projector/cli_projector/query_specs.rb +67 -0
  782. data/lib/hecks/projector/cli_projector/usage.rb +101 -0
  783. data/lib/hecks/projector/cli_projector.rb +15 -532
  784. data/lib/hecks/projector/docs_projector/attributes.rb +78 -0
  785. data/lib/hecks/projector/docs_projector/behaviour.rb +127 -0
  786. data/lib/hecks/projector/docs_projector/closing.rb +40 -0
  787. data/lib/hecks/projector/docs_projector.rb +58 -192
  788. data/lib/hecks/projector/exporter/bindings.rb +174 -0
  789. data/lib/hecks/projector/exporter/translations.rb +127 -0
  790. data/lib/hecks/projector/exporter.rb +8 -279
  791. data/lib/hecks/projector/narrate_projector/commands.rb +108 -0
  792. data/lib/hecks/projector/narrate_projector/reactions.rb +33 -0
  793. data/lib/hecks/projector/narrate_projector.rb +60 -160
  794. data/lib/hecks/projector.rb +22 -13
  795. data/lib/hecks/quality_control/adapters/agent_profile.rb +25 -16
  796. data/lib/hecks/quality_control/adapters/github_checks.rb +42 -6
  797. data/lib/hecks/quality_control/adapters/github_ci_webhook.rb +1 -1
  798. data/lib/hecks/quality_control/adapters/github_issues.rb +22 -10
  799. data/lib/hecks/quality_control/cli/qa_discover_external_domains/parsing.rb +54 -0
  800. data/lib/hecks/quality_control/cli/qa_discover_external_domains/reporting.rb +44 -0
  801. data/lib/hecks/quality_control/cli/qa_discover_external_domains/scanning.rb +119 -0
  802. data/lib/hecks/quality_control/cli/qa_discover_external_domains.rb +28 -155
  803. data/lib/hecks/quality_control/cli/qa_domain_novelty/verdict.rb +76 -0
  804. data/lib/hecks/quality_control/cli/qa_domain_novelty.rb +33 -66
  805. data/lib/hecks/quality_control/cli/qa_generated_domains/arguments.rb +62 -0
  806. data/lib/hecks/quality_control/cli/qa_generated_domains/blueprints.rb +45 -0
  807. data/lib/hecks/quality_control/cli/qa_generated_domains/evaluation.rb +107 -0
  808. data/lib/hecks/quality_control/cli/qa_generated_domains/promotion.rb +107 -0
  809. data/lib/hecks/quality_control/cli/qa_generated_domains/reporting.rb +97 -0
  810. data/lib/hecks/quality_control/cli/qa_generated_domains/shrinking.rb +70 -0
  811. data/lib/hecks/quality_control/cli/qa_generated_domains.rb +43 -327
  812. data/lib/hecks/quality_control/cli/qa_log_bug/arguments.rb +55 -0
  813. data/lib/hecks/quality_control/cli/qa_log_bug/proof.rb +65 -0
  814. data/lib/hecks/quality_control/cli/qa_log_bug.rb +18 -81
  815. data/lib/hecks/quality_control/cli/qa_mine_combinations/arguments.rb +54 -0
  816. data/lib/hecks/quality_control/cli/qa_mine_combinations/booting.rb +96 -0
  817. data/lib/hecks/quality_control/cli/qa_mine_combinations.rb +45 -109
  818. data/lib/hecks/quality_control/cli/qa_open_pr/arguments.rb +55 -0
  819. data/lib/hecks/quality_control/cli/qa_open_pr/recording.rb +79 -0
  820. data/lib/hecks/quality_control/cli/qa_open_pr/rules.rb +122 -0
  821. data/lib/hecks/quality_control/cli/qa_open_pr.rb +41 -200
  822. data/lib/hecks/quality_control/cli/qa_postgres_migrate/copying.rb +45 -0
  823. data/lib/hecks/quality_control/cli/qa_postgres_migrate/reporting.rb +33 -0
  824. data/lib/hecks/quality_control/cli/qa_postgres_migrate.rb +37 -63
  825. data/lib/hecks/quality_control/cli/qa_postgres_role/ownership.rb +57 -0
  826. data/lib/hecks/quality_control/cli/qa_postgres_role.rb +66 -71
  827. data/lib/hecks/quality_control/cli/qa_pr_check/checking.rb +118 -0
  828. data/lib/hecks/quality_control/cli/qa_pr_check/reporting.rb +54 -0
  829. data/lib/hecks/quality_control/cli/qa_pr_check.rb +28 -145
  830. data/lib/hecks/quality_control/cli/qa_seed_angles/seed.rb +80 -0
  831. data/lib/hecks/quality_control/cli/qa_seed_angles.rb +13 -86
  832. data/lib/hecks/quality_control/cli/qa_sweep/all_mode/children.rb +80 -0
  833. data/lib/hecks/quality_control/cli/qa_sweep/all_mode/report.rb +125 -0
  834. data/lib/hecks/quality_control/cli/qa_sweep/all_mode.rb +63 -193
  835. data/lib/hecks/quality_control/cli/qa_sweep/checks/boundary.rb +92 -0
  836. data/lib/hecks/quality_control/cli/qa_sweep/checks/engines.rb +92 -0
  837. data/lib/hecks/quality_control/cli/qa_sweep/checks/seeds.rb +86 -0
  838. data/lib/hecks/quality_control/cli/qa_sweep/checks/shrinking.rb +69 -0
  839. data/lib/hecks/quality_control/cli/qa_sweep/checks.rb +10 -248
  840. data/lib/hecks/quality_control/cli/qa_sweep/conclusion.rb +60 -0
  841. data/lib/hecks/quality_control/cli/qa_sweep/depth.rb +61 -0
  842. data/lib/hecks/quality_control/cli/qa_sweep/dials.rb +26 -13
  843. data/lib/hecks/quality_control/cli/qa_sweep/finding_report/shrunk.rb +42 -0
  844. data/lib/hecks/quality_control/cli/qa_sweep/finding_report.rb +40 -41
  845. data/lib/hecks/quality_control/cli/qa_sweep/parsing/validation.rb +70 -0
  846. data/lib/hecks/quality_control/cli/qa_sweep/parsing.rb +35 -65
  847. data/lib/hecks/quality_control/cli/qa_sweep/release_mode.rb +41 -22
  848. data/lib/hecks/quality_control/cli/qa_sweep/scratch.rb +67 -0
  849. data/lib/hecks/quality_control/cli/qa_sweep/seat.rb +94 -0
  850. data/lib/hecks/quality_control/cli/qa_sweep/seed_loop.rb +149 -0
  851. data/lib/hecks/quality_control/cli/qa_sweep/target_setup.rb +115 -0
  852. data/lib/hecks/quality_control/cli/qa_sweep.rb +22 -445
  853. data/lib/hecks/quality_control/cli/qa_tick/output.rb +107 -0
  854. data/lib/hecks/quality_control/cli/qa_tick/preflight.rb +95 -0
  855. data/lib/hecks/quality_control/cli/qa_tick.rb +42 -175
  856. data/lib/hecks/query_ir/formatting.rb +86 -0
  857. data/lib/hecks/query_ir/rules.rb +132 -0
  858. data/lib/hecks/query_ir/touchpoints.rb +104 -0
  859. data/lib/hecks/query_ir.rb +33 -281
  860. data/lib/hecks/query_ir_mcp/tools.rb +68 -0
  861. data/lib/hecks/query_ir_mcp.rb +27 -71
  862. data/lib/hecks/query_specification/common/comparison.rb +25 -5
  863. data/lib/hecks/query_specification/common/dsl.rb +1 -1
  864. data/lib/hecks/query_specification/common/null_policy.rb +9 -6
  865. data/lib/hecks/query_specification/common/options.rb +21 -14
  866. data/lib/hecks/query_specification/field_path.rb +5 -2
  867. data/lib/hecks/query_specification/hop_path.rb +15 -18
  868. data/lib/hecks/release/lane.rb +22 -0
  869. data/lib/hecks/release/runner/clean_tree.rb +2 -2
  870. data/lib/hecks/release/runner/commands.rb +1 -1
  871. data/lib/hecks/release/runner/options.rb +82 -0
  872. data/lib/hecks/release/runner/preflight.rb +12 -7
  873. data/lib/hecks/release/runner/publishing.rb +86 -0
  874. data/lib/hecks/release/runner/tagger.rb +8 -3
  875. data/lib/hecks/release/runner.rb +40 -156
  876. data/lib/hecks/rendering.rb +13 -9
  877. data/lib/hecks/router/door.rb +37 -0
  878. data/lib/hecks/router/namespace_installer.rb +45 -83
  879. data/lib/hecks/router/options_proxy.rb +44 -0
  880. data/lib/hecks/runtime/adapter_lookup.rb +45 -24
  881. data/lib/hecks/runtime/command_interpreter/argument_gate.rb +16 -8
  882. data/lib/hecks/runtime/command_interpreter/delegation.rb +116 -0
  883. data/lib/hecks/runtime/command_interpreter/enforcement.rb +38 -0
  884. data/lib/hecks/runtime/command_interpreter/hydration.rb +139 -0
  885. data/lib/hecks/runtime/command_interpreter/list_mutations.rb +98 -0
  886. data/lib/hecks/runtime/command_interpreter/mutation_applier.rb +67 -114
  887. data/lib/hecks/runtime/command_interpreter/persisting.rb +96 -0
  888. data/lib/hecks/runtime/command_interpreter.rb +57 -352
  889. data/lib/hecks/runtime/command_rules/admissibility.rb +64 -147
  890. data/lib/hecks/runtime/command_rules/arithmetic.rb +13 -72
  891. data/lib/hecks/runtime/command_rules/authorization.rb +9 -9
  892. data/lib/hecks/runtime/command_rules/emission.rb +13 -14
  893. data/lib/hecks/runtime/command_rules/guard_state.rb +49 -0
  894. data/lib/hecks/runtime/command_rules/invariants.rb +84 -0
  895. data/lib/hecks/runtime/command_rules/operands.rb +88 -0
  896. data/lib/hecks/runtime/command_rules/references.rb +59 -57
  897. data/lib/hecks/runtime/command_rules/tenant_boundary.rb +69 -0
  898. data/lib/hecks/runtime/dependency_planning/analyzer.rb +90 -0
  899. data/lib/hecks/runtime/dependency_planning/expression_reads.rb +73 -0
  900. data/lib/hecks/runtime/dependency_planning/mutation_analysis.rb +89 -0
  901. data/lib/hecks/runtime/dependency_planning/rule_analysis.rb +82 -0
  902. data/lib/hecks/runtime/dependency_planning.rb +3 -250
  903. data/lib/hecks/runtime/dispatcher/queries.rb +62 -0
  904. data/lib/hecks/runtime/dispatcher/result.rb +55 -0
  905. data/lib/hecks/runtime/dispatcher/routing.rb +107 -0
  906. data/lib/hecks/runtime/dispatcher.rb +64 -209
  907. data/lib/hecks/runtime/entity_element/location.rb +124 -0
  908. data/lib/hecks/runtime/entity_element/mutations.rb +150 -0
  909. data/lib/hecks/runtime/entity_element.rb +5 -177
  910. data/lib/hecks/runtime/entity_interpreter/enforcement.rb +51 -0
  911. data/lib/hecks/runtime/entity_interpreter/locating.rb +62 -0
  912. data/lib/hecks/runtime/entity_interpreter/resolution.rb +42 -0
  913. data/lib/hecks/runtime/entity_interpreter/saving.rb +49 -0
  914. data/lib/hecks/runtime/entity_interpreter.rb +45 -164
  915. data/lib/hecks/runtime/identity.rb +15 -9
  916. data/lib/hecks/runtime/instance.rb +11 -7
  917. data/lib/hecks/runtime/interpreting.rb +16 -8
  918. data/lib/hecks/runtime/invocation.rb +3 -155
  919. data/lib/hecks/runtime/invocation_builder.rb +132 -0
  920. data/lib/hecks/runtime/invocation_facts.rb +87 -0
  921. data/lib/hecks/runtime/loader/boot_steps.rb +96 -0
  922. data/lib/hecks/runtime/loader/described.rb +27 -0
  923. data/lib/hecks/runtime/loader.rb +27 -114
  924. data/lib/hecks/runtime/outbox/consumer_runner.rb +40 -0
  925. data/lib/hecks/runtime/outbox/fanout.rb +82 -0
  926. data/lib/hecks/runtime/outbox/relay.rb +149 -0
  927. data/lib/hecks/runtime/outbox.rb +3 -214
  928. data/lib/hecks/runtime/policy_interpreter/arguments.rb +67 -0
  929. data/lib/hecks/runtime/policy_interpreter/fan_out.rb +96 -0
  930. data/lib/hecks/runtime/policy_interpreter.rb +22 -137
  931. data/lib/hecks/runtime/port_operation_interpreter.rb +18 -17
  932. data/lib/hecks/runtime/query_interpreter/arguments.rb +51 -0
  933. data/lib/hecks/runtime/query_interpreter/entity_rows.rb +82 -0
  934. data/lib/hecks/runtime/query_interpreter/outside_answer.rb +89 -0
  935. data/lib/hecks/runtime/query_interpreter.rb +43 -191
  936. data/lib/hecks/runtime/reaction_invocation/identities.rb +92 -0
  937. data/lib/hecks/runtime/reaction_invocation/target_resolution.rb +88 -0
  938. data/lib/hecks/runtime/reaction_invocation.rb +66 -183
  939. data/lib/hecks/runtime/reaction_outcome.rb +7 -3
  940. data/lib/hecks/runtime/read_model_interpreter/head_ordering.rb +49 -0
  941. data/lib/hecks/runtime/read_model_interpreter/reductions.rb +123 -0
  942. data/lib/hecks/runtime/read_model_interpreter/shaping.rb +100 -0
  943. data/lib/hecks/runtime/read_model_interpreter.rb +71 -214
  944. data/lib/hecks/runtime/reference_hop.rb +11 -11
  945. data/lib/hecks/runtime/refusal_wording.rb +11 -8
  946. data/lib/hecks/runtime/registry/chapter_verification.rb +84 -0
  947. data/lib/hecks/runtime/registry/declarations.rb +17 -0
  948. data/lib/hecks/runtime/registry/durability_warnings.rb +71 -0
  949. data/lib/hecks/runtime/registry/hecksagon_rules.rb +124 -0
  950. data/lib/hecks/runtime/registry/merging.rb +49 -0
  951. data/lib/hecks/runtime/registry/providers.rb +139 -0
  952. data/lib/hecks/runtime/registry/query_verification.rb +144 -0
  953. data/lib/hecks/runtime/registry/read_repository.rb +61 -0
  954. data/lib/hecks/runtime/registry/runtime_state.rb +27 -0
  955. data/lib/hecks/runtime/registry/saga_persistence.rb +12 -8
  956. data/lib/hecks/runtime/registry/verification.rb +45 -389
  957. data/lib/hecks/runtime/registry/world_defaults.rb +3 -3
  958. data/lib/hecks/runtime/registry.rb +58 -296
  959. data/lib/hecks/runtime/remote_dispatcher.rb +47 -31
  960. data/lib/hecks/runtime/saga_interpreter/compensation.rb +90 -0
  961. data/lib/hecks/runtime/saga_interpreter/correlation.rb +19 -10
  962. data/lib/hecks/runtime/saga_interpreter/delivery.rb +147 -0
  963. data/lib/hecks/runtime/saga_interpreter/lifecycle.rb +63 -0
  964. data/lib/hecks/runtime/saga_interpreter/transitions.rb +112 -0
  965. data/lib/hecks/runtime/saga_interpreter.rb +41 -320
  966. data/lib/hecks/runtime/tenant_check.rb +14 -9
  967. data/lib/hecks/runtime/value/admission.rb +28 -19
  968. data/lib/hecks/runtime/value/coercion.rb +55 -404
  969. data/lib/hecks/runtime/value/entity_list_coercion.rb +27 -29
  970. data/lib/hecks/runtime/value/field_checks.rb +57 -100
  971. data/lib/hecks/runtime/value/flags.rb +65 -0
  972. data/lib/hecks/runtime/value/identifiers.rb +64 -0
  973. data/lib/hecks/runtime/value/references.rb +195 -0
  974. data/lib/hecks/runtime/value/shape_checks.rb +61 -0
  975. data/lib/hecks/runtime/value/validation.rb +125 -0
  976. data/lib/hecks/runtime/value.rb +18 -6
  977. data/lib/hecks/rust_build/conformance/surface.rb +75 -0
  978. data/lib/hecks/rust_build/conformance.rb +27 -59
  979. data/lib/hecks/rust_build/conformance_fuzz.rb +26 -15
  980. data/lib/hecks/rust_build/coverage.rb +32 -104
  981. data/lib/hecks/rust_build/coverage_parts/expected.rb +68 -0
  982. data/lib/hecks/rust_build/coverage_parts/printer.rb +75 -0
  983. data/lib/hecks/rust_build/host.rb +23 -13
  984. data/lib/hecks/rust_build/kernel_input.rb +19 -12
  985. data/lib/hecks/rust_build/native_build.rb +19 -15
  986. data/lib/hecks/rust_build/project_rust/domain_loader.rb +75 -0
  987. data/lib/hecks/rust_build/project_rust/root_mod/notes.rb +66 -0
  988. data/lib/hecks/rust_build/project_rust/root_mod.rb +22 -55
  989. data/lib/hecks/rust_build/project_rust/target_ir.rb +74 -0
  990. data/lib/hecks/rust_build/project_rust.rb +21 -89
  991. data/lib/hecks/rust_build/wasm.rb +11 -4
  992. data/lib/hecks/rust_build/wasm_browser.rb +7 -7
  993. data/lib/hecks/rust_build/write_if_changed.rb +3 -6
  994. data/lib/hecks/rust_build.rb +7 -3
  995. data/lib/hecks/site/bluebook/site.bluebook +7 -1
  996. data/lib/hecks/storehouse/audit.rb +106 -0
  997. data/lib/hecks/storehouse/callers.rb +73 -0
  998. data/lib/hecks/storehouse/dispatching.rb +149 -0
  999. data/lib/hecks/storehouse/introspection.rb +145 -0
  1000. data/lib/hecks/storehouse/querying.rb +78 -0
  1001. data/lib/hecks/storehouse.rb +43 -451
  1002. data/lib/hecks/tickets/bluebook/tickets.bluebook +29 -0
  1003. data/lib/hecks/tools/argument_gate_matrix/dispatching.rb +69 -0
  1004. data/lib/hecks/tools/argument_gate_matrix/rows.rb +121 -0
  1005. data/lib/hecks/tools/argument_gate_matrix/violations.rb +108 -0
  1006. data/lib/hecks/tools/argument_gate_matrix.rb +43 -212
  1007. data/lib/hecks/tools/ci_gate_decision.rb +21 -14
  1008. data/lib/hecks/tools/ci_gates.rb +40 -26
  1009. data/lib/hecks/tools/comment_style/baseline.rb +41 -0
  1010. data/lib/hecks/tools/comment_style/caps_words.rb +104 -0
  1011. data/lib/hecks/tools/comment_style/cli.rb +121 -0
  1012. data/lib/hecks/tools/comment_style/dictionary.rb +60 -0
  1013. data/lib/hecks/tools/comment_style/fixing.rb +119 -0
  1014. data/lib/hecks/tools/comment_style/long_blocks.rb +51 -0
  1015. data/lib/hecks/tools/comment_style/masking.rb +94 -0
  1016. data/lib/hecks/tools/comment_style/patterns.rb +61 -0
  1017. data/lib/hecks/tools/comment_style/run.rb +161 -0
  1018. data/lib/hecks/tools/comment_style/signature.rb +59 -0
  1019. data/lib/hecks/tools/comment_style/source_file.rb +105 -0
  1020. data/lib/hecks/tools/comment_style/structure_checks.rb +113 -0
  1021. data/lib/hecks/tools/comment_style/text_checks.rb +67 -0
  1022. data/lib/hecks/tools/comment_style/vocabulary.rb +55 -0
  1023. data/lib/hecks/tools/comment_style/walker.rb +136 -0
  1024. data/lib/hecks/tools/comment_style.rb +17 -1000
  1025. data/lib/hecks/tools/corpus_report.rb +26 -16
  1026. data/lib/hecks/tools/deploy_recipe/targets.rb +61 -0
  1027. data/lib/hecks/tools/deploy_recipe/worlds.rb +114 -0
  1028. data/lib/hecks/tools/deploy_recipe.rb +60 -174
  1029. data/lib/hecks/tools/deploy_recipe_lint/checks.rb +78 -0
  1030. data/lib/hecks/tools/deploy_recipe_lint/fixtures.rb +88 -0
  1031. data/lib/hecks/tools/deploy_recipe_lint/makefile.rb +84 -0
  1032. data/lib/hecks/tools/deploy_recipe_lint.rb +29 -192
  1033. data/lib/hecks/tools/drop_implicit_append_fields.rb +20 -12
  1034. data/lib/hecks/tools/era_projection_backfill.rb +50 -33
  1035. data/lib/hecks/tools/era_reattest/reporting.rb +55 -0
  1036. data/lib/hecks/tools/era_reattest.rb +32 -43
  1037. data/lib/hecks/tools/evolve_run/arguments.rb +49 -0
  1038. data/lib/hecks/tools/evolve_run/words.rb +60 -0
  1039. data/lib/hecks/tools/evolve_run.rb +43 -90
  1040. data/lib/hecks/tools/fuzz_sweep/findings.rb +106 -0
  1041. data/lib/hecks/tools/fuzz_sweep/options.rb +69 -0
  1042. data/lib/hecks/tools/fuzz_sweep/pool.rb +74 -0
  1043. data/lib/hecks/tools/fuzz_sweep/reporting.rb +88 -0
  1044. data/lib/hecks/tools/fuzz_sweep.rb +75 -273
  1045. data/lib/hecks/tools/gate.rb +31 -16
  1046. data/lib/hecks/tools/heki_compaction.rb +63 -42
  1047. data/lib/hecks/tools/hoist_local_givens/rewriting.rb +119 -0
  1048. data/lib/hecks/tools/hoist_local_givens.rb +89 -157
  1049. data/lib/hecks/tools/journal_compaction.rb +40 -31
  1050. data/lib/hecks/tools/lanes/files.rb +82 -0
  1051. data/lib/hecks/tools/lanes/live.rb +41 -0
  1052. data/lib/hecks/tools/lanes/rows.rb +45 -0
  1053. data/lib/hecks/tools/lanes/ruleset.rb +44 -0
  1054. data/lib/hecks/tools/lanes/watch_workflow.rb +82 -0
  1055. data/lib/hecks/tools/lanes/workflow.rb +79 -0
  1056. data/lib/hecks/tools/lanes.rb +71 -0
  1057. data/lib/hecks/tools/oidc_manifests.rb +10 -9
  1058. data/lib/hecks/tools/query_ir_run.rb +7 -3
  1059. data/lib/hecks/tools/regeneration_run.rb +40 -26
  1060. data/lib/hecks/tools/rust_comment_style/caps_words.rb +98 -0
  1061. data/lib/hecks/tools/rust_comment_style/fixing.rb +102 -0
  1062. data/lib/hecks/tools/rust_comment_style/masking.rb +85 -0
  1063. data/lib/hecks/tools/rust_comment_style/run.rb +94 -0
  1064. data/lib/hecks/tools/rust_comment_style/source_file.rb +71 -0
  1065. data/lib/hecks/tools/rust_comment_style/structure.rb +79 -0
  1066. data/lib/hecks/tools/rust_comment_style/text_checks.rb +63 -0
  1067. data/lib/hecks/tools/rust_comment_style/tokenizer.rb +102 -0
  1068. data/lib/hecks/tools/rust_comment_style.rb +38 -535
  1069. data/lib/hecks/tools/sequence_script.rb +20 -14
  1070. data/lib/hecks/tools/site_routes/cli.rb +70 -0
  1071. data/lib/hecks/tools/site_routes/root_files.rb +59 -0
  1072. data/lib/hecks/tools/site_routes/templates.rb +77 -0
  1073. data/lib/hecks/tools/site_routes.rb +102 -108
  1074. data/lib/hecks/tools/tail_merge.rb +45 -37
  1075. data/lib/hecks/tools/tenant_provisioning.rb +45 -31
  1076. data/lib/hecks/tools/tools_doc.rb +42 -19
  1077. data/lib/hecks/tools/translation_audit/domain_loading.rb +71 -0
  1078. data/lib/hecks/tools/translation_audit/edges.rb +71 -0
  1079. data/lib/hecks/tools/translation_audit/verdicts.rb +107 -0
  1080. data/lib/hecks/tools/translation_audit.rb +30 -161
  1081. data/lib/hecks/tools/translation_scaffold/reporting.rb +40 -0
  1082. data/lib/hecks/tools/translation_scaffold.rb +77 -60
  1083. data/lib/hecks/tools.rb +1 -0
  1084. data/lib/hecks/vendoring.rb +37 -11
  1085. data/lib/hecks/version.rb +1 -1
  1086. data/lib/hecks/vocabulary.rb +16 -1
  1087. data/lib/rubocop/cop/hecks/fallback_hash_lookup.rb +7 -9
  1088. data/lib/rubocop/cop/hecks/thread_shared_ivar_mutation.rb +8 -6
  1089. data/rust/.cargo/mutants.toml +8 -0
  1090. data/rust/host/Cargo.toml +5 -0
  1091. data/rust/host/HECKS_RELEASE +1 -1
  1092. data/rust/host/src/auth.rs +32 -0
  1093. data/rust/host/src/web.rs +2 -3
  1094. data/rust/src/kernel/dispatch.rs +4 -0
  1095. data/rust/src/kernel/dispatch_guard_tests.rs +506 -0
  1096. data/rust/src/kernel/orchestrate.rs +4 -0
  1097. data/rust/src/kernel/orchestrate_guard_tests.rs +708 -0
  1098. metadata +607 -3
  1099. /data/lib/hecks/bluebook/behaviour/{hexagon.rb → hecksagon.rb} +0 -0
@@ -2,8 +2,10 @@ require_relative "../../projector"
2
2
  require_relative "shared"
3
3
  require_relative "scripts"
4
4
  require_relative "preview"
5
+ require_relative "text_template"
5
6
  require_relative "fargate/settings"
6
7
  require_relative "fargate/assembly"
8
+ require_relative "fargate/stack"
7
9
 
8
10
  module Hecks
9
11
  module Projections
@@ -25,770 +27,63 @@ module Hecks
25
27
  # @return [Hash{String => String}] the generated file contents, keyed by filename
26
28
  # @raise [ArgumentError] if the domain's deploy settings conflict
27
29
  def call(bluebook:, options: {})
28
- world = options.fetch(:world)
29
- domain = options.fetch(:domain_dir)
30
- root = options.fetch(:root)
31
- world_file = options.fetch(:world_file)
32
- cross_domain_registry = options.fetch(:cross_domain_registry)
33
- tenant_options = options[:tenant] || {}
34
-
35
- domain_name = File.basename(domain)
36
- declared_domain_name = world.domain
37
-
38
- deploy_settings = world.for_verb("deployed_to")
39
-
40
- # Same tenant override `Lambda.call` applies; see that method's comment.
41
- if tenant_options[:tenant]
42
- base_stack_name = deploy_settings[:stack_name] || domain_name
43
- deploy_settings = deploy_settings.merge(stack_name: "#{base_stack_name}-#{tenant_options[:tenant]}",
44
- schema: tenant_options[:schema] || tenant_options[:tenant])
45
- end
46
-
47
- infra_name = deploy_settings[:stack_name] || domain_name
48
- db_name = infra_name.gsub(/[^a-zA-Z0-9]/, "")
49
-
50
- # Validated the same way `Lambda.call` validates its own target —
51
- # `deploy.bluebook`'s own `FargateTarget.Declare`, not a
52
- # hand-checked `fetch(:cpu) { raise ... }` chain.
53
- deploy_dispatcher = Hecks.boot(File.expand_path("../../deploy", __dir__))
54
- begin
55
- target = deploy_dispatcher.dispatch(
56
- "Deploy::FargateTarget.Declare",
57
- with: {
58
- domain: { value: declared_domain_name },
59
- region: { value: deploy_settings[:region] },
60
- cpu: { value: deploy_settings.fetch(:cpu, 256) },
61
- memory: { value: deploy_settings.fetch(:memory, 512) },
62
- database: { value: deploy_settings.fetch(:database, "Postgres") },
63
- web: { value: deploy_settings.fetch(:web, "None") },
64
- port: { value: deploy_settings.fetch(:port, 8080) }
65
- }
66
- ).instance
67
- rescue *Hecks::Runtime::DOMAIN_REFUSALS => e
68
- raise ArgumentError, "#{world_file}'s deployed_to(\"AwsFargate\") is invalid: #{e.message}"
69
- end
70
-
71
- region = target.state[:region].value
72
- cpu = target.state[:cpu].value
73
- memory = target.state[:memory].value
74
- database = target.state[:database].value
75
- port = target.state[:port].value
76
- aurora = database == "Aurora"
77
- shared = database == "Shared"
78
- rust_web = target.state[:web].value == "Rust"
79
- # Same `.env.local` convention `Lambda` uses; `make sync-google-oauth`
80
- # owns the secret's lifecycle. Fargate only declares
81
- # GOOGLE_OAUTH_SECRET_ID — the secret itself is never a stack resource.
82
- google_oauth_present = rust_web &&
83
- File.exist?(File.join(domain, ".env.local")) &&
84
- File.read(File.join(domain, ".env.local")).match?(/^GOOGLE_CLIENT_ID=\S/)
85
-
86
- # Every policy in every loaded chapter — see `Lambda.call`'s own
87
- # comment on why this reads the whole registry, not only this
88
- # domain's own top-level list.
89
- cross_domain_fargate_targets = cross_domain_registry.bluebooks.flat_map { |_name, chapter|
90
- chapter.policies.select(&:target_domain).map(&:target_domain)
91
- }.uniq.sort
92
-
93
- # Same "Shared" borrowing `Lambda.call` supports; see that method's
94
- # comment. `owner`/`owner_stack` stay plain `deploy_settings` reads,
95
- # never validated attributes — ownership is a deploy-time wiring fact.
96
- if shared
97
- owner_domain_name = deploy_settings[:owner] or raise ArgumentError, <<~MSG
98
- #{world_file}'s deployed_to("AwsFargate") declares database "Shared" but no owner. Add one, e.g.:
99
-
100
- deployed_to("AwsFargate") do
101
- ...
102
- database "Shared"
103
- owner "Core"
104
- end
105
-
106
- naming the already-deployed domain whose Postgres instance this one borrows.
107
- MSG
108
- owner_stack_name = deploy_settings[:owner_stack] || "hecks-#{owner_domain_name.downcase}"
109
- owner_db_name = owner_domain_name.downcase
110
- end
111
-
112
- hecks_schema = shared ? infra_name : deploy_settings[:schema]
113
-
114
- # `infra_name` is already alphanumeric-only + hyphen-friendly for
115
- # CloudFormation's own logical-id character set, matching
116
- # `Lambda.call`'s own `logical_id` convention.
117
- logical_id = "#{infra_name.split(/[_-]/).map(&:capitalize).join}Service"
118
- stack_prefix = deploy_settings[:stack_prefix] || "hecks"
119
- stack_name = "#{stack_prefix}-#{infra_name}"
120
- desired_count = deploy_settings.fetch(:desired_count, 1)
121
-
122
- # Every optional setting, checked; a world that sets none resolves to the
123
- # derived ids and names the generator has always used.
124
- begin
125
- plan = Settings.resolve(
126
- deploy_settings,
127
- infra_name: infra_name, logical_id: logical_id, db_id: "#{logical_id.sub(/Service\z/, '')}Db",
128
- stack_name: stack_name, port: port, shared: shared
129
- )
130
- rescue ArgumentError => e
131
- raise ArgumentError, "#{world_file}'s deployed_to(\"AwsFargate\"): #{e.message}"
132
- end
133
- ids = plan.ids
134
- names = plan.names
135
- layout = plan.layout
136
-
137
- db_id = ids[:database_prefix]
138
- db_ref_id = aurora ? "#{db_id}Cluster" : db_id
139
- secret_sub = aurora ? "#{db_id}Secret" : "#{db_ref_id}.MasterUserSecret.SecretArn"
140
- secret_intrinsic = aurora ? "!Ref #{db_id}Secret" : "!GetAtt #{db_ref_id}.MasterUserSecret.SecretArn"
141
- db_secret_ref = shared ? "OwningDatabaseSecretArn" : secret_sub
142
-
143
- # Always true here: unlike Lambda's opt-in NAT Gateway, a Fargate task
144
- # always needs internet-facing infra (ALB ingress, ECR/Logs/Secrets
145
- # egress), so `Shared.vpc_and_database_yaml`'s NAT Gateway is unconditional.
146
- network_needs_internet = true
147
-
148
- # Never created when `shared` — this domain's own VPC (and its compute
149
- # security group) is skipped entirely; the task and ALB-ingress rule
150
- # reach through the borrowed owner's security group instead.
151
- compute_security_group_ref = shared ? "!Ref OwningSecurityGroupId" : "!Ref #{ids[:compute_prefix]}SecurityGroup"
152
-
153
- # `logical_id` stays the derived name in prose (descriptions, comments);
154
- # the ids below are what the resources are actually declared with, which
155
- # the world's `logical_ids` setting may replace.
156
- service_id = ids[:service]
157
- ecr_repository_id = ids[:ecr_repository]
158
- cluster_id = ids[:cluster]
159
- task_definition_id = ids[:task_definition]
160
- execution_role_id = ids[:execution_role]
161
- task_role_id = ids[:task_role]
162
- log_group_id = ids[:log_group]
163
- target_group_id = ids[:target_group]
164
- alb_id = ids[:alb]
165
- alb_sg_id = ids[:alb_security_group]
166
- listener_id = ids[:listener]
167
- distribution_id = ids[:distribution]
168
- session_secret_id = ids[:session_secret]
169
- domain_container = layout.domain
170
- alb_sg_description = names[:alb_security_group_description] ||
171
- "#{alb_sg_id} - HTTP ingress from CloudFront only, forwarded to #{logical_id} only"
172
- port_range = Containers.port_range(layout)
173
- vpc_ref = shared ? "!Ref OwningVpcId" : "!Ref #{db_id}Vpc"
174
- sidecar_dir = plan.install_dir
175
- db_name_ref = plan.db_name_parameter ? "!Ref #{plan.db_name_parameter}" : nil
176
-
177
- stack_outputs = Shared.stack_outputs(
178
- shared: shared, db_id: db_id, db_ref_id: db_ref_id, secret_intrinsic: secret_intrinsic,
179
- compute_security_group_ref: compute_security_group_ref, google_oauth_present: network_needs_internet
180
- )
181
- bastion_parameters = Shared.bastion_parameters(shared: shared, google_oauth_present: network_needs_internet)
182
- Shared.check_bastion_parameters!(bastion_parameters, stack_outputs)
183
-
184
- always_params_yaml = <<~ALWAYSPARAMS.rstrip
185
- #{domain_container.tag_parameter}:
186
- Type: String
187
- Default: latest
188
- Description: ECR image tag this task pulls — never hardcode latest in the TaskDefinition; a first deploy and a later rollout share this one parameter.
189
- ALWAYSPARAMS
190
- oauth_params_yaml = google_oauth_present ? <<~OAUTHPARAMS.rstrip : ""
191
- # Same chicken-egg as Lambda's WebRedirectBaseUrl — CloudFront's
192
- # hostname does not exist until this stack does. Empty on a true
193
- # first deploy; `make deploy` looks up Outputs.CloudFrontDomain
194
- # after and self-heals.
195
- WebRedirectBaseUrl:
196
- Type: String
197
- Default: ""
198
- OAUTHPARAMS
199
- # Built outside the heredoc so re-indenting the template can't shift
200
- # this YAML out of sync with SessionSecretRead/env — same pattern
201
- # as `Lambda`'s own `OAUTHPOLICY`.
202
- oauth_task_policy_yaml = google_oauth_present ? <<~OAUTHPOLICY.rstrip : ""
203
- - PolicyName: GoogleOauthSecretRead
204
- PolicyDocument:
205
- Version: '2012-10-17'
206
- Statement:
207
- - Effect: Allow
208
- Action: secretsmanager:GetSecretValue
209
- Resource: !Sub "arn:aws:secretsmanager:${AWS::Region}:${AWS::AccountId}:secret:#{stack_name}-web-google-oauth-*"
210
- OAUTHPOLICY
211
- oauth_task_env_yaml = google_oauth_present ? <<~OAUTHENV.rstrip : ""
212
- - Name: GOOGLE_OAUTH_SECRET_ID
213
- Value: #{stack_name}-web-google-oauth
214
- - Name: GOOGLE_REDIRECT_URI
215
- Value: !Sub "${WebRedirectBaseUrl}/auth/google/callback"
216
- OAUTHENV
217
- owning_params_yaml = shared ? <<~SHAREDPARAMS.rstrip : ""
218
- # The storehouse — #{owner_domain_name}'s own live stack Outputs,
219
- # looked up at deploy time (the generated Makefile's own `deploy:`
220
- # target) via `aws cloudformation describe-stacks`, the identical
221
- # pattern `Lambda`'s own generated Makefile already uses for a
222
- # Shared-mode domain.
223
- OwningVpcId:
224
- Type: AWS::EC2::VPC::Id
225
- OwningSubnetAId:
226
- Type: AWS::EC2::Subnet::Id
227
- OwningSubnetBId:
228
- Type: AWS::EC2::Subnet::Id
229
- # PUBLIC subnets, NOT OwningSubnetAId/OwningSubnetBId above — a
230
- # real, live deploy (a shared-database stack) found the ALB placed in
231
- # the private pair creates successfully and reports its target
232
- # health as healthy (health checks run from inside the VPC), yet
233
- # is completely unreachable from outside it:
234
- # OwningSubnetAId/OwningSubnetBId have MapPublicIpOnLaunch: false
235
- # and no Internet Gateway route. These two — resolved from the
236
- # owner stack's own PublicSubnetId/BastionSubnetId Outputs,
237
- # MapPublicIpOnLaunch: true with a real 0.0.0.0/0 -> igw route —
238
- # are the pair that actually works for an internet-facing ALB.
239
- # Service.NetworkConfiguration below still (correctly) uses the
240
- # private pair for the tasks themselves — only the ALB moves.
241
- OwningPublicSubnetAId:
242
- Type: AWS::EC2::Subnet::Id
243
- OwningPublicSubnetBId:
244
- Type: AWS::EC2::Subnet::Id
245
- OwningSecurityGroupId:
246
- Type: AWS::EC2::SecurityGroup::Id
247
- OwningDatabaseEndpoint:
248
- Type: String
249
- OwningDatabaseSecretArn:
250
- Type: String
251
- SHAREDPARAMS
252
- extra_params_yaml = Settings.parameters_yaml(plan, default_count: desired_count, shared_db_name: owner_db_name).rstrip
253
- parameters_yaml = [always_params_yaml, oauth_params_yaml, owning_params_yaml, extra_params_yaml].reject(&:empty?).join("\n")
254
-
255
- template_yaml = <<~YAML
256
- # GENERATED by hecks deploy project #{domain} — re-run it to refresh
257
- # this file rather than hand-editing. Source: #{world_file}'s own
258
- # deployed_to("AwsFargate") block.
259
- #
260
- # Plain CloudFormation, not SAM — deployed with
261
- # `aws cloudformation deploy`, never `sam deploy`. Self-contained
262
- # the same way `Lambda`'s own template is: this stack owns its own
263
- # private VPC, subnets, and RDS Postgres instance (unless
264
- # database "Shared"), not just the ECS service.
265
- AWSTemplateFormatVersion: '2010-09-09'
266
- Description: >
267
- #{infra_name} — dispatched through hecks's rust/host, running as a
268
- long-lived container on AWS Fargate, backed by its own private RDS
269
- Postgres instance.
270
- #{parameters_yaml.empty? ? "" : "Parameters:\n" + parameters_yaml.each_line.map { |l| " #{l}" }.join}
271
- Resources:
272
- #{shared ? "" : Shared.vpc_and_database_yaml(
273
- db_id: db_id, db_name: db_name, infra_name: infra_name, aurora: aurora,
274
- google_oauth_present: network_needs_internet, compute_logical_id: ids[:compute_prefix],
275
- compute_description: "#{logical_id} - inbound from #{alb_sg_id} only, egress rules attached separately below"
276
- ).each_line.with_index.map { |l, i| (i.zero? ? "" : " ") + l }.join.rstrip}
277
-
278
- #{alb_sg_id}:
279
- Type: AWS::EC2::SecurityGroup
280
- Properties:
281
- VpcId: #{vpc_ref}
282
- GroupDescription: #{alb_sg_description}
283
- SecurityGroupIngress:
284
- # pl-3b927c52 — com.amazonaws.global.cloudfront.origin-
285
- # facing, AWS's own global, account-agnostic managed
286
- # prefix list (confirmed: `aws ec2 describe-managed-
287
- # prefix-lists`, OwnerId "AWS", same id in every
288
- # account/region). NOT 0.0.0.0/0 — the whole reason
289
- # #{distribution_id} above exists is Managed-
290
- # CachingDisabled on every session-cookie-driven
291
- # route; leaving the ALB itself open to the public
292
- # internet on this same port would let anyone bypass
293
- # that distribution (and its HTTPS) entirely and hit
294
- # the plain-HTTP origin directly — the exact gap a
295
- # code review caught the first time this resource was
296
- # added.
297
- - IpProtocol: tcp
298
- FromPort: 80
299
- ToPort: 80
300
- SourcePrefixListId: pl-3b927c52
301
-
302
- #{ids[:ingress_from_alb]}:
303
- Type: AWS::EC2::SecurityGroupIngress
304
- Properties:
305
- GroupId: #{compute_security_group_ref}
306
- IpProtocol: tcp
307
- FromPort: #{port_range.min}
308
- ToPort: #{port_range.max}
309
- SourceSecurityGroupId: !Ref #{alb_sg_id}
310
-
311
- #{ecr_repository_id}:
312
- Type: AWS::ECR::Repository
313
- Properties:
314
- RepositoryName: #{domain_container.repository_name}
315
- ImageScanningConfiguration:
316
- ScanOnPush: true
317
-
318
- #{cluster_id}:
319
- Type: AWS::ECS::Cluster
320
- Properties:
321
- ClusterName: #{names[:cluster]}
322
-
323
- #{log_group_id}:
324
- Type: AWS::Logs::LogGroup
325
- Properties:
326
- LogGroupName: #{names[:log_group]}
327
- RetentionInDays: 30
328
-
329
- # Always minted — HECKS_SERVE_MODE always runs web.rs, which
330
- # panics on an empty SESSION_SECRET (seen live as a 502
331
- # after a database cutover). rust/host fetches this at cold
332
- # start (secrets.rs), never a plain env var.
333
- #{session_secret_id}:
334
- Type: AWS::SecretsManager::Secret
335
- Properties:
336
- # TMPL:session_secret_properties
337
- GenerateSecretString:
338
- SecretStringTemplate: '{}'
339
- GenerateStringKey: session_secret
340
- PasswordLength: 64
341
- ExcludePunctuation: true
342
-
343
- # Pulls the image and writes CloudWatch Logs — AWS's own managed
344
- # AmazonECSTaskExecutionRolePolicy already covers both (ECR auth
345
- # + GetDownloadUrlForLayer, and logs:CreateLogStream/PutLogEvents);
346
- # the one grant that policy does NOT cover is fetching this
347
- # domain's own database secret, added below, least-privilege,
348
- # scoped to the single secret ARN this stack itself depends on.
349
- #{execution_role_id}:
350
- Type: AWS::IAM::Role
351
- Properties:
352
- AssumeRolePolicyDocument:
353
- Version: '2012-10-17'
354
- Statement:
355
- - Effect: Allow
356
- Principal: { Service: ecs-tasks.amazonaws.com }
357
- Action: sts:AssumeRole
358
- ManagedPolicyArns:
359
- - arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy
360
- Policies:
361
- # TMPL:execution_database_grant
362
- # TMPL:extra_execution_policies
363
-
364
- # The container's OWN runtime permissions — rust/host fetches
365
- # DB_SECRET_ARN itself, over the AWS SDK, the same "never let
366
- # CloudFormation/ECS configuration see it resolved" posture
367
- # `Lambda`'s own generated template already holds to (a
368
- # `Secrets:` ContainerDefinition property would resolve it
369
- # into a plain environment variable instead).
370
- #{task_role_id}:
371
- Type: AWS::IAM::Role
372
- Properties:
373
- AssumeRolePolicyDocument:
374
- Version: '2012-10-17'
375
- Statement:
376
- - Effect: Allow
377
- Principal: { Service: ecs-tasks.amazonaws.com }
378
- Action: sts:AssumeRole
379
- Policies:
380
- - PolicyName: #{names[:db_secret_policy]}
381
- PolicyDocument:
382
- Version: '2012-10-17'
383
- Statement:
384
- - Effect: Allow
385
- Action: secretsmanager:GetSecretValue
386
- Resource: !Sub "${#{db_secret_ref}}"
387
- - PolicyName: SessionSecretRead
388
- PolicyDocument:
389
- Version: '2012-10-17'
390
- Statement:
391
- - Effect: Allow
392
- Action: secretsmanager:GetSecretValue
393
- Resource: !Ref #{session_secret_id}
394
- #{oauth_task_policy_yaml.empty? ? "" : "# TMPL:oauth_task_policy"}
395
- # TMPL:cross_domain_fargate_policies
396
- # TMPL:extra_task_policies
397
-
398
- #{task_definition_id}:
399
- Type: AWS::ECS::TaskDefinition
400
- Properties:
401
- Family: #{names[:family]}
402
- RequiresCompatibilities: [FARGATE]
403
- NetworkMode: awsvpc
404
- # ARM64, not Fargate's own x86_64 default — matching the
405
- # generated Makefile's own aarch64-unknown-linux-gnu build
406
- # (below) and Lambda's own arm64 toolchain this reuses; a
407
- # container built for the wrong arch fails at task start,
408
- # not at build time, so this has to agree with the image
409
- # docker-build actually pushes.
410
- RuntimePlatform:
411
- CpuArchitecture: ARM64
412
- OperatingSystemFamily: LINUX
413
- Cpu: "#{cpu}"
414
- Memory: "#{memory}"
415
- ExecutionRoleArn: !GetAtt #{execution_role_id}.Arn
416
- TaskRoleArn: !GetAtt #{task_role_id}.Arn
417
- ContainerDefinitions:
418
- - Name: #{domain_container.name}
419
- Image: !Sub "${#{ecr_repository_id}.RepositoryUri}:${#{domain_container.tag_parameter}}"
420
- # TMPL:domain_essential
421
- PortMappings:
422
- - ContainerPort: #{port}
423
- LogConfiguration:
424
- LogDriver: awslogs
425
- Options:
426
- awslogs-group: !Ref #{log_group_id}
427
- awslogs-region: !Ref AWS::Region
428
- awslogs-stream-prefix: #{domain_container.name}
429
- Environment:
430
- - Name: HECKS_DOMAIN
431
- Value: #{declared_domain_name}
432
- - Name: HECKS_ERA
433
- Value: "1"
434
- - Name: PORT
435
- Value: "#{port}"
436
- # `rust/host/src/server.rs`'s own top-of-`main`
437
- # switch — without it, this container runs as the
438
- # Lambda custom-runtime process `Lambda`'s own
439
- # generated binary always has, which blocks
440
- # forever polling a Runtime API that doesn't exist
441
- # here, never answering the health check or
442
- # anything else on `port`.
443
- - Name: HECKS_SERVE_MODE
444
- Value: "1"
445
- # `web "Rust"` vs `web "None"` is otherwise inert
446
- # here today — both modes generate the identical
447
- # task/service/target-group shape, since a Fargate
448
- # task always answers HTTP on `port` for dispatch
449
- # requests either way. Passed through so
450
- # `rust/host`'s own server loop (server.rs) can
451
- # read it and decide whether to also serve the
452
- # public web UI in-process, the same `web`-shaped
453
- # choice `Lambda`'s own `rust_web` already makes
454
- # for the Lambda path.
455
- - Name: HECKS_WEB
456
- Value: #{target.state[:web].value}
457
- # HECKS_WASM_PATH/HECKS_IR_PATH — main.rs requires
458
- # both unconditionally at boot (ir::ir().ok_or(...)?,
459
- # no fallback, and HECKS_WASM_PATH for every
460
- # dispatch) regardless of `web`/HECKS_SERVE_MODE. A
461
- # container built with neither set crashes before
462
- # ever reaching its own serve loop — found live
463
- # deploying a real domain container, fixed here so every Fargate domain ships
464
- # both sidecars by default. Paths match the
465
- # Dockerfile's own COPY destinations, below.
466
- - Name: HECKS_WASM_PATH
467
- Value: #{sidecar_dir}/#{domain_name}.wasm
468
- - Name: HECKS_IR_PATH
469
- Value: #{sidecar_dir}/#{domain_name}.ir.json
470
- - Name: SESSION_SECRET_ARN
471
- Value: !Ref #{session_secret_id}
472
- - Name: HECKS_CHECKOUT_DOMAIN
473
- Value: #{declared_domain_name}
474
- #{oauth_task_env_yaml.empty? ? "" : "# TMPL:oauth_task_env"}
475
- # TMPL:db_env
476
- # TMPL:domain_env
477
- # TMPL:extra_containers
478
-
479
- #{target_group_id}:
480
- Type: AWS::ElasticLoadBalancingV2::TargetGroup
481
- Properties:
482
- TargetType: ip
483
- Port: #{port}
484
- Protocol: HTTP
485
- VpcId: #{vpc_ref}
486
- HealthCheckPath: #{domain_container.health_path}
487
- HealthCheckPort: "#{port}"
488
- # TMPL:target_group_attributes
489
-
490
- #{alb_id}:
491
- Type: AWS::ElasticLoadBalancingV2::LoadBalancer
492
- Properties:
493
- Name: #{names[:alb]}
494
- Scheme: internet-facing
495
- Type: application
496
- SecurityGroups: [!Ref #{alb_sg_id}]
497
- Subnets: #{shared ? "[!Ref OwningPublicSubnetAId, !Ref OwningPublicSubnetBId]" : "[!Ref #{db_id}PublicSubnet, !Ref #{db_id}BastionPublicSubnet]"}
498
-
499
- #{listener_id}:
500
- Type: AWS::ElasticLoadBalancingV2::Listener
501
- Properties:
502
- LoadBalancerArn: !Ref #{alb_id}
503
- Port: 80
504
- Protocol: HTTP
505
- DefaultActions:
506
- - Type: forward
507
- TargetGroupArn: !Ref #{layout.default.target_group_id}
508
-
509
- # TMPL:extra_target_groups
510
- #{service_id}:
511
- Type: AWS::ECS::Service
512
- DependsOn: #{Containers.depends_on(layout, listener_id)}
513
- Properties:
514
- ServiceName: #{names[:service]}
515
- Cluster: !Ref #{cluster_id}
516
- TaskDefinition: !Ref #{task_definition_id}
517
- DesiredCount: #{plan.desired_count_parameter ? "!Ref #{plan.desired_count_parameter}" : desired_count}
518
- LaunchType: FARGATE
519
- # TMPL:service_tuning
520
- NetworkConfiguration:
521
- AwsvpcConfiguration:
522
- AssignPublicIp: DISABLED
523
- Subnets: #{shared ? "[!Ref OwningSubnetAId, !Ref OwningSubnetBId]" : "[!Ref #{db_id}SubnetA, !Ref #{db_id}SubnetB]"}
524
- SecurityGroups: [#{compute_security_group_ref}]
525
- LoadBalancers:
526
- - ContainerName: #{domain_container.name}
527
- ContainerPort: #{port}
528
- TargetGroupArn: !Ref #{target_group_id}
529
- # TMPL:extra_load_balancers
530
-
531
- # TMPL:distribution
532
-
533
- # TMPL:extra_resources
534
- Outputs:
535
- ServiceUrl:
536
- Value: !Sub "http://${#{alb_id}.DNSName}"
537
- CloudFrontDomain:
538
- Value: !GetAtt #{distribution_id}.DomainName
539
- #{stack_outputs.map { |o| "#{o[:key]}:\n Value: #{o[:ref]}" }.join("\n ")}
540
- # TMPL:extra_outputs
541
- YAML
542
-
543
- # Spliced in after the heredoc renders, not interpolated inside it —
544
- # `<<~` dedents from raw source before `#{...}` evaluates, so a
545
- # multi-line value can't be reindented a second time by the heredoc.
546
- template_yaml = template_yaml.sub(/^([ \t]*)# TMPL:db_env\n/) { db_env_yaml(shared: shared, owner_db_name: owner_db_name, db_ref_id: db_ref_id, db_name: db_name, secret_sub: secret_sub, hecks_schema: hecks_schema, db_name_ref: db_name_ref, base: $1) }
547
- # Indented by the marker's own rendered column, never a hand-computed
548
- # one — the heredoc dedents after interpolation, so a source-counted
549
- # column lands at the wrong depth.
550
- template_yaml = Yaml.splice(template_yaml, "oauth_task_policy", "#{oauth_task_policy_yaml}\n")
551
- template_yaml = Yaml.splice(template_yaml, "oauth_task_env", "#{oauth_task_env_yaml}\n")
552
- template_yaml = template_yaml.sub(/^([ \t]*)# TMPL:cross_domain_fargate_policies\n/) {
553
- cross_domain_fargate_targets.empty? ? "" : cross_domain_fargate_policy_yaml(cross_domain_fargate_targets, $1)
554
- }
555
-
556
- begin
557
- template_yaml = Assembly.apply(
558
- template_yaml, plan,
559
- stack_name: stack_name, vpc_ref: vpc_ref, listener_id: listener_id, alb_id: alb_id, distribution_id: distribution_id,
560
- db_secret_ref: db_secret_ref
561
- )
562
- rescue ArgumentError => e
563
- raise ArgumentError, "#{world_file}'s deployed_to(\"AwsFargate\"): #{e.message}"
564
- end
565
-
566
- bastion_yaml = shared ? nil : Shared.bastion_yaml(
567
- domain: domain, infra_name: infra_name, stack_name: stack_name, db_id: db_id,
568
- google_oauth_present: network_needs_internet, bastion_parameters: bastion_parameters
569
- )
570
-
571
- dockerfile = <<~DOCKERFILE
572
- # GENERATED by hecks deploy project #{domain} — re-run it to refresh this
573
- # file rather than hand-editing. Modeled on a Ruby deployment's own
574
- # Dockerfile shape: build the binary outside the image (this directory's own
575
- # Makefile, before `docker build` runs), ship only the result — one COPY,
576
- # not a from-scratch toolchain install on every deploy.
577
- FROM debian:bookworm-slim
578
-
579
- # ca-certificates — real outbound TLS (Secrets Manager, any third-party
580
- # API this domain calls) needs a real system CA bundle.
581
- # libpq5 — Adapters::PostgresEra's own native `tokio_postgres`/libpq
582
- # linkage needs the actual shared library present at runtime, the same
583
- # reason Lambda's own generated Makefile patches libpq.so onto that
584
- # package's Ruby-side equivalent.
585
- RUN apt-get update -qq && apt-get install -y --no-install-recommends -qq ca-certificates libpq5 \\
586
- && rm -rf /var/lib/apt/lists/*
587
-
588
- COPY #{plan.build_context_dir}#{domain_name}-host #{sidecar_dir}/#{domain_name}-host
589
- # The .wasm/.ir.json sidecars main.rs requires at boot —
590
- # HECKS_WASM_PATH/HECKS_IR_PATH (template.yaml's own
591
- # ContainerDefinitions Environment) point at these exact paths.
592
- COPY #{plan.build_context_dir}#{domain_name}.wasm #{sidecar_dir}/#{domain_name}.wasm
593
- COPY #{plan.build_context_dir}#{domain_name}.ir.json #{sidecar_dir}/#{domain_name}.ir.json
594
-
595
- ENV PORT=#{port}
596
- ENV BIND=0.0.0.0
597
- EXPOSE #{port}
598
-
599
- CMD ["#{sidecar_dir == Settings::DEFAULT_INSTALL_DIR ? domain_name : "#{sidecar_dir}/#{domain_name}"}-host"]
600
- DOCKERFILE
601
-
602
- makefile_content = <<~MAKE
603
- # GENERATED by hecks deploy project #{domain} — re-run it to refresh
604
- # this file rather than hand-editing.
605
- #
606
- # `make deploy` — builds rust/host for this domain, pushes it to this
607
- # stack's own ECR repository, and deploys the CloudFormation stack.
608
- # No SAM anywhere in this path.
609
-
610
- ROOT := #{root}
611
- DOMAIN := #{domain}
612
- STACK := #{stack_name}
613
- BASTION_STACK := #{stack_name}-bastion
614
- REGION := #{region}
615
- IMAGE_TAG := latest
616
-
617
- build:
618
- # aarch64, not x86_64 — matches template.yaml's own
619
- # RuntimePlatform: ARM64 (this Makefile has to build the same
620
- # architecture the task definition declares, or the container
621
- # fails at task start, not at build time), and reuses the same
622
- # working aarch64-unknown-linux-gnu toolchain the Lambda deploy
623
- # path already depends on, rather than standing up a second,
624
- # x86_64-only one.
625
- \t@rustup target list --installed 2>/dev/null | grep -qx aarch64-unknown-linux-gnu || rustup target add aarch64-unknown-linux-gnu
626
- # GNU cross-linker, not Apple clang — rustc's aarch64-unknown-linux-gnu
627
- # target emits `-Wl,--fix-cortex-a53-843419`, which macOS ld rejects
628
- # (found live building a domain image). Same
629
- # toolchain Lambda's generated Makefile already documents.
630
- \t@command -v aarch64-linux-gnu-gcc >/dev/null 2>&1 || { echo "aarch64-linux-gnu-gcc isn't on PATH. Install once with: brew tap messense/macos-cross-toolchains && brew install aarch64-unknown-linux-gnu"; exit 1; }
631
- # The .wasm/.ir.json sidecars main.rs requires at boot,
632
- # unconditionally — see template.yaml's own HECKS_WASM_PATH/
633
- # HECKS_IR_PATH comment for why. `hecks build_wasm` is the same
634
- # generator the Lambda deploy path already uses to produce
635
- # rust/dist/#{domain_name}.wasm/.ir.json from this domain's own
636
- # .bluebook.
637
- \tcd $(ROOT) && HECKS_ENVIRONMENT=memory ruby exe/hecks build.build_wasm domain=$(DOMAIN) --wait
638
- \tcd $(ROOT)/rust/host && CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc rustup run stable cargo build --release --target aarch64-unknown-linux-gnu --bin bootstrap
639
- \tcp $(ROOT)/rust/host/target/aarch64-unknown-linux-gnu/release/bootstrap #{domain_name}-host
640
- \tcp $(ROOT)/rust/dist/#{domain_name}.wasm #{domain_name}.wasm
641
- \tcp $(ROOT)/rust/dist/#{domain_name}.ir.json #{domain_name}.ir.json
642
-
643
- .PHONY: ecr-login
644
- ecr-login:
645
- \taws ecr get-login-password --region $(REGION) | docker login --username AWS --password-stdin $$(aws sts get-caller-identity --query Account --output text).dkr.ecr.$(REGION).amazonaws.com
646
-
647
- .PHONY: docker-build
648
- docker-build: build
649
- # linux/arm64, not the generator's old amd64 default — has to
650
- # match RuntimePlatform/the binary this Makefile's own build:
651
- # step just cross-compiled, above.
652
- \tdocker build --platform linux/arm64 -t #{domain_container.repository_name}:$(IMAGE_TAG) .
653
-
654
- .PHONY: docker-push
655
- docker-push: ecr-login
656
- \tACCOUNT_ID=$$(aws sts get-caller-identity --query Account --output text); \\
657
- \t\tdocker tag #{domain_container.repository_name}:$(IMAGE_TAG) $$ACCOUNT_ID.dkr.ecr.$(REGION).amazonaws.com/#{domain_container.repository_name}:$(IMAGE_TAG); \\
658
- \t\tdocker push $$ACCOUNT_ID.dkr.ecr.$(REGION).amazonaws.com/#{domain_container.repository_name}:$(IMAGE_TAG)
659
-
660
- .PHONY: deploy
661
- deploy: docker-build docker-push
662
- #{shared ? "\t@echo \"Looking up #{owner_stack_name}'s shared VpcId/PrivateSubnetAId/PrivateSubnetBId/PublicSubnetId/BastionSubnetId/FunctionSecurityGroupId/DatabaseEndpoint/DatabaseSecretArn outputs to pass as $(STACK)'s Owning* parameters...\"\n\tOWNER_VPC_ID=$$(aws cloudformation describe-stacks --stack-name #{owner_stack_name} --query \"Stacks[0].Outputs[?OutputKey=='VpcId'].OutputValue\" --output text); \\\n\t\tOWNER_SUBNET_A_ID=$$(aws cloudformation describe-stacks --stack-name #{owner_stack_name} --query \"Stacks[0].Outputs[?OutputKey=='PrivateSubnetAId'].OutputValue\" --output text); \\\n\t\tOWNER_SUBNET_B_ID=$$(aws cloudformation describe-stacks --stack-name #{owner_stack_name} --query \"Stacks[0].Outputs[?OutputKey=='PrivateSubnetBId'].OutputValue\" --output text); \\\n\t\tOWNER_PUBLIC_SUBNET_A_ID=$$(aws cloudformation describe-stacks --stack-name #{owner_stack_name} --query \"Stacks[0].Outputs[?OutputKey=='PublicSubnetId'].OutputValue\" --output text); \\\n\t\tOWNER_PUBLIC_SUBNET_B_ID=$$(aws cloudformation describe-stacks --stack-name #{owner_stack_name} --query \"Stacks[0].Outputs[?OutputKey=='BastionSubnetId'].OutputValue\" --output text); \\\n\t\tOWNER_SG_ID=$$(aws cloudformation describe-stacks --stack-name #{owner_stack_name} --query \"Stacks[0].Outputs[?OutputKey=='FunctionSecurityGroupId'].OutputValue\" --output text); \\\n\t\tOWNER_DB_HOST=$$(aws cloudformation describe-stacks --stack-name #{owner_stack_name} --query \"Stacks[0].Outputs[?OutputKey=='DatabaseEndpoint'].OutputValue\" --output text); \\\n\t\tOWNER_DB_SECRET_ARN=$$(aws cloudformation describe-stacks --stack-name #{owner_stack_name} --query \"Stacks[0].Outputs[?OutputKey=='DatabaseSecretArn'].OutputValue\" --output text); \\\n\t\taws cloudformation deploy --template-file template.yaml --stack-name $(STACK) --region $(REGION) --capabilities CAPABILITY_IAM \\\n\t\t\t--parameter-overrides #{domain_container.tag_parameter}=$(IMAGE_TAG) OwningVpcId=$$OWNER_VPC_ID OwningSubnetAId=$$OWNER_SUBNET_A_ID OwningSubnetBId=$$OWNER_SUBNET_B_ID OwningPublicSubnetAId=$$OWNER_PUBLIC_SUBNET_A_ID OwningPublicSubnetBId=$$OWNER_PUBLIC_SUBNET_B_ID OwningSecurityGroupId=$$OWNER_SG_ID OwningDatabaseEndpoint=$$OWNER_DB_HOST OwningDatabaseSecretArn=$$OWNER_DB_SECRET_ARN" : "\taws cloudformation deploy --template-file template.yaml --stack-name $(STACK) --region $(REGION) --capabilities CAPABILITY_IAM --parameter-overrides #{domain_container.tag_parameter}=$(IMAGE_TAG)"}
663
- \t$(MAKE) mint-era
664
-
665
- #{shared ? <<~SHAREDMINT.rstrip : <<~OWNMINT.rstrip
666
- # mint-era isn't automated yet for a Shared-mode domain (database
667
- # "Shared") — see #{owner_domain_name}'s own deploy directory for
668
- # the manual tunnel path. Exits 0 (not 1) so a genuinely successful
669
- # `make deploy` still reports success.
670
- .PHONY: mint-era
671
- mint-era:
672
- \t@echo "mint-era isn't automated yet for a Shared-mode domain (database \\"Shared\\") -- see #{owner_domain_name}'s own deploy directory's tunnel path. This is NOT a failure."; \\
673
- \texit 0
674
- SHAREDMINT
675
- # `make mint-era` — the same bastion/tunnel/retry/teardown chain
676
- # `Lambda`'s own generated Makefile uses (this directory's own
677
- # bastion.yaml, stood up and torn down for the one boot that mints
678
- # era 1), against this stack's own VPC/RDS instead of a Lambda's.
679
- .PHONY: mint-era
680
- mint-era:
681
- \t@echo "Looking up $(STACK)'s VPC/security group..."
682
- \t#{stack_outputs.map { |o| %($(eval #{o[:var]} := $(shell aws cloudformation describe-stacks --stack-name $(STACK) --query "Stacks[0].Outputs[?OutputKey=='#{o[:key]}'].OutputValue" --output text))) }.join("\n\t")}
683
- \t@echo "Deploying the temporary bastion stack $(BASTION_STACK)..."
684
- \taws cloudformation deploy --template-file bastion.yaml --stack-name $(BASTION_STACK) \\
685
- \t\t--parameter-overrides #{bastion_parameters.map { |p| "#{p[:name]}=$(#{stack_outputs.find { |o| o[:key] == p[:from_output] }[:var]})" }.join(" ")} \\
686
- \t\t--capabilities CAPABILITY_IAM
687
- \t@INSTANCE_ID=$$(aws cloudformation describe-stacks --stack-name $(BASTION_STACK) --query "Stacks[0].Outputs[?OutputKey=='InstanceId'].OutputValue" --output text); \\
688
- \t\techo "Waiting for $$INSTANCE_ID to register with SSM..."; \\
689
- \t\tfor i in $$(seq 1 30); do \\
690
- \t\t\tSTATUS=$$(aws ssm describe-instance-information --filters "Key=InstanceIds,Values=$$INSTANCE_ID" --query "InstanceInformationList[0].PingStatus" --output text 2>/dev/null); \\
691
- \t\t\tif [ "$$STATUS" = "Online" ]; then break; fi; \\
692
- \t\t\tsleep 5; \\
693
- \t\tdone; \\
694
- \t\tDB_PASS=$$(aws secretsmanager get-secret-value --secret-id $(DB_SECRET_ARN) --query SecretString --output text | ruby -rjson -e 'print JSON.parse(STDIN.read)["password"]'); \\
695
- \t\tDB_PASS_URLENC=$$(ruby -rerb -e 'print ERB::Util.url_encode(ARGV[0])' "$$DB_PASS"); \\
696
- \t\tBOOT_STATUS=1; \\
697
- \t\tfor attempt in 1 2 3 4 5; do \\
698
- \t\t\tkill $$TUNNEL_PID 2>/dev/null; \\
699
- \t\t\techo "Opening an SSM tunnel to $(DB_HOST):5432 and minting era 1 (attempt $$attempt/5)..."; \\
700
- \t\t\taws ssm start-session --target $$INSTANCE_ID \\
701
- \t\t\t\t--document-name AWS-StartPortForwardingSessionToRemoteHost \\
702
- \t\t\t\t--parameters "{\\"host\\":[\\"$(DB_HOST)\\"],\\"portNumber\\":[\\"5432\\"],\\"localPortNumber\\":[\\"15432\\"]}" \\
703
- \t\t\t\t>/tmp/$(BASTION_STACK)-tunnel-$$attempt.log 2>&1 & \\
704
- \t\t\tTUNNEL_PID=$$!; \\
705
- \t\t\tfor i in $$(seq 1 15); do \\
706
- \t\t\t\tnc -z localhost 15432 2>/dev/null && break; \\
707
- \t\t\t\tsleep 1; \\
708
- \t\t\tdone; \\
709
- \t\t\tcd $(ROOT) && DATABASE_URL="postgres://postgres:$$DB_PASS_URLENC@localhost:15432/#{db_name}" ruby -Ilib -e 'require "hecks"; require "hecks/ports/persistence/plugins/era"; loading = Hecks::Ports::Loading.bootstrap; directory = loading.bluebook_directory(ARGV[0]); root = loading.shared_root(nil, directory); registry = Hecks::Runtime::Registry.new(root: File.dirname(directory)); Hecks.with_registry(registry) { loading.load_library; loading.load_project(root); loading.load_domain(directory) }; bluebook = registry.bluebooks[#{declared_domain_name.inspect}] or abort "no #{declared_domain_name} bluebook loaded"; current_text = Hecks::Runtime::EraCheck.source_text_for(bluebook, directory); Hecks::Adapters::PostgresEra::LineageManager.check!(registry: registry, bluebook: bluebook, current_text: current_text, settings: { database: ENV["DATABASE_URL"]#{hecks_schema ? ", schema: #{hecks_schema.inspect}" : ""} }); db = Hecks::Adapters::PostgresEra.connect_for(bluebook.name, { database: ENV["DATABASE_URL"]#{hecks_schema ? ", schema: #{hecks_schema.inspect}" : ""} }); lineage = Hecks::Adapters::PostgresEra::Lineage.new(db, bluebook.name); (registry.bluebooks.values - [bluebook]).each { |other| other.aggregates.each { |aggregate| lineage.ensure_first_head!(aggregate.storage_name) } }; db.close; puts "booted OK -- era resolution ran"' $(DOMAIN) && { BOOT_STATUS=0; break; }; \\
710
- \t\t\tBOOT_STATUS=$$?; \\
711
- \t\t\techo "boot check attempt $$attempt/5 failed (exit $$BOOT_STATUS) -- restarting the tunnel and retrying in 3s..."; \\
712
- \t\t\tsleep 3; \\
713
- \t\tdone; \\
714
- \t\tkill $$TUNNEL_PID 2>/dev/null; \\
715
- \t\techo "Tearing down the temporary bastion stack..."; \\
716
- \t\taws cloudformation delete-stack --stack-name $(BASTION_STACK); \\
717
- \t\taws cloudformation wait stack-delete-complete --stack-name $(BASTION_STACK); \\
718
- \t\texit $$BOOT_STATUS
719
- OWNMINT
720
- }
721
- MAKE
30
+ stack = Stack.new(options)
31
+ files = { "template.yaml" => template_yaml(stack) }
32
+ files["bastion.yaml"] = bastion_yaml(stack) unless stack.shared
33
+ files["Dockerfile"] = TextTemplate.render_from("fargate/Dockerfile.tmpl", stack)
34
+ files["Makefile"] = TextTemplate.render_from("fargate/Makefile.tmpl", stack)
35
+ with_previews_and_scripts(files, stack)
36
+ end
722
37
 
723
- files = { "template.yaml" => template_yaml }
724
- files["bastion.yaml"] = bastion_yaml if bastion_yaml
725
- files["Dockerfile"] = dockerfile
726
- files["Makefile"] = makefile_content
727
- # Opt-in per-branch previews: nothing is added unless the domain declares a `preview`
728
- # setting under deployed_to("AwsFargate"). See Preview's own header for the keys.
729
- preview_main = {
730
- infra_name: infra_name, stack_name: stack_name, stack_prefix: stack_prefix, region: region,
731
- cpu: cpu, memory: memory, db_name: shared ? owner_db_name : db_name,
732
- owner_stack: shared ? owner_stack_name : nil, name: infra_name, port: port,
733
- image: "#{domain_container.repository_name}:latest", domain: declared_domain_name, web: target.state[:web].value,
734
- wasm_path: "/usr/local/bin/#{domain_name}.wasm", ir_path: "/usr/local/bin/#{domain_name}.ir.json",
735
- schema: hecks_schema
736
- }
737
- files.merge!(Preview.call(deploy_settings: deploy_settings, main: preview_main))
738
- Scripts.extend_files(files, deploy_settings: deploy_settings, plan: plan,
739
- stack_name: stack_name, region: region)
38
+ # Renders `template.yaml`: the template, then the sections that are spliced in after it
39
+ # renders, not interpolated inside it, since `<<~` dedents from raw source before a value
40
+ # is placed, so a multi-line value could not be reindented a second time.
41
+ #
42
+ # @param stack [Stack] the stack the world declares
43
+ # @return [String] the CloudFormation template
44
+ def template_yaml(stack)
45
+ text = TextTemplate.render_from("fargate/template.yaml.tmpl", stack)
46
+ text = splice_database_env(text, stack)
47
+ # Indented by the marker's own rendered column, never a hand-computed one: the template
48
+ # dedents after interpolation, so a source-counted column lands at the wrong depth.
49
+ text = Yaml.splice(text, "oauth_task_policy", "#{stack.oauth_task_policy_yaml}\n")
50
+ text = Yaml.splice(text, "oauth_task_env", "#{stack.oauth_task_env_yaml}\n")
51
+ assemble(splice_cross_domain_policies(text, stack), stack)
740
52
  end
741
53
 
742
- # Renders DB_HOST/DB_NAME/DB_SECRET_ARN — spliced in after `call`'s
743
- # template heredoc renders; see its `# TMPL:db_env` comment for why.
744
- def db_env_yaml(shared:, owner_db_name:, db_ref_id:, db_name:, secret_sub:, hecks_schema:, base:, db_name_ref: nil)
745
- lines =
746
- if shared
747
- [
748
- "- Name: DB_HOST",
749
- " Value: !Ref OwningDatabaseEndpoint",
750
- "- Name: DB_NAME",
751
- " Value: #{db_name_ref || owner_db_name}",
752
- "- Name: DB_SECRET_ARN",
753
- " Value: !Sub \"${OwningDatabaseSecretArn}\"",
754
- ]
755
- else
756
- [
757
- "- Name: DB_HOST",
758
- " Value: !GetAtt #{db_ref_id}.Endpoint.Address",
759
- "- Name: DB_NAME",
760
- " Value: #{db_name}",
761
- "- Name: DB_SECRET_ARN",
762
- " Value: !Sub \"${#{secret_sub}}\"",
763
- ]
764
- end
765
- lines += ["- Name: HECKS_SCHEMA", " Value: #{hecks_schema}"] if hecks_schema
54
+ def assemble(text, stack)
55
+ Assembly.apply(text, stack.plan, stack.assembly_context)
56
+ rescue ArgumentError => e
57
+ raise ArgumentError, "#{stack.world_file}'s deployed_to(\"AwsFargate\"): #{e.message}"
58
+ end
59
+ private_class_method :assemble
60
+
61
+ # Opt-in per-branch previews: nothing is added unless the domain declares a `preview`
62
+ # setting under deployed_to("AwsFargate"). See Preview's own header for the keys.
63
+ def with_previews_and_scripts(files, stack)
64
+ files.merge!(Preview.call(deploy_settings: stack.deploy_settings, main: stack.preview_main))
65
+ Scripts.extend_files(files, deploy_settings: stack.deploy_settings, plan: stack.plan,
66
+ stack_name: stack.stack_name, region: stack.region)
67
+ end
68
+ private_class_method :with_previews_and_scripts
766
69
 
767
- lines.map { |line| "#{base}#{line}" }.join("\n") + "\n"
70
+ def splice_database_env(text, stack)
71
+ text.sub(/^([ \t]*)# TMPL:db_env\n/) { stack.db_env_yaml(Regexp.last_match(1)) }
768
72
  end
73
+ private_class_method :splice_database_env
769
74
 
770
- # Renders one `AWS::IAM::Role` `Policies` entry per cross-domain target —
771
- # the shape that resource type requires, unlike the bare shorthand
772
- # `Shared.cross_domain_invoke_policy_yaml` renders for SAM.
773
- def cross_domain_fargate_policy_yaml(targets, base)
774
- resources = targets.map { |target|
775
- "#{base} - !Sub \"arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:hecks-#{target.downcase}\""
776
- }.join("\n")
75
+ def splice_cross_domain_policies(text, stack)
76
+ text.sub(/^([ \t]*)# TMPL:cross_domain_fargate_policies\n/) do
77
+ stack.cross_domain_targets.empty? ? "" : stack.cross_domain_policy_yaml(Regexp.last_match(1))
78
+ end
79
+ end
80
+ private_class_method :splice_cross_domain_policies
777
81
 
778
- [
779
- "#{base}# Least-privilege, one ARN per declared `across:` target — see",
780
- "#{base}# Shared.cross_domain_invoke_policy_yaml's own comment for the full",
781
- "#{base}# reasoning; this domain's own task role needs the identical grant.",
782
- "#{base}- PolicyName: CrossDomainInvoke",
783
- "#{base} PolicyDocument:",
784
- "#{base} Version: '2012-10-17'",
785
- "#{base} Statement:",
786
- "#{base} - Effect: Allow",
787
- "#{base} Action: lambda:InvokeFunction",
788
- "#{base} Resource:",
789
- resources,
790
- ].join("\n") + "\n"
82
+ def bastion_yaml(stack)
83
+ Shared.bastion_yaml(stack.network, domain: stack.domain, stack_name: stack.stack_name,
84
+ bastion_parameters: stack.bastion_parameters)
791
85
  end
86
+ private_class_method :bastion_yaml
792
87
  end
793
88
  end
794
89
  end