hecks 2.8.0 → 3.0.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/exe/hecks +50 -7
- data/lib/hecks/adapters/driven/claude_code.rb +4 -104
- data/lib/hecks/adapters/driven/d1.rb +44 -237
- data/lib/hecks/adapters/driven/folder.rb +17 -76
- data/lib/hecks/adapters/driven/google_authentication.rb +15 -49
- data/lib/hecks/adapters/driven/governance_authorization.rb +23 -70
- data/lib/hecks/adapters/driven/heki/journal.rb +8 -41
- data/lib/hecks/adapters/driven/heki/saga_store.rb +12 -54
- data/lib/hecks/adapters/driven/heki/snapshot.rb +4 -12
- data/lib/hecks/adapters/driven/heki.rb +13 -42
- data/lib/hecks/adapters/driven/identity_registry.rb +3 -14
- data/lib/hecks/adapters/driven/in_memory_ordering.rb +9 -26
- data/lib/hecks/adapters/driven/in_process_key_vault.rb +2 -14
- data/lib/hecks/adapters/driven/lambda/client.rb +10 -51
- data/lib/hecks/adapters/driven/lambda.rb +10 -84
- data/lib/hecks/adapters/driven/local_storage.rb +5 -40
- data/lib/hecks/adapters/driven/memory.rb +32 -100
- data/lib/hecks/adapters/driven/mock_stripe_adapter.rb +5 -21
- data/lib/hecks/adapters/driven/postgres/codec.rb +6 -28
- data/lib/hecks/adapters/driven/postgres/outbox.rb +3 -12
- data/lib/hecks/adapters/driven/postgres/reconnect.rb +10 -32
- data/lib/hecks/adapters/driven/postgres/schema_builder.rb +34 -108
- data/lib/hecks/adapters/driven/postgres/shared_connection.rb +180 -0
- data/lib/hecks/adapters/driven/postgres.rb +149 -136
- data/lib/hecks/adapters/driven/postgres_era.adapter +4 -15
- data/lib/hecks/adapters/driven/prism.rb +48 -38
- data/lib/hecks/adapters/driven/sql_query_builder.rb +21 -121
- data/lib/hecks/adapters/driven/sqlite/codec.rb +8 -40
- data/lib/hecks/adapters/driven/sqlite/projection.rb +26 -82
- data/lib/hecks/adapters/driven/sqlite/schema_builder.rb +40 -84
- data/lib/hecks/adapters/driven/sqlite.rb +128 -65
- data/lib/hecks/adapters/driven/tenant_provisioner.rb +76 -62
- data/lib/hecks/adapters/driven.rb +5 -36
- data/lib/hecks/adapters/driving/github_webhook.rb +8 -76
- data/lib/hecks/behaviors/dsl.rb +7 -25
- data/lib/hecks/behaviors/expectations.rb +32 -142
- data/lib/hecks/behaviors/ir.rb +7 -20
- data/lib/hecks/behaviors/rspec.rb +6 -17
- data/lib/hecks/behaviors/runner.rb +10 -34
- data/lib/hecks/behaviors.rb +4 -8
- data/lib/hecks/bench/cli.rb +62 -0
- data/lib/hecks/bench/environment.rb +71 -0
- data/lib/hecks/bench/postgres_probe.rb +30 -0
- data/lib/hecks/bench/report.rb +76 -0
- data/lib/hecks/bench/ruby_runner.rb +93 -0
- data/lib/hecks/bench/run.rb +55 -0
- data/lib/hecks/bench/rust_runner.rb +101 -0
- data/lib/hecks/bench/stats.rb +46 -0
- data/lib/hecks/bench/suite.rb +98 -0
- data/lib/hecks/bench/workload.rb +89 -0
- data/lib/hecks/bench.rb +17 -0
- data/lib/hecks/bluebook/aggregate.rb +9 -75
- data/lib/hecks/bluebook/assembly/aggregate_assembly.rb +9 -38
- data/lib/hecks/bluebook/assembly/build.rb +4 -15
- data/lib/hecks/bluebook/assembly/contract.rb +15 -136
- data/lib/hecks/bluebook/assembly/contracts.rb +56 -174
- data/lib/hecks/bluebook/assembly/marks.rb +31 -223
- data/lib/hecks/bluebook/assembly/specializer.rb +6 -52
- data/lib/hecks/bluebook/assembly.rb +6 -45
- data/lib/hecks/bluebook/attribute.rb +12 -61
- data/lib/hecks/bluebook/behaviour/aggregate.rb +39 -39
- data/lib/hecks/bluebook/behaviour/attribute.rb +3 -14
- data/lib/hecks/bluebook/behaviour/chapter.rb +14 -42
- data/lib/hecks/bluebook/behaviour/command.rb +14 -66
- data/lib/hecks/bluebook/behaviour/domain_port.rb +11 -20
- data/lib/hecks/bluebook/behaviour/entity.rb +7 -27
- data/lib/hecks/bluebook/behaviour/hexagon.rb +23 -41
- data/lib/hecks/bluebook/behaviour/lifecycle.rb +15 -40
- data/lib/hecks/bluebook/behaviour/policy.rb +23 -52
- data/lib/hecks/bluebook/behaviour/process_manager.rb +30 -57
- data/lib/hecks/bluebook/behaviour/read_model.rb +25 -31
- data/lib/hecks/bluebook/behaviour/traits.rb +27 -64
- data/lib/hecks/bluebook/behaviour/value_object.rb +5 -24
- data/lib/hecks/bluebook/capabilities.rb +17 -49
- data/lib/hecks/bluebook/chapter.rb +16 -50
- data/lib/hecks/bluebook/command.rb +23 -81
- data/lib/hecks/bluebook/domain_port.rb +49 -67
- data/lib/hecks/bluebook/dsl/aggregate_builder/sealing.rb +50 -229
- data/lib/hecks/bluebook/dsl/aggregate_builder.rb +50 -377
- data/lib/hecks/bluebook/dsl/attribute_collector.rb +33 -204
- data/lib/hecks/bluebook/dsl/binding_proxy.rb +16 -69
- data/lib/hecks/bluebook/dsl/bluebook_builder/validation.rb +96 -708
- data/lib/hecks/bluebook/dsl/bluebook_builder.rb +63 -169
- data/lib/hecks/bluebook/dsl/bootstrap_table.rb +3 -1
- data/lib/hecks/bluebook/dsl/command_builder.rb +74 -546
- data/lib/hecks/bluebook/dsl/const_shim.rb +8 -41
- data/lib/hecks/bluebook/dsl/domain_port_builder.rb +42 -89
- data/lib/hecks/bluebook/dsl/entity_builder.rb +44 -330
- data/lib/hecks/bluebook/dsl/generic_dispatch.rb +20 -269
- data/lib/hecks/bluebook/dsl/hecksagon_builder.rb +148 -197
- data/lib/hecks/bluebook/dsl/identity_declaration.rb +13 -88
- data/lib/hecks/bluebook/dsl/lifecycle_builder.rb +6 -20
- data/lib/hecks/bluebook/dsl/policy_builder.rb +16 -88
- data/lib/hecks/bluebook/dsl/port_builder.rb +2 -6
- data/lib/hecks/bluebook/dsl/port_operation_builder.rb +22 -96
- data/lib/hecks/bluebook/dsl/process_manager_builder.rb +31 -184
- data/lib/hecks/bluebook/dsl/query_builder.rb +38 -43
- data/lib/hecks/bluebook/dsl/read_model_builder.rb +75 -201
- data/lib/hecks/bluebook/dsl/rule_reference.rb +22 -163
- data/lib/hecks/bluebook/dsl/translation_builder.rb +28 -114
- data/lib/hecks/bluebook/dsl/value_object_builder.rb +10 -124
- data/lib/hecks/bluebook/dsl/word_gate.rb +16 -162
- data/lib/hecks/bluebook/dsl/world_builder.rb +46 -111
- data/lib/hecks/bluebook/entity.rb +13 -71
- data/lib/hecks/bluebook/expression/ast_json.rb +24 -190
- data/lib/hecks/bluebook/expression/ast_reader.rb +12 -54
- data/lib/hecks/bluebook/expression/canonical_form.rb +11 -88
- data/lib/hecks/bluebook/expression/evaluator.rb +47 -295
- data/lib/hecks/bluebook/expression/resolver/block_predicates.rb +30 -147
- data/lib/hecks/bluebook/expression/resolver.rb +39 -661
- data/lib/hecks/bluebook/hexagon.rb +18 -33
- data/lib/hecks/bluebook/lifecycle.rb +5 -16
- data/lib/hecks/bluebook/meta_validator/adapter_judge.rb +1 -7
- data/lib/hecks/bluebook/meta_validator/judge.rb +111 -361
- data/lib/hecks/bluebook/meta_validator/plan.rb +33 -162
- data/lib/hecks/bluebook/meta_validator/port_judge.rb +2 -7
- data/lib/hecks/bluebook/meta_validator/readings.rb +56 -342
- data/lib/hecks/bluebook/meta_validator/reconstruction.rb +25 -176
- data/lib/hecks/bluebook/meta_validator/shapes.rb +53 -267
- data/lib/hecks/bluebook/meta_validator/syntax_boot.rb +47 -306
- data/lib/hecks/bluebook/meta_validator/translation_judge.rb +7 -43
- data/lib/hecks/bluebook/meta_validator/verdict_cache.rb +246 -0
- data/lib/hecks/bluebook/meta_validator/world_judge.rb +6 -18
- data/lib/hecks/bluebook/meta_validator.rb +87 -352
- data/lib/hecks/bluebook/model_check/client_profile.rb +6 -21
- data/lib/hecks/bluebook/model_check.rb +122 -596
- data/lib/hecks/bluebook/pattern_subset.rb +49 -69
- data/lib/hecks/bluebook/process_manager.rb +13 -83
- data/lib/hecks/bluebook/project_loader.rb +3 -39
- data/lib/hecks/bluebook/project_register.rb +12 -60
- data/lib/hecks/bluebook/query.rb +27 -51
- data/lib/hecks/bluebook/read_model.rb +57 -81
- data/lib/hecks/bluebook/reference.rb +7 -41
- data/lib/hecks/bluebook/smoke_test.rb +9 -99
- data/lib/hecks/bluebook/synthesizer.rb +13 -62
- data/lib/hecks/bluebook/translation.rb +26 -62
- data/lib/hecks/bluebook/value_object.rb +11 -36
- data/lib/hecks/bluebook.rb +5 -22
- data/lib/hecks/cache_dir.rb +4 -23
- data/lib/hecks/canonical_json.rb +30 -0
- data/lib/hecks/chapters.rb +102 -0
- data/lib/hecks/cli/behaviors.rb +61 -0
- data/lib/hecks/cli/canonicalise.rb +25 -0
- data/lib/hecks/cli/check_engine_agreement.rb +32 -0
- data/lib/hecks/cli/check_era.rb +88 -0
- data/lib/hecks/cli/console.rb +66 -0
- data/lib/hecks/cli/deploy_template_diff.rb +40 -0
- data/lib/hecks/cli/doc_coverage.rb +32 -0
- data/lib/hecks/cli/document.rb +5 -23
- data/lib/hecks/cli/expression_projection.rb +41 -0
- data/lib/hecks/cli/follow.rb +88 -0
- data/lib/hecks/cli/history.rb +44 -0
- data/lib/hecks/cli/ir.rb +4 -6
- data/lib/hecks/cli/mcp.rb +5 -6
- data/lib/hecks/cli/model_check.rb +24 -88
- data/lib/hecks/cli/pattern_cases.rb +47 -0
- data/lib/hecks/cli/present.rb +39 -0
- data/lib/hecks/cli/project_cli.rb +223 -64
- data/lib/hecks/cli/project_diagrams.rb +4 -10
- data/lib/hecks/cli/project_glossary.rb +44 -0
- data/lib/hecks/cli/reference.rb +46 -0
- data/lib/hecks/cli/refresh_projections.rb +44 -0
- data/lib/hecks/cli/refresh_rspec_runtime_baseline.rb +150 -0
- data/lib/hecks/cli/release.rb +70 -0
- data/lib/hecks/cli/release_gem.rb +59 -0
- data/lib/hecks/cli/rspec_io_parallel_files.rb +137 -0
- data/lib/hecks/cli/rspec_shard_files.rb +66 -0
- data/lib/hecks/cli/run.rb +15 -61
- data/lib/hecks/cli/seed_semantics_corpus.rb +71 -0
- data/lib/hecks/cli/serve_query_ir_mcp.rb +30 -0
- data/lib/hecks/cli/shape.rb +70 -0
- data/lib/hecks/cli/smoke_http.rb +230 -0
- data/lib/hecks/cli/smoke_test.rb +7 -19
- data/lib/hecks/cli/spec_example.rb +27 -0
- data/lib/hecks/cli/statements.rb +32 -0
- data/lib/hecks/cli/stores.rb +4 -6
- data/lib/hecks/cli/stress_concurrency_specs.rb +177 -0
- data/lib/hecks/cli.rb +216 -73
- data/lib/hecks/codemod.rb +324 -0
- data/lib/hecks/construct.rb +8 -34
- data/lib/hecks/corpus.rb +423 -0
- data/lib/hecks/deploy/bluebook/deploy.bluebook +617 -158
- data/lib/hecks/deploy/bluebook/deploy.hecksagon +41 -11
- data/lib/hecks/deploy/oidc.json +82 -2
- data/lib/hecks/doc/reference.rb +351 -0
- data/lib/hecks/doors/cli_door.rb +196 -0
- data/lib/hecks/doors/cli_runner.rb +297 -0
- data/lib/hecks/{facade → doors}/command_request.rb +14 -34
- data/lib/hecks/doors/handle.rb +206 -0
- data/lib/hecks/doors/json_door.rb +132 -0
- data/lib/hecks/doors/launcher_options.rb +129 -0
- data/lib/hecks/{cli → doors}/mcp_door.rb +25 -120
- data/lib/hecks/doors/mcp_door_scope.rb +97 -0
- data/lib/hecks/doors/ruby_door/aggregate_door.rb +162 -0
- data/lib/hecks/doors/ruby_door/chapter.rb +72 -0
- data/lib/hecks/doors/ruby_door.rb +77 -0
- data/lib/hecks/doors.rb +61 -0
- data/lib/hecks/embryonaut_bluebook/lock.rb +3 -35
- data/lib/hecks/embryonaut_bluebook/shape.rb +1 -17
- data/lib/hecks/embryonaut_bluebook/vendor.rb +8 -53
- data/lib/hecks/embryonaut_bluebook/vendor_cli.rb +4 -19
- data/lib/hecks/embryonaut_bluebook.rb +5 -72
- data/lib/hecks/engine_agreement.rb +156 -0
- data/lib/hecks/facade.rb +23 -51
- data/lib/hecks/forms/app.rb +21 -76
- data/lib/hecks/forms/banking_presentation.rb +50 -0
- data/lib/hecks/forms/command_form_renderer.rb +10 -29
- data/lib/hecks/forms/field_renderer.rb +17 -156
- data/lib/hecks/forms/field_shape.rb +31 -222
- data/lib/hecks/forms/html.rb +12 -47
- data/lib/hecks/forms/index_renderer.rb +1 -4
- data/lib/hecks/forms/page.rb +3 -9
- data/lib/hecks/forms/params.rb +14 -60
- data/lib/hecks/forms/port_argument.rb +2 -19
- data/lib/hecks/forms/query_form_renderer.rb +4 -79
- data/lib/hecks/forms/record_renderer.rb +8 -75
- data/lib/hecks/forms/record_table.rb +7 -50
- data/lib/hecks/forms/reference_options.rb +3 -30
- data/lib/hecks/forms/value_object_shape.rb +8 -35
- data/lib/hecks/forms.rb +5 -33
- data/lib/hecks/fqn.rb +5 -12
- data/lib/hecks/framework/bluebook/compliance.bluebook +16 -65
- data/lib/hecks/framework/bluebook/console_settings.bluebook +47 -134
- data/lib/hecks/framework/bluebook/framework.hecksagon +5 -14
- data/lib/hecks/framework/bluebook/governance.bluebook +13 -34
- data/lib/hecks/framework/bluebook/identity.bluebook +11 -26
- data/lib/hecks/framework/bluebook/privacy.bluebook +8 -33
- data/lib/hecks/framework.rb +11 -80
- data/lib/hecks/freezer.rb +5 -39
- data/lib/hecks/fuzzing/bounded_exhaustive_expressions.rb +393 -0
- data/lib/hecks/fuzzing/combination_miner.rb +86 -0
- data/lib/hecks/fuzzing/concurrent_dispatch.rb +214 -0
- data/lib/hecks/fuzzing/coverage_campaign.rb +143 -0
- data/lib/hecks/fuzzing/differential.rb +156 -0
- data/lib/hecks/fuzzing/domain_generator.rb +615 -0
- data/lib/hecks/fuzzing/era_boundary.rb +71 -0
- data/lib/hecks/fuzzing/form_census.rb +136 -0
- data/lib/hecks/fuzzing/generated_domain_check.rb +93 -0
- data/lib/hecks/fuzzing/invalid_value_generator.rb +64 -0
- data/lib/hecks/fuzzing/isolated_boot.rb +301 -0
- data/lib/hecks/fuzzing/nondeterministic.rb +51 -0
- data/lib/hecks/fuzzing/outside_world.rb +45 -0
- data/lib/hecks/fuzzing/persistence_parity.rb +102 -0
- data/lib/hecks/fuzzing/properties/corrections.rb +88 -0
- data/lib/hecks/fuzzing/properties/dispatch_and_mutations.rb +314 -0
- data/lib/hecks/fuzzing/properties/guards.rb +190 -0
- data/lib/hecks/fuzzing/properties/invariants_and_aggregation.rb +300 -0
- data/lib/hecks/fuzzing/properties/lifecycle_and_replay.rb +93 -0
- data/lib/hecks/fuzzing/properties/outbox.rb +89 -0
- data/lib/hecks/fuzzing/properties/querying.rb +175 -0
- data/lib/hecks/fuzzing/properties.rb +162 -0
- data/lib/hecks/fuzzing/qa_settings.rb +123 -0
- data/lib/hecks/fuzzing/replay.rb +505 -0
- data/lib/hecks/fuzzing/rotation_priority.rb +48 -0
- data/lib/hecks/fuzzing/rust_gap_manifest.rb +108 -0
- data/lib/hecks/fuzzing/self_consistency.rb +339 -0
- data/lib/hecks/fuzzing/sequence_generator/adversary.rb +385 -0
- data/lib/hecks/fuzzing/sequence_generator/catalog.rb +132 -0
- data/lib/hecks/fuzzing/sequence_generator/outcome_tracker.rb +95 -0
- data/lib/hecks/fuzzing/sequence_generator/picker.rb +77 -0
- data/lib/hecks/fuzzing/sequence_generator/query_binding.rb +109 -0
- data/lib/hecks/fuzzing/sequence_generator/step_builder.rb +237 -0
- data/lib/hecks/fuzzing/sequence_generator.rb +189 -0
- data/lib/hecks/fuzzing/shrinker.rb +166 -0
- data/lib/hecks/fuzzing/structural_skips.rb +33 -0
- data/lib/hecks/fuzzing/sweep_depth.rb +43 -0
- data/lib/hecks/fuzzing/target_capabilities.rb +163 -0
- data/lib/hecks/fuzzing/value_generator.rb +216 -0
- data/lib/hecks/fuzzing.rb +23 -0
- data/lib/hecks/grammar/evolve.rb +336 -0
- data/lib/hecks/grammar/expression.bluebook +15 -40
- data/lib/hecks/grammar/translation.bluebook +3 -6
- data/lib/hecks/grammar.rb +16 -41
- data/lib/hecks/hecks/adapters/codebase/codemods.rb +45 -0
- data/lib/hecks/hecks/adapters/codebase/conformance.rb +71 -0
- data/lib/hecks/hecks/adapters/codebase/corpus_tasks.rb +202 -0
- data/lib/hecks/hecks/adapters/codebase/gem_registry.rb +80 -0
- data/lib/hecks/hecks/adapters/codebase/kernel_tables.rb +54 -0
- data/lib/hecks/hecks/adapters/codebase/language.rb +240 -0
- data/lib/hecks/hecks/adapters/codebase/npm_registry.rb +102 -0
- data/lib/hecks/hecks/adapters/codebase/publishing.rb +142 -0
- data/lib/hecks/hecks/adapters/codebase/regeneration.rb +67 -0
- data/lib/hecks/hecks/adapters/codebase/release_facts.rb +90 -0
- data/lib/hecks/hecks/adapters/codebase/ruby_child.rb +83 -0
- data/lib/hecks/hecks/adapters/codebase/secret_vault.rb +36 -0
- data/lib/hecks/hecks/adapters/codebase/source_tree.adapter +7 -0
- data/lib/hecks/hecks/adapters/codebase/source_tree.rb +189 -0
- data/lib/hecks/hecks/adapters/codebase/sqlite_fixture.rb +71 -0
- data/lib/hecks/hecks/adapters/codebase/style.rb +171 -0
- data/lib/hecks/hecks/adapters/codebase/test_runner.rb +55 -0
- data/lib/hecks/hecks/adapters/codebase/test_suite.rb +165 -0
- data/lib/hecks/hecks/adapters/codebase/tree.rb +111 -0
- data/lib/hecks/hecks/adapters/console_capture.rb +79 -0
- data/lib/hecks/hecks/adapters/deploy_toolchain.adapter +7 -0
- data/lib/hecks/hecks/adapters/deploy_toolchain.rb +108 -0
- data/lib/hecks/hecks/adapters/git.adapter +7 -0
- data/lib/hecks/hecks/adapters/git.rb +102 -0
- data/lib/hecks/hecks/adapters/host_http.adapter +7 -0
- data/lib/hecks/hecks/adapters/host_http.rb +65 -0
- data/lib/hecks/hecks/adapters/in_process_boot.adapter +7 -0
- data/lib/hecks/hecks/adapters/in_process_boot.rb +197 -0
- data/lib/hecks/hecks/adapters/in_process_operations.rb +202 -0
- data/lib/hecks/hecks/adapters/journal_store/changes.rb +143 -0
- data/lib/hecks/hecks/adapters/journal_store/compaction.rb +145 -0
- data/lib/hecks/hecks/adapters/journal_store/edge_audit.rb +132 -0
- data/lib/hecks/hecks/adapters/journal_store/examination.rb +135 -0
- data/lib/hecks/hecks/adapters/journal_store/held_domain.rb +163 -0
- data/lib/hecks/hecks/adapters/journal_store/readings.rb +187 -0
- data/lib/hecks/hecks/adapters/journal_store.adapter +7 -0
- data/lib/hecks/hecks/adapters/journal_store.rb +64 -0
- data/lib/hecks/hecks/adapters/local_files.adapter +7 -0
- data/lib/hecks/hecks/adapters/local_files.rb +46 -0
- data/lib/hecks/hecks/adapters/pg_admin.adapter +7 -0
- data/lib/hecks/hecks/adapters/pg_admin.rb +245 -0
- data/lib/hecks/hecks/adapters/process_pool.adapter +7 -0
- data/lib/hecks/hecks/adapters/process_pool.rb +119 -0
- data/lib/hecks/hecks/adapters/rust_toolchain.adapter +7 -0
- data/lib/hecks/hecks/adapters/rust_toolchain.rb +179 -0
- data/lib/hecks/hecks/adapters/rust_workspace.rb +150 -0
- data/lib/hecks/hecks/adapters/shell.adapter +7 -0
- data/lib/hecks/hecks/adapters/shell.rb +49 -0
- data/lib/hecks/hecks/adapters/terminal.adapter +7 -0
- data/lib/hecks/hecks/adapters/terminal.rb +74 -0
- data/lib/hecks/hecks/codebase.behaviors +172 -0
- data/lib/hecks/hecks/codebase.bluebook +2453 -0
- data/lib/hecks/hecks/context_map.hecksagon +13 -0
- data/lib/hecks/hecks/custodian.behaviors +179 -0
- data/lib/hecks/hecks/custodian.bluebook +1847 -0
- data/lib/hecks/hecks/deploy.behaviors +74 -0
- data/lib/hecks/hecks/deploy.world +12 -0
- data/lib/hecks/hecks/environments/memory.world +10 -0
- data/lib/hecks/hecks/governance.world +7 -0
- data/lib/hecks/hecks/hecks.behaviors +62 -0
- data/lib/hecks/hecks/hecks.bluebook +124 -0
- data/lib/hecks/hecks/hecks.hecksagon +390 -0
- data/lib/hecks/hecks/hecks.world +42 -0
- data/lib/hecks/ir.rb +14 -83
- data/lib/hecks/kernel_capabilities.rb +194 -0
- data/lib/hecks/language/adapter.bluebook +2 -7
- data/lib/hecks/language/bluebook/aggregate.bluebook +56 -221
- data/lib/hecks/language/bluebook/attaches/paging.bluebook +6 -15
- data/lib/hecks/language/bluebook/bluebook.bluebook +26 -83
- data/lib/hecks/language/bluebook/bluebook.hecksagon +3 -15
- data/lib/hecks/language/bluebook/command.bluebook +27 -144
- data/lib/hecks/language/bluebook/entity.bluebook +24 -97
- data/lib/hecks/language/bluebook/policy.bluebook +16 -67
- data/lib/hecks/language/bluebook/process_manager.bluebook +28 -151
- data/lib/hecks/language/bluebook/projection.bluebook +126 -60
- data/lib/hecks/language/bluebook/query.bluebook +19 -43
- data/lib/hecks/language/bluebook/shape.bluebook +23 -73
- data/lib/hecks/language/bluebook/syntax.bluebook +51 -262
- data/lib/hecks/language/bluebook/vocabulary.bluebook +83 -198
- data/lib/hecks/language/hecksagon/adapter_binding.bluebook +3 -10
- data/lib/hecks/language/hecksagon/domain_port.bluebook +14 -19
- data/lib/hecks/language/hecksagon/hecksagon.bluebook +26 -25
- data/lib/hecks/language/hecksagon/port_operation.bluebook +3 -14
- data/lib/hecks/language/oidc.json +35 -0
- data/lib/hecks/language/port.bluebook +4 -17
- data/lib/hecks/language/translation/translation.bluebook +3 -9
- data/lib/hecks/language/translation/translation_aggregate.bluebook +5 -24
- data/lib/hecks/language/world/wiring.bluebook +1 -3
- data/lib/hecks/language/world/world.bluebook +5 -7
- data/lib/hecks/literal.rb +8 -50
- data/lib/hecks/mcp_stdio_guard.rb +4 -41
- data/lib/hecks/naming.rb +29 -137
- data/lib/hecks/persistence_legacy_fixture/regenerate.rb +161 -0
- data/lib/hecks/persistence_legacy_fixture.rb +113 -0
- data/lib/hecks/ports/access_control.rb +7 -23
- data/lib/hecks/ports/agent/answers.rb +5 -23
- data/lib/hecks/ports/agent.rb +47 -172
- data/lib/hecks/ports/authentication.rb +12 -39
- data/lib/hecks/ports/authorization.rb +16 -43
- data/lib/hecks/ports/clock.rb +5 -45
- data/lib/hecks/ports/extraction.rb +7 -12
- data/lib/hecks/ports/identity_assignment.rb +8 -29
- data/lib/hecks/ports/identity_generation.rb +6 -29
- data/lib/hecks/ports/identity_resolution.rb +2 -10
- data/lib/hecks/ports/key_vault.rb +9 -45
- data/lib/hecks/ports/persistence/append_only.rb +61 -64
- data/lib/hecks/ports/persistence/binding_policy.rb +4 -14
- data/lib/hecks/ports/persistence/codec_boundary.rb +20 -80
- data/lib/hecks/ports/persistence/null_saga_store.rb +4 -20
- data/lib/hecks/ports/persistence/plugin.rb +13 -42
- data/lib/hecks/ports/persistence/plugins/era/era_check.rb +44 -144
- data/lib/hecks/ports/persistence/plugins/era/era_guard/shape_diff.rb +15 -115
- data/lib/hecks/ports/persistence/plugins/era/era_guard.rb +20 -85
- data/lib/hecks/ports/persistence/plugins/era/era_tamper.rb +6 -25
- data/lib/hecks/ports/persistence/plugins/era/expected_era.rb +18 -24
- data/lib/hecks/ports/persistence/plugins/era/lineage.rb +55 -181
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/events.rb +77 -0
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/era_store.rb +12 -122
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/field_cache.rb +28 -128
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/head_compiler.rb +73 -474
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/mint_transaction.rb +31 -124
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/provisioning.rb +45 -219
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/resumable_backfill.rb +13 -108
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/tail_merge.rb +19 -76
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/transform_installer.rb +9 -49
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage.rb +6 -123
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/coverage_check.rb +23 -55
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/era_resolver.rb +14 -72
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/merge_coordinator.rb +7 -16
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/minter.rb +43 -127
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager.rb +13 -45
- data/lib/hecks/ports/persistence/plugins/era/postgres_era.rb +131 -555
- data/lib/hecks/ports/persistence/plugins/era/storage_shape.rb +13 -63
- data/lib/hecks/ports/persistence/plugins/era/translation/approval_file.rb +227 -0
- data/lib/hecks/ports/persistence/plugins/era/translation/audit/approval_digest.rb +2 -17
- data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_one.rb +3 -14
- data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_two.rb +13 -58
- data/lib/hecks/ports/persistence/plugins/era/translation/audit/unfed_report.rb +3 -17
- data/lib/hecks/ports/persistence/plugins/era/translation/audit.rb +9 -26
- data/lib/hecks/ports/persistence/plugins/era/translation/reattest.rb +50 -47
- data/lib/hecks/ports/persistence/plugins/era/translation/rule_compiler.rb +18 -124
- data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/differ.rb +34 -123
- data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/renderer.rb +5 -12
- data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/writer.rb +3 -9
- data/lib/hecks/ports/persistence/plugins/era/translation/scaffold.rb +2 -14
- data/lib/hecks/ports/persistence/plugins/era/translation.rb +1 -0
- data/lib/hecks/ports/persistence/plugins/era.rb +4 -23
- data/lib/hecks/ports/persistence/postgres_dump/connection.rb +7 -23
- data/lib/hecks/ports/persistence/postgres_dump.rb +4 -35
- data/lib/hecks/ports/persistence/remote_runtime.rb +2 -24
- data/lib/hecks/ports/persistence/repository_factory.rb +8 -27
- data/lib/hecks/ports/persistence/state_codec.rb +47 -108
- data/lib/hecks/ports/persistence.rb +7 -14
- data/lib/hecks/ports/projection.rb +42 -84
- data/lib/hecks/ports/query/in_memory.rb +10 -58
- data/lib/hecks/ports/query/ordering.rb +11 -32
- data/lib/hecks/ports/query.rb +14 -37
- data/lib/hecks/ports.rb +2 -8
- data/lib/hecks/projection_files.rb +285 -0
- data/lib/hecks/projections/bootstrap_table.rb +12 -44
- data/lib/hecks/projections/deploy/fargate/assembly.rb +2 -15
- data/lib/hecks/projections/deploy/fargate/cdn.rb +1 -48
- data/lib/hecks/projections/deploy/fargate/cdn_default.rb +2 -11
- data/lib/hecks/projections/deploy/fargate/check.rb +5 -14
- data/lib/hecks/projections/deploy/fargate/containers.rb +3 -78
- data/lib/hecks/projections/deploy/fargate/extras.rb +3 -44
- data/lib/hecks/projections/deploy/fargate/monitoring.rb +0 -44
- data/lib/hecks/projections/deploy/fargate/settings.rb +2 -54
- data/lib/hecks/projections/deploy/fargate/yaml.rb +13 -58
- data/lib/hecks/projections/deploy/fargate.rb +40 -207
- data/lib/hecks/projections/deploy/lambda.rb +191 -708
- data/lib/hecks/projections/deploy/preview/access_yaml.rb +1 -33
- data/lib/hecks/projections/deploy/preview/containers.rb +6 -111
- data/lib/hecks/projections/deploy/preview/preview.sh.erb +1 -1
- data/lib/hecks/projections/deploy/preview/routing_yaml.rb +4 -56
- data/lib/hecks/projections/deploy/preview/script.rb +2 -14
- data/lib/hecks/projections/deploy/preview/settings.rb +3 -33
- data/lib/hecks/projections/deploy/preview/task_yaml.rb +2 -38
- data/lib/hecks/projections/deploy/preview/template.rb +3 -59
- data/lib/hecks/projections/deploy/preview.rb +2 -67
- data/lib/hecks/projections/deploy/scripts/deploy-service.sh.tmpl +1 -1
- data/lib/hecks/projections/deploy/scripts/expected-era.header +1 -1
- data/lib/hecks/projections/deploy/scripts/hosting.mk.tmpl +3 -3
- data/lib/hecks/projections/deploy/scripts/settings.rb +3 -25
- data/lib/hecks/projections/deploy/scripts/smoke-after-deploy.sh.tmpl +1 -1
- data/lib/hecks/projections/deploy/scripts.rb +4 -57
- data/lib/hecks/projections/deploy/shared.rb +48 -147
- data/lib/hecks/projections/deploy/smoke.rb +4 -61
- data/lib/hecks/projections/deploy/template_diff/comparer.rb +3 -25
- data/lib/hecks/projections/deploy/template_diff/loader.rb +2 -11
- data/lib/hecks/projections/deploy/template_diff.rb +5 -57
- data/lib/hecks/projections/diagrams.rb +22 -584
- data/lib/hecks/projections/glossary/html.rb +14 -130
- data/lib/hecks/projections/glossary/markdown.rb +8 -69
- data/lib/hecks/projections/glossary/mermaid.rb +9 -66
- data/lib/hecks/projections/glossary/sensitivity.rb +5 -34
- data/lib/hecks/projections/glossary/sentences.rb +14 -159
- data/lib/hecks/projections/glossary.rb +30 -222
- data/lib/hecks/projections/ir.rb +3 -10
- data/lib/hecks/projections/model/deviations.rb +16 -43
- data/lib/hecks/projections/model.rb +12 -51
- data/lib/hecks/projections/oidc.rb +12 -56
- data/lib/hecks/projections/parser_table.rb +13 -32
- data/lib/hecks/projections/reference.rb +4 -18
- data/lib/hecks/projections/rust_vocabulary.rb +13 -251
- data/lib/hecks/projections/shape.rb +3 -29
- data/lib/hecks/projections/statements.rb +7 -86
- data/lib/hecks/projections/vocabulary.rb +6 -22
- data/lib/hecks/projections.rb +2 -16
- data/lib/hecks/projector/cli_projector.rb +154 -400
- data/lib/hecks/projector/docs_projector.rb +10 -201
- data/lib/hecks/projector/exporter.rb +42 -134
- data/lib/hecks/projector/ir_projector.rb +2 -9
- data/lib/hecks/projector/narrate_projector.rb +15 -189
- data/lib/hecks/projector/target.rb +13 -76
- data/lib/hecks/projector.rb +30 -121
- data/lib/hecks/quality_control/adapters/agent.adapter +7 -0
- data/lib/hecks/quality_control/adapters/agent.rb +58 -0
- data/lib/hecks/quality_control/adapters/angle_tools.adapter +7 -0
- data/lib/hecks/quality_control/adapters/angle_tools.rb +15 -0
- data/lib/hecks/quality_control/adapters/clearance_recorder.rb +36 -0
- data/lib/hecks/quality_control/adapters/clearance_tools.adapter +7 -0
- data/lib/hecks/quality_control/adapters/clearance_tools.rb +17 -0
- data/lib/hecks/quality_control/adapters/git_pr.adapter +7 -0
- data/lib/hecks/quality_control/adapters/git_pr.rb +226 -0
- data/lib/hecks/quality_control/adapters/github_checks.adapter +9 -0
- data/lib/hecks/quality_control/adapters/github_checks.rb +83 -0
- data/lib/hecks/quality_control/adapters/github_ci_webhook.rb +56 -0
- data/lib/hecks/quality_control/adapters/github_issues.adapter +7 -0
- data/lib/hecks/quality_control/adapters/github_issues.rb +49 -0
- data/lib/hecks/quality_control/adapters/qa_tool.rb +59 -0
- data/lib/hecks/quality_control/adapters/sweep_tools.adapter +7 -0
- data/lib/hecks/quality_control/adapters/sweep_tools.rb +51 -0
- data/lib/hecks/quality_control/adapters/target_tools.adapter +7 -0
- data/lib/hecks/quality_control/adapters/target_tools.rb +43 -0
- data/lib/hecks/quality_control/cli/child.rb +45 -0
- data/lib/hecks/quality_control/cli/qa_concurrency_racer.rb +45 -0
- data/lib/hecks/quality_control/cli/qa_discover_external_domains.rb +248 -0
- data/lib/hecks/quality_control/cli/qa_domain_novelty.rb +163 -0
- data/lib/hecks/quality_control/cli/qa_generated_domains.rb +450 -0
- data/lib/hecks/quality_control/cli/qa_log_bug.rb +195 -0
- data/lib/hecks/quality_control/cli/qa_mine_combinations.rb +220 -0
- data/lib/hecks/quality_control/cli/qa_open_pr.rb +305 -0
- data/lib/hecks/quality_control/cli/qa_postgres_migrate.rb +154 -0
- data/lib/hecks/quality_control/cli/qa_postgres_role.rb +159 -0
- data/lib/hecks/quality_control/cli/qa_pr_check.rb +232 -0
- data/lib/hecks/quality_control/cli/qa_seed_angles.rb +142 -0
- data/lib/hecks/quality_control/cli/qa_seed_targets.rb +69 -0
- data/lib/hecks/quality_control/cli/qa_sweep/all_mode.rb +280 -0
- data/lib/hecks/quality_control/cli/qa_sweep/checks.rb +329 -0
- data/lib/hecks/quality_control/cli/qa_sweep/dials.rb +92 -0
- data/lib/hecks/quality_control/cli/qa_sweep/finding_report.rb +117 -0
- data/lib/hecks/quality_control/cli/qa_sweep/parsing.rb +175 -0
- data/lib/hecks/quality_control/cli/qa_sweep/release_mode.rb +60 -0
- data/lib/hecks/quality_control/cli/qa_sweep.rb +611 -0
- data/lib/hecks/quality_control/cli/qa_tick.rb +274 -0
- data/lib/hecks/quality_control/quality_control.bluebook +2224 -0
- data/lib/hecks/quality_control/quality_control.hecksagon +13 -0
- data/lib/hecks/quality_control/quality_control.ports.hecksagon +54 -0
- data/lib/hecks/query_ir.rb +346 -0
- data/lib/hecks/query_ir_mcp.rb +198 -0
- data/lib/hecks/query_specification/common/comparators.rb +5 -26
- data/lib/hecks/query_specification/common/comparison.rb +35 -143
- data/lib/hecks/query_specification/common/dsl.rb +8 -24
- data/lib/hecks/query_specification/common/null_policy.rb +20 -70
- data/lib/hecks/query_specification/common/options.rb +2 -6
- data/lib/hecks/query_specification/common/where_clause.rb +2 -10
- data/lib/hecks/query_specification/field_path.rb +37 -77
- data/lib/hecks/query_specification/hop_path.rb +12 -76
- data/lib/hecks/release/gem_pin.rb +2 -26
- data/lib/hecks/release/runner/ci_publisher.rb +5 -8
- data/lib/hecks/release/runner/clean_tree.rb +42 -0
- data/lib/hecks/release/runner/commands.rb +2 -4
- data/lib/hecks/release/runner/console.rb +6 -0
- data/lib/hecks/release/runner/gem_publisher.rb +15 -9
- data/lib/hecks/release/runner/npm_publisher.rb +9 -53
- data/lib/hecks/release/runner/preflight.rb +29 -20
- data/lib/hecks/release/runner/published.rb +8 -26
- data/lib/hecks/release/runner/tagger.rb +31 -23
- data/lib/hecks/release/runner.rb +60 -38
- data/lib/hecks/rendering.rb +4 -26
- data/lib/hecks/router/namespace_installer.rb +15 -39
- data/lib/hecks/router.rb +4 -8
- data/lib/hecks/runtime/adapter_lookup.rb +124 -0
- data/lib/hecks/runtime/aggregate_lock.rb +8 -33
- data/lib/hecks/runtime/boot_gates.rb +3 -18
- data/lib/hecks/runtime/caller.rb +19 -59
- data/lib/hecks/runtime/capability_graph.rb +5 -21
- data/lib/hecks/runtime/command_interpreter/argument_gate.rb +16 -78
- data/lib/hecks/runtime/command_interpreter/mutation_applier.rb +27 -160
- data/lib/hecks/runtime/command_interpreter.rb +124 -306
- data/lib/hecks/runtime/command_rules/admissibility.rb +95 -366
- data/lib/hecks/runtime/command_rules/arithmetic.rb +66 -196
- data/lib/hecks/runtime/command_rules/authorization.rb +13 -45
- data/lib/hecks/runtime/command_rules/emission.rb +8 -21
- data/lib/hecks/runtime/command_rules/references.rb +23 -202
- data/lib/hecks/runtime/dependency_planning.rb +50 -104
- data/lib/hecks/runtime/dispatcher.rb +134 -243
- data/lib/hecks/runtime/entity_element.rb +40 -462
- data/lib/hecks/runtime/entity_interpreter.rb +64 -219
- data/lib/hecks/runtime/errors.rb +32 -115
- data/lib/hecks/runtime/event.rb +3 -25
- data/lib/hecks/runtime/identity.rb +18 -154
- data/lib/hecks/runtime/instance.rb +18 -150
- data/lib/hecks/runtime/interpreting.rb +14 -70
- data/lib/hecks/runtime/invocation.rb +28 -164
- data/lib/hecks/runtime/loader.rb +109 -194
- data/lib/hecks/runtime/outbox.rb +39 -262
- data/lib/hecks/runtime/policy_interpreter.rb +43 -202
- data/lib/hecks/runtime/port_operation_interpreter.rb +28 -97
- data/lib/hecks/runtime/query_interpreter.rb +122 -187
- data/lib/hecks/runtime/reaction_invocation.rb +36 -138
- data/lib/hecks/runtime/reaction_outcome.rb +89 -0
- data/lib/hecks/runtime/read_model_interpreter.rb +117 -208
- data/lib/hecks/runtime/rebuild_sweep.rb +8 -54
- data/lib/hecks/runtime/reference_hop.rb +8 -81
- data/lib/hecks/runtime/refusal_wording.rb +28 -87
- data/lib/hecks/runtime/registry/saga_persistence.rb +10 -102
- data/lib/hecks/runtime/registry/verification.rb +213 -227
- data/lib/hecks/runtime/registry/world_defaults.rb +4 -53
- data/lib/hecks/runtime/registry.rb +156 -247
- data/lib/hecks/runtime/remote_dispatcher.rb +68 -154
- data/lib/hecks/runtime/routing.rb +4 -15
- data/lib/hecks/runtime/saga_interpreter/correlation.rb +14 -61
- data/lib/hecks/runtime/saga_interpreter.rb +79 -263
- data/lib/hecks/runtime/saga_pending_dispatch.rb +2 -43
- data/lib/hecks/runtime/tenant_check.rb +6 -68
- data/lib/hecks/runtime/tenant_scope.rb +3 -28
- data/lib/hecks/runtime/value/admission.rb +16 -67
- data/lib/hecks/runtime/value/coercion.rb +162 -760
- data/lib/hecks/runtime/value/entity_list_coercion.rb +26 -219
- data/lib/hecks/runtime/value/field_checks.rb +172 -0
- data/lib/hecks/runtime/value.rb +15 -84
- data/lib/hecks/runtime.rb +35 -69
- data/lib/hecks/rust_build/conformance.rb +158 -0
- data/lib/hecks/rust_build/conformance_fuzz.rb +71 -0
- data/lib/hecks/rust_build/coverage.rb +218 -0
- data/lib/hecks/rust_build/native_build.rb +124 -0
- data/lib/hecks/rust_build/project_rust/root_mod.rb +120 -0
- data/lib/hecks/rust_build/project_rust.rb +332 -0
- data/lib/hecks/rust_build/wasm.rb +105 -0
- data/lib/hecks/rust_build/wasm_browser.rb +113 -0
- data/lib/hecks/rust_build.rb +144 -0
- data/lib/hecks/storehouse.rb +155 -582
- data/lib/hecks/tenancy/bluebook/tenancy.bluebook +10 -34
- data/lib/hecks/tenancy/bluebook/tenancy.hecksagon +6 -23
- data/lib/hecks/three_zero/forms.yml +127 -0
- data/lib/hecks/three_zero.rb +12 -0
- data/lib/hecks/tools/argument_gate_matrix.rb +316 -0
- data/lib/hecks/tools/comment_style.rb +1070 -0
- data/lib/hecks/tools/corpus_report.rb +87 -0
- data/lib/hecks/tools/deploy_recipe.rb +255 -0
- data/lib/hecks/tools/deploy_recipe_lint.rb +282 -0
- data/lib/hecks/tools/drop_implicit_append_fields.rb +95 -0
- data/lib/hecks/tools/era_projection_backfill.rb +94 -0
- data/lib/hecks/tools/era_reattest.rb +146 -0
- data/lib/hecks/tools/evolve_run.rb +189 -0
- data/lib/hecks/tools/fuzz_sweep.rb +373 -0
- data/lib/hecks/tools/heki_compaction.rb +100 -0
- data/lib/hecks/tools/hoist_local_givens.rb +246 -0
- data/lib/hecks/tools/journal_compaction.rb +89 -0
- data/lib/hecks/tools/oidc_manifests.rb +70 -0
- data/lib/hecks/tools/query_ir_run.rb +81 -0
- data/lib/hecks/tools/regeneration_run.rb +166 -0
- data/lib/hecks/tools/rust_comment_style.rb +642 -0
- data/lib/hecks/tools/sequence_script.rb +62 -0
- data/lib/hecks/tools/tail_merge.rb +117 -0
- data/lib/hecks/tools/tenant_provisioning.rb +142 -0
- data/lib/hecks/tools/translation_audit.rb +208 -0
- data/lib/hecks/tools/translation_scaffold.rb +131 -0
- data/lib/hecks/tools.rb +86 -0
- data/lib/hecks/vendoring/git_environment.rb +2 -8
- data/lib/hecks/vendoring/git_source.rb +4 -10
- data/lib/hecks/vendoring.rb +7 -46
- data/lib/hecks/version.rb +3 -14
- data/lib/hecks.rb +52 -90
- data/lib/rubocop/cop/hecks/fallback_hash_lookup.rb +8 -46
- data/lib/rubocop/cop/hecks/sequential_hash_rename_in_loop.rb +11 -80
- data/lib/rubocop/cop/hecks/thread_shared_ivar_mutation.rb +10 -99
- data/qa/settings.yml +66 -0
- data/rust/.cargo/config.toml +6 -0
- data/rust/.gitignore +2 -0
- data/rust/Cargo.lock +54 -0
- data/rust/Cargo.toml +61 -0
- data/rust/build/.cargo/config.toml +3 -0
- data/rust/build/.gitignore +1 -0
- data/rust/build/Cargo.lock +7 -0
- data/rust/build/Cargo.toml +19 -0
- data/rust/build/src/build_artifact.rs +47 -0
- data/rust/build/src/cargo_sync.rs +248 -0
- data/rust/build/src/json.rs +421 -0
- data/rust/build/src/lineage_pass.rs +285 -0
- data/rust/build/src/main.rs +51 -0
- data/rust/build/src/optional_pass.rs +150 -0
- data/rust/build/src/pipeline.rs +264 -0
- data/rust/build/src/reserved_names.rs +76 -0
- data/rust/build/src/resolve.rs +124 -0
- data/rust/build/src/root.rs +25 -0
- data/rust/build/src/sidecars.rs +73 -0
- data/rust/build/src/subprocess.rs +51 -0
- data/rust/build/src/tmp.rs +31 -0
- data/rust/codegen/.cargo/config.toml +3 -0
- data/rust/codegen/.gitignore +1 -0
- data/rust/codegen/Cargo.lock +7 -0
- data/rust/codegen/Cargo.toml +20 -0
- data/rust/codegen/src/attr.rs +32 -0
- data/rust/codegen/src/bridging.rs +481 -0
- data/rust/codegen/src/commands.rs +1226 -0
- data/rust/codegen/src/constraints.rs +109 -0
- data/rust/codegen/src/dependency_planning.rs +209 -0
- data/rust/codegen/src/domain_generator.rs +1288 -0
- data/rust/codegen/src/exemplar.rs +230 -0
- data/rust/codegen/src/expr_emitter.rs +87 -0
- data/rust/codegen/src/fielded.rs +192 -0
- data/rust/codegen/src/hecks_naming.rs +33 -0
- data/rust/codegen/src/json.rs +335 -0
- data/rust/codegen/src/json_codec.rs +697 -0
- data/rust/codegen/src/literal.rs +207 -0
- data/rust/codegen/src/main.rs +290 -0
- data/rust/codegen/src/manifest.rs +227 -0
- data/rust/codegen/src/mutations.rs +784 -0
- data/rust/codegen/src/naming.rs +286 -0
- data/rust/codegen/src/ports.rs +208 -0
- data/rust/codegen/src/prelude.rs +116 -0
- data/rust/codegen/src/queries.rs +786 -0
- data/rust/codegen/src/reactions.rs +532 -0
- data/rust/codegen/src/read_models.rs +697 -0
- data/rust/codegen/src/reference_specs.rs +40 -0
- data/rust/codegen/src/registry.rs +966 -0
- data/rust/codegen/src/reserved_names.rs +76 -0
- data/rust/codegen/src/shared.rs +93 -0
- data/rust/codegen/src/skip_reason.rs +25 -0
- data/rust/codegen/src/types.rs +362 -0
- data/rust/host/.cargo/config.toml +3 -0
- data/rust/host/.gitignore +1 -0
- data/rust/host/Cargo.lock +4297 -0
- data/rust/host/Cargo.toml +61 -0
- data/rust/host/HECKS_RELEASE +1 -0
- data/rust/host/rds-ca-bundle.pem +2736 -0
- data/rust/host/src/api.rs +1596 -0
- data/rust/host/src/approval.rs +652 -0
- data/rust/host/src/auth.rs +1287 -0
- data/rust/host/src/bin/expr_harness.rs +46 -0
- data/rust/host/src/bin/lineage_harness.rs +119 -0
- data/rust/host/src/bin/mint_harness.rs +135 -0
- data/rust/host/src/checkout.rs +265 -0
- data/rust/host/src/dispatch.rs +1443 -0
- data/rust/host/src/expr_json.rs +1117 -0
- data/rust/host/src/field_hints.rs +52 -0
- data/rust/host/src/ir.rs +733 -0
- data/rust/host/src/journal.rs +874 -0
- data/rust/host/src/lambda_client.rs +378 -0
- data/rust/host/src/log.rs +147 -0
- data/rust/host/src/main.rs +474 -0
- data/rust/host/src/mint.rs +1865 -0
- data/rust/host/src/payments/keystore.rs +330 -0
- data/rust/host/src/payments/tests.rs +1400 -0
- data/rust/host/src/payments.rs +767 -0
- data/rust/host/src/presentation.rs +698 -0
- data/rust/host/src/presentation_write.rs +1431 -0
- data/rust/host/src/query_step.rs +149 -0
- data/rust/host/src/rate_limit.rs +904 -0
- data/rust/host/src/reference_transform.rs +241 -0
- data/rust/host/src/reference_validate.rs +338 -0
- data/rust/host/src/resend.rs +296 -0
- data/rust/host/src/secrets.rs +106 -0
- data/rust/host/src/server.rs +663 -0
- data/rust/host/src/storage_shape.rs +175 -0
- data/rust/host/src/test_pg.rs +40 -0
- data/rust/host/src/ui_schema.rs +1351 -0
- data/rust/host/src/wasm_runner.rs +191 -0
- data/rust/host/src/web/newsletter/cooldown.rs +126 -0
- data/rust/host/src/web/newsletter/tests.rs +104 -0
- data/rust/host/src/web/newsletter.rs +310 -0
- data/rust/host/src/web/newsletter_send.rs +357 -0
- data/rust/host/src/web/registrations.rs +1505 -0
- data/rust/host/src/web.rs +2937 -0
- data/rust/lsp/.gitignore +1 -0
- data/rust/lsp/Cargo.lock +7 -0
- data/rust/lsp/Cargo.toml +16 -0
- data/rust/lsp/README.md +133 -0
- data/rust/lsp/src/diagnostics.rs +165 -0
- data/rust/lsp/src/json.rs +385 -0
- data/rust/lsp/src/main.rs +399 -0
- data/rust/lsp/src/outline.rs +177 -0
- data/rust/lsp/src/rpc.rs +67 -0
- data/rust/parser/.cargo/config.toml +5 -0
- data/rust/parser/.gitignore +1 -0
- data/rust/parser/Cargo.lock +7 -0
- data/rust/parser/Cargo.toml +21 -0
- data/rust/parser/src/build/closed_sets.rs +27 -0
- data/rust/parser/src/build/identity.rs +276 -0
- data/rust/parser/src/build/mod.rs +12 -0
- data/rust/parser/src/build/naming.rs +141 -0
- data/rust/parser/src/build/pattern_subset.rs +161 -0
- data/rust/parser/src/build/query_derive.rs +72 -0
- data/rust/parser/src/build/query_inference.rs +269 -0
- data/rust/parser/src/build/query_options.rs +100 -0
- data/rust/parser/src/build/read_model.rs +94 -0
- data/rust/parser/src/build/references.rs +32 -0
- data/rust/parser/src/canonical.rs +114 -0
- data/rust/parser/src/diag.rs +55 -0
- data/rust/parser/src/emit.rs +953 -0
- data/rust/parser/src/expr/ast_json.rs +147 -0
- data/rust/parser/src/expr/evaluator.rs +81 -0
- data/rust/parser/src/expr/mod.rs +84 -0
- data/rust/parser/src/expr/resolver.rs +497 -0
- data/rust/parser/src/ir.rs +387 -0
- data/rust/parser/src/keywords.rs +585 -0
- data/rust/parser/src/lex.rs +662 -0
- data/rust/parser/src/main.rs +252 -0
- data/rust/parser/src/parse/aggregate.rs +612 -0
- data/rust/parser/src/parse/chapter.rs +517 -0
- data/rust/parser/src/parse/command.rs +637 -0
- data/rust/parser/src/parse/domain_port.rs +127 -0
- data/rust/parser/src/parse/entity.rs +527 -0
- data/rust/parser/src/parse/file.rs +67 -0
- data/rust/parser/src/parse/hecksagon.rs +231 -0
- data/rust/parser/src/parse/lifecycle.rs +162 -0
- data/rust/parser/src/parse/mod.rs +1262 -0
- data/rust/parser/src/parse/policy.rs +87 -0
- data/rust/parser/src/parse/process_manager.rs +305 -0
- data/rust/parser/src/parse/query.rs +100 -0
- data/rust/parser/src/parse/read_model.rs +214 -0
- data/rust/parser/src/parse/value_object.rs +250 -0
- data/rust/parser/src/ruby_value.rs +422 -0
- data/rust/project/bridging.rb +257 -0
- data/rust/project/commands.rb +877 -0
- data/rust/project/constraints.rb +86 -0
- data/rust/project/dependency_planning.rb +178 -0
- data/rust/project/domain_generator.rb +980 -0
- data/rust/project/exemplar.rb +148 -0
- data/rust/project/expr_emitter.rb +72 -0
- data/rust/project/fielded.rb +141 -0
- data/rust/project/json_codec.rb +641 -0
- data/rust/project/mutations.rb +721 -0
- data/rust/project/naming.rb +205 -0
- data/rust/project/ports.rb +65 -0
- data/rust/project/queries.rb +493 -0
- data/rust/project/reactions.rb +317 -0
- data/rust/project/read_models.rb +690 -0
- data/rust/project/reference_specs.rb +27 -0
- data/rust/project/registry.rb +396 -0
- data/rust/project/skip_reason.rb +29 -0
- data/rust/project/types.rb +225 -0
- data/rust/project/write_if_changed.rb +83 -0
- data/rust/project.rb +30 -0
- data/rust/project_rust_pipeline.rb +383 -0
- data/rust/src/exemplar/commands.rs +279 -0
- data/rust/src/exemplar/constraints.rs +18 -0
- data/rust/src/exemplar/fielded.rs +280 -0
- data/rust/src/exemplar/json.rs +277 -0
- data/rust/src/exemplar/mod.rs +17 -0
- data/rust/src/exemplar/mutations.rs +80 -0
- data/rust/src/exemplar/queries.rs +33 -0
- data/rust/src/exemplar/reactions.rs +88 -0
- data/rust/src/exemplar/read_models.rs +48 -0
- data/rust/src/exemplar/registry.rs +166 -0
- data/rust/src/exemplar/types.rs +44 -0
- data/rust/src/kernel/attribute_shapes/composite.rs +88 -0
- data/rust/src/kernel/attribute_shapes/list.rs +18 -0
- data/rust/src/kernel/attribute_shapes/mod.rs +44 -0
- data/rust/src/kernel/attribute_shapes/optional.rs +9 -0
- data/rust/src/kernel/attribute_shapes/scalar.rs +39 -0
- data/rust/src/kernel/cli.rs +585 -0
- data/rust/src/kernel/dispatch.rs +1090 -0
- data/rust/src/kernel/expr.rs +458 -0
- data/rust/src/kernel/expression_operators/arithmetic.rs +128 -0
- data/rust/src/kernel/expression_operators/comparison.rs +48 -0
- data/rust/src/kernel/expression_operators/enumeration.rs +232 -0
- data/rust/src/kernel/expression_operators/logical.rs +13 -0
- data/rust/src/kernel/expression_operators/membership.rs +18 -0
- data/rust/src/kernel/expression_operators/mod.rs +68 -0
- data/rust/src/kernel/expression_operators/pattern_match.rs +73 -0
- data/rust/src/kernel/expression_operators/positional.rs +126 -0
- data/rust/src/kernel/expression_operators/presence.rs +101 -0
- data/rust/src/kernel/expression_operators/sign_test.rs +16 -0
- data/rust/src/kernel/expression_operators/sized.rs +35 -0
- data/rust/src/kernel/expression_operators/text.rs +79 -0
- data/rust/src/kernel/expression_operators/to_string.rs +18 -0
- data/rust/src/kernel/json.rs +779 -0
- data/rust/src/kernel/mod.rs +133 -0
- data/rust/src/kernel/named_query.rs +219 -0
- data/rust/src/kernel/orchestrate.rs +1810 -0
- data/rust/src/kernel/pattern.rs +307 -0
- data/rust/src/kernel/query_comparators.rs +206 -0
- data/rust/src/kernel/query_ordering.rs +103 -0
- data/rust/src/kernel/read_model.rs +914 -0
- data/rust/src/kernel/reference_lookup.rs +149 -0
- data/rust/src/kernel/repository.rs +468 -0
- data/rust/src/kernel/routing.rs +612 -0
- data/rust/src/kernel/vocab/aggregate_dispatch_order.rs +118 -0
- data/rust/src/kernel/vocab/entity_dispatch_order.rs +114 -0
- data/rust/src/kernel/vocab/field_hint.rs +70 -0
- data/rust/src/kernel/vocab/mod.rs +20 -0
- data/rust/src/kernel/vocab/query_comparator.rs +65 -0
- data/rust/src/kernel/vocab/refusal_template.rs +1592 -0
- data/rust/src/lib.rs +8 -0
- data/rust/src/main.rs +16 -0
- data/rust/web/.gitignore +1 -0
- data/rust/web/Cargo.lock +119 -0
- data/rust/web/Cargo.toml +18 -0
- data/rust/web/src/lib.rs +8 -0
- metadata +478 -12
- data/lib/hecks/facade/cli_door.rb +0 -178
- data/lib/hecks/facade/cli_runner.rb +0 -271
- data/lib/hecks/facade/handle.rb +0 -293
- data/lib/hecks/facade/json_door.rb +0 -247
- data/lib/hecks/facade/surface/aggregate_door.rb +0 -222
- data/lib/hecks/facade/surface/chapter.rb +0 -116
- data/lib/hecks/facade/surface.rb +0 -61
- data/lib/hecks/mcp_door_scope.rb +0 -176
data/lib/hecks/facade/handle.rb
DELETED
|
@@ -1,293 +0,0 @@
|
|
|
1
|
-
require_relative "../naming"
|
|
2
|
-
require_relative "../runtime/caller"
|
|
3
|
-
require_relative "../ports/authorization"
|
|
4
|
-
|
|
5
|
-
module Hecks
|
|
6
|
-
module Facade
|
|
7
|
-
# One record in hand — the object `Pizza.create_pizza!(...)` and
|
|
8
|
-
# `Pizza.find(id)` give back.
|
|
9
|
-
#
|
|
10
|
-
# One shared class, not one minted per aggregate. Rather than subclassing
|
|
11
|
-
# per head and defining a reader per field, this wraps a
|
|
12
|
-
# `Runtime::Instance` state hash, answers readers through
|
|
13
|
-
# `method_missing` and verbs through per-handle singleton methods, and
|
|
14
|
-
# closes over the dispatcher and the aggregate's IR — so a boot mints no
|
|
15
|
-
# classes at all, and two boots in one process each hand out handles bound
|
|
16
|
-
# to their own dispatcher.
|
|
17
|
-
#
|
|
18
|
-
# A non-creating verb is a method returning self, so commands chain :
|
|
19
|
-
#
|
|
20
|
-
# Pizza.create_pizza!(...).add_topping!(...).purchase!(...)
|
|
21
|
-
class Handle
|
|
22
|
-
attr_reader :id
|
|
23
|
-
|
|
24
|
-
# @param dispatcher [Runtime::Dispatcher, Runtime::RemoteDispatcher] the booted
|
|
25
|
-
# dispatcher this record's verbs, `events` and `reload` go through
|
|
26
|
-
# @param domain [String] the owning chapter's name, the first half of `fqn`
|
|
27
|
-
# @param aggregate [Bluebook::Aggregate] the IR of the aggregate this record is one of
|
|
28
|
-
# @param instance [Runtime::Instance] the stored record; its `id` and `state` are
|
|
29
|
-
# read once here and the instance itself is not retained
|
|
30
|
-
def initialize(dispatcher:, domain:, aggregate:, instance:)
|
|
31
|
-
@dispatcher = dispatcher
|
|
32
|
-
@domain = domain
|
|
33
|
-
@ir = aggregate
|
|
34
|
-
@id = instance.id
|
|
35
|
-
@state = instance.state
|
|
36
|
-
define_reference_accessors
|
|
37
|
-
define_verb_methods
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
# Reads one field's raw stored value, without hydrating a reference the way the
|
|
41
|
-
# reference accessor of the same name does.
|
|
42
|
-
#
|
|
43
|
-
# @param key [Symbol, String] the attribute name
|
|
44
|
-
# @return [Object, nil] the value held in state (a scalar, a value object, a list,
|
|
45
|
-
# or a referenced record's id); `nil` when the field is unset or not in state
|
|
46
|
-
def [](key) = redacted(key.to_sym)
|
|
47
|
-
|
|
48
|
-
# Answers the record's state as a plain Hash with the bare identity under `:id`.
|
|
49
|
-
#
|
|
50
|
-
# `id: @id` last, not first — an aggregate is free to declare its own
|
|
51
|
-
# attribute literally named `id` (BurningManPrep's `Item`, `attribute
|
|
52
|
-
# :id, ItemId`, is real corpus now: `identified_by :id` reads
|
|
53
|
-
# that attribute for identity). When it does, `@state[:id]` holds the
|
|
54
|
-
# full wrapped value object, not the bare identity string — merging
|
|
55
|
-
# `@state` on top of `{ id: @id }` would let that wrapped VO silently
|
|
56
|
-
# clobber the correct bare `@id`, so every caller of `to_h` (the JSON
|
|
57
|
-
# door's own `/api/:coll` listing, in particular) would get an object
|
|
58
|
-
# where a plain identity string belongs. `@id` merged last always wins,
|
|
59
|
-
# so `to_h[:id]` is always the true bare identity, regardless of
|
|
60
|
-
# whether the aggregate also happens to declare a same-named field.
|
|
61
|
-
#
|
|
62
|
-
# @return [Hash{Symbol => Object}] a new Hash of every state field by attribute
|
|
63
|
-
# name, plus `:id` holding the identity String
|
|
64
|
-
def to_h = @state.to_h { |key, _| [key, redacted(key)] }.merge(id: @id)
|
|
65
|
-
|
|
66
|
-
# Names the aggregate this record belongs to, in the form every dispatch verb and
|
|
67
|
-
# event is addressed by.
|
|
68
|
-
#
|
|
69
|
-
# @return [String] the fully qualified aggregate name, such as `"Pizzas::Pizza"`
|
|
70
|
-
def fqn = "#{@domain}::#{@ir.hecks_name}"
|
|
71
|
-
|
|
72
|
-
# Lists the events this one record has emitted, filtered out of the dispatcher's
|
|
73
|
-
# whole event log on each call.
|
|
74
|
-
#
|
|
75
|
-
# @return [Array<Runtime::Event>] this record's events in the order the log holds
|
|
76
|
-
# them; `[]` when it has emitted none
|
|
77
|
-
def events
|
|
78
|
-
@dispatcher.events.select { |event| event.aggregate == fqn && event.id == @id }
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
# Refreshes this handle's state from the repository, picking up writes made through
|
|
82
|
-
# another handle or door. Keeps the current state when the record is not found.
|
|
83
|
-
#
|
|
84
|
-
# @return [Facade::Handle] this handle, so the call chains
|
|
85
|
-
# @raise [Runtime::WiringError] if the aggregate's persistence bind cannot be
|
|
86
|
-
# resolved into a repository
|
|
87
|
-
def reload
|
|
88
|
-
stored = repository.find(@id)
|
|
89
|
-
@state = stored.state if stored
|
|
90
|
-
self
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
# Equality is (which aggregate, which ID) — two handles to the same record
|
|
94
|
-
# are the same record, and a Pizza never equals an Account that happens to
|
|
95
|
-
# share an id. With one shared class for every aggregate,
|
|
96
|
-
# `other.is_a?(self.class)` cannot tell them apart ; the fqn says it in data.
|
|
97
|
-
#
|
|
98
|
-
# @param other [Object] anything; only another `Handle` can be equal
|
|
99
|
-
# @return [Boolean] true when `other` is a `Handle` with the same `fqn` and `id`,
|
|
100
|
-
# whatever state either one holds
|
|
101
|
-
def ==(other) = other.is_a?(Handle) && other.fqn == fqn && other.id == @id
|
|
102
|
-
alias eql? ==
|
|
103
|
-
def hash = [Handle, fqn, @id].hash
|
|
104
|
-
|
|
105
|
-
def inspect
|
|
106
|
-
fields = @state.map { |key, value| "#{key}=#{value.inspect}" }.join(" ")
|
|
107
|
-
"#<#{@ir.hecks_name} #{@id} #{fields}>"
|
|
108
|
-
end
|
|
109
|
-
alias to_s inspect
|
|
110
|
-
|
|
111
|
-
# Answers a field reader: `pizza.name` reads `name` out of state.
|
|
112
|
-
#
|
|
113
|
-
# A declared field not yet written arrives here too (nil, the way a
|
|
114
|
-
# defined reader answers). Verbs are not handled here — see
|
|
115
|
-
# `define_verb_methods` for why.
|
|
116
|
-
#
|
|
117
|
-
# @param name [Symbol] the method called, read as an attribute or lifecycle field name
|
|
118
|
-
# @param args [Array<Object>] ignored by a reader; passed on to `super` otherwise
|
|
119
|
-
# @param kwargs [Hash{Symbol => Object}] ignored by a reader; passed on to `super`
|
|
120
|
-
# otherwise
|
|
121
|
-
# @return [Object, nil] the field's value; `nil` for a declared field with nothing
|
|
122
|
-
# written yet
|
|
123
|
-
# @raise [NoMethodError] if `name` is neither a key in state nor a declared field
|
|
124
|
-
def method_missing(name, *args, **kwargs, &)
|
|
125
|
-
return redacted(name) if @state.key?(name) || reader?(name)
|
|
126
|
-
|
|
127
|
-
super
|
|
128
|
-
end
|
|
129
|
-
|
|
130
|
-
def respond_to_missing?(name, include_private = false)
|
|
131
|
-
@state.key?(name) || reader?(name) || super
|
|
132
|
-
end
|
|
133
|
-
|
|
134
|
-
private
|
|
135
|
-
|
|
136
|
-
def repository = @dispatcher.registry.repository(@domain, @ir)
|
|
137
|
-
|
|
138
|
-
# One field's value, with any Privacy::Marking-flagged leaf masked
|
|
139
|
-
# out unless the ambient caller holds a live Governance grant of
|
|
140
|
-
# the marking's own `readable_by` — the read-side half of the
|
|
141
|
-
# Privacy framework member (lib/hecks/framework/bluebook/
|
|
142
|
-
# privacy.bluebook): a marking's presence is what makes a read
|
|
143
|
-
# redacted, not a separate flag this class carries itself.
|
|
144
|
-
#
|
|
145
|
-
# Always the strong check, never the weak string-only fallback
|
|
146
|
-
# `CommandRules::Authorization#refuse_role_mismatch` allows an
|
|
147
|
-
# unidentified caller — a read gate gone wrong is a leak, not a
|
|
148
|
-
# refused command, so an ambient caller with no `actor_id` (or no
|
|
149
|
-
# caller at all) is masked here, full stop, rather than waved
|
|
150
|
-
# through the way a self-asserted `role` string is for a command.
|
|
151
|
-
#
|
|
152
|
-
# One level of nesting only — `attendee.medications` masks inside
|
|
153
|
-
# the returned `Runtime::Value` via its own `#with`; a marking two
|
|
154
|
-
# levels deep is not supported and is left unmasked rather than
|
|
155
|
-
# silently mishandled, since nothing in this corpus needs it yet.
|
|
156
|
-
#
|
|
157
|
-
# @param field [Symbol] the state key being read
|
|
158
|
-
# @return [Object, nil] `@state[field]`, or a copy with the marked leaf replaced by
|
|
159
|
-
# the literal String `"[redacted]"` when the caller is not authorized to see it
|
|
160
|
-
def redacted(field)
|
|
161
|
-
raw = @state[field]
|
|
162
|
-
rows = marked_paths.select { |row| row[:attribute_path][:value].to_s.split(".", 2).first == field.to_s }
|
|
163
|
-
return raw if rows.empty?
|
|
164
|
-
|
|
165
|
-
rows.each do |row|
|
|
166
|
-
path = row[:attribute_path][:value].to_s
|
|
167
|
-
next if authorized_for?(row[:readable_by][:value].to_s)
|
|
168
|
-
|
|
169
|
-
segments = path.split(".", 2)
|
|
170
|
-
if segments.size == 1
|
|
171
|
-
raw = "[redacted]"
|
|
172
|
-
elsif raw.is_a?(Runtime::Value)
|
|
173
|
-
raw = raw.with(segments[1], "[redacted]")
|
|
174
|
-
end
|
|
175
|
-
end
|
|
176
|
-
|
|
177
|
-
raw
|
|
178
|
-
end
|
|
179
|
-
|
|
180
|
-
# Every Privacy::Marking declared for this record's own aggregate — `[]` when the
|
|
181
|
-
# Privacy framework member is not attached in this boot at all, checked once and
|
|
182
|
-
# cheaply rather than paying for a query dispatch every read on a domain that never
|
|
183
|
-
# attached Privacy.
|
|
184
|
-
#
|
|
185
|
-
# @return [Array<Hash>] `Privacy::Marking.ForDomain`'s own rows for this `fqn`
|
|
186
|
-
def marked_paths
|
|
187
|
-
return @marked_paths if defined?(@marked_paths)
|
|
188
|
-
return @marked_paths = [] unless @dispatcher.registry.bluebook("Privacy")
|
|
189
|
-
|
|
190
|
-
@marked_paths = @dispatcher.query("Privacy::Marking.ForDomain", domain: fqn)
|
|
191
|
-
end
|
|
192
|
-
|
|
193
|
-
# Whether the ambient caller holds a live Governance grant of `role`, over this
|
|
194
|
-
# record's own domain — `false` outright for an unidentified caller or a domain
|
|
195
|
-
# with no authorization provider attached, never the weak fallback a command's own
|
|
196
|
-
# role check allows (see `redacted`'s own header for why).
|
|
197
|
-
#
|
|
198
|
-
# @param role [String] the marking's own `readable_by`
|
|
199
|
-
# @return [Boolean] true only for an identified caller holding a live grant
|
|
200
|
-
def authorized_for?(role)
|
|
201
|
-
caller = Runtime::Caller.current
|
|
202
|
-
return false unless caller&.actor_id
|
|
203
|
-
return false unless @dispatcher.registry.authorization_provider_for(@domain)
|
|
204
|
-
|
|
205
|
-
Ports::Authorization.holds_role?(@dispatcher.registry, actor_id: caller.actor_id, role: role,
|
|
206
|
-
as_of: caller.as_of, scope: caller.scope)
|
|
207
|
-
end
|
|
208
|
-
|
|
209
|
-
def reader?(name)
|
|
210
|
-
!@ir.attribute(name).nil? || @ir.lifecycle&.field&.to_sym == name
|
|
211
|
-
end
|
|
212
|
-
|
|
213
|
-
# Non-creating verbs are defined, not dispatched through method_missing.
|
|
214
|
-
#
|
|
215
|
-
# method_missing only runs once Ruby finds no real method already
|
|
216
|
-
# answering the name — and every object already answers `freeze` and
|
|
217
|
-
# `send` (Kernel/Object), among others. A verb whose snake-cased name
|
|
218
|
-
# collided with one of those — `Account::Freeze` -> `freeze`,
|
|
219
|
-
# `ExternalTransfer::Send` -> `send` in the banking corpus, both real —
|
|
220
|
-
# would silently run the Kernel method instead of dispatching: no
|
|
221
|
-
# error, no refusal, the call just does the wrong thing. Defining a
|
|
222
|
-
# real singleton method per verb closes that; the `!` suffix (every
|
|
223
|
-
# command, door and Handle alike) closes it a second, permanent way —
|
|
224
|
-
# `freeze!`/`send!` name nothing Kernel/Object already answers to,
|
|
225
|
-
# so this exact class of collision cannot recur no matter what a
|
|
226
|
-
# future domain names a command.
|
|
227
|
-
def define_verb_methods
|
|
228
|
-
@ir.commands.reject(&:creates?).each do |command|
|
|
229
|
-
define_singleton_method("#{Naming.snake(command.hecks_name)}!") do |**args|
|
|
230
|
-
run(command, **args)
|
|
231
|
-
end
|
|
232
|
-
end
|
|
233
|
-
end
|
|
234
|
-
|
|
235
|
-
# One head addresses the same way as several. `@ir.identified_by` is only
|
|
236
|
-
# the single-head shorthand — nil the moment an identity is composite
|
|
237
|
-
# (`SafeDepositBox`'s `branch_code`/`box_number`) — so building the
|
|
238
|
-
# identity payload from `identity_heads` instead reads every head, one
|
|
239
|
-
# or many alike, straight out of state that already carries them.
|
|
240
|
-
def run(command, **args)
|
|
241
|
-
@state = @dispatcher.dispatch("#{fqn}.#{command.hecks_name}", to: @id, with: args).instance.state
|
|
242
|
-
self
|
|
243
|
-
end
|
|
244
|
-
|
|
245
|
-
# **The other half of a cross-reference**. `transfer.source` already reads
|
|
246
|
-
# the raw value — a plain reader, same as any other attribute, still
|
|
247
|
-
# needed by a `given`. This is the hydrated hop docs/rails-integration.md
|
|
248
|
-
# designed and marked "nothing built": `transfer.source_account`
|
|
249
|
-
# resolves it to the actual Account record, on demand — nothing loads
|
|
250
|
-
# until called, and this hop never triggers the next one. Plain
|
|
251
|
-
# chaining composes for free from here : `payment.disputed_by_customer.name`
|
|
252
|
-
# is two ordinary calls, each individually lazy, which is exactly why
|
|
253
|
-
# this is a named accessor per reference rather than a `through:`
|
|
254
|
-
# option — that shape was considered and rejected in the same design
|
|
255
|
-
# note for hiding how many lookups actually happened behind one call.
|
|
256
|
-
#
|
|
257
|
-
# Defined before verb methods, not after — on the vanishing chance a
|
|
258
|
-
# reference's own accessor name collided with a command's, the verb
|
|
259
|
-
# should win; `initialize` calls this first so `define_verb_methods`
|
|
260
|
-
# defines second and last.
|
|
261
|
-
# No derivation left (ADR 0025, "References"): `reference_to`
|
|
262
|
-
# itself mints the bare attribute name now — `:account`, never
|
|
263
|
-
# `:account_id` — so the accessor is spelled exactly like the
|
|
264
|
-
# attribute it reads, with no `_id`-strip or `as:`-suffix rule to
|
|
265
|
-
# apply first. `piece.account` (a method, defined here) and
|
|
266
|
-
# `piece[:account]` (`Handle#[]`, bracket access reading the raw
|
|
267
|
-
# id straight off `@instance`) never collide despite sharing a
|
|
268
|
-
# name — Ruby dispatches the two completely differently — so no
|
|
269
|
-
# renamed accessor (a "studio_studio"-style double suffix) is needed
|
|
270
|
-
# to keep them apart.
|
|
271
|
-
def define_reference_accessors
|
|
272
|
-
@ir.attributes.select(&:reference?).each do |attribute|
|
|
273
|
-
target = attribute.type.resolve
|
|
274
|
-
# Cross-domain, or otherwise unresolvable — no accessor rather than a guess.
|
|
275
|
-
next unless target
|
|
276
|
-
|
|
277
|
-
domain = @domain
|
|
278
|
-
field = attribute.name
|
|
279
|
-
list = attribute.list?
|
|
280
|
-
target_fqn = "#{domain}::#{target.hecks_name}"
|
|
281
|
-
|
|
282
|
-
define_singleton_method(field) do
|
|
283
|
-
value = self[field]
|
|
284
|
-
door = Object.const_get(target_fqn)
|
|
285
|
-
next Array(value).map { |identity| door.find(identity) } if list
|
|
286
|
-
|
|
287
|
-
value && door.find(value)
|
|
288
|
-
end
|
|
289
|
-
end
|
|
290
|
-
end
|
|
291
|
-
end
|
|
292
|
-
end
|
|
293
|
-
end
|
|
@@ -1,247 +0,0 @@
|
|
|
1
|
-
require "json"
|
|
2
|
-
require_relative "handle"
|
|
3
|
-
require_relative "command_request"
|
|
4
|
-
require_relative "../naming"
|
|
5
|
-
require_relative "../runtime/errors"
|
|
6
|
-
require_relative "../runtime/value"
|
|
7
|
-
|
|
8
|
-
module Hecks
|
|
9
|
-
module Facade
|
|
10
|
-
# **The JSON door** — where Facade meets body-in/body-out callers.
|
|
11
|
-
#
|
|
12
|
-
# `Handle`/`Surface` are Ruby sugar over the dispatcher for a Ruby caller
|
|
13
|
-
# holding real objects — a symbol verb name, a `**kwargs` payload, a
|
|
14
|
-
# `Handle` back in hand. A REST-ish JSON API is a caller holding strings
|
|
15
|
-
# instead: a URL segment naming a collection, a URL segment naming a
|
|
16
|
-
# record or a verb, a parsed request body whose every key arrived as a
|
|
17
|
-
# String because that is all JSON ever gives. Every app that wants to put
|
|
18
|
-
# a JSON API in front of a booted domain has to do that translation —
|
|
19
|
-
# name to door module, string to symbol, nested `Runtime::Value` back to
|
|
20
|
-
# plain data. This is that translation written once, generic, reading the
|
|
21
|
-
# same IR the rest of the facade already reads rather than each app
|
|
22
|
-
# re-deriving "how do I find an aggregate by name" against its own routes.
|
|
23
|
-
#
|
|
24
|
-
# ## No HTTP lives here
|
|
25
|
-
#
|
|
26
|
-
# Same discipline `Router` and `Surface` already
|
|
27
|
-
# hold: this module never sees a request object, never picks a status
|
|
28
|
-
# code, never calls `halt`. Every method here takes plain Ruby values in
|
|
29
|
-
# — a raw JSON String is the one exception, see `.parse` below, every
|
|
30
|
-
# other input is already-parsed data — and returns plain Ruby values
|
|
31
|
-
# out, or raises. Turning a raw request body into that input, and
|
|
32
|
-
# turning a raised exception into an HTTP status, both stay the calling
|
|
33
|
-
# app's job, exactly the way they already are for `Router#dispatch`.
|
|
34
|
-
#
|
|
35
|
-
# ## One refusal class for every miss
|
|
36
|
-
#
|
|
37
|
-
# Every "that doesn't exist" case raises `Runtime::NotFound` — the same
|
|
38
|
-
# class every time, not a new one per caller. `Runtime::NotFound` already
|
|
39
|
-
# sits in `Runtime::DOMAIN_REFUSALS` (runtime/errors.rb) — the family a
|
|
40
|
-
# booted app already has, or trivially can have, one generic `error`
|
|
41
|
-
# handler for, mapping the whole family to a status code without a
|
|
42
|
-
# special case per refusal. A bespoke `JsonDoor::CollectionNotFound` (or
|
|
43
|
-
# three of those, one per flavor of "not found") would just force every
|
|
44
|
-
# app that adopts this door to widen its rescue clause to match it — the
|
|
45
|
-
# opposite of what a shared refusal family is for. So "no such
|
|
46
|
-
# aggregate", "no creating command", "no such command", and "no record
|
|
47
|
-
# with that id" all raise the one class, distinguished only by message.
|
|
48
|
-
module JsonDoor
|
|
49
|
-
module_function
|
|
50
|
-
|
|
51
|
-
# Resolves a domain name and an aggregate name, as two URL segments carry them, to
|
|
52
|
-
# that aggregate's door.
|
|
53
|
-
#
|
|
54
|
-
# "Banking", "Customer" -> the `Banking::Customer` door module `.find` /
|
|
55
|
-
# `.create_...!` / etc already answer for — the same module
|
|
56
|
-
# `Facade::Handle`'s own reference accessors reach with
|
|
57
|
-
# `Object.const_get` (see handle.rb's `define_reference_accessors`).
|
|
58
|
-
#
|
|
59
|
-
# Checked against the current boot's IR first, not against Ruby's
|
|
60
|
-
# constant table directly — a name that names nothing in this
|
|
61
|
-
# registry should refuse before ever asking Ruby whether some
|
|
62
|
-
# same-named constant happens to exist (possibly a stale one, left
|
|
63
|
-
# over from an earlier boot in this same process — the exact hazard
|
|
64
|
-
# `AggregateDoor#port`'s own comment describes at length). Only once
|
|
65
|
-
# the IR confirms the aggregate is real does this read the constant
|
|
66
|
-
# the current boot's `Surface.install` actually minted for it.
|
|
67
|
-
#
|
|
68
|
-
# @param dispatcher [Runtime::Dispatcher, Runtime::RemoteDispatcher] the booted
|
|
69
|
-
# dispatcher whose registry decides whether the aggregate exists
|
|
70
|
-
# @param domain [String, Symbol] the chapter name, such as `"Banking"`
|
|
71
|
-
# @param name [String, Symbol] the aggregate's declared name, such as `"Customer"`
|
|
72
|
-
# @return [Module] the aggregate door installed at `domain::name`
|
|
73
|
-
# @raise [Runtime::NotFound] if the registry holds no such chapter, or the chapter
|
|
74
|
-
# declares no aggregate of that name
|
|
75
|
-
# @raise [NameError] if the IR has the aggregate but no facade constant is
|
|
76
|
-
# installed for it, as after a boot with `install_facade: false`
|
|
77
|
-
def aggregate(dispatcher, domain, name)
|
|
78
|
-
ir = dispatcher.registry.bluebook(domain)&.aggregate(name)
|
|
79
|
-
raise Runtime::NotFound, "#{domain} declares no aggregate named #{name.inspect}" unless ir
|
|
80
|
-
|
|
81
|
-
Object.const_get("#{domain}::#{ir.hecks_name}")
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
# Names the door method that creates a record of this aggregate.
|
|
85
|
-
#
|
|
86
|
-
# The one command a POST to a bare collection URL means — "make one of
|
|
87
|
-
# these". A creating command is one that declares no `references`
|
|
88
|
-
# (`Command#creates?`), and the first one the aggregate declares is the
|
|
89
|
-
# one named here; this just names it the same
|
|
90
|
-
# snake_case-plus-bang a Ruby caller would already ask the door for
|
|
91
|
-
# (`Naming.snake`, the identical call `AggregateDoor` itself makes
|
|
92
|
-
# when it defines that singleton method in the first place — `!`
|
|
93
|
-
# because every command carries it, door and Handle alike).
|
|
94
|
-
#
|
|
95
|
-
# @param klass [Module] an aggregate door, as `aggregate` returns; anything
|
|
96
|
-
# answering `ir` with a `Bluebook::Aggregate` works
|
|
97
|
-
# @return [String] the method name to `public_send` to the door, such as
|
|
98
|
-
# `"create_pizza!"`
|
|
99
|
-
# @raise [Runtime::NotFound] if the aggregate declares no creating command
|
|
100
|
-
def creating_command(klass)
|
|
101
|
-
creating = klass.ir.commands.find(&:creates?)
|
|
102
|
-
raise Runtime::NotFound, "#{klass.ir.hecks_name} declares no creating command" unless creating
|
|
103
|
-
|
|
104
|
-
"#{Naming.snake(creating.hecks_name)}!"
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
# Confirms that a command name arriving as text is one a `Handle` of this aggregate
|
|
108
|
-
# answers, before a caller `public_send`s it.
|
|
109
|
-
#
|
|
110
|
-
# A URL segment or a JSON body's "command" field, checked against what
|
|
111
|
-
# a `Handle` can actually dispatch — not `klass.commands`, which is
|
|
112
|
-
# `AggregateDoor`'s own door-level list and includes the one creating
|
|
113
|
-
# command too (`aggregate_door.rb`'s `commands` singleton method maps
|
|
114
|
-
# every `ir.commands`, full stop). A `Handle` only ever defines
|
|
115
|
-
# singleton methods for the non-creating ones
|
|
116
|
-
# (`Handle#define_verb_methods`, `@ir.commands.reject(&:creates?)`) —
|
|
117
|
-
# the creating command lives on the aggregate class itself, dispatched
|
|
118
|
-
# through `.creating_command` above, not through a `Handle` in hand.
|
|
119
|
-
# Accepting a creating-command name here would let it past this gate
|
|
120
|
-
# clean, only to blow up as a raw `NoMethodError` the moment a caller
|
|
121
|
-
# tries `handle.public_send(name, **args)`, instead of the 404 this
|
|
122
|
-
# method promises. Filtering `reject(&:creates?)` here, the same filter
|
|
123
|
-
# `Handle` itself applies, is what keeps "accepted here" and
|
|
124
|
-
# "dispatchable there" the same set.
|
|
125
|
-
#
|
|
126
|
-
# @param klass [Module] an aggregate door, as `aggregate` returns
|
|
127
|
-
# @param name [String, Symbol] the wanted method name with its bang, such as
|
|
128
|
-
# `"add_topping!"`
|
|
129
|
-
# @return [String] `name` as a String, unchanged, when a `Handle` answers it
|
|
130
|
-
# @raise [Runtime::NotFound] if no non-creating command has that method name,
|
|
131
|
-
# including when `name` is the creating command's or lacks the `!`
|
|
132
|
-
def validate_command!(klass, name)
|
|
133
|
-
wanted = name.to_s
|
|
134
|
-
dispatchable = klass.ir.commands.reject(&:creates?).map { |command| "#{Naming.snake(command.hecks_name)}!" }
|
|
135
|
-
return wanted if dispatchable.include?(wanted)
|
|
136
|
-
|
|
137
|
-
raise Runtime::NotFound, "#{klass.ir.hecks_name} declares no command named #{wanted.inspect}"
|
|
138
|
-
end
|
|
139
|
-
|
|
140
|
-
# Fetches one record by id, refusing a miss instead of answering nil.
|
|
141
|
-
#
|
|
142
|
-
# `klass.find` already answers nil-on-miss — the right shape for a
|
|
143
|
-
# Ruby caller that means to check for itself. A JSON caller asking for
|
|
144
|
-
# one record by id off a URL means to have it, or answer 404 — this is
|
|
145
|
-
# that stricter wrapper, raising the same `Runtime::NotFound` the rest
|
|
146
|
-
# of this door raises rather than handing back nil for the caller to
|
|
147
|
-
# remember to check.
|
|
148
|
-
#
|
|
149
|
-
# @param klass [Module] an aggregate door, as `aggregate` returns
|
|
150
|
-
# @param id [String] the record's identity, as the URL carried it
|
|
151
|
-
# @return [Facade::Handle] the record in hand
|
|
152
|
-
# @raise [Runtime::NotFound] if the repository holds no record with that id
|
|
153
|
-
def find!(klass, id)
|
|
154
|
-
klass.find(id) or raise Runtime::NotFound, "no #{klass.ir.hecks_name} found for id #{id.inspect}"
|
|
155
|
-
end
|
|
156
|
-
|
|
157
|
-
# Converts every Hash key to a Symbol, at every depth of a parsed JSON body.
|
|
158
|
-
#
|
|
159
|
-
# JSON only ever hands back String keys. A command's args, and every
|
|
160
|
-
# nested value-object literal inside them, need symbol keys before
|
|
161
|
-
# `Handle`/`Dispatcher` will accept them at all — this is that
|
|
162
|
-
# recursive conversion, blind to how deep a body nests.
|
|
163
|
-
#
|
|
164
|
-
# @param value [Hash, Array, Object] parsed JSON: a Hash or Array is walked, any
|
|
165
|
-
# other value is a leaf
|
|
166
|
-
# @return [Hash{Symbol => Object}, Array, Object] a new structure of the same shape
|
|
167
|
-
# with Symbol keys; a leaf is returned as it came
|
|
168
|
-
def deep_symbolize(value)
|
|
169
|
-
case value
|
|
170
|
-
when Hash then value.to_h { |k, v| [k.to_sym, deep_symbolize(v)] }
|
|
171
|
-
when Array then value.map { |item| deep_symbolize(item) }
|
|
172
|
-
else value
|
|
173
|
-
end
|
|
174
|
-
end
|
|
175
|
-
|
|
176
|
-
# Unwraps a record, a query row, or any value holding `Runtime::Value`s into plain
|
|
177
|
-
# Hashes, Arrays and scalars.
|
|
178
|
-
#
|
|
179
|
-
# The other direction: a `Handle`, or a query row's plain state hash,
|
|
180
|
-
# carrying a `Runtime::Value` at every level a value object sits at —
|
|
181
|
-
# down to plain Ruby a JSON encoder can walk without knowing what a
|
|
182
|
-
# `Runtime::Value` is.
|
|
183
|
-
#
|
|
184
|
-
# `Runtime::Value.materialize` (runtime/value.rb) already does the
|
|
185
|
-
# actual recursion — its `Hash` branch calls itself on every value,
|
|
186
|
-
# its `Value` branch unwraps through `#to_h`, which itself calls
|
|
187
|
-
# `materialize` on every field, so a value object three levels deep
|
|
188
|
-
# unwraps three levels deep for free. This is not a second unwrapper
|
|
189
|
-
# sitting next to it: `materialize` covers `Hash`/`Array`/`Value`
|
|
190
|
-
# already, and a `Handle` is none of those three, so the one thing
|
|
191
|
-
# this adds is `#to_h`'ing a `Handle` first so `materialize`'s own
|
|
192
|
-
# `Hash` case can take it from there.
|
|
193
|
-
#
|
|
194
|
-
# @param value [Facade::Handle, Runtime::Value, Hash, Array, Object] what to unwrap;
|
|
195
|
-
# a `Handle` is read through its `to_h`, so its `:id` comes along
|
|
196
|
-
# @return [Hash, Array, Object] the same data with every `Runtime::Value` replaced
|
|
197
|
-
# by a Hash of its fields; a value that is none of the listed types is returned
|
|
198
|
-
# as it came
|
|
199
|
-
def materialize(value)
|
|
200
|
-
value = value.to_h if value.is_a?(Handle)
|
|
201
|
-
Runtime::Value.materialize(value)
|
|
202
|
-
end
|
|
203
|
-
|
|
204
|
-
# Turns a command's JSON body, raw or already parsed, into the `to:`/`with:`
|
|
205
|
-
# envelope a dispatcher takes.
|
|
206
|
-
#
|
|
207
|
-
# Parsed JSON and raw JSON text cross the same receiver/payload boundary
|
|
208
|
-
# as CLI and forms. The result is ready to splat into Dispatcher#dispatch
|
|
209
|
-
# and contains no loose routing fields.
|
|
210
|
-
#
|
|
211
|
-
# @param body [String, Hash] raw JSON text, or the Hash it parses to, with String
|
|
212
|
-
# or Symbol keys
|
|
213
|
-
# @param receiver [Symbol, nil] the kind of receiver the command takes: `:aggregate`,
|
|
214
|
-
# `:entity`, or `nil` for none (see `CommandRequest.normalize`)
|
|
215
|
-
# @param legacy_receiver [Symbol, String, Hash{Symbol => Symbol, String}, nil] the
|
|
216
|
-
# flat key, or pair of keys, a body without `to` may name its receiver under;
|
|
217
|
-
# `nil` accepts none
|
|
218
|
-
# @return [Hash{Symbol => Object}] `{ with: facts }`, plus `to:` whenever `receiver`
|
|
219
|
-
# is not `nil`
|
|
220
|
-
# @raise [JSON::ParserError] if `body` is a String that is not valid JSON
|
|
221
|
-
# @raise [Runtime::TypeMismatch] if the body is not a JSON object, or its routing is
|
|
222
|
-
# missing, malformed, or mixed with loose keys beside an explicit `with:`
|
|
223
|
-
# @raise [ArgumentError] if `receiver` is not `nil`, `:aggregate` or `:entity`
|
|
224
|
-
def command_request(body, receiver:, legacy_receiver: nil)
|
|
225
|
-
input = body.is_a?(String) ? parse(body) : body
|
|
226
|
-
CommandRequest.normalize(input, receiver: receiver, legacy_receiver: legacy_receiver)
|
|
227
|
-
end
|
|
228
|
-
|
|
229
|
-
# Parses a raw request body, leaving keys as Strings.
|
|
230
|
-
#
|
|
231
|
-
# The one place a raw JSON string is legitimate input for this door —
|
|
232
|
-
# a POST body, still text at the point a generic, HTTP-blind layer can
|
|
233
|
-
# see it. `JSON::ParserError` already names "this wasn't JSON" exactly
|
|
234
|
-
# right ; wrapping it in a bespoke `JsonDoor`-specific class would
|
|
235
|
-
# only be a second name for the same fact, so it propagates exactly as
|
|
236
|
-
# `JSON.parse` raises it — a calling app catches it the same standard
|
|
237
|
-
# way it would catch any other malformed-input error, no new class to
|
|
238
|
-
# learn.
|
|
239
|
-
#
|
|
240
|
-
# @param raw_json [String] JSON text, such as a POST body
|
|
241
|
-
# @return [Hash{String => Object}, Array, String, Numeric, Boolean, nil] whatever
|
|
242
|
-
# the text encodes; a JSON object becomes a Hash with String keys
|
|
243
|
-
# @raise [JSON::ParserError] if the text is not valid JSON
|
|
244
|
-
def parse(raw_json) = JSON.parse(raw_json)
|
|
245
|
-
end
|
|
246
|
-
end
|
|
247
|
-
end
|