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
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
require_relative "../naming"
|
|
2
|
+
require_relative "../runtime/caller"
|
|
3
|
+
require_relative "../ports/authorization"
|
|
4
|
+
|
|
5
|
+
module Hecks
|
|
6
|
+
module Doors
|
|
7
|
+
# A record in hand: what `Pizza.create_pizza!(...)` and `Pizza.find(id)`
|
|
8
|
+
# give back. One shared class per aggregate; verbs are per-handle singleton methods.
|
|
9
|
+
#
|
|
10
|
+
# Pizza.create_pizza!(...).add_topping!(...).purchase!(...)
|
|
11
|
+
class Handle
|
|
12
|
+
attr_reader :id
|
|
13
|
+
|
|
14
|
+
# @param dispatcher [Runtime::Dispatcher, Runtime::RemoteDispatcher] the booted
|
|
15
|
+
# dispatcher this record's verbs, `events` and `reload` go through
|
|
16
|
+
# @param domain [String] the owning chapter's name, the first half of `fqn`
|
|
17
|
+
# @param aggregate [Bluebook::Aggregate] the IR of the aggregate this record is one of
|
|
18
|
+
# @param instance [Runtime::Instance] the stored record; its `id` and `state` are
|
|
19
|
+
# read once here and the instance itself is not retained
|
|
20
|
+
def initialize(dispatcher:, domain:, aggregate:, instance:)
|
|
21
|
+
@dispatcher = dispatcher
|
|
22
|
+
@domain = domain
|
|
23
|
+
@ir = aggregate
|
|
24
|
+
@id = instance.id
|
|
25
|
+
@state = instance.state
|
|
26
|
+
define_reference_accessors
|
|
27
|
+
define_verb_methods
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Reads one field's raw stored value, without hydrating a reference the way the
|
|
31
|
+
# reference accessor of the same name does.
|
|
32
|
+
#
|
|
33
|
+
# @param key [Symbol, String] the attribute name
|
|
34
|
+
# @return [Object, nil] the value held in state (a scalar, a value object, a list,
|
|
35
|
+
# or a referenced record's id); `nil` when the field is unset or not in state
|
|
36
|
+
def [](key) = redacted(key.to_sym)
|
|
37
|
+
|
|
38
|
+
# Answers the record's state as a Hash, with `:id` merged in last so it
|
|
39
|
+
# always wins over a same-named `id` attribute (BurningManPrep::Item).
|
|
40
|
+
#
|
|
41
|
+
# @return [Hash{Symbol => Object}] every state field by attribute name, plus `:id`
|
|
42
|
+
def to_h = @state.to_h { |key, _| [key, redacted(key)] }.merge(id: @id)
|
|
43
|
+
|
|
44
|
+
# Names the aggregate this record belongs to, in the form every dispatch verb and
|
|
45
|
+
# event is addressed by.
|
|
46
|
+
#
|
|
47
|
+
# @return [String] the fully qualified aggregate name, such as `"Pizzas::Pizza"`
|
|
48
|
+
def fqn = "#{@domain}::#{@ir.hecks_name}"
|
|
49
|
+
|
|
50
|
+
# Lists the events this one record has emitted, filtered out of the dispatcher's
|
|
51
|
+
# whole event log on each call.
|
|
52
|
+
#
|
|
53
|
+
# @return [Array<Runtime::Event>] this record's events in the order the log holds
|
|
54
|
+
# them; `[]` when it has emitted none
|
|
55
|
+
def events
|
|
56
|
+
@dispatcher.events.select { |event| event.aggregate == fqn && event.id == @id }
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Refreshes this handle's state from the repository, picking up writes made through
|
|
60
|
+
# another handle or door. Keeps the current state when the record is not found.
|
|
61
|
+
#
|
|
62
|
+
# @return [Doors::Handle] this handle, so the call chains
|
|
63
|
+
# @raise [Runtime::WiringError] if the aggregate's persistence bind cannot be
|
|
64
|
+
# resolved into a repository
|
|
65
|
+
def reload
|
|
66
|
+
stored = repository.find(@id)
|
|
67
|
+
@state = stored.state if stored
|
|
68
|
+
self
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# Equality is (fqn, id): two handles to the same record are equal, and
|
|
72
|
+
# `other.is_a?(self.class)` can't tell aggregates apart since they share one class.
|
|
73
|
+
#
|
|
74
|
+
# @param other [Object] anything; only another `Handle` can be equal
|
|
75
|
+
# @return [Boolean] true when `other` is a `Handle` with the same `fqn` and `id`
|
|
76
|
+
def ==(other) = other.is_a?(Handle) && other.fqn == fqn && other.id == @id
|
|
77
|
+
alias eql? ==
|
|
78
|
+
def hash = [Handle, fqn, @id].hash
|
|
79
|
+
|
|
80
|
+
def inspect
|
|
81
|
+
fields = @state.map { |key, value| "#{key}=#{value.inspect}" }.join(" ")
|
|
82
|
+
"#<#{@ir.hecks_name} #{@id} #{fields}>"
|
|
83
|
+
end
|
|
84
|
+
alias to_s inspect
|
|
85
|
+
|
|
86
|
+
# Answers a field reader: `pizza.name` reads `name` out of state. A
|
|
87
|
+
# declared field not yet written arrives here too, as `nil`.
|
|
88
|
+
#
|
|
89
|
+
# @param name [Symbol] the method called, read as an attribute or lifecycle field name
|
|
90
|
+
# @param args [Array<Object>] ignored by a reader; passed on to `super` otherwise
|
|
91
|
+
# @param kwargs [Hash{Symbol => Object}] ignored by a reader; passed on to `super` otherwise
|
|
92
|
+
# @return [Object, nil] the field's value; `nil` when nothing is written yet
|
|
93
|
+
# @raise [NoMethodError] if `name` is neither a key in state nor a declared field
|
|
94
|
+
def method_missing(name, *args, **kwargs, &)
|
|
95
|
+
return redacted(name) if @state.key?(name) || reader?(name)
|
|
96
|
+
|
|
97
|
+
super
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def respond_to_missing?(name, include_private = false)
|
|
101
|
+
@state.key?(name) || reader?(name) || super
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
private
|
|
105
|
+
|
|
106
|
+
def repository = @dispatcher.registry.repository(@domain, @ir)
|
|
107
|
+
|
|
108
|
+
# Masks any Privacy::Marking leaf the caller isn't granted to read, and
|
|
109
|
+
# masks an unidentified caller outright (a leak is worse than a refusal
|
|
110
|
+
# commands allow). Nesting is masked one level deep only.
|
|
111
|
+
def redacted(field)
|
|
112
|
+
raw = @state[field]
|
|
113
|
+
rows = marked_paths.select { |row| row[:attribute_path][:value].to_s.split(".", 2).first == field.to_s }
|
|
114
|
+
return raw if rows.empty?
|
|
115
|
+
|
|
116
|
+
rows.each do |row|
|
|
117
|
+
path = row[:attribute_path][:value].to_s
|
|
118
|
+
next if authorized_for?(row[:readable_by][:value].to_s)
|
|
119
|
+
|
|
120
|
+
segments = path.split(".", 2)
|
|
121
|
+
if segments.size == 1
|
|
122
|
+
raw = "[redacted]"
|
|
123
|
+
elsif raw.is_a?(Runtime::Value)
|
|
124
|
+
raw = raw.with(segments[1], "[redacted]")
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
raw
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
# Cached per handle so an unattached-Privacy domain never pays for a query
|
|
132
|
+
# dispatch on every read.
|
|
133
|
+
def marked_paths
|
|
134
|
+
return @marked_paths if defined?(@marked_paths)
|
|
135
|
+
return @marked_paths = [] unless @dispatcher.registry.bluebook("Privacy")
|
|
136
|
+
|
|
137
|
+
@marked_paths = @dispatcher.query("Privacy::Marking.ForDomain", domain: fqn)
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
# False outright for an unidentified caller or an unattached domain, never
|
|
141
|
+
# the weak fallback a command's own role check allows.
|
|
142
|
+
def authorized_for?(role)
|
|
143
|
+
caller = Runtime::Caller.current
|
|
144
|
+
return false unless caller&.actor_id
|
|
145
|
+
return false unless @dispatcher.registry.authorization_provider_for(@domain)
|
|
146
|
+
|
|
147
|
+
Ports::Authorization.holds_role?(@dispatcher.registry, actor_id: caller.actor_id, role: role,
|
|
148
|
+
as_of: caller.as_of, scope: caller.scope)
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def reader?(name)
|
|
152
|
+
!@ir.attribute(name).nil? || @ir.lifecycle&.field&.to_sym == name
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
# Real singleton methods, not method_missing: a verb named `freeze` or
|
|
156
|
+
# `send` (both real, e.g. Account::Freeze, ExternalTransfer::Send) would
|
|
157
|
+
# otherwise silently hit the Kernel method instead of dispatching.
|
|
158
|
+
def define_verb_methods
|
|
159
|
+
@ir.commands.reject(&:creates?).each do |command|
|
|
160
|
+
define_singleton_method("#{Naming.snake(command.hecks_name)}!") do |**args|
|
|
161
|
+
run(command, **args)
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
# `@ir.identified_by` is only the single-head shorthand (nil for a
|
|
167
|
+
# composite identity, e.g. SafeDepositBox's branch_code/box_number);
|
|
168
|
+
# this reads every head through `identity_heads` instead.
|
|
169
|
+
def run(command, **args)
|
|
170
|
+
@state = @dispatcher.dispatch("#{fqn}.#{command.hecks_name}", to: @id, with: args).instance.state
|
|
171
|
+
self
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
# Lazy hop: `transfer.source_account` resolves to the actual record only
|
|
175
|
+
# when called; nothing loads until then, so chains like
|
|
176
|
+
# `payment.disputed_by_customer.name` stay lazy at every step.
|
|
177
|
+
#
|
|
178
|
+
# Defined before verb methods so a same-named verb wins the name on the
|
|
179
|
+
# rare collision; `initialize` calls this first for that reason.
|
|
180
|
+
#
|
|
181
|
+
# The accessor is named like the attribute itself, never `<name>_id`
|
|
182
|
+
# (ADR 0025) — `piece.account` and `piece[:account]` (bracket access,
|
|
183
|
+
# the raw id) never collide despite sharing a name.
|
|
184
|
+
def define_reference_accessors
|
|
185
|
+
@ir.attributes.select(&:reference?).each do |attribute|
|
|
186
|
+
target = attribute.type.resolve
|
|
187
|
+
# Cross-domain, or otherwise unresolvable — no accessor rather than a guess.
|
|
188
|
+
next unless target
|
|
189
|
+
|
|
190
|
+
domain = @domain
|
|
191
|
+
field = attribute.name
|
|
192
|
+
list = attribute.list?
|
|
193
|
+
target_fqn = "#{domain}::#{target.hecks_name}"
|
|
194
|
+
|
|
195
|
+
define_singleton_method(field) do
|
|
196
|
+
value = self[field]
|
|
197
|
+
door = Object.const_get(target_fqn)
|
|
198
|
+
next Array(value).map { |identity| door.find(identity) } if list
|
|
199
|
+
|
|
200
|
+
value && door.find(value)
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
end
|
|
@@ -0,0 +1,132 @@
|
|
|
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 Doors
|
|
10
|
+
# The JSON door: translates URL segments and parsed JSON bodies to and from the facade.
|
|
11
|
+
# No HTTP lives here; every miss raises `Runtime::NotFound`, distinguished by message.
|
|
12
|
+
module JsonDoor
|
|
13
|
+
module_function
|
|
14
|
+
|
|
15
|
+
# Resolves a domain name and an aggregate name, as two URL segments carry them, to
|
|
16
|
+
# that aggregate's door.
|
|
17
|
+
#
|
|
18
|
+
# The name is checked against the current boot's IR before Ruby's constant table, so
|
|
19
|
+
# a stale same-named constant from an earlier boot is never returned.
|
|
20
|
+
#
|
|
21
|
+
# @param dispatcher [Runtime::Dispatcher, Runtime::RemoteDispatcher] the booted dispatcher
|
|
22
|
+
# @param domain [String, Symbol] the chapter name, such as `"Banking"`
|
|
23
|
+
# @param name [String, Symbol] the aggregate's declared name, such as `"Customer"`
|
|
24
|
+
# @return [Module] the aggregate door installed at `domain::name`
|
|
25
|
+
# @raise [Runtime::NotFound] if the chapter or its aggregate is not declared
|
|
26
|
+
# @raise [NameError] if the aggregate has no facade constant (`install_doors: false`)
|
|
27
|
+
def aggregate(dispatcher, domain, name)
|
|
28
|
+
ir = dispatcher.registry.bluebook(domain)&.aggregate(name)
|
|
29
|
+
raise Runtime::NotFound, "#{domain} declares no aggregate named #{name.inspect}" unless ir
|
|
30
|
+
|
|
31
|
+
Object.const_get("#{domain}::#{ir.hecks_name}")
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Names the door method that creates a record of this aggregate: the first command
|
|
35
|
+
# it declares that `creates?`, spelled as a Ruby caller would (`"create_pizza!"`).
|
|
36
|
+
#
|
|
37
|
+
# @param klass [Module] an aggregate door, as `aggregate` returns
|
|
38
|
+
# @return [String] the method name to `public_send` to the door
|
|
39
|
+
# @raise [Runtime::NotFound] if the aggregate declares no creating command
|
|
40
|
+
def creating_command(klass)
|
|
41
|
+
creating = klass.ir.commands.find(&:creates?)
|
|
42
|
+
raise Runtime::NotFound, "#{klass.ir.hecks_name} declares no creating command" unless creating
|
|
43
|
+
|
|
44
|
+
"#{Naming.snake(creating.hecks_name)}!"
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Confirms that a command name arriving as text is one a `Handle` of this aggregate
|
|
48
|
+
# answers, before a caller `public_send`s it.
|
|
49
|
+
#
|
|
50
|
+
# A `Handle` defines only the non-creating commands, so the creating command is
|
|
51
|
+
# rejected here rather than failing later as a raw `NoMethodError`.
|
|
52
|
+
#
|
|
53
|
+
# @param klass [Module] an aggregate door, as `aggregate` returns
|
|
54
|
+
# @param name [String, Symbol] the wanted method name with its bang, such as
|
|
55
|
+
# `"add_topping!"`
|
|
56
|
+
# @return [String] `name` as a String, unchanged, when a `Handle` answers it
|
|
57
|
+
# @raise [Runtime::NotFound] if no non-creating command has that method name
|
|
58
|
+
def validate_command!(klass, name)
|
|
59
|
+
wanted = name.to_s
|
|
60
|
+
dispatchable = klass.ir.commands.reject(&:creates?).map { |command| "#{Naming.snake(command.hecks_name)}!" }
|
|
61
|
+
return wanted if dispatchable.include?(wanted)
|
|
62
|
+
|
|
63
|
+
raise Runtime::NotFound, "#{klass.ir.hecks_name} declares no command named #{wanted.inspect}"
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Fetches one record by id, raising instead of answering nil on a miss.
|
|
67
|
+
#
|
|
68
|
+
# @param klass [Module] an aggregate door, as `aggregate` returns
|
|
69
|
+
# @param id [String] the record's identity, as the URL carried it
|
|
70
|
+
# @return [Doors::Handle] the record in hand
|
|
71
|
+
# @raise [Runtime::NotFound] if the repository holds no record with that id
|
|
72
|
+
def find!(klass, id)
|
|
73
|
+
klass.find(id) or raise Runtime::NotFound, "no #{klass.ir.hecks_name} found for id #{id.inspect}"
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Converts every Hash key to a Symbol, at every depth of a parsed JSON body.
|
|
77
|
+
#
|
|
78
|
+
# @param value [Hash, Array, Object] parsed JSON: a Hash or Array is walked, any
|
|
79
|
+
# other value is a leaf
|
|
80
|
+
# @return [Hash{Symbol => Object}, Array, Object] a new structure of the same shape
|
|
81
|
+
# with Symbol keys; a leaf is returned as it came
|
|
82
|
+
def deep_symbolize(value)
|
|
83
|
+
case value
|
|
84
|
+
when Hash then value.to_h { |k, v| [k.to_sym, deep_symbolize(v)] }
|
|
85
|
+
when Array then value.map { |item| deep_symbolize(item) }
|
|
86
|
+
else value
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# Unwraps a record, a query row, or any value holding `Runtime::Value`s into plain
|
|
91
|
+
# Hashes, Arrays and scalars a JSON encoder can walk.
|
|
92
|
+
#
|
|
93
|
+
# Delegates to `Runtime::Value.materialize`; the only addition is `#to_h` on a
|
|
94
|
+
# `Handle`, which `materialize` does not recognize.
|
|
95
|
+
#
|
|
96
|
+
# @param value [Doors::Handle, Runtime::Value, Hash, Array, Object] what to unwrap;
|
|
97
|
+
# a `Handle` is read through its `to_h`, so its `:id` comes along
|
|
98
|
+
# @return [Hash, Array, Object] the same data with every `Runtime::Value` replaced
|
|
99
|
+
# by a Hash of its fields; any other value is returned as it came
|
|
100
|
+
def materialize(value)
|
|
101
|
+
value = value.to_h if value.is_a?(Handle)
|
|
102
|
+
Runtime::Value.materialize(value)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# Turns a command's JSON body, raw or already parsed, into the `to:`/`with:`
|
|
106
|
+
# envelope a dispatcher takes. The result splats into `Dispatcher#dispatch`.
|
|
107
|
+
#
|
|
108
|
+
# @param body [String, Hash] raw JSON text, or the Hash it parses to
|
|
109
|
+
# @param receiver [Symbol, nil] `:aggregate`, `:entity`, or `nil` for none
|
|
110
|
+
# (see `CommandRequest.normalize`)
|
|
111
|
+
# @param legacy_receiver [Symbol, String, Hash{Symbol => Symbol, String}, nil] the flat key,
|
|
112
|
+
# or pair of keys, a body without `to` may name its receiver under; `nil` accepts none
|
|
113
|
+
# @return [Hash{Symbol => Object}] `{ with: facts }`, plus `to:` unless `receiver` is `nil`
|
|
114
|
+
# @raise [JSON::ParserError] if `body` is a String that is not valid JSON
|
|
115
|
+
# @raise [Runtime::TypeMismatch] if the body is not a JSON object or its routing is malformed
|
|
116
|
+
# @raise [ArgumentError] if `receiver` is not `nil`, `:aggregate` or `:entity`
|
|
117
|
+
def command_request(body, receiver:, legacy_receiver: nil)
|
|
118
|
+
input = body.is_a?(String) ? parse(body) : body
|
|
119
|
+
CommandRequest.normalize(input, receiver: receiver, legacy_receiver: legacy_receiver)
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# Parses a raw request body, leaving keys as Strings. `JSON::ParserError` propagates
|
|
123
|
+
# unwrapped.
|
|
124
|
+
#
|
|
125
|
+
# @param raw_json [String] JSON text, such as a POST body
|
|
126
|
+
# @return [Hash{String => Object}, Array, String, Numeric, Boolean, nil] whatever
|
|
127
|
+
# the text encodes
|
|
128
|
+
# @raise [JSON::ParserError] if the text is not valid JSON
|
|
129
|
+
def parse(raw_json) = JSON.parse(raw_json)
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
end
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
require_relative "../ports/identity_generation"
|
|
2
|
+
require_relative "../runtime/errors"
|
|
3
|
+
require_relative "cli_door"
|
|
4
|
+
|
|
5
|
+
module Hecks
|
|
6
|
+
module Doors
|
|
7
|
+
# What a domain's world file adds to its generated launcher, all of it opt-in.
|
|
8
|
+
#
|
|
9
|
+
# A `.world` that declares a `launcher` setting switches these on for that chapter; a
|
|
10
|
+
# domain without one keeps the launcher's plain forms exactly:
|
|
11
|
+
#
|
|
12
|
+
# launcher "Launcher", run_keys: true, failure_states: %w[flagged failed],
|
|
13
|
+
# names: { "mcp" => "serve_mcp" }
|
|
14
|
+
#
|
|
15
|
+
# - **run_keys** mints the `run` key of a creating command that was given none.
|
|
16
|
+
# - **failure_states** are the lifecycle states `--wait` reports as a failure (exit 1).
|
|
17
|
+
# - **names** maps a launcher name to the command it stands for (see `CliProjector`).
|
|
18
|
+
module LauncherOptions
|
|
19
|
+
SETTING = "launcher".freeze
|
|
20
|
+
WAIT = "--wait".freeze
|
|
21
|
+
RUN_KEY = "run.value".freeze
|
|
22
|
+
|
|
23
|
+
module_function
|
|
24
|
+
|
|
25
|
+
# Reads a chapter's `launcher` setting.
|
|
26
|
+
#
|
|
27
|
+
# @param runtime [Runtime::Dispatcher, Runtime::RemoteDispatcher] the booted domain
|
|
28
|
+
# @param chapter [String] the chapter the command line speaks to
|
|
29
|
+
# @return [Hash{Symbol => Object}, nil] the setting, or nil when the chapter did not opt in
|
|
30
|
+
def settings(runtime, chapter)
|
|
31
|
+
return unless runtime.respond_to?(:registry)
|
|
32
|
+
|
|
33
|
+
found = runtime.registry.world(chapter)&.for_verb(SETTING)
|
|
34
|
+
found.nil? || found.empty? ? nil : found
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# The options the launcher's projection is asked for: the program's name, the chapter's
|
|
38
|
+
# launcher names, and whether run keys are minted (so help shows them optional).
|
|
39
|
+
#
|
|
40
|
+
# @param settings [Hash, nil] the chapter's `launcher` setting
|
|
41
|
+
# @param program [String] how the caller was invoked
|
|
42
|
+
# @return [Hash{Symbol => Object}] the options `Projector::CliProjector` reads
|
|
43
|
+
def projection(settings, program)
|
|
44
|
+
{ program: program, names: settings && settings[:names], mint_run_keys: settings && settings[:run_keys] }
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Takes `--wait` out of a verb's words, unless the verb declares a `wait` argument of its own.
|
|
48
|
+
#
|
|
49
|
+
# `--wait=false` (or `no`, `0`, `off`) is a `--wait` that was switched off; a bare `--wait`
|
|
50
|
+
# may be followed by its Boolean word.
|
|
51
|
+
#
|
|
52
|
+
# @param spec [Hash] the verb's projected spec
|
|
53
|
+
# @param words [Array<String>] the words after the verb
|
|
54
|
+
# @return [Array(Array<String>, Boolean)] the remaining words, and whether `--wait` was given
|
|
55
|
+
# @raise [Runtime::TypeMismatch] if `--wait=` carries something that is not a Boolean word
|
|
56
|
+
def take_wait(spec, words)
|
|
57
|
+
return [words, false] unless words.any? { |word| wait_word?(word) }
|
|
58
|
+
return [words, false] if spec[:arguments].any? { |argument| argument[:path].split(".").first == "wait" }
|
|
59
|
+
|
|
60
|
+
wait = false
|
|
61
|
+
rest = []
|
|
62
|
+
queue = words.dup
|
|
63
|
+
until queue.empty?
|
|
64
|
+
word = queue.shift
|
|
65
|
+
wait_word?(word) ? wait ||= CliDoor.boolean(wait_value(word, queue)) : rest << word
|
|
66
|
+
end
|
|
67
|
+
[rest, wait]
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# @api private
|
|
71
|
+
def wait_word?(word) = word == WAIT || word.start_with?("#{WAIT}=")
|
|
72
|
+
|
|
73
|
+
# The Boolean word a `--wait` carries: after `=`, or the next word when it is one.
|
|
74
|
+
# @api private
|
|
75
|
+
def wait_value(word, queue)
|
|
76
|
+
return word.split("=", 2).last if word.include?("=")
|
|
77
|
+
|
|
78
|
+
CliDoor::BOOLEAN_WORDS.key?(queue.first.to_s.downcase) ? queue.shift : "true"
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Whether a question's text answer reports a gap, which `--wait` turns into a failing exit.
|
|
82
|
+
#
|
|
83
|
+
# The coverage checks end their report with a `GAP (n)` heading; a non-zero count is a
|
|
84
|
+
# finding, and a CI stage that waits on the question fails on it.
|
|
85
|
+
#
|
|
86
|
+
# @param text [String, nil] the question's text answer
|
|
87
|
+
# @return [Boolean] whether a `GAP (n)` heading with n above zero is in the text
|
|
88
|
+
def gap_reported?(text)
|
|
89
|
+
text.is_a?(String) && text.match?(/^GAP \((?!0\))\d+\)/)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Mints the `run` key a creating command was not given, when the domain opted in.
|
|
93
|
+
#
|
|
94
|
+
# An explicit key always wins. Nothing is minted for a command that acts on an existing
|
|
95
|
+
# record. When no identity adapter is bound the run is refused, saying to name a key,
|
|
96
|
+
# rather than sent on without one.
|
|
97
|
+
#
|
|
98
|
+
# @param runtime [Runtime::Dispatcher, Runtime::RemoteDispatcher] the booted domain
|
|
99
|
+
# @param spec [Hash] the verb's projected spec
|
|
100
|
+
# @param args [Hash] the parsed arguments
|
|
101
|
+
# @param settings [Hash, nil] the chapter's `launcher` setting
|
|
102
|
+
# @return [Array(Hash, String)] the arguments, and the key minted (nil when none was)
|
|
103
|
+
# @raise [Runtime::NotFound] if a key is owed but no identity adapter is bound
|
|
104
|
+
def run_key(runtime, spec, args, settings)
|
|
105
|
+
return [args, nil] unless settings && settings[:run_keys] && spec[:creates]
|
|
106
|
+
return [args, nil] unless spec[:arguments].any? { |argument| argument[:path] == RUN_KEY }
|
|
107
|
+
return [args, nil] if args.key?(:run) || !runtime.respond_to?(:registry)
|
|
108
|
+
|
|
109
|
+
key = Ports::IdentityGeneration.uuid(runtime.registry)
|
|
110
|
+
[args.merge(run: { value: key }), key]
|
|
111
|
+
rescue Runtime::WiringError => e
|
|
112
|
+
raise Runtime::NotFound, "cannot mint a run key (#{e.message.lines.first.strip}); name one with run=<key>"
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# Whether a settled record sits in one of the chapter's failure states.
|
|
116
|
+
#
|
|
117
|
+
# @param aggregate [Bluebook::Aggregate, nil] the record's aggregate
|
|
118
|
+
# @param state [Hash, nil] the record's state
|
|
119
|
+
# @param settings [Hash, nil] the chapter's `launcher` setting
|
|
120
|
+
# @return [Boolean] false when the aggregate has no lifecycle
|
|
121
|
+
def failed?(aggregate, state, settings)
|
|
122
|
+
field = aggregate&.lifecycle&.field
|
|
123
|
+
return false unless field && state
|
|
124
|
+
|
|
125
|
+
Array(settings && settings[:failure_states]).map(&:to_s).include?(state[field.to_sym].to_s)
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
end
|