hecks 3.5.0 → 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.
- checksums.yaml +4 -4
- data/examples/pizzas/bluebook/hecksagon/mock_stripe_payment_adapter.rb +1 -1
- data/lib/hecks/adapters/driven/claude_code.rb +11 -7
- data/lib/hecks/adapters/driven/d1/connection.rb +90 -0
- data/lib/hecks/adapters/driven/d1.rb +48 -314
- data/lib/hecks/adapters/driven/folder.rb +20 -10
- data/lib/hecks/adapters/driven/google_authentication.rb +18 -4
- data/lib/hecks/adapters/driven/governance_authorization.rb +2 -2
- data/lib/hecks/adapters/driven/heki/journal.rb +11 -10
- data/lib/hecks/adapters/driven/heki/saga_store.rb +4 -6
- data/lib/hecks/adapters/driven/heki/sagas.rb +55 -0
- data/lib/hecks/adapters/driven/heki.rb +21 -66
- data/lib/hecks/adapters/driven/in_memory_ordering.rb +37 -12
- data/lib/hecks/adapters/driven/lambda/client.rb +1 -1
- data/lib/hecks/adapters/driven/lambda.rb +1 -8
- data/lib/hecks/adapters/driven/memory/outbox_rows.rb +76 -0
- data/lib/hecks/adapters/driven/memory/shared_elements/values.rb +117 -0
- data/lib/hecks/adapters/driven/memory/shared_elements.rb +10 -97
- data/lib/hecks/adapters/driven/memory.rb +3 -65
- data/lib/hecks/adapters/driven/postgres/codec.rb +29 -26
- data/lib/hecks/adapters/driven/postgres/ddl.rb +50 -0
- data/lib/hecks/adapters/driven/postgres/dialect.rb +93 -0
- data/lib/hecks/adapters/driven/postgres/events.rb +57 -0
- data/lib/hecks/adapters/driven/postgres/journal.rb +127 -0
- data/lib/hecks/adapters/driven/postgres/outbox.rb +39 -31
- data/lib/hecks/adapters/driven/postgres/repository.rb +190 -0
- data/lib/hecks/adapters/driven/postgres/sagas.rb +72 -0
- data/lib/hecks/adapters/driven/postgres/schema_builder.rb +13 -41
- data/lib/hecks/adapters/driven/postgres.rb +61 -528
- data/lib/hecks/adapters/driven/prism.rb +1 -1
- data/lib/hecks/adapters/driven/sql_query_builder.rb +45 -53
- data/lib/hecks/adapters/driven/sql_value_members.rb +57 -0
- data/lib/hecks/adapters/driven/sqlite/codec.rb +32 -29
- data/lib/hecks/adapters/driven/sqlite/ddl.rb +68 -0
- data/lib/hecks/adapters/driven/sqlite/dialect.rb +55 -0
- data/lib/hecks/adapters/driven/sqlite/events.rb +61 -0
- data/lib/hecks/adapters/driven/sqlite/journal.rb +125 -0
- data/lib/hecks/adapters/driven/sqlite/outbox.rb +98 -0
- data/lib/hecks/adapters/driven/sqlite/projection.rb +82 -63
- data/lib/hecks/adapters/driven/sqlite/repository.rb +146 -0
- data/lib/hecks/adapters/driven/sqlite/sagas.rb +69 -0
- data/lib/hecks/adapters/driven/sqlite/schema_builder.rb +8 -55
- data/lib/hecks/adapters/driven/sqlite.rb +36 -513
- data/lib/hecks/adapters/driven/tenant_provisioner.rb +13 -7
- data/lib/hecks/adapters/driving/github_webhook.rb +11 -8
- data/lib/hecks/behaviors/dsl.rb +17 -12
- data/lib/hecks/behaviors/expectations/boot.rb +81 -0
- data/lib/hecks/behaviors/expectations/checks.rb +178 -0
- data/lib/hecks/behaviors/expectations/dispatching.rb +93 -0
- data/lib/hecks/behaviors/expectations/qualify.rb +81 -0
- data/lib/hecks/behaviors/expectations.rb +39 -355
- data/lib/hecks/behaviors/rspec.rb +12 -12
- data/lib/hecks/behaviors/runner.rb +20 -11
- data/lib/hecks/bench/cli.rb +16 -13
- data/lib/hecks/bench/environment.rb +1 -1
- data/lib/hecks/bench/report.rb +11 -7
- data/lib/hecks/bench/ruby_runner.rb +13 -8
- data/lib/hecks/bench/rust_runner.rb +19 -11
- data/lib/hecks/bench/suite.rb +48 -20
- data/lib/hecks/bench/workload.rb +42 -31
- data/lib/hecks/bluebook/aggregate.rb +15 -21
- data/lib/hecks/bluebook/assembly/aggregate_assembly.rb +18 -21
- data/lib/hecks/bluebook/assembly/build.rb +12 -7
- data/lib/hecks/bluebook/assembly/contracts/read_models.rb +70 -0
- data/lib/hecks/bluebook/assembly/contracts/rules.rb +84 -0
- data/lib/hecks/bluebook/assembly/contracts/sagas.rb +109 -0
- data/lib/hecks/bluebook/assembly/contracts/structure.rb +91 -0
- data/lib/hecks/bluebook/assembly/contracts.rb +9 -319
- data/lib/hecks/bluebook/assembly/marks.rb +9 -8
- data/lib/hecks/bluebook/attribute.rb +13 -10
- data/lib/hecks/bluebook/behaviour/aggregate.rb +10 -3
- data/lib/hecks/bluebook/behaviour/read_model.rb +26 -13
- data/lib/hecks/bluebook/chapter.rb +22 -14
- data/lib/hecks/bluebook/command.rb +14 -18
- data/lib/hecks/bluebook/domain_port.rb +11 -8
- data/lib/hecks/bluebook/dsl/aggregate_builder/correction_sealing.rb +78 -0
- data/lib/hecks/bluebook/dsl/aggregate_builder/draining.rb +74 -0
- data/lib/hecks/bluebook/dsl/aggregate_builder/query_field_sealing.rb +105 -0
- data/lib/hecks/bluebook/dsl/aggregate_builder/query_sealing.rb +121 -0
- data/lib/hecks/bluebook/dsl/aggregate_builder/relationships.rb +128 -0
- data/lib/hecks/bluebook/dsl/aggregate_builder/rules.rb +84 -0
- data/lib/hecks/bluebook/dsl/aggregate_builder/sealing.rb +61 -249
- data/lib/hecks/bluebook/dsl/aggregate_builder.rb +51 -285
- data/lib/hecks/bluebook/dsl/attribute_collector/identity_resolution.rb +113 -0
- data/lib/hecks/bluebook/dsl/attribute_collector.rb +58 -117
- data/lib/hecks/bluebook/dsl/binding_proxy.rb +24 -19
- data/lib/hecks/bluebook/dsl/bluebook_builder/pending_givens.rb +109 -0
- data/lib/hecks/bluebook/dsl/bluebook_builder/validation/correlation_keys.rb +105 -0
- data/lib/hecks/bluebook/dsl/bluebook_builder/validation/event_shapes.rb +126 -0
- data/lib/hecks/bluebook/dsl/bluebook_builder/validation/hop_tails.rb +79 -0
- data/lib/hecks/bluebook/dsl/bluebook_builder/validation/projected_fields.rb +76 -0
- data/lib/hecks/bluebook/dsl/bluebook_builder/validation/provisions.rb +65 -0
- data/lib/hecks/bluebook/dsl/bluebook_builder/validation/query_hops.rb +123 -0
- data/lib/hecks/bluebook/dsl/bluebook_builder/validation/references.rb +112 -0
- data/lib/hecks/bluebook/dsl/bluebook_builder/validation/with_projections.rb +126 -0
- data/lib/hecks/bluebook/dsl/bluebook_builder/validation.rb +34 -595
- data/lib/hecks/bluebook/dsl/bluebook_builder.rb +18 -107
- data/lib/hecks/bluebook/dsl/command_builder/implicit_attributes.rb +132 -0
- data/lib/hecks/bluebook/dsl/command_builder/mutations.rb +190 -0
- data/lib/hecks/bluebook/dsl/command_builder/owner.rb +22 -0
- data/lib/hecks/bluebook/dsl/command_builder/rules.rb +57 -0
- data/lib/hecks/bluebook/dsl/command_builder.rb +60 -360
- data/lib/hecks/bluebook/dsl/domain_port_builder.rb +19 -13
- data/lib/hecks/bluebook/dsl/entity_builder/rules.rb +96 -0
- data/lib/hecks/bluebook/dsl/entity_builder/scope.rb +25 -0
- data/lib/hecks/bluebook/dsl/entity_builder/sealing.rb +94 -0
- data/lib/hecks/bluebook/dsl/entity_builder.rb +35 -169
- data/lib/hecks/bluebook/dsl/generic_dispatch.rb +53 -24
- data/lib/hecks/bluebook/dsl/hecksagon_builder/chapter_scope.rb +133 -0
- data/lib/hecks/bluebook/dsl/hecksagon_builder.rb +3 -97
- data/lib/hecks/bluebook/dsl/identity_declaration.rb +73 -73
- data/lib/hecks/bluebook/dsl/lifecycle_builder.rb +7 -3
- data/lib/hecks/bluebook/dsl/need_word.rb +1 -1
- data/lib/hecks/bluebook/dsl/port_operation_builder.rb +34 -29
- data/lib/hecks/bluebook/dsl/process_manager_builder.rb +57 -41
- data/lib/hecks/bluebook/dsl/query_builder.rb +12 -15
- data/lib/hecks/bluebook/dsl/read_model_builder/sealing.rb +116 -0
- data/lib/hecks/bluebook/dsl/read_model_builder.rb +25 -102
- data/lib/hecks/bluebook/dsl/rule_reference.rb +26 -12
- data/lib/hecks/bluebook/dsl/translation_builder.rb +24 -14
- data/lib/hecks/bluebook/dsl/value_object_builder.rb +29 -19
- data/lib/hecks/bluebook/dsl/word_gate.rb +34 -27
- data/lib/hecks/bluebook/entity.rb +13 -17
- data/lib/hecks/bluebook/expression/ast_json/emitters.rb +93 -0
- data/lib/hecks/bluebook/expression/ast_json/emitters.rb-e +88 -0
- data/lib/hecks/bluebook/expression/ast_json.rb +49 -76
- data/lib/hecks/bluebook/expression/ast_reader.rb +95 -28
- data/lib/hecks/bluebook/expression/canonical_form.rb +6 -26
- data/lib/hecks/bluebook/expression/evaluator/parser.rb +62 -0
- data/lib/hecks/bluebook/expression/evaluator/scanning.rb +122 -0
- data/lib/hecks/bluebook/expression/evaluator.rb +11 -111
- data/lib/hecks/bluebook/expression/resolver/block_predicates.rb +28 -44
- data/lib/hecks/bluebook/expression/resolver/lookups.rb +77 -0
- data/lib/hecks/bluebook/expression/resolver/operations.rb +78 -0
- data/lib/hecks/bluebook/expression/resolver/parsing.rb +110 -0
- data/lib/hecks/bluebook/expression/resolver/scanning.rb +139 -0
- data/lib/hecks/bluebook/expression/resolver/values.rb +115 -0
- data/lib/hecks/bluebook/expression/resolver.rb +16 -414
- data/lib/hecks/bluebook/{hexagon.rb → hecksagon.rb} +22 -14
- data/lib/hecks/bluebook/keyword_fields.rb +42 -0
- data/lib/hecks/bluebook/meta_validator/adapter_judge.rb +7 -6
- data/lib/hecks/bluebook/meta_validator/judge/cells.rb +99 -0
- data/lib/hecks/bluebook/meta_validator/judge/dispatching.rb +111 -0
- data/lib/hecks/bluebook/meta_validator/judge/identity.rb +108 -0
- data/lib/hecks/bluebook/meta_validator/judge/walking.rb +141 -0
- data/lib/hecks/bluebook/meta_validator/judge.rb +31 -376
- data/lib/hecks/bluebook/meta_validator/modes.rb +137 -0
- data/lib/hecks/bluebook/meta_validator/plan/category.rb +44 -0
- data/lib/hecks/bluebook/meta_validator/plan/verbs.rb +73 -0
- data/lib/hecks/bluebook/meta_validator/plan.rb +38 -122
- data/lib/hecks/bluebook/meta_validator/readings/fields.rb +100 -0
- data/lib/hecks/bluebook/meta_validator/readings.rb +10 -95
- data/lib/hecks/bluebook/meta_validator/reconstruction/heads.rb +89 -0
- data/lib/hecks/bluebook/meta_validator/reconstruction/reading.rb +96 -0
- data/lib/hecks/bluebook/meta_validator/reconstruction.rb +25 -151
- data/lib/hecks/bluebook/meta_validator/shapes/helpers.rb +83 -0
- data/lib/hecks/bluebook/meta_validator/shapes.rb +8 -75
- data/lib/hecks/bluebook/meta_validator/syntax_boot/disk_cache.rb +77 -0
- data/lib/hecks/bluebook/meta_validator/syntax_boot.rb +31 -95
- data/lib/hecks/bluebook/meta_validator/translation_judge/rules.rb +74 -0
- data/lib/hecks/bluebook/meta_validator/translation_judge.rb +15 -65
- data/lib/hecks/bluebook/meta_validator/verdict_cache/tagging.rb +63 -0
- data/lib/hecks/bluebook/meta_validator/verdict_cache.rb +22 -43
- data/lib/hecks/bluebook/meta_validator/world_judge.rb +8 -4
- data/lib/hecks/bluebook/meta_validator.rb +59 -175
- data/lib/hecks/bluebook/model_check/lifecycle_checks.rb +122 -0
- data/lib/hecks/bluebook/model_check/policy_checks.rb +129 -0
- data/lib/hecks/bluebook/model_check/saga_checks.rb +134 -0
- data/lib/hecks/bluebook/model_check/verbs.rb +69 -0
- data/lib/hecks/bluebook/model_check.rb +73 -413
- data/lib/hecks/bluebook/pattern_subset/refusals.rb +54 -0
- data/lib/hecks/bluebook/pattern_subset/scan.rb +58 -0
- data/lib/hecks/bluebook/pattern_subset.rb +93 -134
- data/lib/hecks/bluebook/process_manager.rb +10 -9
- data/lib/hecks/bluebook/project_discovery.rb +10 -7
- data/lib/hecks/bluebook/project_register.rb +42 -41
- data/lib/hecks/bluebook/query.rb +19 -12
- data/lib/hecks/bluebook/read_model.rb +41 -39
- data/lib/hecks/bluebook/smoke_test.rb +51 -36
- data/lib/hecks/bluebook/synthesizer.rb +13 -5
- data/lib/hecks/bluebook/translation.rb +12 -12
- data/lib/hecks/bluebook.rb +1 -1
- data/lib/hecks/chapters.rb +32 -16
- data/lib/hecks/cli/behaviors.rb +22 -15
- data/lib/hecks/cli/check_era.rb +2 -2
- data/lib/hecks/cli/command_table.rb +72 -0
- data/lib/hecks/cli/console.rb +10 -7
- data/lib/hecks/cli/deploy_template_diff.rb +22 -9
- data/lib/hecks/cli/document.rb +14 -10
- data/lib/hecks/cli/domain_stub.rb +1 -1
- data/lib/hecks/cli/domain_writer.rb +1 -1
- data/lib/hecks/cli/expression_projection.rb +8 -6
- data/lib/hecks/cli/follow.rb +10 -4
- data/lib/hecks/cli/interview_aggregate.rb +132 -0
- data/lib/hecks/cli/interview_draft.rb +16 -200
- data/lib/hecks/cli/interview_record.rb +130 -0
- data/lib/hecks/cli/interview_run.rb +19 -8
- data/lib/hecks/cli/interview_session/agent_state.rb +70 -0
- data/lib/hecks/cli/interview_session/catalog.rb +76 -0
- data/lib/hecks/cli/interview_session/manual_findings.rb +48 -0
- data/lib/hecks/cli/interview_session/proposals.rb +90 -0
- data/lib/hecks/cli/interview_session.rb +8 -205
- data/lib/hecks/cli/interview_shape.rb +13 -6
- data/lib/hecks/cli/ir.rb +8 -11
- data/lib/hecks/cli/launcher_words.rb +168 -0
- data/lib/hecks/cli/model_check/examination.rb +93 -0
- data/lib/hecks/cli/model_check/sources.rb +57 -0
- data/lib/hecks/cli/model_check.rb +28 -134
- data/lib/hecks/cli/project_cli/launcher_source.rb +177 -0
- data/lib/hecks/cli/project_cli/templates.rb +106 -0
- data/lib/hecks/cli/project_cli.rb +57 -236
- data/lib/hecks/cli/project_diagrams.rb +26 -4
- data/lib/hecks/cli/project_glossary.rb +19 -9
- data/lib/hecks/cli/refresh_rspec_runtime_baseline.rb +29 -13
- data/lib/hecks/cli/release.rb +29 -22
- data/lib/hecks/cli/release_gem.rb +12 -6
- data/lib/hecks/cli/rspec_io_parallel_files.rb +87 -30
- data/lib/hecks/cli/rspec_shard_files.rb +24 -9
- data/lib/hecks/cli/run.rb +25 -44
- data/lib/hecks/cli/run_expectations.rb +63 -0
- data/lib/hecks/cli/seed_semantics_corpus.rb +37 -17
- data/lib/hecks/cli/smoke_http/checks.rb +66 -0
- data/lib/hecks/cli/smoke_http/settings.rb +63 -0
- data/lib/hecks/cli/smoke_http/transport.rb +45 -0
- data/lib/hecks/cli/smoke_http.rb +8 -142
- data/lib/hecks/cli/smoke_test.rb +18 -4
- data/lib/hecks/cli/stores.rb +7 -4
- data/lib/hecks/cli/stress_concurrency_specs/reporting.rb +44 -0
- data/lib/hecks/cli/stress_concurrency_specs/usage.rb +28 -0
- data/lib/hecks/cli/stress_concurrency_specs.rb +82 -80
- data/lib/hecks/cli.rb +32 -208
- data/lib/hecks/codemod/runner.rb +92 -0
- data/lib/hecks/codemod/sweep.rb +94 -0
- data/lib/hecks/codemod.rb +22 -165
- data/lib/hecks/corpus/routes.rb +34 -0
- data/lib/hecks/corpus/rust.rb +193 -0
- data/lib/hecks/corpus/sources.rb +46 -0
- data/lib/hecks/corpus.rb +28 -265
- data/lib/hecks/doc/reference/coverage.rb +70 -0
- data/lib/hecks/doc/reference/harvester.rb +55 -0
- data/lib/hecks/doc/reference/readme.rb +89 -0
- data/lib/hecks/doc/reference/rendering.rb +149 -0
- data/lib/hecks/doc/reference.rb +14 -273
- data/lib/hecks/doors/cli_door/nesting.rb +34 -0
- data/lib/hecks/doors/cli_door/shorthand.rb +85 -0
- data/lib/hecks/doors/cli_door.rb +23 -95
- data/lib/hecks/doors/cli_runner/answers.rb +138 -0
- data/lib/hecks/doors/cli_runner/resolution.rb +146 -0
- data/lib/hecks/doors/cli_runner/settling.rb +115 -0
- data/lib/hecks/doors/cli_runner/streaming.rb +90 -0
- data/lib/hecks/doors/cli_runner/suggestions.rb +43 -0
- data/lib/hecks/doors/cli_runner.rb +12 -336
- data/lib/hecks/doors/command_request.rb +42 -31
- data/lib/hecks/doors/handle.rb +32 -30
- data/lib/hecks/doors/launcher_options.rb +62 -7
- data/lib/hecks/doors/mcp_door/properties.rb +47 -0
- data/lib/hecks/doors/mcp_door/tool_calls.rb +113 -0
- data/lib/hecks/doors/mcp_door/tool_definitions/auditing.rb +51 -0
- data/lib/hecks/doors/mcp_door/tool_definitions/calling.rb +69 -0
- data/lib/hecks/doors/mcp_door/tool_definitions/reading.rb +97 -0
- data/lib/hecks/doors/mcp_door/tool_definitions.rb +15 -0
- data/lib/hecks/doors/mcp_door.rb +55 -301
- data/lib/hecks/doors/mcp_door_scope/argument_policy.rb +92 -0
- data/lib/hecks/doors/mcp_door_scope/env_problems.rb +55 -0
- data/lib/hecks/doors/mcp_door_scope/presenter.rb +78 -0
- data/lib/hecks/doors/mcp_door_scope.rb +16 -172
- data/lib/hecks/doors/ruby_door/aggregate_door.rb +1 -1
- data/lib/hecks/doors/ruby_door/chapter.rb +33 -16
- data/lib/hecks/doors/ruby_door.rb +14 -11
- data/lib/hecks/doors/usage_cache.rb +14 -8
- data/lib/hecks/doors.rb +10 -4
- data/lib/hecks/embryonaut_bluebook/manifest.rb +11 -3
- data/lib/hecks/embryonaut_bluebook/registry/changelog.rb +26 -0
- data/lib/hecks/embryonaut_bluebook/registry/versions.rb +27 -0
- data/lib/hecks/embryonaut_bluebook/registry.rb +27 -37
- data/lib/hecks/embryonaut_bluebook/vendor/acceptance.rb +37 -0
- data/lib/hecks/embryonaut_bluebook/vendor.rb +22 -36
- data/lib/hecks/embryonaut_bluebook/vendor_cli.rb +9 -6
- data/lib/hecks/embryonaut_bluebook.rb +16 -11
- data/lib/hecks/engine_agreement.rb +24 -17
- data/lib/hecks/forms/app/commands.rb +98 -0
- data/lib/hecks/forms/app/queries.rb +62 -0
- data/lib/hecks/forms/app/records.rb +67 -0
- data/lib/hecks/forms/app/responses.rb +46 -0
- data/lib/hecks/forms/app.rb +33 -221
- data/lib/hecks/forms/banking_presentation.rb +5 -0
- data/lib/hecks/forms/command_form_renderer.rb +55 -14
- data/lib/hecks/forms/field_controls.rb +95 -0
- data/lib/hecks/forms/field_renderer.rb +34 -88
- data/lib/hecks/forms/field_shape.rb +9 -34
- data/lib/hecks/forms/html.rb +1 -1
- data/lib/hecks/forms/index_renderer.rb +14 -9
- data/lib/hecks/forms/page.rb +2 -106
- data/lib/hecks/forms/page_assets.rb +88 -0
- data/lib/hecks/forms/page_script.rb +28 -0
- data/lib/hecks/forms/params.rb +17 -8
- data/lib/hecks/forms/query_form_renderer.rb +11 -7
- data/lib/hecks/forms/record_renderer.rb +28 -19
- data/lib/hecks/forms/reference_options.rb +1 -1
- data/lib/hecks/forms/text_shape.rb +40 -0
- data/lib/hecks/fqn.rb +64 -32
- data/lib/hecks/framework.rb +10 -3
- data/lib/hecks/freezer.rb +10 -1
- data/lib/hecks/fuzzing/bounded_exhaustive_expressions/fragments.rb +61 -0
- data/lib/hecks/fuzzing/bounded_exhaustive_expressions/productions.rb +217 -0
- data/lib/hecks/fuzzing/bounded_exhaustive_expressions.rb +5 -194
- data/lib/hecks/fuzzing/combination_miner.rb +23 -12
- data/lib/hecks/fuzzing/concurrent_dispatch/racing.rb +64 -0
- data/lib/hecks/fuzzing/concurrent_dispatch/world_copy.rb +66 -0
- data/lib/hecks/fuzzing/concurrent_dispatch.rb +31 -107
- data/lib/hecks/fuzzing/coverage_campaign.rb +7 -7
- data/lib/hecks/fuzzing/differential/wire_comparison.rb +74 -0
- data/lib/hecks/fuzzing/differential.rb +59 -84
- data/lib/hecks/fuzzing/domain_generator/block_rendering.rb +70 -0
- data/lib/hecks/fuzzing/domain_generator/builder/attribute_shapes.rb +105 -0
- data/lib/hecks/fuzzing/domain_generator/builder/shapes.rb +97 -0
- data/lib/hecks/fuzzing/domain_generator/builder/wiring.rb +128 -0
- data/lib/hecks/fuzzing/domain_generator/builder.rb +105 -0
- data/lib/hecks/fuzzing/domain_generator/pruning.rb +90 -0
- data/lib/hecks/fuzzing/domain_generator/removals.rb +62 -0
- data/lib/hecks/fuzzing/domain_generator/rendering.rb +94 -0
- data/lib/hecks/fuzzing/domain_generator/tokens.rb +38 -0
- data/lib/hecks/fuzzing/domain_generator.rb +7 -555
- data/lib/hecks/fuzzing/era_boundary.rb +34 -24
- data/lib/hecks/fuzzing/form_census.rb +18 -8
- data/lib/hecks/fuzzing/generated_domain_check.rb +23 -11
- data/lib/hecks/fuzzing/isolated_boot/copying.rb +62 -0
- data/lib/hecks/fuzzing/isolated_boot/postgres_scratch.rb +133 -0
- data/lib/hecks/fuzzing/isolated_boot/worlds.rb +102 -0
- data/lib/hecks/fuzzing/isolated_boot.rb +25 -252
- data/lib/hecks/fuzzing/persistence_parity.rb +5 -5
- data/lib/hecks/fuzzing/properties/aggregation_recompute.rb +121 -0
- data/lib/hecks/fuzzing/properties/catalog.rb +138 -0
- data/lib/hecks/fuzzing/properties/corrections.rb +23 -20
- data/lib/hecks/fuzzing/properties/dispatch_and_mutations.rb +64 -185
- data/lib/hecks/fuzzing/properties/group_by_recompute.rb +69 -0
- data/lib/hecks/fuzzing/properties/guards.rb +76 -108
- data/lib/hecks/fuzzing/properties/invariants_and_aggregation.rb +66 -227
- data/lib/hecks/fuzzing/properties/lifecycle_and_replay.rb +46 -35
- data/lib/hecks/fuzzing/properties/mutation_recompute.rb +162 -0
- data/lib/hecks/fuzzing/properties/outbox.rb +41 -24
- data/lib/hecks/fuzzing/properties/piece_invariants.rb +61 -0
- data/lib/hecks/fuzzing/properties/policy_wiring.rb +140 -0
- data/lib/hecks/fuzzing/properties/query_rows.rb +67 -0
- data/lib/hecks/fuzzing/properties/querying.rb +69 -90
- data/lib/hecks/fuzzing/properties/references.rb +100 -0
- data/lib/hecks/fuzzing/properties/tenant_scope.rb +84 -0
- data/lib/hecks/fuzzing/properties.rb +6 -119
- data/lib/hecks/fuzzing/qa_settings.rb +23 -17
- data/lib/hecks/fuzzing/replay/fan_out.rb +78 -0
- data/lib/hecks/fuzzing/replay/filters.rb +72 -0
- data/lib/hecks/fuzzing/replay/guard_check.rb +88 -0
- data/lib/hecks/fuzzing/replay/mutation_trace.rb +117 -0
- data/lib/hecks/fuzzing/replay/observation.rb +60 -0
- data/lib/hecks/fuzzing/replay/read_only_steps.rb +84 -0
- data/lib/hecks/fuzzing/replay/session.rb +151 -0
- data/lib/hecks/fuzzing/replay.rb +35 -442
- data/lib/hecks/fuzzing/rust_gap_manifest.rb +3 -4
- data/lib/hecks/fuzzing/self_consistency/saga_redelivery.rb +133 -0
- data/lib/hecks/fuzzing/self_consistency/sagas.rb +93 -0
- data/lib/hecks/fuzzing/self_consistency/value_objects.rb +87 -0
- data/lib/hecks/fuzzing/self_consistency.rb +8 -213
- data/lib/hecks/fuzzing/sequence_generator/adversary/argument_mutations.rb +116 -0
- data/lib/hecks/fuzzing/sequence_generator/adversary/caller_draw.rb +68 -0
- data/lib/hecks/fuzzing/sequence_generator/adversary/identity_mutations.rb +62 -0
- data/lib/hecks/fuzzing/sequence_generator/adversary/precedence_mutations.rb +126 -0
- data/lib/hecks/fuzzing/sequence_generator/adversary.rb +23 -283
- data/lib/hecks/fuzzing/sequence_generator/argument_drawing.rb +78 -0
- data/lib/hecks/fuzzing/sequence_generator/catalog.rb +69 -53
- data/lib/hecks/fuzzing/sequence_generator/identity_shaping.rb +85 -0
- data/lib/hecks/fuzzing/sequence_generator/outcome_tracker.rb +20 -16
- data/lib/hecks/fuzzing/sequence_generator/picker.rb +12 -6
- data/lib/hecks/fuzzing/sequence_generator/prefixing.rb +45 -0
- data/lib/hecks/fuzzing/sequence_generator/query_binding.rb +19 -8
- data/lib/hecks/fuzzing/sequence_generator/step_builder.rb +43 -144
- data/lib/hecks/fuzzing/sequence_generator.rb +65 -63
- data/lib/hecks/fuzzing/shrinker.rb +33 -29
- data/lib/hecks/fuzzing/target_capabilities.rb +10 -4
- data/lib/hecks/fuzzing/value_generator.rb +27 -17
- data/lib/hecks/gate/stages.yml +10 -0
- data/lib/hecks/grammar/evolve/arguments.rb +90 -0
- data/lib/hecks/grammar/evolve/keywords.rb +81 -0
- data/lib/hecks/grammar/evolve/seeds.rb +172 -0
- data/lib/hecks/grammar/evolve.rb +22 -263
- data/lib/hecks/grammar/operators.rb +111 -0
- data/lib/hecks/grammar.rb +53 -126
- data/lib/hecks/hecks/adapters/bluebook_report.rb +6 -6
- data/lib/hecks/hecks/adapters/codebase/codemods.rb +1 -1
- data/lib/hecks/hecks/adapters/codebase/corpus_tasks.rb +23 -9
- data/lib/hecks/hecks/adapters/codebase/language/edits.rb +75 -0
- data/lib/hecks/hecks/adapters/codebase/language.rb +30 -72
- data/lib/hecks/hecks/adapters/codebase/promotion/candidates.rb +54 -0
- data/lib/hecks/hecks/adapters/codebase/promotion/gate.rb +50 -0
- data/lib/hecks/hecks/adapters/codebase/promotion/move.rb +70 -0
- data/lib/hecks/hecks/adapters/codebase/promotion/standing.rb +88 -0
- data/lib/hecks/hecks/adapters/codebase/promotion/watch.rb +83 -0
- data/lib/hecks/hecks/adapters/codebase/promotion.rb +115 -0
- data/lib/hecks/hecks/adapters/codebase/publishing.rb +31 -12
- data/lib/hecks/hecks/adapters/codebase/regeneration.rb +43 -6
- data/lib/hecks/hecks/adapters/codebase/release_facts.rb +16 -5
- data/lib/hecks/hecks/adapters/codebase/source_tree.rb +9 -1
- data/lib/hecks/hecks/adapters/codebase/sqlite_fixture.rb +1 -1
- data/lib/hecks/hecks/adapters/codebase/style.rb +1 -1
- data/lib/hecks/hecks/adapters/codebase/test_runner.rb +11 -5
- data/lib/hecks/hecks/adapters/codebase/test_suite.rb +27 -8
- data/lib/hecks/hecks/adapters/console_capture.rb +21 -17
- data/lib/hecks/hecks/adapters/cost_explorer.rb +11 -6
- data/lib/hecks/hecks/adapters/deploy_plans.rb +3 -3
- data/lib/hecks/hecks/adapters/deploy_toolchain/answers.rb +141 -0
- data/lib/hecks/hecks/adapters/deploy_toolchain/scripts.rb +95 -0
- data/lib/hecks/hecks/adapters/deploy_toolchain/statuses.rb +74 -0
- data/lib/hecks/hecks/adapters/deploy_toolchain.rb +21 -239
- data/lib/hecks/hecks/adapters/finding_github.rb +2 -2
- data/lib/hecks/hecks/adapters/first_admin.rb +22 -8
- data/lib/hecks/hecks/adapters/git.rb +18 -5
- data/lib/hecks/hecks/adapters/git_refs.rb +144 -0
- data/lib/hecks/hecks/adapters/github_rulesets.rb +126 -0
- data/lib/hecks/hecks/adapters/host_http.rb +16 -6
- data/lib/hecks/hecks/adapters/in_process_boot.rb +9 -5
- data/lib/hecks/hecks/adapters/in_process_operations/tailing.rb +61 -0
- data/lib/hecks/hecks/adapters/in_process_operations.rb +33 -35
- data/lib/hecks/hecks/adapters/journal_store/changes.rb +21 -15
- data/lib/hecks/hecks/adapters/journal_store/edge_audit.rb +29 -12
- data/lib/hecks/hecks/adapters/journal_store/readings/attestation.rb +52 -0
- data/lib/hecks/hecks/adapters/journal_store/readings/scaffolding.rb +52 -0
- data/lib/hecks/hecks/adapters/journal_store/readings.rb +5 -62
- data/lib/hecks/hecks/adapters/local_files.rb +27 -10
- data/lib/hecks/hecks/adapters/pg_admin/ownership.rb +115 -0
- data/lib/hecks/hecks/adapters/pg_admin.rb +14 -87
- data/lib/hecks/hecks/adapters/process_pool.rb +54 -22
- data/lib/hecks/hecks/adapters/rust_toolchain.rb +12 -4
- data/lib/hecks/hecks/adapters/site_toolchain.rb +16 -7
- data/lib/hecks/hecks/adapters/terminal.rb +13 -9
- data/lib/hecks/hecks/codebase.bluebook +322 -5
- data/lib/hecks/hecks/hecks.hecksagon +16 -0
- data/lib/hecks/hecks/hecks.world +10 -2
- data/lib/hecks/kernel_capabilities/templates.rb +92 -0
- data/lib/hecks/kernel_capabilities.rb +18 -85
- data/lib/hecks/language/bluebook/vocabulary.bluebook +43 -1
- data/lib/hecks/literal/item_splitter.rb +50 -0
- data/lib/hecks/literal.rb +29 -38
- data/lib/hecks/mcp_stdio_guard.rb +8 -8
- data/lib/hecks/naming.rb +9 -3
- data/lib/hecks/persistence_legacy_fixture/postgres_stores.rb +81 -0
- data/lib/hecks/persistence_legacy_fixture/regenerate.rb +26 -66
- data/lib/hecks/persistence_legacy_fixture.rb +13 -10
- data/lib/hecks/ports/access_control.rb +13 -10
- data/lib/hecks/ports/agent/answers.rb +2 -2
- data/lib/hecks/ports/agent.rb +13 -10
- data/lib/hecks/ports/authentication.rb +13 -10
- data/lib/hecks/ports/authorization.rb +13 -10
- data/lib/hecks/ports/clock.rb +13 -10
- data/lib/hecks/ports/extraction.rb +13 -12
- data/lib/hecks/ports/identity_assignment.rb +13 -10
- data/lib/hecks/ports/identity_generation.rb +13 -10
- data/lib/hecks/ports/identity_resolution.rb +13 -10
- data/lib/hecks/ports/key_vault.rb +13 -10
- data/lib/hecks/ports/persistence/append_only.rb +5 -5
- data/lib/hecks/ports/persistence/binding_policy.rb +33 -9
- data/lib/hecks/ports/persistence/codec_boundary.rb +22 -11
- data/lib/hecks/ports/persistence/constants.rb +10 -0
- data/lib/hecks/ports/persistence/plugins/era/era_check.rb +18 -16
- data/lib/hecks/ports/persistence/plugins/era/era_guard/shape_diff.rb +27 -18
- data/lib/hecks/ports/persistence/plugins/era/era_guard.rb +52 -23
- data/lib/hecks/ports/persistence/plugins/era/era_tamper.rb +14 -8
- data/lib/hecks/ports/persistence/plugins/era/expected_era.rb +17 -6
- data/lib/hecks/ports/persistence/plugins/era/lineage/coverage.rb +58 -0
- data/lib/hecks/ports/persistence/plugins/era/lineage/rewrite.rb +130 -0
- data/lib/hecks/ports/persistence/plugins/era/lineage/rules.rb +25 -0
- data/lib/hecks/ports/persistence/plugins/era/lineage.rb +20 -180
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/boot.rb +41 -0
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/class_methods.rb +105 -0
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/dialect.rb +137 -0
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/events.rb +25 -28
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/head_writes.rb +62 -0
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/journal.rb +128 -0
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/base_sql.rb +74 -0
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/chain_sql.rb +169 -0
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/domain_rename.rb +91 -0
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/era_integrity.rb +99 -0
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/era_store.rb +0 -73
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/field_cache.rb +55 -39
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/head_compiler.rb +51 -222
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/merge_writes.rb +120 -0
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/mint_transaction.rb +85 -60
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/provisioning.rb +97 -181
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/resumable_backfill.rb +19 -19
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/sql_templates.rb +88 -0
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/tail_merge.rb +77 -118
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/transform_installer.rb +3 -117
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/transform_sql.rb +116 -0
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage.rb +3 -1
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/context.rb +38 -0
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/coverage_check.rb +43 -25
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/era_resolver.rb +62 -38
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/merge_coordinator.rb +21 -16
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/minter.rb +66 -86
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/refusals.rb +75 -0
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager.rb +27 -9
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/query_phases.rb +63 -0
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/sagas.rb +78 -0
- data/lib/hecks/ports/persistence/plugins/era/postgres_era.rb +28 -482
- data/lib/hecks/ports/persistence/plugins/era/translation/approval_file.rb +40 -12
- data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_one.rb +22 -15
- data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_two.rb +39 -19
- data/lib/hecks/ports/persistence/plugins/era/translation/audit/unfed_report.rb +16 -16
- data/lib/hecks/ports/persistence/plugins/era/translation/rule_compiler.rb +48 -25
- data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/differ.rb +60 -99
- data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/path_diff.rb +57 -0
- data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/renderer.rb +21 -11
- data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/writer.rb +13 -4
- data/lib/hecks/ports/persistence/postgres_dump/connection.rb +4 -2
- data/lib/hecks/ports/persistence/postgres_dump.rb +13 -7
- data/lib/hecks/ports/persistence/repository_factory.rb +35 -11
- data/lib/hecks/ports/persistence/state_codec.rb +10 -0
- data/lib/hecks/ports/persistence.rb +1 -10
- data/lib/hecks/ports/projection.rb +34 -21
- data/lib/hecks/ports/query/in_memory.rb +16 -8
- data/lib/hecks/projection_files/expression_tables.rb +64 -0
- data/lib/hecks/projection_files/texts.rb +67 -0
- data/lib/hecks/projection_files.rb +19 -103
- data/lib/hecks/projections/bootstrap_table.rb +43 -29
- data/lib/hecks/projections/deploy/bastion_lines.rb +32 -0
- data/lib/hecks/projections/deploy/box/access.rb +73 -0
- data/lib/hecks/projections/deploy/box/caddy.rb +87 -0
- data/lib/hecks/projections/deploy/box/compose.rb +70 -0
- data/lib/hecks/projections/deploy/box/hosting.rb +4 -105
- data/lib/hecks/projections/deploy/box/hosting_parts.rb +97 -0
- data/lib/hecks/projections/deploy/box/hosting_settings.rb +1 -1
- data/lib/hecks/projections/deploy/box/roll_recipe.rb +1 -1
- data/lib/hecks/projections/deploy/box/roll_scripts.rb +135 -0
- data/lib/hecks/projections/deploy/box/settings/checks.rb +38 -0
- data/lib/hecks/projections/deploy/box/settings/containers.rb +123 -0
- data/lib/hecks/projections/deploy/box/settings/origin.rb +56 -0
- data/lib/hecks/projections/deploy/box/settings/patterns.rb +43 -0
- data/lib/hecks/projections/deploy/box/settings/types.rb +72 -0
- data/lib/hecks/projections/deploy/box/settings.rb +58 -263
- data/lib/hecks/projections/deploy/box/stack_yaml.rb +107 -0
- data/lib/hecks/projections/deploy/box/templates/MIGRATION.md.tmpl +39 -0
- data/lib/hecks/projections/deploy/box/templates/Makefile.tmpl +24 -0
- data/lib/hecks/projections/deploy/box/templates/deploy-box.sh.tmpl +41 -1
- data/lib/hecks/projections/deploy/box/templates/deploy-service.services-roll.part +2 -1
- data/lib/hecks/projections/deploy/box/templates/deploy-service.taskdef-roll.part +2 -1
- data/lib/hecks/projections/deploy/box/templates/deploy-usage-services.tmpl +4 -0
- data/lib/hecks/projections/deploy/box/templates/deploy-usage-taskdef.tmpl +5 -0
- data/lib/hecks/projections/deploy/box/templates/ecr-repository.yaml.tmpl +9 -0
- data/lib/hecks/projections/deploy/box/templates/mode-summary-services.tmpl +2 -0
- data/lib/hecks/projections/deploy/box/templates/mode-summary-taskdef.tmpl +4 -0
- data/lib/hecks/projections/deploy/box/templates/services-block.tmpl +9 -0
- data/lib/hecks/projections/deploy/box/templates/tunnel-egress.yaml.tmpl +11 -0
- data/lib/hecks/projections/deploy/box/templates/writable-secrets.yaml.tmpl +7 -0
- data/lib/hecks/projections/deploy/box.rb +33 -493
- data/lib/hecks/projections/deploy/fargate/assembly.rb +13 -142
- data/lib/hecks/projections/deploy/fargate/cdn/behaviors.rb +76 -0
- data/lib/hecks/projections/deploy/fargate/cdn/lines.rb +112 -0
- data/lib/hecks/projections/deploy/fargate/cdn/options.rb +85 -0
- data/lib/hecks/projections/deploy/fargate/cdn.rb +23 -215
- data/lib/hecks/projections/deploy/fargate/check.rb +16 -6
- data/lib/hecks/projections/deploy/fargate/containers/definition_lines.rb +61 -0
- data/lib/hecks/projections/deploy/fargate/containers/reading.rb +86 -0
- data/lib/hecks/projections/deploy/fargate/containers/rendering.rb +132 -0
- data/lib/hecks/projections/deploy/fargate/containers/routing.rb +93 -0
- data/lib/hecks/projections/deploy/fargate/containers.rb +10 -286
- data/lib/hecks/projections/deploy/fargate/extras/reading.rb +90 -0
- data/lib/hecks/projections/deploy/fargate/extras/rendering.rb +81 -0
- data/lib/hecks/projections/deploy/fargate/extras.rb +9 -158
- data/lib/hecks/projections/deploy/fargate/monitoring/alarms.rb +115 -0
- data/lib/hecks/projections/deploy/fargate/monitoring/reading.rb +84 -0
- data/lib/hecks/projections/deploy/fargate/monitoring/topic.rb +59 -0
- data/lib/hecks/projections/deploy/fargate/monitoring/warmer.rb +90 -0
- data/lib/hecks/projections/deploy/fargate/monitoring/warmer_roles.rb +76 -0
- data/lib/hecks/projections/deploy/fargate/monitoring.rb +14 -348
- data/lib/hecks/projections/deploy/fargate/sections.rb +115 -0
- data/lib/hecks/projections/deploy/fargate/settings/ids.rb +55 -0
- data/lib/hecks/projections/deploy/fargate/settings/tuning.rb +77 -0
- data/lib/hecks/projections/deploy/fargate/settings.rb +17 -104
- data/lib/hecks/projections/deploy/fargate/stack/blocks.rb +91 -0
- data/lib/hecks/projections/deploy/fargate/stack/readers.rb +87 -0
- data/lib/hecks/projections/deploy/fargate/stack/recipes.rb +106 -0
- data/lib/hecks/projections/deploy/fargate/stack.rb +146 -0
- data/lib/hecks/projections/deploy/fargate/task_sections.rb +56 -0
- data/lib/hecks/projections/deploy/fargate/yaml.rb +1 -1
- data/lib/hecks/projections/deploy/fargate.rb +51 -756
- data/lib/hecks/projections/deploy/lambda/pii.rb +49 -0
- data/lib/hecks/projections/deploy/lambda/stack/blocks.rb +118 -0
- data/lib/hecks/projections/deploy/lambda/stack/checks.rb +64 -0
- data/lib/hecks/projections/deploy/lambda/stack/deploy_chain.rb +119 -0
- data/lib/hecks/projections/deploy/lambda/stack/readers.rb +62 -0
- data/lib/hecks/projections/deploy/lambda/stack/reading.rb +170 -0
- data/lib/hecks/projections/deploy/lambda/stack/reading_web.rb +53 -0
- data/lib/hecks/projections/deploy/lambda/stack/recipes.rb +112 -0
- data/lib/hecks/projections/deploy/lambda/stack/web.rb +57 -0
- data/lib/hecks/projections/deploy/lambda/stack.rb +54 -0
- data/lib/hecks/projections/deploy/lambda.rb +77 -1885
- data/lib/hecks/projections/deploy/preview/access_yaml.rb +8 -74
- data/lib/hecks/projections/deploy/preview/containers.rb +18 -7
- data/lib/hecks/projections/deploy/preview/routing_yaml.rb +15 -87
- data/lib/hecks/projections/deploy/preview/settings.rb +7 -4
- data/lib/hecks/projections/deploy/preview/task_yaml.rb +42 -106
- data/lib/hecks/projections/deploy/preview/template.rb +11 -106
- data/lib/hecks/projections/deploy/preview/yaml_text.rb +1 -1
- data/lib/hecks/projections/deploy/scripts/hosting.mk.tmpl +1 -1
- data/lib/hecks/projections/deploy/scripts/settings.rb +14 -6
- data/lib/hecks/projections/deploy/scripts.rb +11 -9
- data/lib/hecks/projections/deploy/shared/rows.rb +48 -0
- data/lib/hecks/projections/deploy/shared.rb +89 -449
- data/lib/hecks/projections/deploy/smoke.rb +15 -10
- data/lib/hecks/projections/deploy/template_diff/comparer.rb +21 -147
- data/lib/hecks/projections/deploy/template_diff/normalizer.rb +60 -0
- data/lib/hecks/projections/deploy/template_diff/value_diff.rb +136 -0
- data/lib/hecks/projections/deploy/template_diff.rb +8 -3
- data/lib/hecks/projections/deploy/templates/fargate/Dockerfile.tmpl +28 -0
- data/lib/hecks/projections/deploy/templates/fargate/Makefile.tmpl +63 -0
- data/lib/hecks/projections/deploy/templates/fargate/always_params.tmpl +4 -0
- data/lib/hecks/projections/deploy/templates/fargate/deploy_plain.tmpl +1 -0
- data/lib/hecks/projections/deploy/templates/fargate/deploy_shared.tmpl +11 -0
- data/lib/hecks/projections/deploy/templates/fargate/mint_era_own.tmpl +44 -0
- data/lib/hecks/projections/deploy/templates/fargate/mint_era_shared.tmpl +8 -0
- data/lib/hecks/projections/deploy/templates/fargate/missing_owner.tmpl +9 -0
- data/lib/hecks/projections/deploy/templates/fargate/oauth_params.tmpl +7 -0
- data/lib/hecks/projections/deploy/templates/fargate/oauth_task_env.tmpl +4 -0
- data/lib/hecks/projections/deploy/templates/fargate/oauth_task_policy.tmpl +7 -0
- data/lib/hecks/projections/deploy/templates/fargate/owning_params.tmpl +33 -0
- data/lib/hecks/projections/deploy/templates/fargate/template.yaml.tmpl +281 -0
- data/lib/hecks/projections/deploy/templates/lambda/Makefile.tmpl +218 -0
- data/lib/hecks/projections/deploy/templates/lambda/aurora_depends.tmpl +18 -0
- data/lib/hecks/projections/deploy/templates/lambda/build_dispatch_none.tmpl +10 -0
- data/lib/hecks/projections/deploy/templates/lambda/build_pg.tmpl +15 -0
- data/lib/hecks/projections/deploy/templates/lambda/build_plain.tmpl +2 -0
- data/lib/hecks/projections/deploy/templates/lambda/build_web.tmpl +11 -0
- data/lib/hecks/projections/deploy/templates/lambda/env_blind_guard.tmpl +4 -0
- data/lib/hecks/projections/deploy/templates/lambda/mint_era_own.tmpl +122 -0
- data/lib/hecks/projections/deploy/templates/lambda/mint_era_shared.tmpl +47 -0
- data/lib/hecks/projections/deploy/templates/lambda/missing_owner.tmpl +9 -0
- data/lib/hecks/projections/deploy/templates/lambda/nat_comment_oauth.tmpl +14 -0
- data/lib/hecks/projections/deploy/templates/lambda/nat_comment_plain.tmpl +3 -0
- data/lib/hecks/projections/deploy/templates/lambda/oauth_note.tmpl +8 -0
- data/lib/hecks/projections/deploy/templates/lambda/params_oauth.tmpl +13 -0
- data/lib/hecks/projections/deploy/templates/lambda/params_shared.tmpl +33 -0
- data/lib/hecks/projections/deploy/templates/lambda/pg_native.tmpl +71 -0
- data/lib/hecks/projections/deploy/templates/lambda/pii_oac.tmpl +8 -0
- data/lib/hecks/projections/deploy/templates/lambda/pii_permission.tmpl +8 -0
- data/lib/hecks/projections/deploy/templates/lambda/pii_resources.tmpl +116 -0
- data/lib/hecks/projections/deploy/templates/lambda/predeploy_bridge.tmpl +30 -0
- data/lib/hecks/projections/deploy/templates/lambda/predeploy_bridge_oauth.tmpl +12 -0
- data/lib/hecks/projections/deploy/templates/lambda/predeploy_bridge_plain.tmpl +7 -0
- data/lib/hecks/projections/deploy/templates/lambda/rename_schema_own.tmpl +93 -0
- data/lib/hecks/projections/deploy/templates/lambda/rename_schema_shared.tmpl +7 -0
- data/lib/hecks/projections/deploy/templates/lambda/rust_oauth_env.tmpl +17 -0
- data/lib/hecks/projections/deploy/templates/lambda/rust_oauth_policy.tmpl +16 -0
- data/lib/hecks/projections/deploy/templates/lambda/rust_session_secret.tmpl +13 -0
- data/lib/hecks/projections/deploy/templates/lambda/samconfig.toml.tmpl +12 -0
- data/lib/hecks/projections/deploy/templates/lambda/shared_note.tmpl +6 -0
- data/lib/hecks/projections/deploy/templates/lambda/sync_oauth.tmpl +23 -0
- data/lib/hecks/projections/deploy/templates/lambda/template.yaml.tmpl +187 -0
- data/lib/hecks/projections/deploy/templates/lambda/translation_own.tmpl +46 -0
- data/lib/hecks/projections/deploy/templates/lambda/translation_shared.tmpl +2 -0
- data/lib/hecks/projections/deploy/templates/lambda/web_function.tmpl +207 -0
- data/lib/hecks/projections/deploy/templates/lambda/web_google_oauth_env.tmpl +12 -0
- data/lib/hecks/projections/deploy/templates/lambda/web_no_oauth_env.tmpl +7 -0
- data/lib/hecks/projections/deploy/templates/lambda/web_oauth_policy.tmpl +4 -0
- data/lib/hecks/projections/deploy/templates/lambda/webhook_secret_resource.tmpl +20 -0
- data/lib/hecks/projections/deploy/templates/preview/alb.tmpl +8 -0
- data/lib/hecks/projections/deploy/templates/preview/alb_security_group.tmpl +11 -0
- data/lib/hecks/projections/deploy/templates/preview/assume_role.tmpl +6 -0
- data/lib/hecks/projections/deploy/templates/preview/base_parameters.tmpl +24 -0
- data/lib/hecks/projections/deploy/templates/preview/cluster.tmpl +4 -0
- data/lib/hecks/projections/deploy/templates/preview/container_secret.tmpl +9 -0
- data/lib/hecks/projections/deploy/templates/preview/db_init_script.sh.tmpl +23 -0
- data/lib/hecks/projections/deploy/templates/preview/db_init_secrets.tmpl +5 -0
- data/lib/hecks/projections/deploy/templates/preview/db_init_task.tmpl +39 -0
- data/lib/hecks/projections/deploy/templates/preview/desired_count.tmpl +5 -0
- data/lib/hecks/projections/deploy/templates/preview/distribution.tmpl +24 -0
- data/lib/hecks/projections/deploy/templates/preview/execution_role.tmpl +16 -0
- data/lib/hecks/projections/deploy/templates/preview/header.tmpl +16 -0
- data/lib/hecks/projections/deploy/templates/preview/ingress.tmpl +8 -0
- data/lib/hecks/projections/deploy/templates/preview/listener.tmpl +9 -0
- data/lib/hecks/projections/deploy/templates/preview/listener_rule.tmpl +11 -0
- data/lib/hecks/projections/deploy/templates/preview/log_group.tmpl +5 -0
- data/lib/hecks/projections/deploy/templates/preview/log_options.tmpl +5 -0
- data/lib/hecks/projections/deploy/templates/preview/outputs.tmpl +14 -0
- data/lib/hecks/projections/deploy/templates/preview/service.tmpl +17 -0
- data/lib/hecks/projections/deploy/templates/preview/session_secret.tmpl +11 -0
- data/lib/hecks/projections/deploy/templates/preview/target_group.tmpl +9 -0
- data/lib/hecks/projections/deploy/templates/preview/task_definition.tmpl +15 -0
- data/lib/hecks/projections/deploy/templates/preview/task_role.tmpl +22 -0
- data/lib/hecks/projections/deploy/templates/shared/aurora_db.tmpl +52 -0
- data/lib/hecks/projections/deploy/templates/shared/bastion.tmpl +74 -0
- data/lib/hecks/projections/deploy/templates/shared/bastion_own_public.tmpl +41 -0
- data/lib/hecks/projections/deploy/templates/shared/bastion_reuse_public.tmpl +10 -0
- data/lib/hecks/projections/deploy/templates/shared/nat_gateway.tmpl +102 -0
- data/lib/hecks/projections/deploy/templates/shared/oauth_egress.tmpl +17 -0
- data/lib/hecks/projections/deploy/templates/shared/plain_db.tmpl +16 -0
- data/lib/hecks/projections/deploy/templates/shared/vpc_and_database.tmpl +67 -0
- data/lib/hecks/projections/deploy/text_template.rb +35 -0
- data/lib/hecks/projections/diagrams/dispatch.rb +114 -0
- data/lib/hecks/projections/diagrams/statecharts.rb +59 -0
- data/lib/hecks/projections/diagrams/structure.rb +114 -0
- data/lib/hecks/projections/diagrams.rb +33 -256
- data/lib/hecks/projections/glossary/entries.rb +140 -0
- data/lib/hecks/projections/glossary/html/page.rb +96 -0
- data/lib/hecks/projections/glossary/html/parser.rb +66 -0
- data/lib/hecks/projections/glossary/html/sections.rb +78 -0
- data/lib/hecks/projections/glossary/html.rb +7 -179
- data/lib/hecks/projections/glossary/index.rb +45 -0
- data/lib/hecks/projections/glossary/markdown.rb +22 -11
- data/lib/hecks/projections/glossary/mermaid.rb +44 -31
- data/lib/hecks/projections/glossary/sensitivity.rb +7 -4
- data/lib/hecks/projections/glossary/sentences/value_objects.rb +77 -0
- data/lib/hecks/projections/glossary/sentences.rb +42 -81
- data/lib/hecks/projections/glossary/slugs.rb +33 -0
- data/lib/hecks/projections/glossary.rb +22 -190
- data/lib/hecks/projections/model.rb +20 -14
- data/lib/hecks/projections/rust_vocabulary/arguments/support.rb +33 -0
- data/lib/hecks/projections/rust_vocabulary/arguments.rb +171 -0
- data/lib/hecks/projections/rust_vocabulary/enum_body.rb +114 -0
- data/lib/hecks/projections/rust_vocabulary/tests.rb +144 -0
- data/lib/hecks/projections/rust_vocabulary.rb +24 -293
- data/lib/hecks/projections/site/admin.rb +15 -9
- data/lib/hecks/projections/site/admin_cms/templates/membership.rb +115 -0
- data/lib/hecks/projections/site/admin_cms/templates/session_strategy.rb +90 -0
- data/lib/hecks/projections/site/admin_cms/templates/sso.rb +101 -0
- data/lib/hecks/projections/site/admin_cms/templates/sso_tail.rb +54 -0
- data/lib/hecks/projections/site/admin_cms/templates/users.rb +83 -0
- data/lib/hecks/projections/site/admin_cms/templates.rb +14 -369
- data/lib/hecks/projections/site/admin_cms.rb +15 -9
- data/lib/hecks/projections/site/edge/behaviours.rb +10 -6
- data/lib/hecks/projections/site/edge/checks.rb +30 -80
- data/lib/hecks/projections/site/edge/findings.rb +28 -0
- data/lib/hecks/projections/site/edge/route_checks.rb +110 -0
- data/lib/hecks/projections/site/edge/row_reader.rb +52 -0
- data/lib/hecks/projections/site/edge/rules.rb +28 -26
- data/lib/hecks/projections/site/edge.rb +20 -31
- data/lib/hecks/projections/site/live_edge.rb +9 -7
- data/lib/hecks/projections/site/payload/fields/definitions.rb +90 -0
- data/lib/hecks/projections/site/payload/fields/readers.rb +69 -0
- data/lib/hecks/projections/site/payload/fields.rb +14 -111
- data/lib/hecks/projections/site/payload/lifecycle/text.rb +84 -0
- data/lib/hecks/projections/site/payload/lifecycle/text_tail.rb +106 -0
- data/lib/hecks/projections/site/payload/lifecycle.rb +8 -166
- data/lib/hecks/projections/site/payload/model.rb +22 -22
- data/lib/hecks/projections/site/payload/specs/wire.rb +69 -0
- data/lib/hecks/projections/site/payload/specs.rb +24 -68
- data/lib/hecks/projections/site/payload_driver.rb +19 -17
- data/lib/hecks/projections/site/root_rows.rb +12 -4
- data/lib/hecks/projections/site/routes_ts/helpers.rb +79 -0
- data/lib/hecks/projections/site/routes_ts/listings.rb +75 -0
- data/lib/hecks/projections/site/routes_ts/navigation.rb +79 -0
- data/lib/hecks/projections/site/routes_ts.rb +27 -175
- data/lib/hecks/projections/site/site_admin/access.rb +104 -0
- data/lib/hecks/projections/site/site_admin/session.rb +127 -0
- data/lib/hecks/projections/site/site_admin.rb +12 -219
- data/lib/hecks/projections/site/site_cdn.rb +12 -7
- data/lib/hecks/projections/site/site_host/dockerfile.rb +75 -0
- data/lib/hecks/projections/site/site_host/templates.rb +7 -63
- data/lib/hecks/projections/site/site_root/workflow.rb +65 -0
- data/lib/hecks/projections/site/site_root.rb +3 -54
- data/lib/hecks/projections/site/table/checks.rb +28 -57
- data/lib/hecks/projections/site/table/link_builder.rb +14 -5
- data/lib/hecks/projections/site/table/navigation_checks.rb +75 -0
- data/lib/hecks/projections/site/table/row_builder.rb +31 -53
- data/lib/hecks/projections/site/table/row_defaults.rb +65 -0
- data/lib/hecks/projections/site/table.rb +9 -5
- data/lib/hecks/projections/vocabulary.rb +34 -31
- data/lib/hecks/projector/cli_audience.rb +42 -0
- data/lib/hecks/projector/cli_projector/claims.rb +149 -0
- data/lib/hecks/projector/cli_projector/command_help.rb +65 -0
- data/lib/hecks/projector/cli_projector/command_specs.rb +133 -0
- data/lib/hecks/projector/cli_projector/listing.rb +100 -0
- data/lib/hecks/projector/cli_projector/option_specs.rb +116 -0
- data/lib/hecks/projector/cli_projector/query_specs.rb +67 -0
- data/lib/hecks/projector/cli_projector/usage.rb +101 -0
- data/lib/hecks/projector/cli_projector.rb +15 -532
- data/lib/hecks/projector/docs_projector/attributes.rb +78 -0
- data/lib/hecks/projector/docs_projector/behaviour.rb +127 -0
- data/lib/hecks/projector/docs_projector/closing.rb +40 -0
- data/lib/hecks/projector/docs_projector.rb +58 -192
- data/lib/hecks/projector/exporter/bindings.rb +174 -0
- data/lib/hecks/projector/exporter/translations.rb +127 -0
- data/lib/hecks/projector/exporter.rb +8 -279
- data/lib/hecks/projector/narrate_projector/commands.rb +108 -0
- data/lib/hecks/projector/narrate_projector/reactions.rb +33 -0
- data/lib/hecks/projector/narrate_projector.rb +60 -160
- data/lib/hecks/projector.rb +22 -13
- data/lib/hecks/quality_control/adapters/agent_profile.rb +25 -16
- data/lib/hecks/quality_control/adapters/github_checks.rb +42 -6
- data/lib/hecks/quality_control/adapters/github_ci_webhook.rb +1 -1
- data/lib/hecks/quality_control/adapters/github_issues.rb +22 -10
- data/lib/hecks/quality_control/cli/qa_discover_external_domains/parsing.rb +54 -0
- data/lib/hecks/quality_control/cli/qa_discover_external_domains/reporting.rb +44 -0
- data/lib/hecks/quality_control/cli/qa_discover_external_domains/scanning.rb +119 -0
- data/lib/hecks/quality_control/cli/qa_discover_external_domains.rb +28 -155
- data/lib/hecks/quality_control/cli/qa_domain_novelty/verdict.rb +76 -0
- data/lib/hecks/quality_control/cli/qa_domain_novelty.rb +33 -66
- data/lib/hecks/quality_control/cli/qa_generated_domains/arguments.rb +62 -0
- data/lib/hecks/quality_control/cli/qa_generated_domains/blueprints.rb +45 -0
- data/lib/hecks/quality_control/cli/qa_generated_domains/evaluation.rb +107 -0
- data/lib/hecks/quality_control/cli/qa_generated_domains/promotion.rb +107 -0
- data/lib/hecks/quality_control/cli/qa_generated_domains/reporting.rb +97 -0
- data/lib/hecks/quality_control/cli/qa_generated_domains/shrinking.rb +70 -0
- data/lib/hecks/quality_control/cli/qa_generated_domains.rb +43 -327
- data/lib/hecks/quality_control/cli/qa_log_bug/arguments.rb +55 -0
- data/lib/hecks/quality_control/cli/qa_log_bug/proof.rb +65 -0
- data/lib/hecks/quality_control/cli/qa_log_bug.rb +18 -81
- data/lib/hecks/quality_control/cli/qa_mine_combinations/arguments.rb +54 -0
- data/lib/hecks/quality_control/cli/qa_mine_combinations/booting.rb +96 -0
- data/lib/hecks/quality_control/cli/qa_mine_combinations.rb +45 -109
- data/lib/hecks/quality_control/cli/qa_open_pr/arguments.rb +55 -0
- data/lib/hecks/quality_control/cli/qa_open_pr/recording.rb +79 -0
- data/lib/hecks/quality_control/cli/qa_open_pr/rules.rb +122 -0
- data/lib/hecks/quality_control/cli/qa_open_pr.rb +41 -200
- data/lib/hecks/quality_control/cli/qa_postgres_migrate/copying.rb +45 -0
- data/lib/hecks/quality_control/cli/qa_postgres_migrate/reporting.rb +33 -0
- data/lib/hecks/quality_control/cli/qa_postgres_migrate.rb +37 -63
- data/lib/hecks/quality_control/cli/qa_postgres_role/ownership.rb +57 -0
- data/lib/hecks/quality_control/cli/qa_postgres_role.rb +66 -71
- data/lib/hecks/quality_control/cli/qa_pr_check/checking.rb +118 -0
- data/lib/hecks/quality_control/cli/qa_pr_check/reporting.rb +54 -0
- data/lib/hecks/quality_control/cli/qa_pr_check.rb +28 -145
- data/lib/hecks/quality_control/cli/qa_seed_angles/seed.rb +80 -0
- data/lib/hecks/quality_control/cli/qa_seed_angles.rb +13 -86
- data/lib/hecks/quality_control/cli/qa_sweep/all_mode/children.rb +80 -0
- data/lib/hecks/quality_control/cli/qa_sweep/all_mode/report.rb +125 -0
- data/lib/hecks/quality_control/cli/qa_sweep/all_mode.rb +63 -193
- data/lib/hecks/quality_control/cli/qa_sweep/checks/boundary.rb +92 -0
- data/lib/hecks/quality_control/cli/qa_sweep/checks/engines.rb +92 -0
- data/lib/hecks/quality_control/cli/qa_sweep/checks/seeds.rb +86 -0
- data/lib/hecks/quality_control/cli/qa_sweep/checks/shrinking.rb +69 -0
- data/lib/hecks/quality_control/cli/qa_sweep/checks.rb +10 -248
- data/lib/hecks/quality_control/cli/qa_sweep/conclusion.rb +60 -0
- data/lib/hecks/quality_control/cli/qa_sweep/depth.rb +61 -0
- data/lib/hecks/quality_control/cli/qa_sweep/dials.rb +26 -13
- data/lib/hecks/quality_control/cli/qa_sweep/finding_report/shrunk.rb +42 -0
- data/lib/hecks/quality_control/cli/qa_sweep/finding_report.rb +40 -41
- data/lib/hecks/quality_control/cli/qa_sweep/parsing/validation.rb +70 -0
- data/lib/hecks/quality_control/cli/qa_sweep/parsing.rb +35 -65
- data/lib/hecks/quality_control/cli/qa_sweep/release_mode.rb +41 -22
- data/lib/hecks/quality_control/cli/qa_sweep/scratch.rb +67 -0
- data/lib/hecks/quality_control/cli/qa_sweep/seat.rb +94 -0
- data/lib/hecks/quality_control/cli/qa_sweep/seed_loop.rb +149 -0
- data/lib/hecks/quality_control/cli/qa_sweep/target_setup.rb +115 -0
- data/lib/hecks/quality_control/cli/qa_sweep.rb +22 -445
- data/lib/hecks/quality_control/cli/qa_tick/output.rb +107 -0
- data/lib/hecks/quality_control/cli/qa_tick/preflight.rb +95 -0
- data/lib/hecks/quality_control/cli/qa_tick.rb +42 -175
- data/lib/hecks/query_ir/formatting.rb +86 -0
- data/lib/hecks/query_ir/rules.rb +132 -0
- data/lib/hecks/query_ir/touchpoints.rb +104 -0
- data/lib/hecks/query_ir.rb +33 -281
- data/lib/hecks/query_ir_mcp/tools.rb +68 -0
- data/lib/hecks/query_ir_mcp.rb +27 -71
- data/lib/hecks/query_specification/common/comparison.rb +25 -5
- data/lib/hecks/query_specification/common/dsl.rb +1 -1
- data/lib/hecks/query_specification/common/null_policy.rb +9 -6
- data/lib/hecks/query_specification/common/options.rb +21 -14
- data/lib/hecks/query_specification/field_path.rb +5 -2
- data/lib/hecks/query_specification/hop_path.rb +15 -18
- data/lib/hecks/release/lane.rb +22 -0
- data/lib/hecks/release/runner/clean_tree.rb +2 -2
- data/lib/hecks/release/runner/commands.rb +1 -1
- data/lib/hecks/release/runner/options.rb +82 -0
- data/lib/hecks/release/runner/preflight.rb +12 -7
- data/lib/hecks/release/runner/publishing.rb +86 -0
- data/lib/hecks/release/runner/tagger.rb +8 -3
- data/lib/hecks/release/runner.rb +40 -156
- data/lib/hecks/rendering.rb +13 -9
- data/lib/hecks/router/door.rb +37 -0
- data/lib/hecks/router/namespace_installer.rb +45 -83
- data/lib/hecks/router/options_proxy.rb +44 -0
- data/lib/hecks/runtime/adapter_lookup.rb +45 -24
- data/lib/hecks/runtime/command_interpreter/argument_gate.rb +16 -8
- data/lib/hecks/runtime/command_interpreter/delegation.rb +116 -0
- data/lib/hecks/runtime/command_interpreter/enforcement.rb +38 -0
- data/lib/hecks/runtime/command_interpreter/hydration.rb +139 -0
- data/lib/hecks/runtime/command_interpreter/list_mutations.rb +98 -0
- data/lib/hecks/runtime/command_interpreter/mutation_applier.rb +67 -114
- data/lib/hecks/runtime/command_interpreter/persisting.rb +96 -0
- data/lib/hecks/runtime/command_interpreter.rb +57 -352
- data/lib/hecks/runtime/command_rules/admissibility.rb +64 -147
- data/lib/hecks/runtime/command_rules/arithmetic.rb +13 -72
- data/lib/hecks/runtime/command_rules/authorization.rb +9 -9
- data/lib/hecks/runtime/command_rules/emission.rb +13 -14
- data/lib/hecks/runtime/command_rules/guard_state.rb +49 -0
- data/lib/hecks/runtime/command_rules/invariants.rb +84 -0
- data/lib/hecks/runtime/command_rules/operands.rb +88 -0
- data/lib/hecks/runtime/command_rules/references.rb +59 -57
- data/lib/hecks/runtime/command_rules/tenant_boundary.rb +69 -0
- data/lib/hecks/runtime/dependency_planning/analyzer.rb +90 -0
- data/lib/hecks/runtime/dependency_planning/expression_reads.rb +73 -0
- data/lib/hecks/runtime/dependency_planning/mutation_analysis.rb +89 -0
- data/lib/hecks/runtime/dependency_planning/rule_analysis.rb +82 -0
- data/lib/hecks/runtime/dependency_planning.rb +3 -250
- data/lib/hecks/runtime/dispatcher/queries.rb +62 -0
- data/lib/hecks/runtime/dispatcher/result.rb +55 -0
- data/lib/hecks/runtime/dispatcher/routing.rb +107 -0
- data/lib/hecks/runtime/dispatcher.rb +64 -209
- data/lib/hecks/runtime/entity_element/location.rb +124 -0
- data/lib/hecks/runtime/entity_element/mutations.rb +150 -0
- data/lib/hecks/runtime/entity_element.rb +5 -177
- data/lib/hecks/runtime/entity_interpreter/enforcement.rb +51 -0
- data/lib/hecks/runtime/entity_interpreter/locating.rb +62 -0
- data/lib/hecks/runtime/entity_interpreter/resolution.rb +42 -0
- data/lib/hecks/runtime/entity_interpreter/saving.rb +49 -0
- data/lib/hecks/runtime/entity_interpreter.rb +45 -164
- data/lib/hecks/runtime/identity.rb +15 -9
- data/lib/hecks/runtime/instance.rb +11 -7
- data/lib/hecks/runtime/interpreting.rb +16 -8
- data/lib/hecks/runtime/invocation.rb +3 -155
- data/lib/hecks/runtime/invocation_builder.rb +132 -0
- data/lib/hecks/runtime/invocation_facts.rb +87 -0
- data/lib/hecks/runtime/loader/boot_steps.rb +96 -0
- data/lib/hecks/runtime/loader/described.rb +27 -0
- data/lib/hecks/runtime/loader.rb +27 -114
- data/lib/hecks/runtime/outbox/consumer_runner.rb +40 -0
- data/lib/hecks/runtime/outbox/fanout.rb +82 -0
- data/lib/hecks/runtime/outbox/relay.rb +149 -0
- data/lib/hecks/runtime/outbox.rb +3 -214
- data/lib/hecks/runtime/policy_interpreter/arguments.rb +67 -0
- data/lib/hecks/runtime/policy_interpreter/fan_out.rb +96 -0
- data/lib/hecks/runtime/policy_interpreter.rb +22 -137
- data/lib/hecks/runtime/port_operation_interpreter.rb +18 -17
- data/lib/hecks/runtime/query_interpreter/arguments.rb +51 -0
- data/lib/hecks/runtime/query_interpreter/entity_rows.rb +82 -0
- data/lib/hecks/runtime/query_interpreter/outside_answer.rb +89 -0
- data/lib/hecks/runtime/query_interpreter.rb +43 -191
- data/lib/hecks/runtime/reaction_invocation/identities.rb +92 -0
- data/lib/hecks/runtime/reaction_invocation/target_resolution.rb +88 -0
- data/lib/hecks/runtime/reaction_invocation.rb +66 -183
- data/lib/hecks/runtime/reaction_outcome.rb +7 -3
- data/lib/hecks/runtime/read_model_interpreter/head_ordering.rb +49 -0
- data/lib/hecks/runtime/read_model_interpreter/reductions.rb +123 -0
- data/lib/hecks/runtime/read_model_interpreter/shaping.rb +100 -0
- data/lib/hecks/runtime/read_model_interpreter.rb +71 -214
- data/lib/hecks/runtime/reference_hop.rb +11 -11
- data/lib/hecks/runtime/refusal_wording.rb +11 -8
- data/lib/hecks/runtime/registry/chapter_verification.rb +84 -0
- data/lib/hecks/runtime/registry/declarations.rb +17 -0
- data/lib/hecks/runtime/registry/durability_warnings.rb +71 -0
- data/lib/hecks/runtime/registry/hecksagon_rules.rb +124 -0
- data/lib/hecks/runtime/registry/merging.rb +49 -0
- data/lib/hecks/runtime/registry/providers.rb +139 -0
- data/lib/hecks/runtime/registry/query_verification.rb +144 -0
- data/lib/hecks/runtime/registry/read_repository.rb +61 -0
- data/lib/hecks/runtime/registry/runtime_state.rb +27 -0
- data/lib/hecks/runtime/registry/saga_persistence.rb +12 -8
- data/lib/hecks/runtime/registry/verification.rb +45 -389
- data/lib/hecks/runtime/registry/world_defaults.rb +3 -3
- data/lib/hecks/runtime/registry.rb +58 -296
- data/lib/hecks/runtime/remote_dispatcher.rb +47 -31
- data/lib/hecks/runtime/saga_interpreter/compensation.rb +90 -0
- data/lib/hecks/runtime/saga_interpreter/correlation.rb +19 -10
- data/lib/hecks/runtime/saga_interpreter/delivery.rb +147 -0
- data/lib/hecks/runtime/saga_interpreter/lifecycle.rb +63 -0
- data/lib/hecks/runtime/saga_interpreter/transitions.rb +112 -0
- data/lib/hecks/runtime/saga_interpreter.rb +41 -320
- data/lib/hecks/runtime/tenant_check.rb +14 -9
- data/lib/hecks/runtime/value/admission.rb +28 -19
- data/lib/hecks/runtime/value/coercion.rb +55 -404
- data/lib/hecks/runtime/value/entity_list_coercion.rb +27 -29
- data/lib/hecks/runtime/value/field_checks.rb +57 -100
- data/lib/hecks/runtime/value/flags.rb +65 -0
- data/lib/hecks/runtime/value/identifiers.rb +64 -0
- data/lib/hecks/runtime/value/references.rb +195 -0
- data/lib/hecks/runtime/value/shape_checks.rb +61 -0
- data/lib/hecks/runtime/value/validation.rb +125 -0
- data/lib/hecks/runtime/value.rb +18 -6
- data/lib/hecks/rust_build/conformance/surface.rb +75 -0
- data/lib/hecks/rust_build/conformance.rb +27 -59
- data/lib/hecks/rust_build/conformance_fuzz.rb +26 -15
- data/lib/hecks/rust_build/coverage.rb +32 -104
- data/lib/hecks/rust_build/coverage_parts/expected.rb +68 -0
- data/lib/hecks/rust_build/coverage_parts/printer.rb +75 -0
- data/lib/hecks/rust_build/host.rb +23 -13
- data/lib/hecks/rust_build/kernel_input.rb +19 -12
- data/lib/hecks/rust_build/native_build.rb +19 -15
- data/lib/hecks/rust_build/project_rust/domain_loader.rb +75 -0
- data/lib/hecks/rust_build/project_rust/root_mod/notes.rb +66 -0
- data/lib/hecks/rust_build/project_rust/root_mod.rb +22 -55
- data/lib/hecks/rust_build/project_rust/target_ir.rb +74 -0
- data/lib/hecks/rust_build/project_rust.rb +21 -89
- data/lib/hecks/rust_build/wasm.rb +11 -4
- data/lib/hecks/rust_build/wasm_browser.rb +7 -7
- data/lib/hecks/rust_build/write_if_changed.rb +3 -6
- data/lib/hecks/rust_build.rb +7 -3
- data/lib/hecks/storehouse/audit.rb +106 -0
- data/lib/hecks/storehouse/callers.rb +73 -0
- data/lib/hecks/storehouse/dispatching.rb +149 -0
- data/lib/hecks/storehouse/introspection.rb +145 -0
- data/lib/hecks/storehouse/querying.rb +78 -0
- data/lib/hecks/storehouse.rb +43 -451
- data/lib/hecks/tickets/bluebook/tickets.bluebook +29 -0
- data/lib/hecks/tools/argument_gate_matrix/dispatching.rb +69 -0
- data/lib/hecks/tools/argument_gate_matrix/rows.rb +121 -0
- data/lib/hecks/tools/argument_gate_matrix/violations.rb +108 -0
- data/lib/hecks/tools/argument_gate_matrix.rb +43 -212
- data/lib/hecks/tools/ci_gate_decision.rb +21 -14
- data/lib/hecks/tools/ci_gates.rb +40 -26
- data/lib/hecks/tools/comment_style/baseline.rb +41 -0
- data/lib/hecks/tools/comment_style/caps_words.rb +104 -0
- data/lib/hecks/tools/comment_style/cli.rb +121 -0
- data/lib/hecks/tools/comment_style/dictionary.rb +60 -0
- data/lib/hecks/tools/comment_style/fixing.rb +119 -0
- data/lib/hecks/tools/comment_style/long_blocks.rb +51 -0
- data/lib/hecks/tools/comment_style/masking.rb +94 -0
- data/lib/hecks/tools/comment_style/patterns.rb +61 -0
- data/lib/hecks/tools/comment_style/run.rb +161 -0
- data/lib/hecks/tools/comment_style/signature.rb +59 -0
- data/lib/hecks/tools/comment_style/source_file.rb +105 -0
- data/lib/hecks/tools/comment_style/structure_checks.rb +113 -0
- data/lib/hecks/tools/comment_style/text_checks.rb +67 -0
- data/lib/hecks/tools/comment_style/vocabulary.rb +55 -0
- data/lib/hecks/tools/comment_style/walker.rb +136 -0
- data/lib/hecks/tools/comment_style.rb +17 -1000
- data/lib/hecks/tools/corpus_report.rb +26 -16
- data/lib/hecks/tools/deploy_recipe/targets.rb +61 -0
- data/lib/hecks/tools/deploy_recipe/worlds.rb +114 -0
- data/lib/hecks/tools/deploy_recipe.rb +60 -174
- data/lib/hecks/tools/deploy_recipe_lint/checks.rb +78 -0
- data/lib/hecks/tools/deploy_recipe_lint/fixtures.rb +88 -0
- data/lib/hecks/tools/deploy_recipe_lint/makefile.rb +84 -0
- data/lib/hecks/tools/deploy_recipe_lint.rb +29 -192
- data/lib/hecks/tools/drop_implicit_append_fields.rb +20 -12
- data/lib/hecks/tools/era_projection_backfill.rb +50 -33
- data/lib/hecks/tools/era_reattest/reporting.rb +55 -0
- data/lib/hecks/tools/era_reattest.rb +32 -43
- data/lib/hecks/tools/evolve_run/arguments.rb +49 -0
- data/lib/hecks/tools/evolve_run/words.rb +60 -0
- data/lib/hecks/tools/evolve_run.rb +43 -90
- data/lib/hecks/tools/fuzz_sweep/findings.rb +106 -0
- data/lib/hecks/tools/fuzz_sweep/options.rb +69 -0
- data/lib/hecks/tools/fuzz_sweep/pool.rb +74 -0
- data/lib/hecks/tools/fuzz_sweep/reporting.rb +88 -0
- data/lib/hecks/tools/fuzz_sweep.rb +75 -273
- data/lib/hecks/tools/gate.rb +31 -16
- data/lib/hecks/tools/heki_compaction.rb +63 -42
- data/lib/hecks/tools/hoist_local_givens/rewriting.rb +119 -0
- data/lib/hecks/tools/hoist_local_givens.rb +89 -157
- data/lib/hecks/tools/journal_compaction.rb +40 -31
- data/lib/hecks/tools/lanes/files.rb +82 -0
- data/lib/hecks/tools/lanes/live.rb +41 -0
- data/lib/hecks/tools/lanes/rows.rb +45 -0
- data/lib/hecks/tools/lanes/ruleset.rb +44 -0
- data/lib/hecks/tools/lanes/watch_workflow.rb +82 -0
- data/lib/hecks/tools/lanes/workflow.rb +79 -0
- data/lib/hecks/tools/lanes.rb +71 -0
- data/lib/hecks/tools/oidc_manifests.rb +10 -9
- data/lib/hecks/tools/query_ir_run.rb +7 -3
- data/lib/hecks/tools/regeneration_run.rb +40 -26
- data/lib/hecks/tools/rust_comment_style/caps_words.rb +98 -0
- data/lib/hecks/tools/rust_comment_style/fixing.rb +102 -0
- data/lib/hecks/tools/rust_comment_style/masking.rb +85 -0
- data/lib/hecks/tools/rust_comment_style/run.rb +94 -0
- data/lib/hecks/tools/rust_comment_style/source_file.rb +71 -0
- data/lib/hecks/tools/rust_comment_style/structure.rb +79 -0
- data/lib/hecks/tools/rust_comment_style/text_checks.rb +63 -0
- data/lib/hecks/tools/rust_comment_style/tokenizer.rb +102 -0
- data/lib/hecks/tools/rust_comment_style.rb +38 -535
- data/lib/hecks/tools/sequence_script.rb +20 -14
- data/lib/hecks/tools/site_routes/cli.rb +70 -0
- data/lib/hecks/tools/site_routes/root_files.rb +59 -0
- data/lib/hecks/tools/site_routes/templates.rb +77 -0
- data/lib/hecks/tools/site_routes.rb +84 -160
- data/lib/hecks/tools/tail_merge.rb +45 -37
- data/lib/hecks/tools/tenant_provisioning.rb +45 -31
- data/lib/hecks/tools/tools_doc.rb +42 -19
- data/lib/hecks/tools/translation_audit/domain_loading.rb +71 -0
- data/lib/hecks/tools/translation_audit/edges.rb +71 -0
- data/lib/hecks/tools/translation_audit/verdicts.rb +107 -0
- data/lib/hecks/tools/translation_audit.rb +30 -161
- data/lib/hecks/tools/translation_scaffold/reporting.rb +40 -0
- data/lib/hecks/tools/translation_scaffold.rb +77 -60
- data/lib/hecks/tools.rb +1 -0
- data/lib/hecks/vendoring.rb +37 -11
- data/lib/hecks/version.rb +1 -1
- data/lib/hecks/vocabulary.rb +16 -1
- data/lib/rubocop/cop/hecks/fallback_hash_lookup.rb +7 -9
- data/lib/rubocop/cop/hecks/thread_shared_ivar_mutation.rb +8 -6
- data/rust/.cargo/mutants.toml +8 -0
- data/rust/host/Cargo.toml +5 -0
- data/rust/host/HECKS_RELEASE +1 -1
- data/rust/host/src/auth.rs +32 -0
- data/rust/host/src/web.rs +2 -3
- data/rust/src/kernel/dispatch.rs +4 -0
- data/rust/src/kernel/dispatch_guard_tests.rs +506 -0
- data/rust/src/kernel/orchestrate.rs +4 -0
- data/rust/src/kernel/orchestrate_guard_tests.rs +708 -0
- metadata +591 -3
- /data/lib/hecks/bluebook/behaviour/{hexagon.rb → hecksagon.rb} +0 -0
|
@@ -7,6 +7,13 @@ require_relative "../../../../adapters/driven/postgres/shared_connection"
|
|
|
7
7
|
require_relative "postgres_era/lineage"
|
|
8
8
|
require_relative "postgres_era/lineage_manager"
|
|
9
9
|
require_relative "postgres_era/events"
|
|
10
|
+
require_relative "postgres_era/class_methods"
|
|
11
|
+
require_relative "postgres_era/boot"
|
|
12
|
+
require_relative "postgres_era/sagas"
|
|
13
|
+
require_relative "postgres_era/journal"
|
|
14
|
+
require_relative "postgres_era/dialect"
|
|
15
|
+
require_relative "postgres_era/query_phases"
|
|
16
|
+
require_relative "postgres_era/head_writes"
|
|
10
17
|
require_relative "../../../../ports/persistence/append_only"
|
|
11
18
|
require_relative "../../../../query_specification/common/order_by"
|
|
12
19
|
require_relative "../../../../runtime/errors"
|
|
@@ -23,6 +30,13 @@ module Hecks
|
|
|
23
30
|
include Adapters::PostgresOutbox
|
|
24
31
|
include Adapters::PostgresReconnect
|
|
25
32
|
include Events
|
|
33
|
+
include Sagas
|
|
34
|
+
include Journal
|
|
35
|
+
include Boot
|
|
36
|
+
include Dialect
|
|
37
|
+
include QueryPhases
|
|
38
|
+
include HeadWrites
|
|
39
|
+
extend ClassMethods
|
|
26
40
|
|
|
27
41
|
attr_reader :aggregate
|
|
28
42
|
|
|
@@ -30,7 +44,7 @@ module Hecks
|
|
|
30
44
|
#
|
|
31
45
|
# `:cross_process_lock` lets dispatch hold `with_write_lock` instead of the in-process
|
|
32
46
|
# mutex, which `rust/host` in another OS process cannot see (ADR 0036). `:atomic_append`
|
|
33
|
-
# tells `RepositoryFactory.build` that `append`
|
|
47
|
+
# tells `RepositoryFactory.build` that `append` already commits the snapshot in
|
|
34
48
|
# the same transaction as the journal row, so replaying the journal through `project` on
|
|
35
49
|
# boot has nothing left to fix up.
|
|
36
50
|
#
|
|
@@ -47,86 +61,6 @@ module Hecks
|
|
|
47
61
|
# @return [Boolean] always true
|
|
48
62
|
def self.tenant_capable? = true
|
|
49
63
|
|
|
50
|
-
# Resolves this boot's era, minting the next one when the shape drifted and a translation
|
|
51
|
-
# edge covers it. Delegates to `LineageManager.check!`.
|
|
52
|
-
#
|
|
53
|
-
# @param settings [Hash{Symbol, String => Object}] persistence settings; needs `database`
|
|
54
|
-
# @param directory [String, nil] where `HECKS_SCAFFOLD=1` writes a translation edge
|
|
55
|
-
# @return [Integer, nil] the ordinal of the era this boot minted, or nil when none
|
|
56
|
-
# @raise [Runtime::WiringError] if the database is unreachable or the mint refuses
|
|
57
|
-
# @raise [Bluebook::DSL::Malformed] if a held era's text parses under no grammar
|
|
58
|
-
def self.era_check!(registry:, bluebook:, current_text:, settings:, directory: nil)
|
|
59
|
-
LineageManager.check!(
|
|
60
|
-
registry: registry, bluebook: bluebook, current_text: current_text,
|
|
61
|
-
settings: settings, directory: directory
|
|
62
|
-
)
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
# Reads one setting under either its Symbol or String spelling.
|
|
66
|
-
#
|
|
67
|
-
# Uses `key?` rather than `||` so a stored `false` is not mistaken for an absent key.
|
|
68
|
-
#
|
|
69
|
-
# @return [Object, nil] the stored value, or `default` when neither spelling is present
|
|
70
|
-
def self.setting(settings, key, default: nil)
|
|
71
|
-
return settings[key] if settings.key?(key)
|
|
72
|
-
|
|
73
|
-
str_key = key.to_s
|
|
74
|
-
return settings[str_key] if settings.key?(str_key)
|
|
75
|
-
|
|
76
|
-
default
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
# Opens a connection to the declared database, selecting the declared `schema` if any.
|
|
80
|
-
# The caller owns the connection and closes it.
|
|
81
|
-
#
|
|
82
|
-
# @param name [String] the domain or aggregate name, used only in refusal messages
|
|
83
|
-
# @param settings [Hash{Symbol, String => Object}] `database` is a name or `postgres://` URL
|
|
84
|
-
# @return [PG::Connection] an open connection
|
|
85
|
-
# @raise [Runtime::WiringError] if `database` is missing or Postgres refuses a statement
|
|
86
|
-
def self.connect_for(name, settings)
|
|
87
|
-
# Lazy so a domain that never wires PostgresEra does not need the pg gem.
|
|
88
|
-
begin
|
|
89
|
-
require "pg"
|
|
90
|
-
rescue LoadError
|
|
91
|
-
raise LoadError, "#{name} binds PostgresEra, which needs the pg gem: add `gem \"pg\"` to the Gemfile"
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
declared = setting(settings, :database)
|
|
95
|
-
if declared.to_s.empty?
|
|
96
|
-
raise Runtime::WiringError,
|
|
97
|
-
"#{name} binds PostgresEra, which needs a database connection, " \
|
|
98
|
-
"but its world declares no \"database\"."
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
connection =
|
|
102
|
-
if declared.start_with?("postgres://", "postgresql://")
|
|
103
|
-
PG.connect(declared)
|
|
104
|
-
else
|
|
105
|
-
PG.connect(dbname: declared)
|
|
106
|
-
end
|
|
107
|
-
|
|
108
|
-
# A declared `schema` means the instance is shared; search_path makes every unqualified
|
|
109
|
-
# name this adapter and its lineage classes build resolve inside that schema.
|
|
110
|
-
schema = setting(settings, :schema)
|
|
111
|
-
if schema.to_s != ""
|
|
112
|
-
# Idempotent: the schema may not exist yet on the first boot.
|
|
113
|
-
connection.exec("CREATE SCHEMA IF NOT EXISTS #{connection.quote_ident(schema)}")
|
|
114
|
-
connection.exec("SET search_path TO #{connection.quote_ident(schema)}")
|
|
115
|
-
end
|
|
116
|
-
|
|
117
|
-
# Provisioning re-runs CREATE ... IF NOT EXISTS on every boot; silence the notices.
|
|
118
|
-
# Warnings and above still surface.
|
|
119
|
-
connection.exec("SET client_min_messages = warning")
|
|
120
|
-
connection
|
|
121
|
-
rescue StandardError => e
|
|
122
|
-
# PG is only defined once the gem loads, so the clause cannot name it.
|
|
123
|
-
raise unless defined?(PG::Error) && e.is_a?(PG::Error)
|
|
124
|
-
|
|
125
|
-
raise Runtime::WiringError,
|
|
126
|
-
"cannot bind PostgresEra at #{declared} for #{name}: #{e.message.strip} " \
|
|
127
|
-
"-- to run without a database, set HECKS_ENVIRONMENT=memory (a domain needs an environments/memory overlay)"
|
|
128
|
-
end
|
|
129
|
-
|
|
130
64
|
# Joins the process's shared connection for the declared database and schema, so every
|
|
131
65
|
# aggregate of a domain runs on one connection, then provisions the journal, this
|
|
132
66
|
# aggregate's head and field caches, and the event, saga and outbox tables. Every step is
|
|
@@ -139,29 +73,11 @@ module Hecks
|
|
|
139
73
|
@aggregate = aggregate
|
|
140
74
|
@settings = settings
|
|
141
75
|
@db = PostgresSharedConnection.for(aggregate.name, settings, connector: self.class)
|
|
142
|
-
|
|
143
|
-
# advisory lock from (ADR 0036). A bare aggregate with no owner falls back to its own name.
|
|
144
|
-
@domain = self.class.setting(
|
|
145
|
-
settings, :domain, default: aggregate.hecks_owner&.name || aggregate.storage_name
|
|
146
|
-
).to_s
|
|
76
|
+
@domain = journal_domain(aggregate, settings)
|
|
147
77
|
@lineage = Lineage.new(@db, @domain)
|
|
148
78
|
@lineage.ensure_base!
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
@era = settings.key?(:era) ? settings[:era] : settings["era"]
|
|
152
|
-
@era ||= @lineage.current_era
|
|
153
|
-
# Non-nil only for a held-but-superseded boot. `append` and `atomic_put` refuse on it
|
|
154
|
-
# because a superuser walks through the RLS fence.
|
|
155
|
-
@superseded_by = settings.key?(:superseded_by) ? settings[:superseded_by] : settings["superseded_by"]
|
|
156
|
-
# Idempotent self-healing against any boot-ordering surprise.
|
|
157
|
-
@lineage.ensure_head_snapshot!(table, @era)
|
|
158
|
-
@lineage.ensure_first_head!(table) if @era == 1
|
|
159
|
-
# One row-cache table per where-field the aggregate's queries use; `query` consults it
|
|
160
|
-
# to skip the head reduction.
|
|
161
|
-
@field_caches = ensure_field_caches!
|
|
162
|
-
create_event_table!
|
|
163
|
-
create_saga_table!
|
|
164
|
-
create_outbox_table!
|
|
79
|
+
resolve_era!(settings)
|
|
80
|
+
provision!
|
|
165
81
|
end
|
|
166
82
|
|
|
167
83
|
# Names this aggregate in storage: the journal's `aggregate` value and the stem of its
|
|
@@ -191,16 +107,11 @@ module Hecks
|
|
|
191
107
|
# @return [Array<Runtime::Instance>] every saved record
|
|
192
108
|
# @raise [Runtime::WiringError] if `order_by` names no attribute of this aggregate
|
|
193
109
|
def all(order_by: nil, direction: :asc)
|
|
194
|
-
return
|
|
195
|
-
|
|
196
|
-
name = order_by.to_s.split(".").first
|
|
197
|
-
unless @aggregate.lifecycle&.field.to_s == name || @aggregate.attribute(name)
|
|
198
|
-
raise Runtime::WiringError,
|
|
199
|
-
"#{@aggregate.name} has no attribute #{order_by.inspect} to order by"
|
|
200
|
-
end
|
|
110
|
+
return head_instances("ORDER BY id") unless order_by
|
|
201
111
|
|
|
112
|
+
refuse_unknown_order_field!(order_by)
|
|
202
113
|
spec = QuerySpecification::Common::OrderBy.new(field: order_by, direction: direction)
|
|
203
|
-
|
|
114
|
+
head_instances("ORDER BY #{order_clause(spec, nil)}")
|
|
204
115
|
end
|
|
205
116
|
|
|
206
117
|
# Counts current records in SQL against the head view, without loading any state.
|
|
@@ -239,69 +150,7 @@ module Hecks
|
|
|
239
150
|
# @yield the dispatch order; an exception rolls the transaction back
|
|
240
151
|
# @return [Object] the block's own value
|
|
241
152
|
# @raise [PG::ConnectionBad] if the connection dropped; it reconnects, then re-raises
|
|
242
|
-
def with_write_lock(&
|
|
243
|
-
|
|
244
|
-
# Appends one entry to the journal and updates the head snapshot and every field cache,
|
|
245
|
-
# all in one transaction under the domain's write lock.
|
|
246
|
-
#
|
|
247
|
-
# The lock precedes the INSERT because the ordinal comes from `nextval()` inside it. It is
|
|
248
|
-
# a different key from `mint_era!`'s, so it serializes writes, never a write against a mint.
|
|
249
|
-
# `project` stays out of it: AppendOnly#recover! already replays it on every boot.
|
|
250
|
-
#
|
|
251
|
-
# @param entry [Ports::Persistence::Entry] the save or delete to journal
|
|
252
|
-
# @return [Ports::Persistence::Entry] the same entry, unchanged
|
|
253
|
-
# @raise [Runtime::WiringError] if this boot's era has been superseded by a mint
|
|
254
|
-
# @raise [PG::Error] if Postgres refuses a statement, such as the era fence's RLS
|
|
255
|
-
def append(entry)
|
|
256
|
-
refuse_superseded_write!
|
|
257
|
-
transaction do
|
|
258
|
-
lock_writes!
|
|
259
|
-
append_and_project!(entry)
|
|
260
|
-
end
|
|
261
|
-
entry
|
|
262
|
-
end
|
|
263
|
-
|
|
264
|
-
# Refuses a write from a checkout whose era a later mint has superseded.
|
|
265
|
-
# Runs before the transaction so a stale checkout takes no lock; reads stay allowed.
|
|
266
|
-
#
|
|
267
|
-
# @return [nil] when this boot's era is current
|
|
268
|
-
# @raise [Runtime::WiringError] if the boot gate marked this era superseded
|
|
269
|
-
def refuse_superseded_write!
|
|
270
|
-
return unless @superseded_by
|
|
271
|
-
|
|
272
|
-
raise Runtime::WiringError,
|
|
273
|
-
"cannot write #{table} for #{@domain}: this checkout booted era #{@era}, which era " \
|
|
274
|
-
"#{@superseded_by} has superseded — its shape was replaced by a mint, and a write here would " \
|
|
275
|
-
"land in a partition no newer head reads. Reads still work; pull the current bluebook and " \
|
|
276
|
-
"reboot to write again."
|
|
277
|
-
end
|
|
278
|
-
|
|
279
|
-
# Saves an entry and reports whether it inserted or replaced, decided under the same lock
|
|
280
|
-
# that guards the write.
|
|
281
|
-
#
|
|
282
|
-
# @param entry [Ports::Persistence::Entry] the save to journal
|
|
283
|
-
# @param insert_only [Boolean] when true, an id already in the head is left untouched
|
|
284
|
-
# @return [Symbol] `:inserted`, `:replaced`, or `:conflicted` when `insert_only` hit a record
|
|
285
|
-
# @raise [Runtime::WiringError] if this boot's era has been superseded by a mint
|
|
286
|
-
# @raise [PG::Error] if Postgres refuses a statement
|
|
287
|
-
def atomic_put(entry, insert_only: false)
|
|
288
|
-
refuse_superseded_write!
|
|
289
|
-
status = nil
|
|
290
|
-
transaction do
|
|
291
|
-
lock_writes!
|
|
292
|
-
exists = !@db.exec_params(
|
|
293
|
-
"SELECT 1 FROM #{quoted_head} WHERE id = $1 LIMIT 1",
|
|
294
|
-
[entry.id.to_s]
|
|
295
|
-
).ntuples.zero?
|
|
296
|
-
if insert_only && exists
|
|
297
|
-
status = :conflicted
|
|
298
|
-
next
|
|
299
|
-
end
|
|
300
|
-
status = exists ? :replaced : :inserted
|
|
301
|
-
append_and_project!(entry)
|
|
302
|
-
end
|
|
303
|
-
status
|
|
304
|
-
end
|
|
153
|
+
def with_write_lock(&) = transaction { lock_writes!; yield } # rubocop:disable Style/Semicolon
|
|
305
154
|
|
|
306
155
|
# Builds the instance an entry describes, writing nothing; the head is derived, so
|
|
307
156
|
# projecting is reading.
|
|
@@ -315,50 +164,6 @@ module Hecks
|
|
|
315
164
|
Runtime::Instance.new(aggregate: @aggregate, id: entry.id, state: entry.state)
|
|
316
165
|
end
|
|
317
166
|
|
|
318
|
-
# Reads this aggregate's whole journal, every era, in write order. States are decoded but
|
|
319
|
-
# not translated: an ancestor era's row keeps the shape it was written in.
|
|
320
|
-
#
|
|
321
|
-
# @return [Array<Ports::Persistence::Entry>] entries by ascending ordinal
|
|
322
|
-
def entries
|
|
323
|
-
@db.exec_params(
|
|
324
|
-
"SELECT aggregate_id, operation, state, mirrors FROM #{@lineage.quoted_journal} " \
|
|
325
|
-
"WHERE aggregate = $1 ORDER BY ordinal",
|
|
326
|
-
[table]
|
|
327
|
-
).map do |row|
|
|
328
|
-
state = row["state"] && JSON.parse(row["state"])
|
|
329
|
-
Ports::Persistence::Entry.new(
|
|
330
|
-
operation: row["operation"] || "save",
|
|
331
|
-
id: row["aggregate_id"],
|
|
332
|
-
state: Ports::Persistence::StateCodec.decode(@aggregate, state),
|
|
333
|
-
mirrors: row["mirrors"] && JSON.parse(row["mirrors"])
|
|
334
|
-
)
|
|
335
|
-
end
|
|
336
|
-
end
|
|
337
|
-
|
|
338
|
-
# Deletes this aggregate's journal rows, refusing when row-level security turns the DELETE
|
|
339
|
-
# into a silent no-op.
|
|
340
|
-
#
|
|
341
|
-
# The journal forces RLS with no DELETE policy, so an ordinary connection matches zero rows
|
|
342
|
-
# without error; comparing the count before with the DELETE's own count exposes that.
|
|
343
|
-
# Head snapshots, field caches, `events` and saga rows are left as they are.
|
|
344
|
-
#
|
|
345
|
-
# @return [Adapters::PostgresEra] this adapter
|
|
346
|
-
# @raise [Runtime::WiringError] if the journal held rows and the DELETE removed none
|
|
347
|
-
def reset!
|
|
348
|
-
before = @db.exec_params(
|
|
349
|
-
"SELECT count(*) FROM #{@lineage.quoted_journal} WHERE aggregate = $1", [table]
|
|
350
|
-
)[0]["count"].to_i
|
|
351
|
-
result = @db.exec_params("DELETE FROM #{@lineage.quoted_journal} WHERE aggregate = $1", [table])
|
|
352
|
-
if before.positive? && result.cmd_tuples.zero?
|
|
353
|
-
raise Runtime::WiringError,
|
|
354
|
-
"reset! deleted 0 of #{before} row(s) for #{table} in #{@lineage.quoted_journal} — " \
|
|
355
|
-
"FORCE ROW LEVEL SECURITY admits no DELETE policy on the journal, so this connection's " \
|
|
356
|
-
"DELETE silently matched nothing. reset! only works connected as an actual Postgres " \
|
|
357
|
-
"superuser or a role granted BYPASSRLS, not as the provisioner or an app role."
|
|
358
|
-
end
|
|
359
|
-
self
|
|
360
|
-
end
|
|
361
|
-
|
|
362
167
|
# Journals an instance's current state as a save entry. A direct-adapter convenience for
|
|
363
168
|
# specs and consoles; a runtime saves through `Ports::Persistence::AppendOnly`.
|
|
364
169
|
#
|
|
@@ -377,279 +182,20 @@ module Hecks
|
|
|
377
182
|
# @param id [String, Object] the record's identity, journaled as `id.to_s`
|
|
378
183
|
# @return [true] always
|
|
379
184
|
# @raise [Runtime::WiringError] if this boot's era has been superseded by a mint
|
|
380
|
-
def delete(id)
|
|
185
|
+
def delete(id) # rubocop:disable Naming/PredicateMethod -- the repository port's verb, not a question
|
|
381
186
|
entry = Ports::Persistence::Entry.new(operation: "delete", id: id.to_s, state: nil)
|
|
382
187
|
append(entry)
|
|
383
188
|
true
|
|
384
189
|
end
|
|
385
190
|
|
|
386
|
-
# Saga rows keep `domain` as a column so domains sharing one schema stay isolated. No lock
|
|
387
|
-
# here: `SagaInterpreter`'s own mutex already serializes in-process writers.
|
|
388
|
-
|
|
389
|
-
# Checkpoints one saga instance, replacing the row for the same (domain, process manager,
|
|
390
|
-
# correlation) if one exists.
|
|
391
|
-
#
|
|
392
|
-
# @param memory [Hash] the saga's memory, stored as JSON
|
|
393
|
-
# @param completed_compensations [Array] compensable legs already completed, stored as JSON
|
|
394
|
-
# @return [PG::Result] the upsert's result
|
|
395
|
-
def save_saga(process_manager:, correlation:, state:, memory:, completed_compensations: [])
|
|
396
|
-
@db.exec_params(
|
|
397
|
-
"INSERT INTO hecks_saga_instances (domain, process_manager, correlation, state, memory, completed_compensations) " \
|
|
398
|
-
"VALUES ($1, $2, $3, $4, $5, $6) " \
|
|
399
|
-
"ON CONFLICT (domain, process_manager, correlation) DO UPDATE " \
|
|
400
|
-
"SET state = EXCLUDED.state, memory = EXCLUDED.memory, " \
|
|
401
|
-
"completed_compensations = EXCLUDED.completed_compensations, updated_at = now()",
|
|
402
|
-
[@domain, process_manager.to_s, correlation.to_s, state.to_s, JSON.generate(memory),
|
|
403
|
-
JSON.generate(completed_compensations)]
|
|
404
|
-
)
|
|
405
|
-
end
|
|
406
|
-
|
|
407
|
-
# Removes a finished saga instance's checkpoint; a no-op when no such row exists.
|
|
408
|
-
#
|
|
409
|
-
# @return [PG::Result] the DELETE's result
|
|
410
|
-
def delete_saga(process_manager:, correlation:)
|
|
411
|
-
@db.exec_params(
|
|
412
|
-
"DELETE FROM hecks_saga_instances WHERE domain = $1 AND process_manager = $2 AND correlation = $3",
|
|
413
|
-
[@domain, process_manager.to_s, correlation.to_s]
|
|
414
|
-
)
|
|
415
|
-
end
|
|
416
|
-
|
|
417
|
-
# Yields every saga checkpoint stored for this domain, so a booting registry can rehydrate.
|
|
418
|
-
#
|
|
419
|
-
# @yieldparam memory [Hash{Symbol => Object}] the saga's memory, keys symbolized
|
|
420
|
-
# @return [Enumerator, PG::Result] an enumerator when no block is given
|
|
421
|
-
def each_saga
|
|
422
|
-
return enum_for(:each_saga) unless block_given?
|
|
423
|
-
|
|
424
|
-
@db.exec_params(
|
|
425
|
-
"SELECT process_manager, correlation, state, memory, completed_compensations " \
|
|
426
|
-
"FROM hecks_saga_instances WHERE domain = $1",
|
|
427
|
-
[@domain]
|
|
428
|
-
).each do |row|
|
|
429
|
-
yield row["process_manager"], row["correlation"], row["state"],
|
|
430
|
-
JSON.parse(row["memory"], symbolize_names: true),
|
|
431
|
-
JSON.parse(row["completed_compensations"] || "[]", symbolize_names: true)
|
|
432
|
-
end
|
|
433
|
-
end
|
|
434
|
-
|
|
435
191
|
private
|
|
436
192
|
|
|
437
|
-
def
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
[@lineage.domain]
|
|
441
|
-
)
|
|
442
|
-
end
|
|
443
|
-
|
|
444
|
-
def append_and_project!(entry)
|
|
445
|
-
state_json = entry.state && JSON.generate(Ports::Persistence::StateCodec.encode(@aggregate, entry.state))
|
|
446
|
-
ordinal = @db.exec_params(
|
|
447
|
-
"INSERT INTO #{@lineage.quoted_journal} (era, aggregate, aggregate_id, operation, state, mirrors) " \
|
|
448
|
-
"VALUES ($1, $2, $3, $4, $5, $6) RETURNING ordinal",
|
|
449
|
-
[@era, table, entry.id, entry.operation, state_json,
|
|
450
|
-
entry.mirrors && JSON.generate(entry.mirrors)]
|
|
451
|
-
)[0]["ordinal"]
|
|
452
|
-
|
|
453
|
-
if entry.save?
|
|
454
|
-
@db.exec_params(
|
|
455
|
-
"INSERT INTO #{quoted_head_snapshot} (id, ordinal, operation, state) VALUES ($1, $2, 'save', $3) " \
|
|
456
|
-
"ON CONFLICT (id) DO UPDATE SET ordinal = EXCLUDED.ordinal, operation = EXCLUDED.operation, " \
|
|
457
|
-
"state = EXCLUDED.state WHERE #{quoted_head_snapshot}.ordinal < EXCLUDED.ordinal",
|
|
458
|
-
[entry.id, ordinal, state_json]
|
|
459
|
-
)
|
|
460
|
-
# Same transaction and ordinal, so every cache is exactly as current as the snapshot.
|
|
461
|
-
@field_caches.each do |field, cache_table|
|
|
462
|
-
@lineage.upsert_field_cache_row!(cache_table, entry.id, ordinal, state_json, query_expression(field))
|
|
463
|
-
end
|
|
464
|
-
else
|
|
465
|
-
# A tombstone row, not a bare DELETE: without one, an ancestor era's saved row would win
|
|
466
|
-
# the head's DISTINCT ON and the deleted record would read back. The ordinal guard keeps
|
|
467
|
-
# a stale replayed delete from clobbering a newer save.
|
|
468
|
-
@db.exec_params(
|
|
469
|
-
"INSERT INTO #{quoted_head_snapshot} (id, ordinal, operation, state) VALUES ($1, $2, 'delete', NULL) " \
|
|
470
|
-
"ON CONFLICT (id) DO UPDATE SET ordinal = EXCLUDED.ordinal, operation = EXCLUDED.operation, " \
|
|
471
|
-
"state = EXCLUDED.state WHERE #{quoted_head_snapshot}.ordinal < EXCLUDED.ordinal",
|
|
472
|
-
[entry.id, ordinal]
|
|
473
|
-
)
|
|
474
|
-
@field_caches.each_value { |cache_table| @lineage.delete_field_cache_row!(cache_table, entry.id) }
|
|
475
|
-
end
|
|
476
|
-
|
|
477
|
-
ordinal
|
|
478
|
-
end
|
|
479
|
-
|
|
480
|
-
def select_list = "id, state"
|
|
481
|
-
def from_relation = quoted_head
|
|
482
|
-
def dialect_name = "PostgresEra"
|
|
483
|
-
def empty_in_clause = "FALSE"
|
|
484
|
-
|
|
485
|
-
def placeholder(binds, value)
|
|
486
|
-
binds << value
|
|
487
|
-
"$#{binds.size}"
|
|
488
|
-
end
|
|
489
|
-
|
|
490
|
-
def contains_clause(expression, placeholder)
|
|
491
|
-
"position(#{placeholder} in #{expression}) > 0"
|
|
492
|
-
end
|
|
493
|
-
|
|
494
|
-
def list_contains_clause(column, member, placeholder)
|
|
495
|
-
target = member.empty? ? "elem #>> '{}'" : "elem ->> #{text_literal(member)}"
|
|
496
|
-
elements = "jsonb_array_elements(state #> ARRAY[#{text_literal(column)}]::text[]) AS elem"
|
|
497
|
-
"EXISTS (SELECT 1 FROM #{elements} WHERE #{target} = #{placeholder})"
|
|
498
|
-
end
|
|
499
|
-
|
|
500
|
-
def plain_column(name) = jsonb_path([name])
|
|
501
|
-
|
|
502
|
-
def nested_expression(name, path, member)
|
|
503
|
-
segments = path.empty? ? [name, (member || "value").to_s] : [name, *path]
|
|
504
|
-
jsonb_path(segments)
|
|
505
|
-
end
|
|
506
|
-
|
|
507
|
-
def comparable_expression(expression, value)
|
|
508
|
-
value.is_a?(Numeric) ? "(#{expression})::numeric" : expression
|
|
509
|
-
end
|
|
510
|
-
|
|
511
|
-
def execute_query(sql, binds)
|
|
512
|
-
@db.exec_params(sql, binds).map { |row| instance(row) }
|
|
513
|
-
end
|
|
514
|
-
|
|
515
|
-
def instance(row)
|
|
516
|
-
Runtime::Instance.new(aggregate: @aggregate, id: row["id"], state: decode(row["state"]))
|
|
517
|
-
end
|
|
518
|
-
|
|
519
|
-
# Runs after SQL-side era translation, as the last step of every read.
|
|
520
|
-
def decode(state_json)
|
|
521
|
-
Ports::Persistence::StateCodec.decode(@aggregate, JSON.parse(state_json))
|
|
522
|
-
end
|
|
523
|
-
|
|
524
|
-
def quote_ident(name) = PG::Connection.quote_ident(name.to_s)
|
|
525
|
-
def quoted_head = quote_ident(@lineage.head_view(table))
|
|
526
|
-
def quoted_head_snapshot = quote_ident(@lineage.head_snapshot(table, @era))
|
|
527
|
-
|
|
528
|
-
def order_expression(field)
|
|
529
|
-
expression = query_expression(field)
|
|
530
|
-
numeric_field?(field) ? "(#{expression})::numeric" : expression
|
|
531
|
-
end
|
|
532
|
-
|
|
533
|
-
# Postgres defaults to NULLS LAST on ASC; place nulls explicitly (first ascending, last
|
|
534
|
-
# descending) so a declared query answers the same on every adapter.
|
|
535
|
-
def order_clause(order_by, policy)
|
|
536
|
-
direction = order_by.direction.to_s.downcase == "desc" ? "DESC" : "ASC"
|
|
537
|
-
nulls = case policy&.mode.to_s
|
|
538
|
-
when "first" then " NULLS FIRST"
|
|
539
|
-
when "last" then " NULLS LAST"
|
|
540
|
-
else direction == "DESC" ? " NULLS LAST" : " NULLS FIRST"
|
|
541
|
-
end
|
|
542
|
-
"#{order_expression(order_by.field)} #{direction}#{nulls}, id #{direction}"
|
|
543
|
-
end
|
|
544
|
-
|
|
545
|
-
# One shared walk decides numericness at any depth, so a nested path is not ordered as text.
|
|
546
|
-
def numeric_field?(field)
|
|
547
|
-
name, *path = field.to_s.split(".")
|
|
548
|
-
QuerySpecification::FieldPath.numeric?(@aggregate.attribute(name), path) do |type|
|
|
549
|
-
Runtime::Value.value_object_for(@aggregate, type)
|
|
550
|
-
end
|
|
551
|
-
end
|
|
552
|
-
|
|
553
|
-
# `ARRAY[...]` of escaped literals, never the '{a,b}' syntax: that form has no escaping, so
|
|
554
|
-
# a quote in a segment would become live SQL.
|
|
555
|
-
def jsonb_path(segments)
|
|
556
|
-
"state #>> ARRAY[#{segments.map { |segment| text_literal(segment) }.join(', ')}]::text[]"
|
|
557
|
-
end
|
|
558
|
-
|
|
559
|
-
def text_literal(text) = "'#{text.to_s.gsub("'", "''")}'"
|
|
560
|
-
|
|
561
|
-
# Where-fields of the aggregate's and its entities' queries that a cache table can represent;
|
|
562
|
-
# order_by-only fields never needed a cache.
|
|
563
|
-
def ensure_field_caches!
|
|
564
|
-
cached_where_fields.to_h do |field|
|
|
565
|
-
[field, @lineage.ensure_field_cache!(table, @era, field, query_expression(field))]
|
|
566
|
-
end
|
|
567
|
-
end
|
|
568
|
-
|
|
569
|
-
def cached_where_fields
|
|
570
|
-
fields = declared_queries.flat_map do |q|
|
|
571
|
-
q.wheres.map do |clause|
|
|
572
|
-
clause.field.to_s
|
|
573
|
-
end
|
|
574
|
-
end
|
|
575
|
-
fields.uniq.select { |field| cacheable_field?(field) }
|
|
576
|
-
end
|
|
577
|
-
|
|
578
|
-
def declared_queries
|
|
579
|
-
@aggregate.queries + @aggregate.entities.flat_map(&:queries)
|
|
580
|
-
end
|
|
581
|
-
|
|
582
|
-
# List fields are excluded: a one-value cache row cannot hold `contains` membership.
|
|
583
|
-
def cacheable_field?(field)
|
|
584
|
-
name = field.to_s.split(".").first
|
|
585
|
-
return true if @aggregate.lifecycle&.field.to_s == name
|
|
586
|
-
|
|
587
|
-
attribute = @aggregate.attribute(name)
|
|
588
|
-
!attribute.nil? && !attribute.list?
|
|
589
|
-
end
|
|
590
|
-
|
|
591
|
-
# A clause is cache-served when its field has a cache table and it is not a null comparison,
|
|
592
|
-
# which `NullPolicy` intercepts before `where_clause`.
|
|
593
|
-
def cache_eligible?(clause, value)
|
|
594
|
-
@field_caches.key?(clause.field.to_s) &&
|
|
595
|
-
QuerySpecification::Common::NullPolicy.sql_predicate(query_expression(clause.field, value: value), clause.op,
|
|
596
|
-
value).nil?
|
|
597
|
-
end
|
|
598
|
-
|
|
599
|
-
# Phase one: candidate ids from the narrow cache tables, INTERSECTed. Reuses `where_clause`
|
|
600
|
-
# against each cache's `value` column, so every operator `super` supports works here.
|
|
601
|
-
def cache_phase(cached)
|
|
602
|
-
binds = []
|
|
603
|
-
clauses = cached.map do |clause, value|
|
|
604
|
-
cache_table = @lineage.field_cache(table, @era, clause.field.to_s)
|
|
605
|
-
"SELECT id FROM #{quote_ident(cache_table)} WHERE #{where_clause(clause.op.to_s, quote_ident('value'), value, binds,
|
|
606
|
-
field: clause.field)}"
|
|
607
|
-
end
|
|
608
|
-
@db.exec_params(clauses.join("\nINTERSECT\n"), binds).map { |row| row["id"] }
|
|
609
|
-
end
|
|
610
|
-
|
|
611
|
-
# Phase two: the head view restricted to phase one's ids plus the clauses it could not
|
|
612
|
-
# accelerate. Repeats the tail of `SqlQueryBuilder#query` so that module stays untouched.
|
|
613
|
-
def head_phase(declared, uncached, ids, args)
|
|
614
|
-
binds = []
|
|
615
|
-
clauses = ["id IN (#{ids.map { |id| placeholder(binds, id) }.join(', ')})"]
|
|
616
|
-
uncached.each do |clause, value|
|
|
617
|
-
expression = query_expression(clause.field, value: value)
|
|
618
|
-
if (null_predicate = QuerySpecification::Common::NullPolicy.sql_predicate(expression, clause.op, value))
|
|
619
|
-
clauses << null_predicate.first
|
|
620
|
-
next
|
|
621
|
-
end
|
|
622
|
-
clauses << where_clause(clause.op.to_s, expression, value, binds, field: clause.field)
|
|
623
|
-
end
|
|
624
|
-
|
|
625
|
-
sql = "SELECT #{select_list} FROM #{from_relation} WHERE #{clauses.join(' AND ')}"
|
|
626
|
-
sql << if declared.order_by
|
|
627
|
-
" ORDER BY #{order_clause(declared.order_by, declared.null_semantics)}"
|
|
628
|
-
else
|
|
629
|
-
" ORDER BY id"
|
|
630
|
-
end
|
|
631
|
-
sql << " LIMIT #{placeholder(binds, query_value(declared.limit.value, args).to_i)}" if declared.limit
|
|
632
|
-
sql << unbounded_limit if !declared.limit && declared.offset
|
|
633
|
-
sql << " OFFSET #{placeholder(binds, query_value(declared.offset.value, args).to_i)}" if declared.offset
|
|
634
|
-
execute_query(sql, binds)
|
|
635
|
-
end
|
|
193
|
+
def refuse_unknown_order_field!(order_by)
|
|
194
|
+
name = order_by.to_s.split(".").first
|
|
195
|
+
return if @aggregate.lifecycle&.field.to_s == name || @aggregate.attribute(name)
|
|
636
196
|
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
CREATE TABLE IF NOT EXISTS hecks_saga_instances (
|
|
640
|
-
domain text NOT NULL,
|
|
641
|
-
process_manager text NOT NULL,
|
|
642
|
-
correlation text NOT NULL,
|
|
643
|
-
state text NOT NULL,
|
|
644
|
-
memory jsonb NOT NULL,
|
|
645
|
-
completed_compensations jsonb NOT NULL DEFAULT '[]'::jsonb,
|
|
646
|
-
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
647
|
-
PRIMARY KEY (domain, process_manager, correlation)
|
|
648
|
-
)
|
|
649
|
-
SQL
|
|
650
|
-
# Covers a table created before this column existed, where IF NOT EXISTS is a no-op.
|
|
651
|
-
@db.exec("ALTER TABLE hecks_saga_instances ADD COLUMN IF NOT EXISTS completed_compensations jsonb " \
|
|
652
|
-
"NOT NULL DEFAULT '[]'::jsonb")
|
|
197
|
+
raise Runtime::WiringError,
|
|
198
|
+
"#{@aggregate.name} has no attribute #{order_by.inspect} to order by"
|
|
653
199
|
end
|
|
654
200
|
end
|
|
655
201
|
end
|
|
@@ -102,7 +102,7 @@ module Hecks
|
|
|
102
102
|
# @return [String] names both versions
|
|
103
103
|
def host_refusal(rehearsal, host_version = HOST_RELEASE)
|
|
104
104
|
line = release_line(host_version)&.join(".")
|
|
105
|
-
"the rehearsal ran on Hecks #{rehearsal[
|
|
105
|
+
"the rehearsal ran on Hecks #{rehearsal["host_version"]}, but this host is Hecks #{host_version}; " \
|
|
106
106
|
"a rehearsal counts only on a host of the same major.minor (#{line}.x) — " \
|
|
107
107
|
"re-run the rehearsal on this host and approve again"
|
|
108
108
|
end
|
|
@@ -143,15 +143,8 @@ module Hecks
|
|
|
143
143
|
# @raise [ArgumentError] if `approved_by` is blank or `approved_at` is not a time, or if the
|
|
144
144
|
# edge needs a rehearsal and none that passed was given
|
|
145
145
|
def build(edge:, approved_by:, approved_at:, rehearsal: nil)
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
"and when (approved_at, an ISO 8601 time)"
|
|
149
|
-
end
|
|
150
|
-
|
|
151
|
-
if needs_rehearsal?(edge) && !rehearsed?(rehearsal)
|
|
152
|
-
raise ArgumentError, "an edge with a compute or rekey rule is approved on a rehearsal that passed: " \
|
|
153
|
-
"name the snapshot, the host version, the result (pass) and when it ran"
|
|
154
|
-
end
|
|
146
|
+
refuse_unattributed!(approved_by, approved_at)
|
|
147
|
+
refuse_unrehearsed!(edge, rehearsal)
|
|
155
148
|
|
|
156
149
|
document = { "edge" => edge_name(edge), "edge_digest" => edge_digest(edge),
|
|
157
150
|
"approved_by" => approved_by, "approved_at" => approved_at }
|
|
@@ -159,6 +152,32 @@ module Hecks
|
|
|
159
152
|
document
|
|
160
153
|
end
|
|
161
154
|
|
|
155
|
+
# Refuses an approval that does not say who approved it and when.
|
|
156
|
+
#
|
|
157
|
+
# @param approved_by [String] who approved it
|
|
158
|
+
# @param approved_at [String] when, as an ISO 8601 UTC time
|
|
159
|
+
# @return [void]
|
|
160
|
+
# @raise [ArgumentError] if either is blank or malformed
|
|
161
|
+
def refuse_unattributed!(approved_by, approved_at)
|
|
162
|
+
return if attributed?("approved_by" => approved_by, "approved_at" => approved_at)
|
|
163
|
+
|
|
164
|
+
raise ArgumentError, "an approval names who approved it (approved_by, your git identity) " \
|
|
165
|
+
"and when (approved_at, an ISO 8601 time)"
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
# Refuses the approval of a compute or rekey edge that carries no passing rehearsal.
|
|
169
|
+
#
|
|
170
|
+
# @param edge [Bluebook::Translation] the parsed translation edge
|
|
171
|
+
# @param rehearsal [Hash{String => String}, nil] the rehearsal block
|
|
172
|
+
# @return [void]
|
|
173
|
+
# @raise [ArgumentError] if the edge needs a rehearsal and none that passed was given
|
|
174
|
+
def refuse_unrehearsed!(edge, rehearsal)
|
|
175
|
+
return unless needs_rehearsal?(edge) && !rehearsed?(rehearsal)
|
|
176
|
+
|
|
177
|
+
raise ArgumentError, "an edge with a compute or rekey rule is approved on a rehearsal that passed: " \
|
|
178
|
+
"name the snapshot, the host version, the result (pass) and when it ran"
|
|
179
|
+
end
|
|
180
|
+
|
|
162
181
|
# Writes an edge's approval file, replacing an earlier approval of the same edge.
|
|
163
182
|
#
|
|
164
183
|
# @param directory [String] the domain's bluebook directory
|
|
@@ -217,11 +236,20 @@ module Hecks
|
|
|
217
236
|
|
|
218
237
|
digest = edge_digest(edge)
|
|
219
238
|
stale = read_all(directory).find do |approval|
|
|
220
|
-
approval["edge_digest"] == digest &&
|
|
221
|
-
!host_compatible?(approval["rehearsal"], host_version)
|
|
239
|
+
approval["edge_digest"] == digest && stale_host?(approval, host_version)
|
|
222
240
|
end
|
|
223
241
|
host_refusal(stale["rehearsal"], host_version) if stale
|
|
224
242
|
end
|
|
243
|
+
|
|
244
|
+
# Whether an attributed approval's passing rehearsal ran on an incompatible host.
|
|
245
|
+
#
|
|
246
|
+
# @param approval [Hash{String => Object}] one parsed approval
|
|
247
|
+
# @param host_version [String] the running host's release
|
|
248
|
+
# @return [Boolean]
|
|
249
|
+
def stale_host?(approval, host_version)
|
|
250
|
+
attributed?(approval) && rehearsed?(approval["rehearsal"]) &&
|
|
251
|
+
!host_compatible?(approval["rehearsal"], host_version)
|
|
252
|
+
end
|
|
225
253
|
end
|
|
226
254
|
end
|
|
227
255
|
end
|