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,7 +5,7 @@ require_relative "../../rendering"
|
|
|
5
5
|
module Hecks
|
|
6
6
|
module Runtime
|
|
7
7
|
class Value
|
|
8
|
-
#
|
|
8
|
+
# How a `list_of` attribute's own elements GET hydrated — entity-typed
|
|
9
9
|
# and value-object-typed alike — split out of `Coercion` (this file's
|
|
10
10
|
# sibling, extended into `Value` alongside it exactly the way
|
|
11
11
|
# `Admission` already is) once `Coercion` itself grew past
|
|
@@ -16,19 +16,19 @@ module Hecks
|
|
|
16
16
|
# made the split necessary). Cross-calls into `Coercion`'s own
|
|
17
17
|
# `for_attribute`/`build`/`fields_for`/`value_object_for`/
|
|
18
18
|
# `trusting_stored_state?` work unqualified here exactly as they did
|
|
19
|
-
# before the split, because both modules land on the
|
|
19
|
+
# before the split, because both modules land on the same `Value`
|
|
20
20
|
# singleton class once extended — `self` never has to know which file
|
|
21
21
|
# a sibling method actually lives in.
|
|
22
22
|
module EntityListCoercion
|
|
23
|
-
# S17, ADR 0026 —
|
|
23
|
+
# S17, ADR 0026 — searches the whole entity tree, not only the
|
|
24
24
|
# root's own direct children. `aggregate` here is always the
|
|
25
|
-
#
|
|
25
|
+
# root aggregate — `for_attribute`'s own `aggregate` argument is
|
|
26
26
|
# never reassigned as hydration recurses into a nested element,
|
|
27
27
|
# because coercion has to resolve value objects, and only the
|
|
28
28
|
# root answers `.value_object` at all (Entity's own header
|
|
29
|
-
# comment: an entity must
|
|
29
|
+
# comment: an entity must not answer to it, or `Value.
|
|
30
30
|
# for_attribute` could no longer tell a piece from a head). So
|
|
31
|
-
# a
|
|
31
|
+
# a nested entity — Dispatch, inside Handler — is not a direct
|
|
32
32
|
# child of the root the way Handler itself is, and a plain
|
|
33
33
|
# `aggregate.entities.find` stops one level short of it.
|
|
34
34
|
def find_entity(construct, name)
|
|
@@ -57,16 +57,16 @@ module Hecks
|
|
|
57
57
|
# raw `Hash`) then always failed, since `Hash#==` refuses anything
|
|
58
58
|
# that isn't itself a compatible Hash — the bug ADR 0047 traces in
|
|
59
59
|
# full. Delegating to `hydrate_value_object_list` below closes
|
|
60
|
-
# that gap the same way the
|
|
60
|
+
# that gap the same way the entity branch already worked: build a
|
|
61
61
|
# real, validated `Value` per element, reusing `for_attribute`'s
|
|
62
62
|
# own composite-construction path rather than inventing a second
|
|
63
63
|
# one.
|
|
64
64
|
# BUG#32 (QualityControl ledger) — `remove:`'s own single-target
|
|
65
65
|
# value used to fall straight into `Array(value).map { ... }`
|
|
66
|
-
# below
|
|
66
|
+
# below unguarded, unlike this method's own delegated
|
|
67
67
|
# `hydrate_value_object_list` sibling, whose `value.is_a?(Array)`
|
|
68
68
|
# check exists for exactly this shape (see that method's own
|
|
69
|
-
# comment). For an
|
|
69
|
+
# comment). For an entity-typed list, `remove:`'s scalar target
|
|
70
70
|
# (`Ledger.Void`'s `sequence: EntrySequence`) is never a Hash, so
|
|
71
71
|
# `Array(2)` merely wrapped it as `[2]` rather than shredding it —
|
|
72
72
|
# but the wrapping itself was still wrong: `MutationApplier#
|
|
@@ -89,7 +89,7 @@ module Hecks
|
|
|
89
89
|
acc[key] = field ? for_attribute(aggregate, field, field_value) : field_value
|
|
90
90
|
end
|
|
91
91
|
end
|
|
92
|
-
# BUG#33 — only a genuine
|
|
92
|
+
# BUG#33 — only a genuine whole-list offering (`value.is_a?(Array)`)
|
|
93
93
|
# is a caller naming every element's own identity at once; the
|
|
94
94
|
# single-target shape this same method also hydrates (a `remove:`
|
|
95
95
|
# target, wrapped one level up by `Array()`) never reaches this
|
|
@@ -101,16 +101,16 @@ module Hecks
|
|
|
101
101
|
|
|
102
102
|
# `MutationApplier#check_entity_collision`'s own guard
|
|
103
103
|
# (mutation_applier.rb), extended from a single caller-supplied
|
|
104
|
-
#
|
|
104
|
+
# append (BUG#13) to a whole-list replace — `sets :entries` bare
|
|
105
105
|
# (`Ledger.ReplaceEntries`, the corpus's first `list_of(ENTITY)`
|
|
106
106
|
# command argument/mutation, qa/stress_domains/corrections). The
|
|
107
107
|
# array branch above rebuilds each offered element's own declared
|
|
108
|
-
# fields but never checked the
|
|
108
|
+
# fields but never checked the offered list itself for either way
|
|
109
109
|
# it can misname its own entities:
|
|
110
110
|
#
|
|
111
111
|
# - two elements sharing one identity — the same silent-duplicate
|
|
112
112
|
# hazard BUG#13's own comment describes: `EntityInterpreter#
|
|
113
|
-
# element_of`'s own `find_index` always matches the
|
|
113
|
+
# element_of`'s own `find_index` always matches the first
|
|
114
114
|
# match, so the second becomes permanently unaddressable by any
|
|
115
115
|
# later command.
|
|
116
116
|
# - an element missing its identity altogether — there is no
|
|
@@ -120,14 +120,14 @@ module Hecks
|
|
|
120
120
|
# whole state, offered at once), so an absent identity is
|
|
121
121
|
# refused rather than guessed.
|
|
122
122
|
#
|
|
123
|
-
#
|
|
123
|
+
# Non-composite identities only, exactly BUG#13's own scope
|
|
124
124
|
# (`entity.identified_by` answers a single Symbol only when
|
|
125
125
|
# `identity_heads.size == 1`, `Behaviour::Traits#derive_identity`) —
|
|
126
126
|
# a composite identity's own duplicate/missing question is the
|
|
127
127
|
# same pre-existing, narrower gap BUG#13 documented and left open,
|
|
128
128
|
# not widened here.
|
|
129
129
|
#
|
|
130
|
-
#
|
|
130
|
+
# Skipped under `trusting_stored_state?`, the same guard `validate!`
|
|
131
131
|
# already gives every value object (C6.3): a record already
|
|
132
132
|
# written is trusted as it was, so tightening this check can never
|
|
133
133
|
# make an old, already-persisted record unreadable.
|
|
@@ -144,32 +144,32 @@ module Hecks
|
|
|
144
144
|
offered = fields[identity]
|
|
145
145
|
if offered.nil?
|
|
146
146
|
raise TypeMismatch,
|
|
147
|
-
RefusalWording.
|
|
148
|
-
|
|
149
|
-
|
|
147
|
+
RefusalWording.render_site("TypeMismatch", "numeric_field",
|
|
148
|
+
type: entity.hecks_name, field: identity,
|
|
149
|
+
expected: field&.type, offered: "nil")
|
|
150
150
|
end
|
|
151
151
|
|
|
152
152
|
if seen.include?(offered)
|
|
153
153
|
raise AlreadyExists,
|
|
154
|
-
RefusalWording.
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
154
|
+
RefusalWording.render_site("AlreadyExists", "entity_duplicate",
|
|
155
|
+
entity: entity.hecks_name, aggregate: aggregate.hecks_name,
|
|
156
|
+
identity: entity.identity_paths.join(", "),
|
|
157
|
+
offered: [Rendering.describe(offered)])
|
|
158
158
|
end
|
|
159
159
|
seen << offered
|
|
160
160
|
end
|
|
161
161
|
end
|
|
162
162
|
|
|
163
163
|
# BUG#32 — `remove:`'s own single-target value against an
|
|
164
|
-
#
|
|
165
|
-
#
|
|
164
|
+
# entity-typed list. An entity is never offered to `remove:`
|
|
165
|
+
# whole the way a value object is (`hydrate_value_object_list`'s
|
|
166
166
|
# own `element == value` full-value-equality shape) — an entity
|
|
167
167
|
# must never answer `.value_object` at all (`Entity`'s own header
|
|
168
168
|
# comment), so there is no whole-value shape here to rebuild in
|
|
169
|
-
# the first place, only the
|
|
170
|
-
# have to
|
|
169
|
+
# the first place, only the one field a caller would otherwise
|
|
170
|
+
# have to name to address that element any other way
|
|
171
171
|
# (`EntityElement#element_of`'s own `wants`). So this coerces the
|
|
172
|
-
# offered scalar against the entity's
|
|
172
|
+
# offered scalar against the entity's own identity field's
|
|
173
173
|
# declared type — not the entity's full shape — and hands back a
|
|
174
174
|
# real, correctly-typed `Value` ready to compare against each
|
|
175
175
|
# stored element's own identity field
|
|
@@ -177,9 +177,9 @@ module Hecks
|
|
|
177
177
|
# `MutationApplier#removed` and `EntityElement#
|
|
178
178
|
# removed_from_element` match against).
|
|
179
179
|
#
|
|
180
|
-
# A
|
|
180
|
+
# A composite identity (more than one head) has no single field a
|
|
181
181
|
# bare `remove:` target could mean, so this passes the value
|
|
182
|
-
# through
|
|
182
|
+
# through uncoerced rather than guessing which head — the same
|
|
183
183
|
# "nothing in this corpus needs it yet" boundary
|
|
184
184
|
# `MutationApplier#check_entity_collision`'s own header already
|
|
185
185
|
# draws for entity identity elsewhere in this runtime.
|
|
@@ -200,7 +200,7 @@ module Hecks
|
|
|
200
200
|
|
|
201
201
|
# The value-object sibling of the entity branch above: an element
|
|
202
202
|
# already shaped like the target `Value` (or a `Hash`/scalar that
|
|
203
|
-
# `fields_for` can still open) is rebuilt through the
|
|
203
|
+
# `fields_for` can still open) is rebuilt through the same `build`
|
|
204
204
|
# a scalar composite attribute already uses (`for_attribute`'s own
|
|
205
205
|
# `coerced = ... build(value_object, fields_for(...), aggregate)`
|
|
206
206
|
# line) — same defaults, same `pattern:`/`admits:`/invariant
|
|
@@ -210,15 +210,15 @@ module Hecks
|
|
|
210
210
|
# element passes through unchanged, exactly as the entity branch's
|
|
211
211
|
# own non-Hash elements do.
|
|
212
212
|
#
|
|
213
|
-
#
|
|
213
|
+
# Not `Array(value).map` (unlike the entity branch above) — `value`
|
|
214
214
|
# here is not always genuinely list-shaped. `MutationApplier#
|
|
215
215
|
# removed`'s own `Value.for_attribute(aggregate, attribute, value)`
|
|
216
|
-
# call (`attribute` = the
|
|
217
|
-
# = the single
|
|
216
|
+
# call (`attribute` = the list attribute, `mutation.target`; `value`
|
|
217
|
+
# = the single remove-target argument, already a real `Value` by
|
|
218
218
|
# the time it gets here) reuses this exact branch — for `remove:`,
|
|
219
219
|
# not for a whole-list `sets`. `Array(a_real_Value)` alone would be
|
|
220
220
|
# harmless (`Value` defines neither `to_a` nor `to_ary`, so Kernel
|
|
221
|
-
# wraps it `[value]`), but `Array(a_Hash)` is
|
|
221
|
+
# wraps it `[value]`), but `Array(a_Hash)` is not harmless: Ruby's
|
|
222
222
|
# `Array()` opens a bare Hash into its own `[[k, v], ...]` pairs,
|
|
223
223
|
# not `[hash]` — silently shredding a single-element Hash-shaped
|
|
224
224
|
# target into garbage instead of hydrating it. Branching on
|
data/lib/hecks/runtime/value.rb
CHANGED
|
@@ -8,7 +8,7 @@ require_relative "value/admission"
|
|
|
8
8
|
module Hecks
|
|
9
9
|
module Runtime
|
|
10
10
|
# A typed value object in hand: frozen fields, read by name. How one is
|
|
11
|
-
#
|
|
11
|
+
# made — coerced from a raw argument, checked against its declared
|
|
12
12
|
# numeric types, patterns and closed sets — is the class-side engine in
|
|
13
13
|
# value/coercion.rb, value/entity_list_coercion.rb (a `list_of`
|
|
14
14
|
# attribute's own elements — split out once growing Coercion tripped
|
|
@@ -22,10 +22,10 @@ module Hecks
|
|
|
22
22
|
|
|
23
23
|
attr_reader :value_object
|
|
24
24
|
|
|
25
|
-
#
|
|
25
|
+
# Frozen through, not just on top.
|
|
26
26
|
#
|
|
27
27
|
# `@fields.freeze` alone stops a key being added or removed and
|
|
28
|
-
# nothing else: the String, Array or Hash a field
|
|
28
|
+
# nothing else: the String, Array or Hash a field holds stays
|
|
29
29
|
# mutable, so `vo[:value] << "!"` edits a value object in place —
|
|
30
30
|
# demonstrated on a real dispatch before this was written, not
|
|
31
31
|
# supposed. Same shape as the three freezing bugs already fixed
|
|
@@ -33,7 +33,7 @@ module Hecks
|
|
|
33
33
|
# was frozen and the contents were not.
|
|
34
34
|
#
|
|
35
35
|
# A value object is the one thing in the domain that has no
|
|
36
|
-
# identity to change over — `with` already answers a
|
|
36
|
+
# identity to change over — `with` already answers a new one rather
|
|
37
37
|
# than mutating — so freezing it through is what it always claimed
|
|
38
38
|
# to be.
|
|
39
39
|
def initialize(value_object, fields)
|
|
@@ -68,13 +68,13 @@ module Hecks
|
|
|
68
68
|
# `materialize`, but a single-attribute value object (`sole_attribute`
|
|
69
69
|
# — [[feedback_name_the_scalar_field]]) recurses into its own bare
|
|
70
70
|
# field instead of building `{field: ...}` — a Board's own `label`
|
|
71
|
-
# unwraps to `"Kanban"`, not `{value: "Kanban"}`.
|
|
71
|
+
# unwraps to `"Kanban"`, not `{value: "Kanban"}`. Not a replacement
|
|
72
72
|
# for `materialize` itself: every existing report/query/command
|
|
73
73
|
# caller keeps the wrapped shape it already depends on (Banking's
|
|
74
74
|
# own `CustomerPortfolio` reads `payment[:amount][:cents]`, and
|
|
75
75
|
# changing that out from under it would be a real breaking change,
|
|
76
76
|
# not a bug fix). This is read_model_interpreter.rb's own opt-in,
|
|
77
|
-
# used
|
|
77
|
+
# used only for a `group_by`-declared head's own rows — grouping
|
|
78
78
|
# needs a real scalar to key by regardless, so a report already
|
|
79
79
|
# asking for that gets the unwrap for free.
|
|
80
80
|
def self.materialize_unwrapped(value)
|
|
@@ -83,12 +83,12 @@ module Hecks
|
|
|
83
83
|
sole = value.value_object.sole_attribute
|
|
84
84
|
return materialize_unwrapped(value[sole.name]) if sole
|
|
85
85
|
|
|
86
|
-
#
|
|
86
|
+
# Not `value.to_h` — `Value#to_h` materializes each field through
|
|
87
87
|
# plain `materialize`, so a VO nested inside a multi-attribute VO
|
|
88
88
|
# would already be a plain Hash by the time this method ever saw
|
|
89
89
|
# it, and never reach the `when self` branch above. Read each
|
|
90
90
|
# field straight off `value` instead, so recursion actually
|
|
91
|
-
# happens through
|
|
91
|
+
# happens through this method the whole way down.
|
|
92
92
|
value.value_object.attributes.to_h { |attr| [attr.name, materialize_unwrapped(value[attr.name])] }
|
|
93
93
|
when Array then value.map { |item| materialize_unwrapped(item) }
|
|
94
94
|
when Hash then value.transform_values { |item| materialize_unwrapped(item) }
|
|
@@ -96,17 +96,17 @@ module Hecks
|
|
|
96
96
|
end
|
|
97
97
|
end
|
|
98
98
|
|
|
99
|
-
#
|
|
99
|
+
# Reduces an append-only sub-log to its current state — the same
|
|
100
100
|
# "a later fact supersedes an earlier one" reduction this runtime
|
|
101
|
-
# already performs replaying an
|
|
101
|
+
# already performs replaying an aggregate's own command history
|
|
102
102
|
# into its current attributes, applied here to a single `list_of`
|
|
103
|
-
#
|
|
103
|
+
# field acting as its own miniature append-only log (a placement
|
|
104
104
|
# history, a tombstone-style soft-delete list, a versioned
|
|
105
105
|
# setting). `rows` is what a `list_of` attribute hands back — an
|
|
106
106
|
# Array of `Value`, in append order — and `key` names the field
|
|
107
107
|
# that identifies "the same logical thing" across entries.
|
|
108
108
|
#
|
|
109
|
-
#
|
|
109
|
+
# **Grouping only, never interpretation**. What counts as "removed,"
|
|
110
110
|
# how to order what survives — that meaning belongs to whichever
|
|
111
111
|
# domain declared the field, never here: a generic reduction that
|
|
112
112
|
# started guessing domain semantics would need to keep guessing
|
|
@@ -119,17 +119,17 @@ module Hecks
|
|
|
119
119
|
def method_missing(name, *args)
|
|
120
120
|
return @fields[name] if @fields.key?(name)
|
|
121
121
|
|
|
122
|
-
#
|
|
122
|
+
# The language rule, not a convenience: any value object with
|
|
123
123
|
# exactly one declared attribute answers `.value`, whatever that
|
|
124
124
|
# attribute is actually named — a single-attribute value object
|
|
125
|
-
# is a
|
|
125
|
+
# is a name for a scalar, not a genuine group
|
|
126
126
|
# ([[feedback_name_the_scalar_field]], `Behaviour::ValueObject#
|
|
127
127
|
# sole_attribute`), so `money.value` reads `Money`'s own `amount`
|
|
128
128
|
# exactly as `label.value` reads a shorthand-declared `value`.
|
|
129
|
-
#
|
|
130
|
-
# literally named `value` is already answered there (and
|
|
129
|
+
# After the real-field lookup above, on purpose: a field
|
|
130
|
+
# literally named `value` is already answered there (and is the
|
|
131
131
|
# sole attribute whenever the count is one), so this branch only
|
|
132
|
-
# ever aliases, never shadows. A
|
|
132
|
+
# ever aliases, never shadows. A multi-attribute value object
|
|
133
133
|
# keeps its NoMethodError — `sole_attribute` answers nil for it,
|
|
134
134
|
# and falling through to `super` is exactly the refusal it
|
|
135
135
|
# always gave: with two or more fields there is no single value
|
|
@@ -151,15 +151,15 @@ module Hecks
|
|
|
151
151
|
|
|
152
152
|
private
|
|
153
153
|
|
|
154
|
-
#
|
|
154
|
+
# **The `.value` alias for indexed access** — the same language rule
|
|
155
155
|
# `method_missing` above enforces for method reads, applied to
|
|
156
156
|
# `[]`/`key?`/`with`: `:value` names a single-attribute value
|
|
157
157
|
# object's sole field whatever that field is actually called. A
|
|
158
|
-
#
|
|
158
|
+
# real key always wins first (a field literally named `value` is
|
|
159
159
|
# its own answer, and is the sole attribute anyway whenever the
|
|
160
160
|
# count is one), so this only ever resolves a `:value` that would
|
|
161
|
-
# otherwise
|
|
162
|
-
# `with(:value, x)` in particular
|
|
161
|
+
# otherwise miss — it can never redirect a genuine field read.
|
|
162
|
+
# `with(:value, x)` in particular needs this: merging a literal
|
|
163
163
|
# `:value` key beside a sole field named `amount` would build a
|
|
164
164
|
# two-key hash for a one-field shape and be refused (or worse,
|
|
165
165
|
# stored) downstream — aliasing at the merge is what keeps the
|
data/lib/hecks/runtime.rb
CHANGED
|
@@ -6,24 +6,24 @@
|
|
|
6
6
|
# declaration is being collected into — sat on the top-level Hecks module
|
|
7
7
|
# beside the DSL words.
|
|
8
8
|
#
|
|
9
|
-
# What lives here is what
|
|
9
|
+
# What lives here is what runs a domain :
|
|
10
10
|
#
|
|
11
11
|
# Runtime.boot(path) load a directory and return its Dispatcher
|
|
12
12
|
# Runtime.with_registry(r) bind the ambient registry for the duration of a load
|
|
13
13
|
# Runtime.current_registry the registry a declaration is landing in, or nil
|
|
14
14
|
#
|
|
15
|
-
# What does
|
|
15
|
+
# What does not live here is what declares one — `Hecks.bluebook`,
|
|
16
16
|
# `.hecksagon`, `.port`, `.adapter`, `.world` are loading words and stay on the
|
|
17
17
|
# top-level module, which now reads as a facade over this.
|
|
18
18
|
#
|
|
19
19
|
# runtime = Hecks::Runtime.boot("examples/pizzas/bluebook")
|
|
20
20
|
# runtime.dispatch("Pizzas::Pizza.CreatePizza", name: "Margherita")
|
|
21
21
|
#
|
|
22
|
-
#
|
|
22
|
+
# Note, and it is the reason this file exists : `current_registry` is still
|
|
23
23
|
# process-global. Each boot builds a fresh Registry, and `Loader.bind_runtime`
|
|
24
|
-
# installs a fresh facade door whose modules close over
|
|
24
|
+
# installs a fresh facade door whose modules close over that boot's dispatcher
|
|
25
25
|
# — no class-level runtime binding remains, so two boots in one process no
|
|
26
|
-
# longer share dispatch state, only the top-level
|
|
26
|
+
# longer share dispatch state, only the top-level name (the last-bound door
|
|
27
27
|
# wins the constant, which is what per-boot install means). Owning the state
|
|
28
28
|
# here was the first move ; the dispatcher reachable per-runtime rather than
|
|
29
29
|
# through a constant was the second, and it is done — the door is the only
|
|
@@ -91,7 +91,7 @@ module Hecks
|
|
|
91
91
|
# the block — who a command's declared `role`, if any, is checked
|
|
92
92
|
# against.
|
|
93
93
|
#
|
|
94
|
-
# `as_of:` is
|
|
94
|
+
# `as_of:` is optional, same opt-in shape as `actor_id:` — a caller
|
|
95
95
|
# that wants a Governance `RoleAssignment`'s `starts_at` enforced
|
|
96
96
|
# passes `as_of: Ports::Clock.now(registry)` here, at the door,
|
|
97
97
|
# exactly where `cli_runner.rb` already merges `Clock.now` into a
|
|
@@ -99,7 +99,7 @@ module Hecks
|
|
|
99
99
|
# itself — see `Ports::Clock`'s own header for why — so an unbound
|
|
100
100
|
# `as_of` leaves `starts_at` unchecked, exactly as before.
|
|
101
101
|
#
|
|
102
|
-
# `scope:` is
|
|
102
|
+
# `scope:` is optional too — a caller that states which scope it is
|
|
103
103
|
# acting in gets that scope checked against the matching
|
|
104
104
|
# `RoleAssignment`'s own `scope`, not just its `role_name`. See
|
|
105
105
|
# `Runtime::Caller::Current`'s own header for why this lives here
|