hecks 1.3.0 → 1.4.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/lib/hecks/adapters/driven/claude_code.rb +7 -7
- data/lib/hecks/adapters/driven/d1.rb +187 -23
- data/lib/hecks/adapters/driven/folder.rb +10 -10
- data/lib/hecks/adapters/driven/google_authentication.rb +8 -8
- data/lib/hecks/adapters/driven/governance_authorization.rb +31 -13
- data/lib/hecks/adapters/driven/heki/journal.rb +5 -4
- data/lib/hecks/adapters/driven/heki/saga_store.rb +5 -5
- data/lib/hecks/adapters/driven/heki.rb +13 -7
- data/lib/hecks/adapters/driven/identity_registry.rb +2 -2
- data/lib/hecks/adapters/driven/in_memory_ordering.rb +3 -3
- data/lib/hecks/adapters/driven/lambda/client.rb +34 -9
- data/lib/hecks/adapters/driven/lambda.rb +39 -33
- data/lib/hecks/adapters/driven/local_storage.rb +17 -10
- data/lib/hecks/adapters/driven/memory.rb +205 -9
- data/lib/hecks/adapters/driven/mock_stripe_adapter.rb +1 -1
- data/lib/hecks/adapters/driven/postgres/codec.rb +27 -11
- data/lib/hecks/adapters/driven/postgres/outbox.rb +40 -2
- data/lib/hecks/adapters/driven/postgres/reconnect.rb +23 -7
- data/lib/hecks/adapters/driven/postgres/schema_builder.rb +14 -14
- data/lib/hecks/adapters/driven/postgres.rb +175 -28
- data/lib/hecks/adapters/driven/prism.rb +4 -4
- data/lib/hecks/adapters/driven/sql_query_builder.rb +34 -22
- data/lib/hecks/adapters/driven/sqlite/codec.rb +38 -10
- data/lib/hecks/adapters/driven/sqlite/projection.rb +60 -32
- data/lib/hecks/adapters/driven/sqlite/schema_builder.rb +12 -12
- data/lib/hecks/adapters/driven/sqlite.rb +181 -21
- data/lib/hecks/adapters/driven.rb +4 -4
- data/lib/hecks/adapters/driving/github_webhook.rb +18 -18
- data/lib/hecks/behaviors/dsl.rb +2 -2
- data/lib/hecks/behaviors/expectations.rb +23 -23
- data/lib/hecks/behaviors/ir.rb +1 -1
- data/lib/hecks/behaviors/rspec.rb +1 -1
- data/lib/hecks/behaviors/runner.rb +2 -2
- data/lib/hecks/behaviors.rb +1 -1
- data/lib/hecks/bluebook/aggregate.rb +13 -13
- data/lib/hecks/bluebook/assembly/aggregate_assembly.rb +10 -10
- data/lib/hecks/bluebook/assembly/build.rb +1 -1
- data/lib/hecks/bluebook/assembly/contract.rb +39 -16
- data/lib/hecks/bluebook/assembly/contracts.rb +40 -38
- data/lib/hecks/bluebook/assembly/marks.rb +18 -18
- data/lib/hecks/bluebook/assembly/specializer.rb +19 -21
- data/lib/hecks/bluebook/assembly.rb +9 -9
- data/lib/hecks/bluebook/attribute.rb +9 -9
- data/lib/hecks/bluebook/behaviour/aggregate.rb +11 -11
- data/lib/hecks/bluebook/behaviour/attribute.rb +5 -5
- data/lib/hecks/bluebook/behaviour/chapter.rb +23 -5
- data/lib/hecks/bluebook/behaviour/command.rb +23 -23
- data/lib/hecks/bluebook/behaviour/domain_port.rb +7 -7
- data/lib/hecks/bluebook/behaviour/entity.rb +8 -8
- data/lib/hecks/bluebook/behaviour/hexagon.rb +4 -4
- data/lib/hecks/bluebook/behaviour/lifecycle.rb +5 -5
- data/lib/hecks/bluebook/behaviour/policy.rb +12 -12
- data/lib/hecks/bluebook/behaviour/process_manager.rb +7 -7
- data/lib/hecks/bluebook/behaviour/query.rb +1 -1
- data/lib/hecks/bluebook/behaviour/read_model.rb +8 -8
- data/lib/hecks/bluebook/behaviour/traits.rb +12 -12
- data/lib/hecks/bluebook/behaviour/value_object.rb +6 -6
- data/lib/hecks/bluebook/capabilities.rb +27 -0
- data/lib/hecks/bluebook/chapter.rb +28 -9
- data/lib/hecks/bluebook/command.rb +12 -12
- data/lib/hecks/bluebook/domain_port.rb +9 -9
- data/lib/hecks/bluebook/dsl/adapter_builder.rb +24 -0
- data/lib/hecks/bluebook/dsl/aggregate_builder/sealing.rb +49 -49
- data/lib/hecks/bluebook/dsl/aggregate_builder.rb +96 -96
- data/lib/hecks/bluebook/dsl/attribute_collector.rb +41 -41
- data/lib/hecks/bluebook/dsl/binding_proxy.rb +22 -2
- data/lib/hecks/bluebook/dsl/bluebook_builder/validation.rb +111 -74
- data/lib/hecks/bluebook/dsl/bluebook_builder.rb +48 -30
- data/lib/hecks/bluebook/dsl/bootstrap_table.rb +116 -0
- data/lib/hecks/bluebook/dsl/command_builder.rb +103 -103
- data/lib/hecks/bluebook/dsl/const_shim.rb +46 -15
- data/lib/hecks/bluebook/dsl/domain_port_builder.rb +90 -25
- data/lib/hecks/bluebook/dsl/entity_builder.rb +56 -56
- data/lib/hecks/bluebook/dsl/generic_dispatch.rb +148 -132
- data/lib/hecks/bluebook/dsl/hecksagon_builder.rb +89 -30
- data/lib/hecks/bluebook/dsl/identity_declaration.rb +17 -17
- data/lib/hecks/bluebook/dsl/lifecycle_builder.rb +27 -4
- data/lib/hecks/bluebook/dsl/policy_builder.rb +30 -21
- data/lib/hecks/bluebook/dsl/port_builder.rb +38 -7
- data/lib/hecks/bluebook/dsl/port_operation_builder.rb +56 -22
- data/lib/hecks/bluebook/dsl/process_manager_builder.rb +35 -35
- data/lib/hecks/bluebook/dsl/query_builder.rb +5 -5
- data/lib/hecks/bluebook/dsl/read_model_builder.rb +34 -34
- data/lib/hecks/bluebook/dsl/rule_reference.rb +41 -39
- data/lib/hecks/bluebook/dsl/translation_builder.rb +9 -9
- data/lib/hecks/bluebook/dsl/value_object_builder.rb +16 -16
- data/lib/hecks/bluebook/dsl/word_gate.rb +59 -53
- data/lib/hecks/bluebook/dsl/world_builder.rb +51 -8
- data/lib/hecks/bluebook/entity.rb +11 -11
- data/lib/hecks/bluebook/expression/ast_json.rb +20 -20
- data/lib/hecks/bluebook/expression/ast_reader.rb +3 -3
- data/lib/hecks/bluebook/expression/canonical_form.rb +9 -9
- data/lib/hecks/bluebook/expression/evaluator.rb +18 -18
- data/lib/hecks/bluebook/expression/resolver/block_predicates.rb +18 -18
- data/lib/hecks/bluebook/expression/resolver.rb +60 -62
- data/lib/hecks/bluebook/hexagon.rb +1 -1
- data/lib/hecks/bluebook/lifecycle.rb +1 -1
- data/lib/hecks/bluebook/meta_validator/adapter_judge.rb +1 -1
- data/lib/hecks/bluebook/meta_validator/judge.rb +101 -87
- data/lib/hecks/bluebook/meta_validator/plan.rb +39 -39
- data/lib/hecks/bluebook/meta_validator/port_judge.rb +2 -2
- data/lib/hecks/bluebook/meta_validator/readings.rb +43 -43
- data/lib/hecks/bluebook/meta_validator/reconstruction.rb +44 -37
- data/lib/hecks/bluebook/meta_validator/shapes.rb +25 -21
- data/lib/hecks/bluebook/meta_validator/syntax_boot.rb +145 -31
- data/lib/hecks/bluebook/meta_validator/translation_judge.rb +6 -6
- data/lib/hecks/bluebook/meta_validator/world_judge.rb +5 -5
- data/lib/hecks/bluebook/meta_validator.rb +70 -70
- data/lib/hecks/bluebook/model_check.rb +170 -84
- data/lib/hecks/bluebook/pattern_subset.rb +9 -9
- data/lib/hecks/bluebook/policy.rb +15 -13
- data/lib/hecks/bluebook/process_manager.rb +14 -14
- data/lib/hecks/bluebook/project_register.rb +6 -6
- data/lib/hecks/bluebook/query.rb +4 -4
- data/lib/hecks/bluebook/read_model.rb +14 -14
- data/lib/hecks/bluebook/reference.rb +8 -8
- data/lib/hecks/bluebook/smoke_test.rb +19 -19
- data/lib/hecks/bluebook/synthesizer.rb +12 -12
- data/lib/hecks/bluebook/translation.rb +4 -4
- data/lib/hecks/bluebook/value_object.rb +6 -6
- data/lib/hecks/bluebook.rb +2 -2
- data/lib/hecks/codemod/legacy_dispatch_args.rb +299 -0
- data/lib/hecks/codemod/legacy_dispatch_recorder.rb +186 -0
- data/lib/hecks/codemod.rb +36 -35
- data/lib/hecks/construct.rb +6 -6
- data/lib/hecks/corpus.rb +317 -0
- data/lib/hecks/deprecation.rb +95 -0
- data/lib/hecks/doc/reference.rb +19 -19
- data/lib/hecks/embryonaut_bluebook.rb +11 -11
- data/lib/hecks/facade/cli_door.rb +69 -10
- data/lib/hecks/facade/cli_runner.rb +105 -24
- data/lib/hecks/facade/command_request.rb +23 -0
- data/lib/hecks/facade/handle.rb +79 -32
- data/lib/hecks/facade/json_door.rb +106 -25
- data/lib/hecks/facade/surface/aggregate_door.rb +42 -27
- data/lib/hecks/facade/surface/chapter.rb +26 -17
- data/lib/hecks/facade/surface.rb +16 -3
- data/lib/hecks/facade.rb +15 -4
- data/lib/hecks/forms/app.rb +46 -30
- data/lib/hecks/forms/command_form_renderer.rb +70 -9
- data/lib/hecks/forms/field_renderer.rb +142 -6
- data/lib/hecks/forms/field_shape.rb +180 -19
- data/lib/hecks/forms/html.rb +51 -7
- data/lib/hecks/forms/index_renderer.rb +14 -2
- data/lib/hecks/forms/params.rb +120 -23
- data/lib/hecks/forms/port_argument.rb +2 -2
- data/lib/hecks/forms/query_form_renderer.rb +2 -2
- data/lib/hecks/forms/record_renderer.rb +2 -2
- data/lib/hecks/forms/record_table.rb +1 -1
- data/lib/hecks/forms/value_object_shape.rb +3 -3
- data/lib/hecks/forms.rb +24 -4
- data/lib/hecks/fqn.rb +1 -1
- data/lib/hecks/framework/bluebook/governance.bluebook +9 -0
- data/lib/hecks/framework.rb +48 -17
- data/lib/hecks/freezer.rb +11 -11
- data/lib/hecks/fuzzing/bounded_exhaustive_expressions.rb +90 -90
- data/lib/hecks/fuzzing/combination_miner.rb +119 -0
- data/lib/hecks/fuzzing/concurrent_dispatch.rb +140 -45
- data/lib/hecks/fuzzing/coverage_campaign.rb +118 -0
- data/lib/hecks/fuzzing/differential.rb +158 -0
- data/lib/hecks/fuzzing/domain_generator.rb +694 -0
- data/lib/hecks/fuzzing/era_boundary.rb +37 -18
- data/lib/hecks/fuzzing/form_census.rb +35 -20
- data/lib/hecks/fuzzing/generated_domain_check.rb +95 -0
- data/lib/hecks/fuzzing/invalid_value_generator.rb +6 -6
- data/lib/hecks/fuzzing/isolated_boot.rb +62 -62
- data/lib/hecks/fuzzing/nondeterministic.rb +67 -0
- data/lib/hecks/fuzzing/persistence_parity.rb +19 -21
- data/lib/hecks/fuzzing/properties/corrections.rb +9 -9
- data/lib/hecks/fuzzing/properties/dispatch_and_mutations.rb +154 -49
- data/lib/hecks/fuzzing/properties/guards.rb +42 -42
- data/lib/hecks/fuzzing/properties/invariants_and_aggregation.rb +32 -32
- data/lib/hecks/fuzzing/properties/lifecycle_and_replay.rb +22 -35
- data/lib/hecks/fuzzing/properties/outbox.rb +24 -24
- data/lib/hecks/fuzzing/properties/querying.rb +17 -17
- data/lib/hecks/fuzzing/properties.rb +64 -40
- data/lib/hecks/fuzzing/qa_settings.rb +152 -0
- data/lib/hecks/fuzzing/replay.rb +114 -114
- data/lib/hecks/fuzzing/rotation_priority.rb +10 -10
- data/lib/hecks/fuzzing/rust_gap_manifest.rb +113 -0
- data/lib/hecks/fuzzing/self_consistency.rb +141 -112
- data/lib/hecks/fuzzing/sequence_generator/adversary.rb +35 -35
- data/lib/hecks/fuzzing/sequence_generator/catalog.rb +18 -11
- data/lib/hecks/fuzzing/sequence_generator/outcome_tracker.rb +13 -12
- data/lib/hecks/fuzzing/sequence_generator/picker.rb +21 -12
- data/lib/hecks/fuzzing/sequence_generator/step_builder.rb +58 -31
- data/lib/hecks/fuzzing/sequence_generator.rb +111 -23
- data/lib/hecks/fuzzing/shrinker.rb +197 -0
- data/lib/hecks/fuzzing/structural_skips.rb +23 -130
- data/lib/hecks/fuzzing/sweep_depth.rb +4 -4
- data/lib/hecks/fuzzing/target_capabilities.rb +49 -18
- data/lib/hecks/fuzzing/value_generator.rb +14 -14
- data/lib/hecks/fuzzing.rb +5 -0
- data/lib/hecks/grammar/evolve.rb +10 -10
- data/lib/hecks/grammar.rb +7 -7
- data/lib/hecks/ir.rb +13 -13
- data/lib/hecks/language/bluebook/bluebook.bluebook +41 -0
- data/lib/hecks/language/bluebook/policy.bluebook +11 -1
- data/lib/hecks/language/bluebook/vocabulary.bluebook +348 -13
- data/lib/hecks/language/oidc.json +5 -0
- data/lib/hecks/literal.rb +9 -9
- data/lib/hecks/naming.rb +25 -25
- data/lib/hecks/ports/access_control.rb +58 -2
- data/lib/hecks/ports/agent/answers.rb +83 -6
- data/lib/hecks/ports/agent.rb +119 -35
- data/lib/hecks/ports/authentication.rb +44 -4
- data/lib/hecks/ports/authorization.rb +53 -11
- data/lib/hecks/ports/clock.rb +42 -23
- data/lib/hecks/ports/extraction.rb +16 -0
- data/lib/hecks/ports/identity_assignment.rb +24 -2
- data/lib/hecks/ports/identity_generation.rb +17 -3
- data/lib/hecks/ports/identity_resolution.rb +18 -1
- data/lib/hecks/ports/loading.rb +4 -0
- data/lib/hecks/ports/persistence/append_only.rb +172 -8
- data/lib/hecks/ports/persistence/binding_policy.rb +34 -0
- data/lib/hecks/ports/persistence/codec_boundary.rb +178 -0
- data/lib/hecks/ports/persistence/execution.rb +4 -0
- data/lib/hecks/ports/persistence/null_saga_store.rb +12 -1
- data/lib/hecks/ports/persistence/plugin.rb +42 -4
- data/lib/hecks/ports/persistence/plugins/era/era_check.rb +218 -25
- data/lib/hecks/ports/persistence/plugins/era/era_guard/shape_diff.rb +77 -9
- data/lib/hecks/ports/persistence/plugins/era/era_guard.rb +81 -24
- data/lib/hecks/ports/persistence/plugins/era/era_tamper.rb +29 -18
- data/lib/hecks/ports/persistence/plugins/era/lineage.rb +144 -60
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/era_store.rb +103 -8
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/field_cache.rb +98 -23
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/head_compiler.rb +282 -109
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/mint_transaction.rb +63 -25
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/provisioning.rb +118 -66
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/resumable_backfill.rb +51 -28
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/tail_merge.rb +28 -5
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/transform_installer.rb +25 -12
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage.rb +129 -34
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/coverage_check.rb +51 -6
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/era_resolver.rb +33 -9
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/merge_coordinator.rb +16 -0
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/minter.rb +57 -4
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager.rb +25 -2
- data/lib/hecks/ports/persistence/plugins/era/postgres_era.rb +314 -90
- data/lib/hecks/ports/persistence/plugins/era/storage_shape.rb +68 -10
- data/lib/hecks/ports/persistence/plugins/era/translation/audit/approval_digest.rb +9 -3
- data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_one.rb +9 -2
- data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_two.rb +42 -8
- data/lib/hecks/ports/persistence/plugins/era/translation/audit/unfed_report.rb +16 -1
- data/lib/hecks/ports/persistence/plugins/era/translation/audit.rb +36 -5
- data/lib/hecks/ports/persistence/plugins/era/translation/reattest.rb +23 -3
- data/lib/hecks/ports/persistence/plugins/era/translation/rule_compiler.rb +18 -19
- data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/differ.rb +5 -5
- data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/writer.rb +1 -1
- data/lib/hecks/ports/persistence/plugins/era/translation/scaffold.rb +2 -2
- data/lib/hecks/ports/persistence/plugins/era.rb +12 -2
- data/lib/hecks/ports/persistence/remote_runtime.rb +9 -2
- data/lib/hecks/ports/persistence/repository_factory.rb +23 -3
- data/lib/hecks/ports/persistence/state_codec.rb +319 -0
- data/lib/hecks/ports/persistence.rb +36 -1
- data/lib/hecks/ports/projection.rb +61 -7
- data/lib/hecks/ports/query/in_memory.rb +3 -3
- data/lib/hecks/ports/query/ordering.rb +6 -6
- data/lib/hecks/ports/query.rb +35 -0
- data/lib/hecks/projections/bootstrap_table.rb +112 -0
- data/lib/hecks/projections/diagrams.rb +75 -75
- data/lib/hecks/projections/glossary/html.rb +3 -3
- data/lib/hecks/projections/glossary/markdown.rb +3 -3
- data/lib/hecks/projections/glossary/mermaid.rb +1 -1
- data/lib/hecks/projections/glossary/sections.rb +1 -1
- data/lib/hecks/projections/glossary/sentences.rb +5 -5
- data/lib/hecks/projections/glossary.rb +15 -15
- data/lib/hecks/projections/ir.rb +1 -1
- data/lib/hecks/projections/model/deviations.rb +18 -17
- data/lib/hecks/projections/model.rb +25 -21
- data/lib/hecks/projections/oidc.rb +7 -7
- data/lib/hecks/projections/parser_table.rb +5 -5
- data/lib/hecks/projections/reference.rb +3 -3
- data/lib/hecks/projections/rust_vocabulary.rb +443 -0
- data/lib/hecks/projections/shape.rb +2 -2
- data/lib/hecks/projections/statements.rb +11 -11
- data/lib/hecks/projections/vocabulary.rb +9 -9
- data/lib/hecks/projections.rb +5 -3
- data/lib/hecks/projector/cli_projector.rb +29 -29
- data/lib/hecks/projector/docs_projector.rb +13 -13
- data/lib/hecks/projector/exporter.rb +42 -21
- data/lib/hecks/projector/ir_projector.rb +1 -1
- data/lib/hecks/projector/narrate_projector.rb +11 -11
- data/lib/hecks/projector/target.rb +13 -13
- data/lib/hecks/projector.rb +15 -15
- data/lib/hecks/query_ir.rb +47 -47
- data/lib/hecks/query_specification/common/comparators.rb +19 -3
- data/lib/hecks/query_specification/common/comparison.rb +109 -27
- data/lib/hecks/query_specification/common/dsl.rb +65 -9
- data/lib/hecks/query_specification/common/null_policy.rb +57 -13
- data/lib/hecks/query_specification/common/null_semantics.rb +4 -0
- data/lib/hecks/query_specification/common/options.rb +25 -0
- data/lib/hecks/query_specification/field_path.rb +69 -15
- data/lib/hecks/query_specification/hop_path.rb +57 -20
- data/lib/hecks/query_specification/read_model/specification.rb +4 -0
- data/lib/hecks/rendering.rb +3 -3
- data/lib/hecks/router/namespace_installer.rb +3 -3
- data/lib/hecks/router.rb +1 -1
- data/lib/hecks/runtime/aggregate_lock.rb +11 -11
- data/lib/hecks/runtime/boot_gates.rb +3 -3
- data/lib/hecks/runtime/caller.rb +8 -8
- data/lib/hecks/runtime/capability_graph.rb +2 -2
- data/lib/hecks/runtime/command_interpreter/argument_gate.rb +22 -25
- data/lib/hecks/runtime/command_interpreter/mutation_applier.rb +42 -63
- data/lib/hecks/runtime/command_interpreter.rb +159 -102
- data/lib/hecks/runtime/command_rules/admissibility.rb +69 -69
- data/lib/hecks/runtime/command_rules/arithmetic.rb +137 -91
- data/lib/hecks/runtime/command_rules/authorization.rb +38 -17
- data/lib/hecks/runtime/command_rules/emission.rb +18 -1
- data/lib/hecks/runtime/command_rules/references.rb +35 -35
- data/lib/hecks/runtime/command_rules.rb +3 -0
- data/lib/hecks/runtime/dependency_planning.rb +11 -11
- data/lib/hecks/runtime/dispatcher.rb +283 -90
- data/lib/hecks/runtime/entity_element.rb +151 -67
- data/lib/hecks/runtime/entity_interpreter.rb +108 -82
- data/lib/hecks/runtime/errors.rb +19 -19
- data/lib/hecks/runtime/event.rb +6 -6
- data/lib/hecks/runtime/identity.rb +22 -22
- data/lib/hecks/runtime/instance.rb +39 -14
- data/lib/hecks/runtime/interpreting.rb +12 -12
- data/lib/hecks/runtime/invocation.rb +276 -0
- data/lib/hecks/runtime/loader.rb +14 -14
- data/lib/hecks/runtime/outbox.rb +23 -23
- data/lib/hecks/runtime/policy_interpreter.rb +54 -54
- data/lib/hecks/runtime/port_operation_interpreter.rb +22 -19
- data/lib/hecks/runtime/query_interpreter.rb +55 -64
- data/lib/hecks/runtime/reaction_invocation.rb +20 -20
- data/lib/hecks/runtime/read_model_interpreter.rb +40 -40
- data/lib/hecks/runtime/rebuild_sweep.rb +4 -4
- data/lib/hecks/runtime/reference_hop.rb +6 -6
- data/lib/hecks/runtime/refusal_wording.rb +92 -115
- data/lib/hecks/runtime/registry/saga_persistence.rb +21 -21
- data/lib/hecks/runtime/registry/verification.rb +36 -26
- data/lib/hecks/runtime/registry.rb +45 -28
- data/lib/hecks/runtime/remote_dispatcher.rb +38 -23
- data/lib/hecks/runtime/routing.rb +10 -153
- data/lib/hecks/runtime/saga_interpreter/correlation.rb +17 -17
- data/lib/hecks/runtime/saga_interpreter.rb +64 -64
- data/lib/hecks/runtime/saga_pending_dispatch.rb +12 -12
- data/lib/hecks/runtime/tenant_check.rb +9 -9
- data/lib/hecks/runtime/tenant_scope.rb +5 -5
- data/lib/hecks/runtime/value/admission.rb +75 -30
- data/lib/hecks/runtime/value/coercion.rb +318 -127
- data/lib/hecks/runtime/value/entity_list_coercion.rb +34 -34
- data/lib/hecks/runtime/value.rb +21 -21
- data/lib/hecks/runtime.rb +7 -7
- data/lib/hecks/storehouse.rb +64 -64
- data/lib/hecks/version.rb +3 -3
- data/lib/hecks/vocabulary.rb +205 -4
- data/lib/hecks.rb +13 -11
- data/lib/rubocop/cop/hecks/fallback_hash_lookup.rb +11 -11
- data/lib/rubocop/cop/hecks/sequential_hash_rename_in_loop.rb +14 -12
- data/lib/rubocop/cop/hecks/thread_shared_ivar_mutation.rb +11 -11
- metadata +22 -2
|
@@ -5,12 +5,15 @@ module Hecks
|
|
|
5
5
|
module Adapters
|
|
6
6
|
class PostgresEra
|
|
7
7
|
module LineageManager
|
|
8
|
-
# The boot-time resolution: which era
|
|
8
|
+
# The boot-time resolution: which era is this checkout? First
|
|
9
9
|
# boot holds era 1; a quiet reboot changes nothing; a
|
|
10
10
|
# held-but-superseded shape boots read-only-toward-the-fence; an
|
|
11
11
|
# unheld shape goes to the minter.
|
|
12
12
|
module EraResolver
|
|
13
13
|
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
14
|
+
# Resolves which era this boot is and records it on the registry, holding era 1
|
|
15
|
+
# on a first boot and minting the next era when the shape is one no era holds.
|
|
16
|
+
#
|
|
14
17
|
# A single order-dependent dispatch over a closed set of four
|
|
15
18
|
# boot scenarios (first boot / quiet reboot / held-but-superseded
|
|
16
19
|
# / unheld-shape-goes-to-minter), each already explained by its
|
|
@@ -18,11 +21,32 @@ module Hecks
|
|
|
18
21
|
# `ensure`. Splitting the branches into separate methods would
|
|
19
22
|
# turn each `return` (which exits `check!`, closing `db`) into a
|
|
20
23
|
# sentinel value threaded back up, obscuring the mutual
|
|
21
|
-
# exclusivity that
|
|
24
|
+
# exclusivity that is the method's whole point.
|
|
25
|
+
#
|
|
26
|
+
# @param registry [Runtime::Registry] the booting registry; `resolved_eras` gets
|
|
27
|
+
# this domain's ordinal on every path but a first boot (where the adapter
|
|
28
|
+
# self-resolves to era 1), and `superseded_eras` gets the newest ordinal when
|
|
29
|
+
# this checkout's shape is held but superseded
|
|
30
|
+
# @param bluebook [Bluebook::Chapter] the domain being booted
|
|
31
|
+
# @param current_text [String] the domain's bluebook source as it stands on disk,
|
|
32
|
+
# held verbatim as the new era's text on a first boot or a mint
|
|
33
|
+
# @param settings [Hash{Symbol, String => Object}] the world's persistence settings
|
|
34
|
+
# for this binding; `database` is required, `schema`, `role` (a Postgres role to
|
|
35
|
+
# grant this era's privileges to) and `allow_superuser` are honored
|
|
36
|
+
# @param directory [String, nil] the domain's bluebook directory, where
|
|
37
|
+
# `HECKS_SCAFFOLD=1` writes a translation edge; nil disables scaffolding
|
|
38
|
+
# @return [Integer, nil] the ordinal of the era this boot minted, or nil when it
|
|
39
|
+
# minted nothing (first boot, quiet reboot, or a held-but-superseded shape)
|
|
40
|
+
# @raise [Runtime::WiringError] if the database cannot be reached, the connection
|
|
41
|
+
# is a superuser or has BYPASSRLS without `allow_superuser`, a declared
|
|
42
|
+
# `formerly_known_as` rename cannot be applied, a held text fails its integrity
|
|
43
|
+
# check, or the shape is unheld and `mint!` refuses
|
|
44
|
+
# @raise [Bluebook::DSL::Malformed] if a held era's text parses under neither the
|
|
45
|
+
# current nor the legacy grammar
|
|
22
46
|
def check!(registry:, bluebook:, current_text:, settings:, directory: nil)
|
|
23
47
|
db = PostgresEra.connect_for(bluebook.name, settings)
|
|
24
48
|
lineage = Lineage.new(db, bluebook.name, formerly_known_as: bluebook.formerly_known_as)
|
|
25
|
-
#
|
|
49
|
+
# First, before ensure_base! provisions or verifies anything —
|
|
26
50
|
# the one point every PostgresEra boot passes through, and the
|
|
27
51
|
# earliest at which the connection's own role is known. See
|
|
28
52
|
# check_fence_applies!'s own header (BUG#24) for why a
|
|
@@ -39,7 +63,7 @@ module Hecks
|
|
|
39
63
|
lineage.hold_first!(current_text, projection: Runtime::StorageShape.project(bluebook))
|
|
40
64
|
bluebook.aggregates.each { |aggregate| lineage.ensure_first_head!(aggregate.storage_name) }
|
|
41
65
|
# hold_first! already established era 1 as current for
|
|
42
|
-
#
|
|
66
|
+
# every role; this one just needs its own privileges.
|
|
43
67
|
lineage.grant_role!(role, aggregates: bluebook.aggregates, era: 1) if role
|
|
44
68
|
return
|
|
45
69
|
end
|
|
@@ -52,7 +76,7 @@ module Hecks
|
|
|
52
76
|
# is permanently the old one — the frozen text is authentic
|
|
53
77
|
# record ("this domain really was called that, at the
|
|
54
78
|
# time") and must never be rewritten. Only the in-memory
|
|
55
|
-
# shape used for
|
|
79
|
+
# shape used for this comparison is normalized, and only
|
|
56
80
|
# where it exactly matches the declared old name, so an
|
|
57
81
|
# unrelated domain that happens to shape-match some other
|
|
58
82
|
# domain's history still shows up as a real mismatch.
|
|
@@ -74,9 +98,9 @@ module Hecks
|
|
|
74
98
|
matched, = shapes.find { |_, shape| shape == current_shape }
|
|
75
99
|
if matched
|
|
76
100
|
# A held-but-superseded era — an old checkout still running.
|
|
77
|
-
# It may keep
|
|
101
|
+
# It may keep booting and reading (PostgresEra is the one
|
|
78
102
|
# adapter that recognizes this rather than refusing), but it
|
|
79
|
-
# may not keep
|
|
103
|
+
# may not keep writing: the shared era fence was already
|
|
80
104
|
# advanced past this ordinal by whichever mint superseded
|
|
81
105
|
# it, and nothing here may roll that back. Granting only
|
|
82
106
|
# this role's privileges, never advance_era!, is what keeps
|
|
@@ -84,11 +108,11 @@ module Hecks
|
|
|
84
108
|
# called with a superseded ordinal.
|
|
85
109
|
lineage.grant_role!(role, aggregates: bluebook.aggregates, era: matched[:ordinal]) if role
|
|
86
110
|
registry.resolved_eras[bluebook.name] = matched[:ordinal]
|
|
87
|
-
# ...and the boot
|
|
111
|
+
# ...and the boot remembers that it is superseded, not only
|
|
88
112
|
# which era it is: `RepositoryFactory.build` hands this to
|
|
89
113
|
# the adapter as `superseded_by:`, and `PostgresEra#append`
|
|
90
114
|
# refuses on it before issuing the INSERT. That is the
|
|
91
|
-
# in-process half of "may not keep
|
|
115
|
+
# in-process half of "may not keep writing" — the half that
|
|
92
116
|
# holds even for a connection the RLS fence cannot bite
|
|
93
117
|
# (a superuser under allow_superuser; BUG#24).
|
|
94
118
|
registry.superseded_eras[bluebook.name] = latest[:ordinal]
|
data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/merge_coordinator.rb
CHANGED
|
@@ -10,6 +10,22 @@ module Hecks
|
|
|
10
10
|
# world's post-cut writes into the head by their recorded global
|
|
11
11
|
# ordinals, under the full audit, in one transaction.
|
|
12
12
|
module MergeCoordinator
|
|
13
|
+
# Merges the writes old checkouts made after the last mint into the current
|
|
14
|
+
# era's head, on a connection of its own that it closes afterwards.
|
|
15
|
+
#
|
|
16
|
+
# @param registry [Runtime::Registry] the loaded registry; supplies the
|
|
17
|
+
# translation edges the chain is built from
|
|
18
|
+
# @param bluebook [Bluebook::Chapter] the domain whose tail is merged
|
|
19
|
+
# @param settings [Hash{Symbol, String => Object}] the world's persistence
|
|
20
|
+
# settings for this binding; `database` is required
|
|
21
|
+
# @param winners [Hash{String => String}] record id to `"old"` or `"new"`, naming
|
|
22
|
+
# which world's whole record wins for each id both worlds touched since the cut
|
|
23
|
+
# @return [true] when the merge committed
|
|
24
|
+
# @raise [Runtime::WiringError] if the database cannot be reached, the domain
|
|
25
|
+
# stands at era 1, the edge chain is broken, a record touched by both worlds
|
|
26
|
+
# has no named winner, the post-merge audit reports violations, another mint
|
|
27
|
+
# or merge holds the domain lock for 10 seconds, or Postgres refuses a
|
|
28
|
+
# statement; every refusal rolls the merge back
|
|
13
29
|
def merge!(registry:, bluebook:, settings:, winners: {})
|
|
14
30
|
db = PostgresEra.connect_for(bluebook.name, settings)
|
|
15
31
|
lineage = Lineage.new(db, bluebook.name, formerly_known_as: bluebook.formerly_known_as)
|
|
@@ -12,6 +12,29 @@ module Hecks
|
|
|
12
12
|
# reviewed, check coverage, audit the live chain, and mint — or
|
|
13
13
|
# refuse toward the authoring loop by name.
|
|
14
14
|
module Minter
|
|
15
|
+
# Mints the next era for a drifted shape in one transaction, after proving the
|
|
16
|
+
# edge is present, current, approved where it must be, covering, and audited.
|
|
17
|
+
#
|
|
18
|
+
# @param registry [Runtime::Registry] the booting registry; supplies the loaded
|
|
19
|
+
# translation edges
|
|
20
|
+
# @param bluebook [Bluebook::Chapter] the domain as currently declared
|
|
21
|
+
# @param current_text [String] the domain's bluebook source, held verbatim as the
|
|
22
|
+
# new era's text
|
|
23
|
+
# @param lineage [Adapters::PostgresEra::Lineage] the domain's lineage, on an open
|
|
24
|
+
# connection
|
|
25
|
+
# @param latest [Hash{Symbol => Object}] the newest held era, as `Lineage#eras`
|
|
26
|
+
# returns it (`:ordinal`, `:hash`, `:label`, `:held_text`, `:watermark`)
|
|
27
|
+
# @param role [String, nil] a Postgres role to grant the new era's privileges to;
|
|
28
|
+
# nil grants nothing
|
|
29
|
+
# @param directory [String, nil] the domain's bluebook directory, where
|
|
30
|
+
# `HECKS_SCAFFOLD=1` writes a missing edge; nil disables scaffolding
|
|
31
|
+
# @return [Integer] the ordinal of the era just minted
|
|
32
|
+
# @raise [Runtime::WiringError] if no edge leaves the latest era, more than one
|
|
33
|
+
# does, the edge targets another shape, a compute or rekey edge lacks a current
|
|
34
|
+
# approval, the edge leaves drift uncovered, the chain is broken, the audit
|
|
35
|
+
# reports violations, or the mint transaction itself fails
|
|
36
|
+
# @raise [Bluebook::DSL::Malformed] if the latest held text parses under neither
|
|
37
|
+
# the current nor the legacy grammar
|
|
15
38
|
def mint!(registry, bluebook, current_text, lineage, latest, role: nil, directory: nil)
|
|
16
39
|
ensure_named!(lineage, latest)
|
|
17
40
|
latest = lineage.eras.last
|
|
@@ -34,12 +57,28 @@ module Hecks
|
|
|
34
57
|
ordinal
|
|
35
58
|
end
|
|
36
59
|
|
|
37
|
-
#
|
|
38
|
-
#
|
|
60
|
+
# Finds the one translation edge that leaves the held era, and
|
|
61
|
+
# validates it: exactly one edge must leave (eras fork
|
|
39
62
|
# mechanically — a second edge from the same source is a wiring
|
|
40
63
|
# mistake, not a merge to resolve automatically), and it must
|
|
41
64
|
# target the current shape's label (otherwise the edge is stale
|
|
42
65
|
# and boot must not silently mint past it).
|
|
66
|
+
#
|
|
67
|
+
# @param registry [Runtime::Registry] the registry whose loaded `translations`
|
|
68
|
+
# are searched
|
|
69
|
+
# @param bluebook [Bluebook::Chapter] the domain as currently declared
|
|
70
|
+
# @param lineage [Adapters::PostgresEra::Lineage] the domain's lineage, used only
|
|
71
|
+
# when scaffolding a missing edge
|
|
72
|
+
# @param latest [Hash{Symbol => Object}] the newest held era, already named;
|
|
73
|
+
# `:label` is the edge's required source and `:ordinal` appears in refusals
|
|
74
|
+
# @param label [String] the current shape's label, the edge's required target
|
|
75
|
+
# @param ordinal [Integer] the ordinal of the era about to be minted
|
|
76
|
+
# @param directory [String, nil] where `HECKS_SCAFFOLD=1` writes a missing edge;
|
|
77
|
+
# nil disables scaffolding
|
|
78
|
+
# @return [Bluebook::Translation] the single edge from `latest[:label]` to `label`
|
|
79
|
+
# @raise [Runtime::WiringError] if no edge leaves the latest era (naming the
|
|
80
|
+
# scaffold it wrote, when it wrote one), more than one does, or the one edge
|
|
81
|
+
# targets a label other than `label`
|
|
43
82
|
def resolve_edge!(registry, bluebook, lineage, latest, label, ordinal, directory)
|
|
44
83
|
edges = registry.translations.select { |t| t.domain == bluebook.name && t.from == latest[:label] }
|
|
45
84
|
refuse_toward_the_scaffold!(registry, bluebook, lineage, latest, ordinal, directory) if edges.empty?
|
|
@@ -58,15 +97,29 @@ module Hecks
|
|
|
58
97
|
edge
|
|
59
98
|
end
|
|
60
99
|
|
|
100
|
+
# Refuses a mint whose edge carries a compute or rekey rule without a recorded
|
|
101
|
+
# approval that still matches the edge and the journal.
|
|
102
|
+
#
|
|
61
103
|
# A compute's (and, the same way, a rekey's) only verification
|
|
62
104
|
# is the audit's human-approved sample — mint stays
|
|
63
105
|
# non-interactive by requiring the approval to already exist,
|
|
64
|
-
# recorded
|
|
106
|
+
# recorded in this database by `bin/translation_audit …
|
|
65
107
|
# --approve` and bound to what was actually reviewed: this
|
|
66
108
|
# edge's parsed content, and the journal as it stood when the
|
|
67
109
|
# samples were read. A journal that has advanced past the
|
|
68
110
|
# review invalidates it — the approved samples no longer cover
|
|
69
111
|
# the data.
|
|
112
|
+
#
|
|
113
|
+
# @param bluebook [Bluebook::Chapter] the domain, named in the refusal
|
|
114
|
+
# @param lineage [Adapters::PostgresEra::Lineage] the domain's lineage, which holds
|
|
115
|
+
# the recorded approvals and the journal's last ordinal
|
|
116
|
+
# @param edge [Bluebook::Translation] the edge about to be minted through
|
|
117
|
+
# @param ordinal [Integer] the ordinal of the era about to be minted
|
|
118
|
+
# @return [nil] when the edge has no compute or rekey rule, or its approval is
|
|
119
|
+
# current
|
|
120
|
+
# @raise [Runtime::WiringError] if no approval is recorded for this shape pair, the
|
|
121
|
+
# approval's edge digest differs from this edge's, or the journal has advanced
|
|
122
|
+
# past the reviewed ordinal
|
|
70
123
|
def ensure_compute_rekey_approved!(bluebook, lineage, edge, ordinal)
|
|
71
124
|
return unless edge.aggregates.any? { |declared| !declared.computes.empty? || !declared.rekeys.empty? }
|
|
72
125
|
|
|
@@ -88,7 +141,7 @@ module Hecks
|
|
|
88
141
|
|
|
89
142
|
# No edge yet: the boot refuses toward the authoring loop —
|
|
90
143
|
# naming both tools and the era ordinal. With HECKS_SCAFFOLD=1
|
|
91
|
-
# the boot
|
|
144
|
+
# the boot runs the scaffold first (an explicit flag, never a
|
|
92
145
|
# silent side-effect) and the refusal names the file it wrote.
|
|
93
146
|
def refuse_toward_the_scaffold!(registry, bluebook, lineage, latest, ordinal, directory)
|
|
94
147
|
if ENV["HECKS_SCAFFOLD"] == "1" && directory
|
|
@@ -12,7 +12,7 @@ module Hecks
|
|
|
12
12
|
class PostgresEra
|
|
13
13
|
# The PostgresEra side of the boot-time era gate. Where every other
|
|
14
14
|
# adapter's era check can only hold texts and refuse, this one
|
|
15
|
-
#
|
|
15
|
+
# acts: a drifted shape whose translation edge exists, matches by
|
|
16
16
|
# shape label, covers the whole diff, and passes the audit mints
|
|
17
17
|
# the next era — one transaction — and boots into it. Everything
|
|
18
18
|
# else refuses, as loudly and as specifically as the situation
|
|
@@ -38,10 +38,24 @@ module Hecks
|
|
|
38
38
|
|
|
39
39
|
module_function
|
|
40
40
|
|
|
41
|
-
#
|
|
41
|
+
# Collects the translation edge for every step from era 1 to the current shape.
|
|
42
|
+
#
|
|
43
|
+
# The full chain, one edge per step in original mint order —
|
|
42
44
|
# never flattened. Each step is found by its stored labels;
|
|
43
45
|
# every mint required its own edge, so a break in the chain is a
|
|
44
46
|
# deleted file, and deserves its own refusal.
|
|
47
|
+
#
|
|
48
|
+
# @param registry [Runtime::Registry] the registry whose loaded `translations`
|
|
49
|
+
# are searched
|
|
50
|
+
# @param bluebook [Bluebook::Chapter] the domain; only edges declared for its
|
|
51
|
+
# name are considered
|
|
52
|
+
# @param eras [Array<Hash{Symbol => Object}>] the ancestor eras in ordinal order,
|
|
53
|
+
# as `Lineage#eras` returns them; only `:label` is read
|
|
54
|
+
# @param current_label [String] the shape label the last step must lead to
|
|
55
|
+
# @return [Array<Hash{Symbol => Bluebook::Translation}>] one `{ translation: edge }`
|
|
56
|
+
# per step, in mint order; `[]` when `eras` is empty
|
|
57
|
+
# @raise [Runtime::WiringError] if no loaded translation leads one label to the
|
|
58
|
+
# next
|
|
45
59
|
def edge_chain(registry, bluebook, eras, current_label)
|
|
46
60
|
labels = eras.map { |era| era[:label] } + [current_label]
|
|
47
61
|
(0...(labels.size - 1)).map do |index|
|
|
@@ -57,9 +71,18 @@ module Hecks
|
|
|
57
71
|
end
|
|
58
72
|
end
|
|
59
73
|
|
|
74
|
+
# Parses a held era's bluebook text into a throwaway registry, leaving the live
|
|
75
|
+
# one untouched.
|
|
76
|
+
#
|
|
60
77
|
# Held texts live in rows, not files, but the predicate
|
|
61
78
|
# extractor reads source from disk at the eval path — so a
|
|
62
79
|
# shadow parse writes the text to a scratch file first.
|
|
80
|
+
#
|
|
81
|
+
# @param source [String] bluebook source text, as held in `hecks_eras.held_text`
|
|
82
|
+
# @return [Bluebook::Chapter, nil] the first bluebook the text declares, or nil
|
|
83
|
+
# when it declares none
|
|
84
|
+
# @raise [Bluebook::DSL::Malformed] if the text parses under neither the current
|
|
85
|
+
# grammar nor the legacy shadow-parse fallback
|
|
63
86
|
def shadow(source)
|
|
64
87
|
file = Tempfile.new(["hecks-era-", ".bluebook"])
|
|
65
88
|
file.write(source)
|