hecks 0.2.0 → 1.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 +5 -5
- data/lib/hecks/adapters/driven/claude_code.adapter +3 -0
- data/lib/hecks/adapters/driven/claude_code.rb +127 -0
- data/lib/hecks/adapters/driven/d1.adapter +12 -0
- data/lib/hecks/adapters/driven/d1.rb +427 -0
- data/lib/hecks/adapters/driven/folder.adapter +3 -0
- data/lib/hecks/adapters/driven/folder.rb +199 -0
- data/lib/hecks/adapters/driven/google_authentication.adapter +3 -0
- data/lib/hecks/adapters/driven/google_authentication.rb +100 -0
- data/lib/hecks/adapters/driven/governance_authorization.adapter +3 -0
- data/lib/hecks/adapters/driven/governance_authorization.rb +101 -0
- data/lib/hecks/adapters/driven/heki/journal.rb +56 -0
- data/lib/hecks/adapters/driven/heki/saga_store.rb +99 -0
- data/lib/hecks/adapters/driven/heki/snapshot.rb +65 -0
- data/lib/hecks/adapters/driven/heki.adapter +4 -0
- data/lib/hecks/adapters/driven/heki.rb +179 -0
- data/lib/hecks/adapters/driven/identity_registry.adapter +3 -0
- data/lib/hecks/adapters/driven/identity_registry.rb +26 -0
- data/lib/hecks/adapters/driven/in_memory_ordering.rb +51 -0
- data/lib/hecks/adapters/driven/lambda/client.rb +63 -0
- data/lib/hecks/adapters/driven/lambda.adapter +4 -0
- data/lib/hecks/adapters/driven/lambda.rb +145 -0
- data/lib/hecks/adapters/driven/memory.adapter +3 -0
- data/lib/hecks/adapters/driven/memory.rb +103 -0
- data/lib/hecks/adapters/driven/mock_stripe_adapter.adapter +3 -0
- data/lib/hecks/adapters/driven/mock_stripe_adapter.rb +28 -0
- data/lib/hecks/adapters/driven/postgres/codec.rb +88 -0
- data/lib/hecks/adapters/driven/postgres/schema_builder.rb +207 -0
- data/lib/hecks/adapters/driven/postgres.adapter +5 -0
- data/lib/hecks/adapters/driven/postgres.rb +438 -0
- data/lib/hecks/adapters/driven/postgres_era.adapter +17 -0
- data/lib/hecks/adapters/driven/prism.adapter +3 -0
- data/lib/hecks/adapters/driven/prism.rb +80 -0
- data/lib/hecks/adapters/driven/secure_random_identity.adapter +3 -0
- data/lib/hecks/adapters/driven/secure_random_identity.rb +14 -0
- data/lib/hecks/adapters/driven/sql_query_builder.rb +221 -0
- data/lib/hecks/adapters/driven/sqlite/codec.rb +80 -0
- data/lib/hecks/adapters/driven/sqlite/projection.rb +172 -0
- data/lib/hecks/adapters/driven/sqlite/schema_builder.rb +192 -0
- data/lib/hecks/adapters/driven/sqlite.adapter +9 -0
- data/lib/hecks/adapters/driven/sqlite.rb +306 -0
- data/lib/hecks/adapters/driven/system_clock.adapter +3 -0
- data/lib/hecks/adapters/driven/system_clock.rb +14 -0
- data/lib/hecks/adapters/driven.rb +54 -0
- data/lib/hecks/adapters.rb +6 -0
- data/lib/hecks/behaviors/dsl.rb +125 -0
- data/lib/hecks/behaviors/expectations.rb +340 -0
- data/lib/hecks/behaviors/ir.rb +31 -0
- data/lib/hecks/behaviors/rspec.rb +42 -0
- data/lib/hecks/behaviors/runner.rb +96 -0
- data/lib/hecks/behaviors.rb +25 -0
- data/lib/hecks/bluebook/aggregate.rb +108 -0
- data/lib/hecks/bluebook/assembly/aggregate_assembly.rb +134 -0
- data/lib/hecks/bluebook/assembly/build.rb +48 -0
- data/lib/hecks/bluebook/assembly/contract.rb +112 -0
- data/lib/hecks/bluebook/assembly/contracts.rb +438 -0
- data/lib/hecks/bluebook/assembly/marks.rb +228 -0
- data/lib/hecks/bluebook/assembly/specializer.rb +70 -0
- data/lib/hecks/bluebook/assembly.rb +91 -0
- data/lib/hecks/bluebook/attribute.rb +96 -0
- data/lib/hecks/bluebook/behaviour/aggregate.rb +83 -0
- data/lib/hecks/bluebook/behaviour/attribute.rb +27 -0
- data/lib/hecks/bluebook/behaviour/chapter.rb +72 -0
- data/lib/hecks/bluebook/behaviour/command.rb +116 -0
- data/lib/hecks/bluebook/behaviour/domain_port.rb +25 -0
- data/lib/hecks/bluebook/behaviour/entity.rb +59 -0
- data/lib/hecks/bluebook/behaviour/hexagon.rb +50 -0
- data/lib/hecks/bluebook/behaviour/lifecycle.rb +68 -0
- data/lib/hecks/bluebook/behaviour/policy.rb +52 -0
- data/lib/hecks/bluebook/behaviour/process_manager.rb +51 -0
- data/lib/hecks/bluebook/behaviour/query.rb +10 -0
- data/lib/hecks/bluebook/behaviour/read_model.rb +29 -0
- data/lib/hecks/bluebook/behaviour/traits.rb +81 -0
- data/lib/hecks/bluebook/behaviour/value_object.rb +33 -0
- data/lib/hecks/bluebook/chapter.rb +78 -0
- data/lib/hecks/bluebook/command.rb +124 -0
- data/lib/hecks/bluebook/domain_port.rb +102 -0
- data/lib/hecks/bluebook/dsl/adapter_builder.rb +34 -0
- data/lib/hecks/bluebook/dsl/aggregate_builder.rb +1018 -0
- data/lib/hecks/bluebook/dsl/attribute_collector.rb +348 -0
- data/lib/hecks/bluebook/dsl/binding_proxy.rb +71 -0
- data/lib/hecks/bluebook/dsl/bluebook_builder.rb +1087 -0
- data/lib/hecks/bluebook/dsl/command_builder.rb +714 -0
- data/lib/hecks/bluebook/dsl/const_shim.rb +81 -0
- data/lib/hecks/bluebook/dsl/domain_port_builder.rb +79 -0
- data/lib/hecks/bluebook/dsl/entity_builder.rb +430 -0
- data/lib/hecks/bluebook/dsl/generic_dispatch.rb +366 -0
- data/lib/hecks/bluebook/dsl/hecksagon_builder.rb +163 -0
- data/lib/hecks/bluebook/dsl/identity_declaration.rb +191 -0
- data/lib/hecks/bluebook/dsl/lifecycle_builder.rb +44 -0
- data/lib/hecks/bluebook/dsl/malformed.rb +7 -0
- data/lib/hecks/bluebook/dsl/policy_builder.rb +135 -0
- data/lib/hecks/bluebook/dsl/port_builder.rb +39 -0
- data/lib/hecks/bluebook/dsl/port_operation_builder.rb +142 -0
- data/lib/hecks/bluebook/dsl/process_manager_builder.rb +306 -0
- data/lib/hecks/bluebook/dsl/query_builder.rb +113 -0
- data/lib/hecks/bluebook/dsl/read_model_builder.rb +233 -0
- data/lib/hecks/bluebook/dsl/rule_reference.rb +173 -0
- data/lib/hecks/bluebook/dsl/translation_builder.rb +243 -0
- data/lib/hecks/bluebook/dsl/value_object_builder.rb +178 -0
- data/lib/hecks/bluebook/dsl/word_gate.rb +228 -0
- data/lib/hecks/bluebook/dsl/world_builder.rb +117 -0
- data/lib/hecks/bluebook/dsl.rb +45 -0
- data/lib/hecks/bluebook/entity.rb +103 -0
- data/lib/hecks/bluebook/expression/canonical_form.rb +123 -0
- data/lib/hecks/bluebook/expression/evaluator.rb +304 -0
- data/lib/hecks/bluebook/expression/projection.json +218 -0
- data/lib/hecks/bluebook/expression/resolver/block_predicates.rb +233 -0
- data/lib/hecks/bluebook/expression/resolver.rb +781 -0
- data/lib/hecks/bluebook/expression.rb +13 -0
- data/lib/hecks/bluebook/hexagon.rb +60 -0
- data/lib/hecks/bluebook/lifecycle.rb +42 -0
- data/lib/hecks/bluebook/meta_validator/adapter_judge.rb +54 -0
- data/lib/hecks/bluebook/meta_validator/judge.rb +621 -0
- data/lib/hecks/bluebook/meta_validator/plan.rb +332 -0
- data/lib/hecks/bluebook/meta_validator/port_judge.rb +51 -0
- data/lib/hecks/bluebook/meta_validator/readings.rb +360 -0
- data/lib/hecks/bluebook/meta_validator/reconstruction.rb +351 -0
- data/lib/hecks/bluebook/meta_validator/shapes.rb +266 -0
- data/lib/hecks/bluebook/meta_validator/syntax_boot.rb +255 -0
- data/lib/hecks/bluebook/meta_validator/translation_judge.rb +138 -0
- data/lib/hecks/bluebook/meta_validator/world_judge.rb +78 -0
- data/lib/hecks/bluebook/meta_validator.rb +542 -0
- data/lib/hecks/bluebook/model_check.rb +445 -0
- data/lib/hecks/bluebook/pattern_subset.rb +184 -0
- data/lib/hecks/bluebook/policy.rb +41 -0
- data/lib/hecks/bluebook/process_manager.rb +128 -0
- data/lib/hecks/bluebook/project_discovery.rb +30 -0
- data/lib/hecks/bluebook/project_loader.rb +40 -0
- data/lib/hecks/bluebook/project_register.rb +82 -0
- data/lib/hecks/bluebook/query.rb +61 -0
- data/lib/hecks/bluebook/read_model.rb +109 -0
- data/lib/hecks/bluebook/reference.rb +74 -0
- data/lib/hecks/bluebook/smoke_test.rb +166 -0
- data/lib/hecks/bluebook/synthesizer.rb +95 -0
- data/lib/hecks/bluebook/translation.rb +92 -0
- data/lib/hecks/bluebook/value_object.rb +66 -0
- data/lib/hecks/bluebook.rb +74 -0
- data/lib/hecks/codemod.rb +342 -0
- data/lib/hecks/construct.rb +71 -0
- data/lib/hecks/deploy/bluebook/deploy.bluebook +219 -0
- data/lib/hecks/deploy/bluebook/deploy.hecksagon +4 -0
- data/lib/hecks/deploy/oidc.json +18 -0
- data/lib/hecks/doc/reference.rb +410 -0
- data/lib/hecks/embryonaut_bluebook.rb +75 -0
- data/lib/hecks/facade/cli_door.rb +119 -0
- data/lib/hecks/facade/cli_runner.rb +190 -0
- data/lib/hecks/facade/command_request.rb +105 -0
- data/lib/hecks/facade/handle.rb +173 -0
- data/lib/hecks/facade/json_door.rb +166 -0
- data/lib/hecks/facade/surface/aggregate_door.rb +185 -0
- data/lib/hecks/facade/surface/chapter.rb +107 -0
- data/lib/hecks/facade/surface.rb +48 -0
- data/lib/hecks/facade.rb +44 -0
- data/lib/hecks/forms/app.rb +341 -0
- data/lib/hecks/forms/command_form_renderer.rb +113 -0
- data/lib/hecks/forms/examples/banking_console.bluebook +3 -0
- data/lib/hecks/forms/field_renderer.rb +177 -0
- data/lib/hecks/forms/field_shape.rb +232 -0
- data/lib/hecks/forms/html.rb +84 -0
- data/lib/hecks/forms/index_renderer.rb +35 -0
- data/lib/hecks/forms/page.rb +157 -0
- data/lib/hecks/forms/params.rb +161 -0
- data/lib/hecks/forms/port_argument.rb +46 -0
- data/lib/hecks/forms/query_form_renderer.rb +114 -0
- data/lib/hecks/forms/record_renderer.rb +119 -0
- data/lib/hecks/forms/record_table.rb +68 -0
- data/lib/hecks/forms/reference_options.rb +30 -0
- data/lib/hecks/forms/value_object_shape.rb +46 -0
- data/lib/hecks/forms.rb +54 -0
- data/lib/hecks/fqn.rb +94 -0
- data/lib/hecks/framework/bluebook/compliance.bluebook +1 -0
- data/lib/hecks/framework/bluebook/console_settings.bluebook +489 -0
- data/lib/hecks/framework/bluebook/framework.hecksagon +32 -0
- data/lib/hecks/framework/bluebook/governance.bluebook +145 -0
- data/lib/hecks/framework/bluebook/identity.bluebook +90 -0
- data/lib/hecks/framework/oidc.json +39 -0
- data/lib/hecks/framework.rb +90 -0
- data/lib/hecks/freezer.rb +67 -0
- data/lib/hecks/fuzzing/bounded_exhaustive_expressions.rb +527 -0
- data/lib/hecks/fuzzing/invalid_value_generator.rb +86 -0
- data/lib/hecks/fuzzing/isolated_boot.rb +286 -0
- data/lib/hecks/fuzzing/properties.rb +1192 -0
- data/lib/hecks/fuzzing/replay.rb +668 -0
- data/lib/hecks/fuzzing/sequence_generator/catalog.rb +93 -0
- data/lib/hecks/fuzzing/sequence_generator/outcome_tracker.rb +80 -0
- data/lib/hecks/fuzzing/sequence_generator/picker.rb +96 -0
- data/lib/hecks/fuzzing/sequence_generator/step_builder.rb +250 -0
- data/lib/hecks/fuzzing/sequence_generator.rb +131 -0
- data/lib/hecks/fuzzing/value_generator.rb +200 -0
- data/lib/hecks/fuzzing.rb +12 -0
- data/lib/hecks/grammar/evolve.rb +324 -0
- data/lib/hecks/grammar/expression.bluebook +420 -0
- data/lib/hecks/grammar/expression_operators.json +1648 -0
- data/lib/hecks/grammar/grammar.hecksagon +20 -0
- data/lib/hecks/grammar/oidc.json +69 -0
- data/lib/hecks/grammar/translation.bluebook +203 -0
- data/lib/hecks/grammar.rb +178 -0
- data/lib/hecks/ir.rb +126 -0
- data/lib/hecks/language/adapter.bluebook +116 -0
- data/lib/hecks/language/bluebook/aggregate.bluebook +581 -0
- data/lib/hecks/language/bluebook/attaches/paging.bluebook +76 -0
- data/lib/hecks/language/bluebook/bluebook.bluebook +256 -0
- data/lib/hecks/language/bluebook/bluebook.hecksagon +24 -0
- data/lib/hecks/language/bluebook/command.bluebook +471 -0
- data/lib/hecks/language/bluebook/entity.bluebook +392 -0
- data/lib/hecks/language/bluebook/policy.bluebook +189 -0
- data/lib/hecks/language/bluebook/process_manager.bluebook +381 -0
- data/lib/hecks/language/bluebook/projection.bluebook +267 -0
- data/lib/hecks/language/bluebook/query.bluebook +245 -0
- data/lib/hecks/language/bluebook/shape.bluebook +292 -0
- data/lib/hecks/language/bluebook/syntax.bluebook +448 -0
- data/lib/hecks/language/bluebook/vocabulary.bluebook +379 -0
- data/lib/hecks/language/hecksagon/adapter_binding.bluebook +51 -0
- data/lib/hecks/language/hecksagon/domain_port.bluebook +76 -0
- data/lib/hecks/language/hecksagon/hecksagon.bluebook +131 -0
- data/lib/hecks/language/hecksagon/port_operation.bluebook +102 -0
- data/lib/hecks/language/oidc.json +333 -0
- data/lib/hecks/language/port.bluebook +120 -0
- data/lib/hecks/language/translation/translation.bluebook +110 -0
- data/lib/hecks/language/translation/translation_aggregate.bluebook +267 -0
- data/lib/hecks/language/world/wiring.bluebook +62 -0
- data/lib/hecks/language/world/world.bluebook +84 -0
- data/lib/hecks/literal.rb +125 -0
- data/lib/hecks/naming.rb +174 -0
- data/lib/hecks/ports/access_control.port +9 -0
- data/lib/hecks/ports/access_control.rb +62 -0
- data/lib/hecks/ports/agent/answers.rb +104 -0
- data/lib/hecks/ports/agent.port +8 -0
- data/lib/hecks/ports/agent.rb +167 -0
- data/lib/hecks/ports/authentication.port +6 -0
- data/lib/hecks/ports/authentication.rb +50 -0
- data/lib/hecks/ports/authorization.port +7 -0
- data/lib/hecks/ports/authorization.rb +62 -0
- data/lib/hecks/ports/clock.port +5 -0
- data/lib/hecks/ports/clock.rb +62 -0
- data/lib/hecks/ports/extraction.port +5 -0
- data/lib/hecks/ports/extraction.rb +37 -0
- data/lib/hecks/ports/identity_assignment.port +5 -0
- data/lib/hecks/ports/identity_assignment.rb +45 -0
- data/lib/hecks/ports/identity_generation.port +5 -0
- data/lib/hecks/ports/identity_generation.rb +49 -0
- data/lib/hecks/ports/identity_resolution.port +5 -0
- data/lib/hecks/ports/identity_resolution.rb +40 -0
- data/lib/hecks/ports/loading.port +4 -0
- data/lib/hecks/ports/loading.rb +13 -0
- data/lib/hecks/ports/persistence/append_only.rb +138 -0
- data/lib/hecks/ports/persistence/binding_policy.rb +56 -0
- data/lib/hecks/ports/persistence/execution.rb +23 -0
- data/lib/hecks/ports/persistence/null_saga_store.rb +25 -0
- data/lib/hecks/ports/persistence/plugin.rb +54 -0
- data/lib/hecks/ports/persistence/plugins/era/era_check.rb +169 -0
- data/lib/hecks/ports/persistence/plugins/era/era_guard/shape_diff.rb +128 -0
- data/lib/hecks/ports/persistence/plugins/era/era_guard.rb +161 -0
- data/lib/hecks/ports/persistence/plugins/era/era_tamper.rb +61 -0
- data/lib/hecks/ports/persistence/plugins/era/lineage.rb +304 -0
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/era_store.rb +171 -0
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/field_cache.rb +190 -0
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/head_compiler.rb +478 -0
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/mint_transaction.rb +166 -0
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/provisioning.rb +314 -0
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/resumable_backfill.rb +168 -0
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/tail_merge.rb +170 -0
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/transform_installer.rb +134 -0
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage.rb +137 -0
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/coverage_check.rb +89 -0
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/era_resolver.rb +85 -0
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/merge_coordinator.rb +43 -0
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/minter.rb +132 -0
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager.rb +74 -0
- data/lib/hecks/ports/persistence/plugins/era/postgres_era.rb +758 -0
- data/lib/hecks/ports/persistence/plugins/era/storage_shape.rb +120 -0
- data/lib/hecks/ports/persistence/plugins/era/translation/audit/approval_digest.rb +31 -0
- data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_one.rb +46 -0
- data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_two.rb +102 -0
- data/lib/hecks/ports/persistence/plugins/era/translation/audit/unfed_report.rb +46 -0
- data/lib/hecks/ports/persistence/plugins/era/translation/audit.rb +70 -0
- data/lib/hecks/ports/persistence/plugins/era/translation/reattest.rb +72 -0
- data/lib/hecks/ports/persistence/plugins/era/translation/rule_compiler.rb +120 -0
- data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/differ.rb +183 -0
- data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/renderer.rb +41 -0
- data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/writer.rb +28 -0
- data/lib/hecks/ports/persistence/plugins/era/translation/scaffold.rb +30 -0
- data/lib/hecks/ports/persistence/plugins/era/translation.rb +11 -0
- data/lib/hecks/ports/persistence/plugins/era.rb +48 -0
- data/lib/hecks/ports/persistence/remote_runtime.rb +42 -0
- data/lib/hecks/ports/persistence/repository_factory.rb +30 -0
- data/lib/hecks/ports/persistence.port +4 -0
- data/lib/hecks/ports/persistence.rb +39 -0
- data/lib/hecks/ports/projection.port +4 -0
- data/lib/hecks/ports/projection.rb +96 -0
- data/lib/hecks/ports/query/in_memory.rb +60 -0
- data/lib/hecks/ports/query/ordering.rb +41 -0
- data/lib/hecks/ports/query.rb +36 -0
- data/lib/hecks/ports.rb +27 -0
- data/lib/hecks/projections/diagrams.rb +642 -0
- data/lib/hecks/projections/ir.rb +18 -0
- data/lib/hecks/projections/model/deviations.rb +98 -0
- data/lib/hecks/projections/model.rb +145 -0
- data/lib/hecks/projections/oidc.rb +110 -0
- data/lib/hecks/projections/parser_table.rb +159 -0
- data/lib/hecks/projections/reference.rb +38 -0
- data/lib/hecks/projections/shape.rb +44 -0
- data/lib/hecks/projections/statements.rb +110 -0
- data/lib/hecks/projections/vocabulary.rb +100 -0
- data/lib/hecks/projections.rb +32 -0
- data/lib/hecks/projector/cli_projector.rb +446 -0
- data/lib/hecks/projector/docs_projector.rb +321 -0
- data/lib/hecks/projector/exporter.rb +158 -0
- data/lib/hecks/projector/ir_projector.rb +18 -0
- data/lib/hecks/projector/narrate_projector.rb +243 -0
- data/lib/hecks/projector/target.rb +97 -0
- data/lib/hecks/projector.rb +186 -0
- data/lib/hecks/query_ir.rb +411 -0
- data/lib/hecks/query_specification/common/authorization_spec.rb +9 -0
- data/lib/hecks/query_specification/common/comparators.rb +25 -0
- data/lib/hecks/query_specification/common/comparison.rb +174 -0
- data/lib/hecks/query_specification/common/cursor_spec.rb +9 -0
- data/lib/hecks/query_specification/common/dsl.rb +58 -0
- data/lib/hecks/query_specification/common/inspection_spec.rb +9 -0
- data/lib/hecks/query_specification/common/limit_spec.rb +9 -0
- data/lib/hecks/query_specification/common/null_policy.rb +92 -0
- data/lib/hecks/query_specification/common/null_semantics.rb +11 -0
- data/lib/hecks/query_specification/common/offset_spec.rb +9 -0
- data/lib/hecks/query_specification/common/options.rb +32 -0
- data/lib/hecks/query_specification/common/order_by.rb +9 -0
- data/lib/hecks/query_specification/common/specification.rb +10 -0
- data/lib/hecks/query_specification/common/where_clause.rb +9 -0
- data/lib/hecks/query_specification/field_path.rb +107 -0
- data/lib/hecks/query_specification/hop_path.rb +132 -0
- data/lib/hecks/query_specification/read_model/specification.rb +18 -0
- data/lib/hecks/query_specification.rb +14 -0
- data/lib/hecks/rendering.rb +48 -0
- data/lib/hecks/router/namespace_installer.rb +157 -0
- data/lib/hecks/router.rb +70 -0
- data/lib/hecks/runtime/aggregate_lock.rb +45 -0
- data/lib/hecks/runtime/boot_gates.rb +41 -0
- data/lib/hecks/runtime/caller.rb +66 -0
- data/lib/hecks/runtime/capability_graph.rb +44 -0
- data/lib/hecks/runtime/command_interpreter/argument_gate.rb +135 -0
- data/lib/hecks/runtime/command_interpreter/mutation_applier.rb +260 -0
- data/lib/hecks/runtime/command_interpreter.rb +497 -0
- data/lib/hecks/runtime/command_rules/admissibility.rb +357 -0
- data/lib/hecks/runtime/command_rules/arithmetic.rb +260 -0
- data/lib/hecks/runtime/command_rules/authorization.rb +65 -0
- data/lib/hecks/runtime/command_rules/emission.rb +34 -0
- data/lib/hecks/runtime/command_rules/references.rb +189 -0
- data/lib/hecks/runtime/command_rules.rb +28 -0
- data/lib/hecks/runtime/dependency_planning.rb +245 -0
- data/lib/hecks/runtime/dispatcher.rb +301 -0
- data/lib/hecks/runtime/entity_element.rb +253 -0
- data/lib/hecks/runtime/entity_interpreter.rb +299 -0
- data/lib/hecks/runtime/errors.rb +122 -0
- data/lib/hecks/runtime/event.rb +51 -0
- data/lib/hecks/runtime/identity.rb +156 -0
- data/lib/hecks/runtime/instance.rb +175 -0
- data/lib/hecks/runtime/interpreting.rb +90 -0
- data/lib/hecks/runtime/loader.rb +184 -0
- data/lib/hecks/runtime/policy_interpreter.rb +366 -0
- data/lib/hecks/runtime/port_operation_interpreter.rb +210 -0
- data/lib/hecks/runtime/query_interpreter.rb +286 -0
- data/lib/hecks/runtime/reaction_invocation.rb +253 -0
- data/lib/hecks/runtime/read_model_interpreter.rb +341 -0
- data/lib/hecks/runtime/rebuild_sweep.rb +74 -0
- data/lib/hecks/runtime/reference_hop.rb +99 -0
- data/lib/hecks/runtime/refusal_wording.rb +126 -0
- data/lib/hecks/runtime/registry/saga_persistence.rb +142 -0
- data/lib/hecks/runtime/registry/verification.rb +246 -0
- data/lib/hecks/runtime/registry.rb +279 -0
- data/lib/hecks/runtime/remote_dispatcher.rb +143 -0
- data/lib/hecks/runtime/routing.rb +96 -0
- data/lib/hecks/runtime/saga_interpreter/correlation.rb +97 -0
- data/lib/hecks/runtime/saga_interpreter.rb +503 -0
- data/lib/hecks/runtime/saga_pending_dispatch.rb +45 -0
- data/lib/hecks/runtime/tenant_check.rb +84 -0
- data/lib/hecks/runtime/tenant_scope.rb +55 -0
- data/lib/hecks/runtime/value/admission.rb +130 -0
- data/lib/hecks/runtime/value/coercion.rb +565 -0
- data/lib/hecks/runtime/value/invariant_violation.rb +5 -0
- data/lib/hecks/runtime/value.rb +125 -0
- data/lib/hecks/runtime.rb +107 -0
- data/lib/hecks/storehouse.rb +632 -0
- data/lib/hecks/version.rb +16 -0
- data/lib/hecks/vocabulary.rb +218 -0
- data/lib/hecks.rb +123 -6
- data/lib/rubocop/cop/hecks/fallback_hash_lookup.rb +90 -0
- data/lib/rubocop/cop/hecks/sequential_hash_rename_in_loop.rb +128 -0
- data/lib/rubocop/cop/hecks/thread_shared_ivar_mutation.rb +160 -0
- metadata +412 -222
- data/bin/hecks +0 -7
- data/bin/hecks-package +0 -65
- data/bin/hecks_console +0 -12
- data/bin/hecks_serverless +0 -6
- data/lib/cli/build.rb +0 -14
- data/lib/cli/command_runner.rb +0 -28
- data/lib/cli/console.rb +0 -10
- data/lib/cli/generate.rb +0 -37
- data/lib/cli/hecks-cli.rb +0 -27
- data/lib/cli/test.rb +0 -57
- data/lib/console/commands.rb +0 -8
- data/lib/console/hecks-console.rb +0 -1
- data/lib/packager/README.md +0 -0
- data/lib/packager/app_runner.rb +0 -21
- data/lib/packager/args.rb +0 -26
- data/lib/packager/compatibility/fixnum.rb +0 -6
- data/lib/packager/hecks.rb +0 -39
- data/lib/packager/query_runner.rb +0 -21
- data/lib/packager/resources/Dockerfile +0 -11
- data/lib/packager/resources/app_binary +0 -7
- data/lib/packager/resources/bundle_config +0 -3
- data/lib/packager/resources/traveling-ruby-20150715-2.2.2-linux-x86_64.tar.gz +0 -0
- data/lib/packager/resources/traveling-ruby-20150715-2.2.2-osx.tar.gz +0 -0
- data/lib/serverless/Domain +0 -32
- data/lib/serverless/cli.rb +0 -75
- data/lib/serverless/resources/command_name.js +0 -5
- data/lib/serverless/resources/environment.js +0 -7
- data/lib/serverless/resources/handler.js.tt +0 -28
- data/lib/serverless/resources/run_binary.js +0 -22
- data/lib/serverless/resources/serverless.yml +0 -20
|
@@ -0,0 +1,381 @@
|
|
|
1
|
+
Hecks.bluebook "Bluebook" do
|
|
2
|
+
aggregate "ProcessManager" do
|
|
3
|
+
description "One process manager — what correlates its instances, what starts and ends it, and the states it moves through."
|
|
4
|
+
|
|
5
|
+
reference_to Bluebook
|
|
6
|
+
|
|
7
|
+
# THE CHAPTER IT IS IN, AND ITS NAME — the same shape a policy takes, and for
|
|
8
|
+
# the same reason.
|
|
9
|
+
identified_by :bluebook, :name
|
|
10
|
+
|
|
11
|
+
attribute :name, ProcessManagerName
|
|
12
|
+
attribute :correlates_by, ProcessManagerText
|
|
13
|
+
attribute :starts_on, ProcessManagerText
|
|
14
|
+
attribute :ends_on, ProcessManagerText
|
|
15
|
+
attribute :states, list_of(SagaState)
|
|
16
|
+
# S17, ADR 0026 — Handler nested here (see `entity "Handler"`, below),
|
|
17
|
+
# an entity rather than its own root aggregate. `list_of(Handler)`
|
|
18
|
+
# forward-references it the same way banking's own `attribute :ledger,
|
|
19
|
+
# list_of(LedgerEntry)` names LedgerEntry before it is declared.
|
|
20
|
+
attribute :handlers, list_of(Handler)
|
|
21
|
+
|
|
22
|
+
value_object "ProcessManagerName" do
|
|
23
|
+
attribute :value, String
|
|
24
|
+
invariant("a process manager is named") { !value.to_s.empty? }
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
value_object "ProcessManagerText" do
|
|
28
|
+
attribute :value, String
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
value_object "SagaState" do
|
|
32
|
+
attribute :name, String
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# S17, ADR 0026 — HandlerText/DispatchText/Binding, hoisted up from
|
|
36
|
+
# the old standalone `aggregate "Handler"`/`aggregate "Dispatch"`. An
|
|
37
|
+
# entity cannot declare its own `value_object` (EntityBuilder has no
|
|
38
|
+
# such method — a piece borrows its owning aggregate's, the same way
|
|
39
|
+
# LedgerEntry borrows Account's Money), so these live here now, at
|
|
40
|
+
# the ROOT, where BOTH `entity "Handler"` and its own nested `entity
|
|
41
|
+
# "Dispatch"` can still reach them — a piece mints no value objects
|
|
42
|
+
# of its own AT ANY DEPTH, so there is exactly one pool however deep
|
|
43
|
+
# the nesting goes (`EntityBuilder#entity`'s own comment).
|
|
44
|
+
value_object "HandlerText" do
|
|
45
|
+
attribute :value, String
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
value_object "DispatchText" do
|
|
49
|
+
attribute :value, String
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
value_object "Binding" do
|
|
53
|
+
attribute :key, String
|
|
54
|
+
attribute :value, String
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# ONE DISPATCH'S OWN ORDER AMONG ITS HANDLER'S SIBLINGS — named
|
|
58
|
+
# DispatchPosition rather than reusing ProcessManager's own `Position`
|
|
59
|
+
# four lines below (same discipline as `MemberPosition`/shape.bluebook's
|
|
60
|
+
# own comment on the identical choice): that one orders process
|
|
61
|
+
# managers among a CHAPTER's siblings ; this one orders dispatches
|
|
62
|
+
# within ONE handler. Same shape, different fact.
|
|
63
|
+
#
|
|
64
|
+
# Part of `identified_by`, below, alongside `command_name` — a real
|
|
65
|
+
# handler fans the SAME command out more than once with different
|
|
66
|
+
# `with:` bindings each leg (item #151's own real example: one
|
|
67
|
+
# BodyPulse handler dispatching Signal.FireSignal once per organ),
|
|
68
|
+
# and `command_name` alone collided the instant it did: the Judge's
|
|
69
|
+
# own `entity_duplicate` check raised the moment a second dispatch of
|
|
70
|
+
# the same command was declared, an uncaught crash for a legitimate,
|
|
71
|
+
# common pattern. `position` names WHICH send this is and is safe to
|
|
72
|
+
# fold into identity exactly where it would not be for Handler's own
|
|
73
|
+
# `from_state` (a real business value) — a Dispatch is declared once,
|
|
74
|
+
# at load time, and never re-addressed by identity afterward.
|
|
75
|
+
value_object "DispatchPosition" do
|
|
76
|
+
attribute :value, Integer
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# The way back: everything DECLARED IN the chapter above. The parent
|
|
80
|
+
# reference IS the query.
|
|
81
|
+
# WHERE IT SITS AMONG ITS SIBLINGS. Declaration order is a FACT ABOUT THE
|
|
82
|
+
# SOURCE — the IR is a contract read straight from this file,
|
|
83
|
+
# field for field AND INDEX FOR INDEX. So the language HOLDS it, instead of
|
|
84
|
+
# inheriting it from whatever order a store happens to iterate: an ask that
|
|
85
|
+
# does not say how it is ordered is answered in identity order, which is
|
|
86
|
+
# right for every other ask and fatal for the one that is the SOURCE.
|
|
87
|
+
value_object "Position" do
|
|
88
|
+
attribute :value, Integer
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
attribute :position, Position
|
|
92
|
+
|
|
93
|
+
query "DeclaredIn" do
|
|
94
|
+
attribute :bluebook, ProcessManagerText
|
|
95
|
+
where(bluebook: :bluebook)
|
|
96
|
+
order_by :position
|
|
97
|
+
end
|
|
98
|
+
command "Declare" do
|
|
99
|
+
role "Language"
|
|
100
|
+
goal "Open a process manager on a chapter"
|
|
101
|
+
|
|
102
|
+
reference_to Bluebook
|
|
103
|
+
attribute :name, ProcessManagerName
|
|
104
|
+
attribute :correlates_by, ProcessManagerText
|
|
105
|
+
attribute :starts_on, ProcessManagerText
|
|
106
|
+
# A PROCEDURE NEED NOT DECLARE AN ENDING. The runtime has always held
|
|
107
|
+
# this optional — ProcessManagerBuilder defaults `@ends_on` to nil,
|
|
108
|
+
# validates only correlates_by/starts_on/states/handlers,
|
|
109
|
+
# and fills it only if the line is written. The
|
|
110
|
+
# language was the one saying it was required, and nothing in the corpus
|
|
111
|
+
# had to disagree because every procedure in it happens to end.
|
|
112
|
+
attribute :ends_on, ProcessManagerText, optional: true
|
|
113
|
+
|
|
114
|
+
attribute :position, Position, optional: true
|
|
115
|
+
sets :bluebook
|
|
116
|
+
sets :name
|
|
117
|
+
sets :correlates_by
|
|
118
|
+
sets :starts_on
|
|
119
|
+
sets :ends_on
|
|
120
|
+
sets :position
|
|
121
|
+
emits SagaDeclared
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
command "State" do
|
|
125
|
+
role "Language"
|
|
126
|
+
goal "Attach one state to the process manager"
|
|
127
|
+
|
|
128
|
+
attribute :name, ProcessManagerText
|
|
129
|
+
|
|
130
|
+
sets :states, append: { name: :name }
|
|
131
|
+
|
|
132
|
+
emits SagaStateAttached
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
# THE HANDLER'S OWN CREATION. S17, ADR 0026 — Handler is a genuine
|
|
136
|
+
# ENTITY now (`entity "Handler"`, below), and an entity is never
|
|
137
|
+
# created through its own dotted verb — banking's own LedgerEntry is
|
|
138
|
+
# created by `Account.LogEntry`, an ordinary append on the OWNER,
|
|
139
|
+
# never by a `LedgerEntry.Declare` of its own
|
|
140
|
+
# (`EntityInterpreter#element_of` only LOCATES an element already on
|
|
141
|
+
# the list — it has no path that creates one). So Handler's creation
|
|
142
|
+
# moved here, onto ProcessManager, mirroring `State` beside it: a
|
|
143
|
+
# bare, aggregate-level append.
|
|
144
|
+
command "Handler" do
|
|
145
|
+
role "Language"
|
|
146
|
+
goal "Open a handler inside a process manager"
|
|
147
|
+
|
|
148
|
+
attribute :event_type, HandlerText
|
|
149
|
+
# A LEG ALWAYS SAYS WHERE IT MOVES FROM. There is no wildcard leg to be
|
|
150
|
+
# optional for: `on "Event", transition: { from => to }` is the only
|
|
151
|
+
# spelling the runtime reads, and it refuses anything else —
|
|
152
|
+
# `single_transition` raises unless the hash holds exactly one from => to
|
|
153
|
+
# pair, so a leg without one
|
|
154
|
+
# is never built at all. `optional: true` here was
|
|
155
|
+
# the language admitting a leg the runtime cannot parse.
|
|
156
|
+
attribute :from_state, HandlerText
|
|
157
|
+
attribute :to_state, HandlerText
|
|
158
|
+
|
|
159
|
+
sets :handlers, append: { event_type: :event_type, from_state: :from_state, to_state: :to_state }
|
|
160
|
+
|
|
161
|
+
emits LegDeclared
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
# S17, ADR 0026 — ONE HANDLER, nested rather than its own root
|
|
165
|
+
# aggregate. No `saga` field. It named the old word for a process
|
|
166
|
+
# manager, held nothing — ProcessManagerHandler has no such reader,
|
|
167
|
+
# so every Handler record's saga was empty — and repeated the parent
|
|
168
|
+
# that its own containment already carries. A field that names the
|
|
169
|
+
# wrong thing, holds nothing, and duplicates the reference beside it.
|
|
170
|
+
#
|
|
171
|
+
# `event_type` is an event name, or one of the Trigger vocabulary's
|
|
172
|
+
# members when the leg answers something no aggregate announces — but
|
|
173
|
+
# NOT, alone, Handler's own identity any more (items #151/#152's own
|
|
174
|
+
# finding): a state machine legitimately answers the SAME event
|
|
175
|
+
# differently depending on which state it is currently in — one event
|
|
176
|
+
# name, several distinct legs (a BodyPulse handler that moves
|
|
177
|
+
# `attentive -> attentive` and, separately, `sleeping_light ->
|
|
178
|
+
# sleeping_light`) — and `event_type` alone collided the instant a
|
|
179
|
+
# real corpus declared that shape: the Judge's own `entity_duplicate`
|
|
180
|
+
# check raised `AlreadyExists` the moment the second leg was declared,
|
|
181
|
+
# an uncaught crash, not a refusal, for a common, legitimate pattern.
|
|
182
|
+
# `from_state` joins it below for exactly this reason — a real
|
|
183
|
+
# business value, not a stand-in for missing meaning, the same
|
|
184
|
+
# distinction `DispatchPosition`'s own comment (above) draws for its
|
|
185
|
+
# sibling `Dispatch`. The process manager this leg belongs to stays
|
|
186
|
+
# structural (which list this element sits in), never a stored field.
|
|
187
|
+
entity "Handler" do
|
|
188
|
+
description "One handler inside a process manager — the event it answers, the state move it makes, and the commands it sends. Nested under the process manager because a handler holds nested dispatches, which hold nested bindings."
|
|
189
|
+
|
|
190
|
+
attribute :event_type, HandlerText
|
|
191
|
+
attribute :from_state, HandlerText
|
|
192
|
+
attribute :to_state, HandlerText
|
|
193
|
+
# S17, ADR 0026 — Dispatch nested here too (see `entity "Dispatch"`,
|
|
194
|
+
# below), one level further in than Handler itself.
|
|
195
|
+
attribute :dispatches, list_of(Dispatch)
|
|
196
|
+
|
|
197
|
+
# BOTH FIELDS TOGETHER — see the class-level comment above.
|
|
198
|
+
identified_by :event_type, :from_state
|
|
199
|
+
|
|
200
|
+
# THE DISPATCH'S OWN CREATION — same reason Handler's own creation
|
|
201
|
+
# lives on ProcessManager, one level up: an entity is never created
|
|
202
|
+
# through its own dotted verb. Reached as a DOTTED verb itself
|
|
203
|
+
# (`ProcessManager.Handler.Dispatch`) since Handler, the owner
|
|
204
|
+
# doing the creating here, is an entity too, not a real aggregate
|
|
205
|
+
# with a bare verb of its own to dispatch into.
|
|
206
|
+
command "Dispatch" do
|
|
207
|
+
role "Language"
|
|
208
|
+
goal "Open a dispatch inside a handler"
|
|
209
|
+
|
|
210
|
+
attribute :command_name, DispatchText
|
|
211
|
+
# THE WALK INDEX, never author-supplied — the same generic
|
|
212
|
+
# POSITION handling `ValueObject.Member`'s own creating command
|
|
213
|
+
# already relies on (`Judge#appends`), which fills this from
|
|
214
|
+
# where the walk found the dispatch, not from a field the row
|
|
215
|
+
# happens to hold. No real `.bluebook` author ever calls this
|
|
216
|
+
# verb directly; only the Judge's own replay does.
|
|
217
|
+
attribute :position, DispatchPosition
|
|
218
|
+
|
|
219
|
+
sets :dispatches, append: { command_name: :command_name, position: :position }
|
|
220
|
+
|
|
221
|
+
emits SendDeclared
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
# S17, ADR 0026 — ONE COMMAND A HANDLER DISPATCHES, nested two
|
|
225
|
+
# levels in rather than its own root aggregate — "no life outside
|
|
226
|
+
# its Handler" (the ADR's own words). The bindings are an open
|
|
227
|
+
# map, which no value object can hold — that was always a reason
|
|
228
|
+
# it could not be one, never a reason it could not be an entity.
|
|
229
|
+
# `command_name` ALONE used to be Dispatch's own identity, the same
|
|
230
|
+
# shape Handler's own `event_type` took one level up — and collided
|
|
231
|
+
# the same way, for the same real reason (item #151): one handler
|
|
232
|
+
# fanning the SAME command out several times with different `with:`
|
|
233
|
+
# bindings each time (one BodyPulse handler dispatching
|
|
234
|
+
# Signal.FireSignal once per organ). `position` joins it below —
|
|
235
|
+
# see `DispatchPosition`'s own comment for why that field, unlike
|
|
236
|
+
# Handler's `from_state`, is safe to fold into identity.
|
|
237
|
+
entity "Dispatch" do
|
|
238
|
+
description "One command a handler dispatches, with the arguments it binds. Nested under the handler because the bindings are an open map, which no value object can hold."
|
|
239
|
+
|
|
240
|
+
attribute :command_name, DispatchText
|
|
241
|
+
attribute :position, DispatchPosition
|
|
242
|
+
|
|
243
|
+
identified_by :command_name, :position
|
|
244
|
+
|
|
245
|
+
attribute :with_spec, list_of(Binding)
|
|
246
|
+
|
|
247
|
+
command "Bind" do
|
|
248
|
+
role "Language"
|
|
249
|
+
goal "Bind one argument of the dispatched command"
|
|
250
|
+
|
|
251
|
+
attribute :key, DispatchText
|
|
252
|
+
attribute :value, DispatchText
|
|
253
|
+
|
|
254
|
+
sets :with_spec, append: { key: :key, value: :value }
|
|
255
|
+
|
|
256
|
+
emits BindingAttached
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
# THE COMPENSATING DISPATCH THIS ONE COMPENSATES FOR, IF ANY —
|
|
260
|
+
# FLAT FIELDS on THIS SAME entity, mirroring `command_name`/
|
|
261
|
+
# `with_spec` above one-for-one, rather than a nested (or
|
|
262
|
+
# self-referential) second `Dispatch`: an entity's own attribute
|
|
263
|
+
# type has to resolve against a value object, and neither a
|
|
264
|
+
# self-reference to `Dispatch` (written from inside its own
|
|
265
|
+
# block, before it exists to reference) nor a plain nested
|
|
266
|
+
# entity reference passes that check the way `Handler.
|
|
267
|
+
# dispatches: list_of(Dispatch)` does — that one resolves a
|
|
268
|
+
# SIBLING already fully built by the time deferred construction
|
|
269
|
+
# (ADR 0028) finishes; a dispatch compensating for itself has no
|
|
270
|
+
# such sibling. `compensates_command_name` absent means no
|
|
271
|
+
# compensation; present, together with whatever
|
|
272
|
+
# `compensates_with_spec` holds, is everything
|
|
273
|
+
# `Reconstruction#dispatch` needs to assemble the SAME
|
|
274
|
+
# `DispatchSpec` shape `compensates` (the real, author-facing
|
|
275
|
+
# word) fills.
|
|
276
|
+
attribute :compensates_command_name, DispatchText, optional: true
|
|
277
|
+
attribute :compensates_with_spec, list_of(Binding)
|
|
278
|
+
|
|
279
|
+
command "Compensates" do
|
|
280
|
+
role "Language"
|
|
281
|
+
goal "Name the command this dispatch compensates for"
|
|
282
|
+
|
|
283
|
+
attribute :compensates_command_name, DispatchText
|
|
284
|
+
|
|
285
|
+
sets :compensates_command_name
|
|
286
|
+
|
|
287
|
+
emits "CompensationDeclared"
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
command "BindCompensation" do
|
|
291
|
+
role "Language"
|
|
292
|
+
goal "Bind one argument of the compensation's own dispatched command"
|
|
293
|
+
|
|
294
|
+
attribute :key, DispatchText
|
|
295
|
+
attribute :value, DispatchText
|
|
296
|
+
|
|
297
|
+
sets :compensates_with_spec, append: { key: :key, value: :value }
|
|
298
|
+
|
|
299
|
+
emits "CompensationBindingAttached"
|
|
300
|
+
end
|
|
301
|
+
end
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
# HOW PROCESSMANAGER IS SPELLED. These rows live with the concept
|
|
305
|
+
# they describe; SyntaxBoot discovers every aggregate-local seed table.
|
|
306
|
+
# Contexts represented here: ProcessManager, Handler.
|
|
307
|
+
value_object "KeywordSeed" do
|
|
308
|
+
attribute :word, String
|
|
309
|
+
attribute :context, String, admits: "Syntax::Context"
|
|
310
|
+
attribute :body, String, admits: "Syntax::Body"
|
|
311
|
+
attribute :inner, String
|
|
312
|
+
attribute :opens, String
|
|
313
|
+
attribute :fills, String
|
|
314
|
+
attribute :status, String, default: "admitted", admits: "Syntax::Status"
|
|
315
|
+
attribute :was, String
|
|
316
|
+
attribute :resolves_via, String, default: "", admits: "Syntax::ResolutionScope"
|
|
317
|
+
attribute :disambiguator, String, default: "", admits: "Syntax::Disambiguator"
|
|
318
|
+
|
|
319
|
+
member word: "correlates_by", context: "ProcessManager", body: "none", inner: "", opens: "", fills: "correlates_by"
|
|
320
|
+
# BARE CONSTANT ACCEPTED (ADR 0025, S6 — "events first-class"),
|
|
321
|
+
# `starts_on Transfer::TransferRequested` / `ends_on
|
|
322
|
+
# Transfer::TransferSettled`, same `kind: "constant"` + `kind:
|
|
323
|
+
# "text"` ArgumentSeed pair `emits`/policy's own `on` already
|
|
324
|
+
# carry (this row's own comment there). Now `calls:`-routed
|
|
325
|
+
# (`starts_on_impl`/`ends_on_impl`, hand-written — GenericDispatch's
|
|
326
|
+
# own `COERCE_BY_KIND` has no "constant" entry, so a bare
|
|
327
|
+
# constant needs the same `Naming.event_ref` resolution `on_impl`/
|
|
328
|
+
# `transition_impl` already do, not the plain `.to_s` a single
|
|
329
|
+
# `kind: "text"` row used to get for free).
|
|
330
|
+
member word: "starts_on", context: "ProcessManager", body: "none", inner: "", opens: "", fills: "", calls: "starts_on_impl"
|
|
331
|
+
member word: "ends_on", context: "ProcessManager", body: "none", inner: "", opens: "", fills: "", calls: "ends_on_impl"
|
|
332
|
+
member word: "transition", context: "ProcessManager", body: "keywords", inner: "Handler", opens: "Handler", fills: "", calls: "transition_impl"
|
|
333
|
+
member word: "transition", context: "ProcessManager", body: "none", inner: "", opens: "", fills: "", calls: "transition_impl"
|
|
334
|
+
# TWO ROWS, the SAME PAIR SHAPE `transition` takes just above —
|
|
335
|
+
# `body: "none"` was already the only row (`opens: "Dispatch"`
|
|
336
|
+
# already anticipated a block, unused until now); `body:
|
|
337
|
+
# "keywords"` is the new one, opening `compensates` on the
|
|
338
|
+
# dispatch it sits inside (per-dispatch saga compensation — see
|
|
339
|
+
# `ProcessManagerBuilder::HandlerBuilder#dispatch_impl`'s own
|
|
340
|
+
# comment).
|
|
341
|
+
member word: "dispatch", context: "Handler", body: "keywords", inner: "Dispatch", opens: "Dispatch", fills: "", calls: "dispatch_impl"
|
|
342
|
+
member word: "dispatch", context: "Handler", body: "none", inner: "", opens: "Dispatch", fills: "", calls: "dispatch_impl"
|
|
343
|
+
member word: "compensates", context: "Dispatch", body: "none", inner: "", opens: "", fills: "", calls: "compensates_impl"
|
|
344
|
+
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
value_object "ArgumentSeed" do
|
|
348
|
+
attribute :keyword, String
|
|
349
|
+
attribute :context, String, admits: "Syntax::Context"
|
|
350
|
+
attribute :at, String
|
|
351
|
+
attribute :named, String
|
|
352
|
+
attribute :kind, String, admits: "Syntax::ArgumentKind"
|
|
353
|
+
attribute :required, String
|
|
354
|
+
attribute :fills, String
|
|
355
|
+
attribute :selects, String
|
|
356
|
+
attribute :pair_key_fills, String
|
|
357
|
+
attribute :pair_value_fills, String
|
|
358
|
+
attribute :pairs_shape, String, admits: "Syntax::PairsShape"
|
|
359
|
+
attribute :status, String, default: "admitted", admits: "Syntax::Status"
|
|
360
|
+
attribute :variadic, String
|
|
361
|
+
attribute :coerce, String
|
|
362
|
+
attribute :blank_message, String
|
|
363
|
+
|
|
364
|
+
member keyword: "correlates_by", context: "ProcessManager", at: "1", named: "", kind: "symbol", required: "true", fills: "correlates_by"
|
|
365
|
+
member keyword: "starts_on", context: "ProcessManager", at: "1", named: "", kind: "constant", required: "true", fills: "starts_on"
|
|
366
|
+
member keyword: "starts_on", context: "ProcessManager", at: "1", named: "", kind: "text", required: "true", fills: "starts_on"
|
|
367
|
+
member keyword: "ends_on", context: "ProcessManager", at: "1", named: "", kind: "constant", required: "true", fills: "ends_on"
|
|
368
|
+
member keyword: "ends_on", context: "ProcessManager", at: "1", named: "", kind: "text", required: "true", fills: "ends_on"
|
|
369
|
+
member keyword: "transition", context: "ProcessManager", at: "1", named: "", kind: "pairs", required: "true", fills: "", pair_key_fills: "event_type", pair_value_fills: "to_state", pairs_shape: "fields"
|
|
370
|
+
member keyword: "transition", context: "ProcessManager", at: "", named: "from", kind: "text", required: "true", fills: "from_state"
|
|
371
|
+
member keyword: "transition", context: "ProcessManager", at: "", named: "from", kind: "list", required: "false", fills: "from_state"
|
|
372
|
+
member keyword: "dispatch", context: "Handler", at: "1", named: "", kind: "constant", required: "true", fills: "command_name"
|
|
373
|
+
member keyword: "dispatch", context: "Handler", at: "1", named: "", kind: "text", required: "true", fills: "command_name"
|
|
374
|
+
member keyword: "dispatch", context: "Handler", at: "", named: "with", kind: "pairs", required: "false", fills: "with_spec", pairs_shape: "verbatim"
|
|
375
|
+
member keyword: "compensates", context: "Dispatch", at: "1", named: "", kind: "constant", required: "true", fills: "command_name"
|
|
376
|
+
member keyword: "compensates", context: "Dispatch", at: "1", named: "", kind: "text", required: "true", fills: "command_name"
|
|
377
|
+
member keyword: "compensates", context: "Dispatch", at: "", named: "with", kind: "pairs", required: "false", fills: "with_spec", pairs_shape: "verbatim"
|
|
378
|
+
|
|
379
|
+
end
|
|
380
|
+
end
|
|
381
|
+
end
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
Hecks.bluebook "Bluebook" do
|
|
2
|
+
aggregate "ReadModel" do
|
|
3
|
+
description "One read model — the aggregate heads it gathers and the reference it hangs from."
|
|
4
|
+
|
|
5
|
+
reference_to Bluebook
|
|
6
|
+
|
|
7
|
+
# THE CHAPTER IT IS IN, AND ITS NAME.
|
|
8
|
+
identified_by :bluebook, :name
|
|
9
|
+
|
|
10
|
+
attribute :name, ReadModelName
|
|
11
|
+
attribute :description, ProjectionPurpose
|
|
12
|
+
attribute :query_name, ReadModelText
|
|
13
|
+
attribute :reference_name, ReadModelText
|
|
14
|
+
attribute :reference_target, ReadModelText
|
|
15
|
+
attribute :aggregate_heads, list_of(Head)
|
|
16
|
+
# The same open map a query carries — see Query's AskOption. A read model
|
|
17
|
+
# inherits every specification option an ask has, so it holds them the same way.
|
|
18
|
+
attribute :options, list_of(ProjectionOption)
|
|
19
|
+
# WHICH of the eligible head's own fields to nest its rows under, in
|
|
20
|
+
# declared order. Rows, not a single value object with N fields — an
|
|
21
|
+
# arbitrary NUMBER of fields, the same reason `aggregate_heads`/
|
|
22
|
+
# `options` are lists rather than fixed attributes.
|
|
23
|
+
attribute :group_by, list_of(GroupByField)
|
|
24
|
+
# `count`/`median_field` are the OTHER two reductions a read model
|
|
25
|
+
# may declare over its one eligible head, siblings of `group_by`
|
|
26
|
+
# rather than of `options` — same permissive `ReadModelText` shape,
|
|
27
|
+
# and the same UNmarked-optional spelling `reference_name`/
|
|
28
|
+
# `reference_target` already use just above (permissiveness lives
|
|
29
|
+
# in `ReadModelText`'s own lack of an invariant, not in an
|
|
30
|
+
# `optional:` flag this chapter's aggregate-level attributes never
|
|
31
|
+
# carry) — "true"/"" for `count`, a field name or "" for
|
|
32
|
+
# `median_field`, both legitimately absent on a read model that
|
|
33
|
+
# declares neither.
|
|
34
|
+
attribute :count, ReadModelText, optional: true
|
|
35
|
+
attribute :median_field, ReadModelText, optional: true
|
|
36
|
+
|
|
37
|
+
value_object "ReadModelName" do
|
|
38
|
+
attribute :value, String
|
|
39
|
+
invariant("a read model is named") { !value.to_s.empty? }
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
value_object "ReadModelText" do
|
|
43
|
+
# deliberately permissive : query_name / ref_name / ref_target are
|
|
44
|
+
# legitimately empty on a read model that has not named them yet
|
|
45
|
+
attribute :value, String
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
value_object "ProjectionPurpose" do
|
|
49
|
+
attribute :value, String
|
|
50
|
+
invariant("a description says something") { !value.to_s.empty? }
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
value_object "Head" do
|
|
54
|
+
attribute :aggregate, String
|
|
55
|
+
attribute :as, String
|
|
56
|
+
attribute :many, String
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
value_object "ProjectionOption" do
|
|
60
|
+
attribute :option, String
|
|
61
|
+
attribute :key, String
|
|
62
|
+
attribute :value, String
|
|
63
|
+
attribute :at, String
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
value_object "GroupByField" do
|
|
67
|
+
attribute :field, String
|
|
68
|
+
invariant("a group_by field is named") { !field.to_s.empty? }
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# The way back: everything DECLARED IN the chapter above. The parent
|
|
72
|
+
# reference IS the query.
|
|
73
|
+
# WHERE IT SITS AMONG ITS SIBLINGS. Declaration order is a FACT ABOUT THE
|
|
74
|
+
# SOURCE — the IR is a contract read straight from this file,
|
|
75
|
+
# field for field AND INDEX FOR INDEX. So the language HOLDS it, instead of
|
|
76
|
+
# inheriting it from whatever order a store happens to iterate: an ask that
|
|
77
|
+
# does not say how it is ordered is answered in identity order, which is
|
|
78
|
+
# right for every other ask and fatal for the one that is the SOURCE.
|
|
79
|
+
value_object "Position" do
|
|
80
|
+
attribute :value, Integer
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
attribute :position, Position
|
|
84
|
+
|
|
85
|
+
query "DeclaredIn" do
|
|
86
|
+
attribute :bluebook, ReadModelText
|
|
87
|
+
where(bluebook: :bluebook)
|
|
88
|
+
order_by :position
|
|
89
|
+
end
|
|
90
|
+
command "Declare" do
|
|
91
|
+
role "Language"
|
|
92
|
+
goal "Open a read model on a chapter"
|
|
93
|
+
|
|
94
|
+
reference_to Bluebook
|
|
95
|
+
attribute :name, ReadModelName
|
|
96
|
+
attribute :description, ProjectionPurpose, optional: true
|
|
97
|
+
attribute :query_name, ReadModelText
|
|
98
|
+
# Both optional now — a ROOTLESS read model (no `reference_to`
|
|
99
|
+
# declared at all) has neither. Permanently empty, not "not yet
|
|
100
|
+
# set" — see Gather's own comment below for why that distinction
|
|
101
|
+
# matters.
|
|
102
|
+
attribute :reference_name, ReadModelText, optional: true
|
|
103
|
+
attribute :reference_target, ReadModelText, optional: true
|
|
104
|
+
|
|
105
|
+
attribute :position, Position, optional: true
|
|
106
|
+
sets :bluebook
|
|
107
|
+
sets :name
|
|
108
|
+
sets :description
|
|
109
|
+
sets :query_name
|
|
110
|
+
sets :reference_name
|
|
111
|
+
sets :reference_target
|
|
112
|
+
sets :position
|
|
113
|
+
emits ProjectionDeclared
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
command "Gather" do
|
|
117
|
+
role "Language"
|
|
118
|
+
goal "Attach one aggregate head to the read model"
|
|
119
|
+
|
|
120
|
+
# A HEAD IS THE AGGREGATE IT NAMES. There is no head with nothing gathered:
|
|
121
|
+
# `add_aggregate_head` is only ever reached from an `include Target`,
|
|
122
|
+
# so the builder cannot produce one
|
|
123
|
+
# without it — the field is a plain
|
|
124
|
+
# required, non-empty name. `as` and
|
|
125
|
+
# `many` are both DERIVED from it when the author does not spell them, which
|
|
126
|
+
# is the clearest statement that it is the part that cannot be missing.
|
|
127
|
+
attribute :aggregate, ReadModelText
|
|
128
|
+
attribute :as, ReadModelText
|
|
129
|
+
attribute :many, ReadModelText
|
|
130
|
+
|
|
131
|
+
# NOT "reference_target must already be set" anymore — reference_target
|
|
132
|
+
# is fixed forever at Declare time (nothing ever changes it later), so
|
|
133
|
+
# that rule was really "this read model must have SOME reference, ever"
|
|
134
|
+
# — exactly the constraint a ROOTLESS read model (bulk, no root,
|
|
135
|
+
# `group_by`'s own real use) deliberately doesn't meet, permanently,
|
|
136
|
+
# on purpose, not by omission. Removed rather than relaxed: there is
|
|
137
|
+
# no runtime fact left here that distinguishes "forgot to declare a
|
|
138
|
+
# reference" from "declared rootless on purpose" — both look
|
|
139
|
+
# identical (`reference_target` empty) by the time Gather is judged.
|
|
140
|
+
|
|
141
|
+
sets :aggregate_heads, append: { aggregate: :aggregate, as: :as, many: :many }
|
|
142
|
+
|
|
143
|
+
emits HeadGathered
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
command "GroupBy" do
|
|
147
|
+
role "Language"
|
|
148
|
+
goal "Nest one collection's own rows by one of its own fields"
|
|
149
|
+
|
|
150
|
+
attribute :field, ReadModelText
|
|
151
|
+
|
|
152
|
+
given("a group_by field is named") { !field.value.to_s.empty? }
|
|
153
|
+
|
|
154
|
+
sets :group_by, append: { field: :field }
|
|
155
|
+
|
|
156
|
+
emits GroupByFieldAdded
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
# `count`/`median` are LATE-SET scalars, the same shape `Lifecycle`'s
|
|
160
|
+
# own `state_field`/`state_start` already are on `Aggregate`
|
|
161
|
+
# (aggregate.bluebook) — a command carrying its own value and a bare
|
|
162
|
+
# `sets field, to: field` copying it onto the record, rather
|
|
163
|
+
# than an `append:` (they are not lists, and there is only ever one
|
|
164
|
+
# of each). `count`/`median_field` are declared here, not folded
|
|
165
|
+
# into `Declare`, for the same reason `GroupBy` is its own command
|
|
166
|
+
# above: neither is known until the DSL body runs past `include`.
|
|
167
|
+
command "Count" do
|
|
168
|
+
role "Language"
|
|
169
|
+
goal "Mark the read model as a bare row count over its one eligible collection"
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
sets :count
|
|
173
|
+
|
|
174
|
+
emits CountDeclared
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
command "Median" do
|
|
178
|
+
role "Language"
|
|
179
|
+
goal "Mark the read model as the median of one numeric field across its one eligible collection"
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
given("a median field is named") { !median_field.value.to_s.empty? }
|
|
183
|
+
|
|
184
|
+
sets :median_field
|
|
185
|
+
|
|
186
|
+
emits MedianFieldSet
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
command "Option" do
|
|
190
|
+
role "Language"
|
|
191
|
+
goal "Attach one part of one specification option to the read model"
|
|
192
|
+
|
|
193
|
+
attribute :option, ReadModelText
|
|
194
|
+
attribute :key, ReadModelText
|
|
195
|
+
# Same reading as Query.Option above — an option key may stand alone.
|
|
196
|
+
attribute :value, ReadModelText, optional: true
|
|
197
|
+
attribute :at, ReadModelText, optional: true
|
|
198
|
+
|
|
199
|
+
given("an option is named") { !option.value.to_s.empty? }
|
|
200
|
+
|
|
201
|
+
sets :options, append: { option: :option, key: :key, value: :value, at: :at }
|
|
202
|
+
|
|
203
|
+
emits OptionAttached
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
# HOW READMODEL IS SPELLED. These rows live with the concept
|
|
207
|
+
# they describe; SyntaxBoot discovers every aggregate-local seed table.
|
|
208
|
+
# Contexts represented here: ReadModel.
|
|
209
|
+
value_object "KeywordSeed" do
|
|
210
|
+
attribute :word, String
|
|
211
|
+
attribute :context, String, admits: "Syntax::Context"
|
|
212
|
+
attribute :body, String, admits: "Syntax::Body"
|
|
213
|
+
attribute :inner, String
|
|
214
|
+
attribute :opens, String
|
|
215
|
+
attribute :fills, String
|
|
216
|
+
attribute :status, String, default: "admitted", admits: "Syntax::Status"
|
|
217
|
+
attribute :was, String
|
|
218
|
+
attribute :resolves_via, String, default: "", admits: "Syntax::ResolutionScope"
|
|
219
|
+
attribute :disambiguator, String, default: "", admits: "Syntax::Disambiguator"
|
|
220
|
+
|
|
221
|
+
member word: "description", context: "ReadModel", body: "none", inner: "", opens: "", fills: "description"
|
|
222
|
+
member word: "reference_to", context: "ReadModel", body: "none", inner: "", opens: "", fills: "reference_target", calls: "reference_to_impl"
|
|
223
|
+
member word: "include", context: "ReadModel", body: "none", inner: "", opens: "", fills: "aggregate_heads", calls: "include_impl"
|
|
224
|
+
member word: "group_by", context: "ReadModel", body: "none", inner: "", opens: "", fills: "group_by", calls: "group_by_impl"
|
|
225
|
+
member word: "count", context: "ReadModel", body: "none", inner: "", opens: "", fills: "count"
|
|
226
|
+
member word: "median", context: "ReadModel", body: "none", inner: "", opens: "", fills: "median_field"
|
|
227
|
+
member word: "where", context: "ReadModel", body: "none", inner: "", opens: "", fills: "options", calls: "where_impl"
|
|
228
|
+
member word: "order_by", context: "ReadModel", body: "none", inner: "", opens: "", fills: "options", calls: "order_by_impl"
|
|
229
|
+
member word: "authorize", context: "ReadModel", body: "none", inner: "", opens: "", fills: "options", calls: "authorize_impl"
|
|
230
|
+
member word: "inspect_query", context: "ReadModel", body: "none", inner: "", opens: "", fills: "options"
|
|
231
|
+
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
value_object "ArgumentSeed" do
|
|
235
|
+
attribute :keyword, String
|
|
236
|
+
attribute :context, String, admits: "Syntax::Context"
|
|
237
|
+
attribute :at, String
|
|
238
|
+
attribute :named, String
|
|
239
|
+
attribute :kind, String, admits: "Syntax::ArgumentKind"
|
|
240
|
+
attribute :required, String
|
|
241
|
+
attribute :fills, String
|
|
242
|
+
attribute :selects, String
|
|
243
|
+
attribute :pair_key_fills, String
|
|
244
|
+
attribute :pair_value_fills, String
|
|
245
|
+
attribute :pairs_shape, String, admits: "Syntax::PairsShape"
|
|
246
|
+
attribute :status, String, default: "admitted", admits: "Syntax::Status"
|
|
247
|
+
attribute :variadic, String
|
|
248
|
+
attribute :coerce, String
|
|
249
|
+
attribute :blank_message, String
|
|
250
|
+
|
|
251
|
+
member keyword: "description", context: "ReadModel", at: "1", named: "", kind: "text", required: "true", fills: "description", coerce: "false"
|
|
252
|
+
member keyword: "reference_to", context: "ReadModel", at: "1", named: "", kind: "constant", required: "true", fills: "reference_target"
|
|
253
|
+
member keyword: "reference_to", context: "ReadModel", at: "", named: "as", kind: "symbol", required: "false", fills: "reference_name"
|
|
254
|
+
member keyword: "include", context: "ReadModel", at: "1", named: "", kind: "constant", required: "true", fills: "aggregate"
|
|
255
|
+
member keyword: "include", context: "ReadModel", at: "", named: "as", kind: "symbol", required: "false", fills: "as"
|
|
256
|
+
member keyword: "group_by", context: "ReadModel", at: "1", named: "", kind: "symbol", required: "true", fills: "group_by", variadic: "true"
|
|
257
|
+
member keyword: "median", context: "ReadModel", at: "1", named: "", kind: "symbol", required: "true", fills: "median_field"
|
|
258
|
+
member keyword: "where", context: "ReadModel", at: "1", named: "", kind: "pairs", required: "true", fills: ""
|
|
259
|
+
member keyword: "order_by", context: "ReadModel", at: "1", named: "", kind: "symbol", required: "true", fills: "field"
|
|
260
|
+
member keyword: "order_by", context: "ReadModel", at: "2", named: "", kind: "symbol", required: "false", fills: "direction"
|
|
261
|
+
member keyword: "authorize", context: "ReadModel", at: "1", named: "", kind: "symbol", required: "true", fills: "policy"
|
|
262
|
+
member keyword: "authorize", context: "ReadModel", at: "", named: "tenant", kind: "symbol", required: "false", fills: "tenant"
|
|
263
|
+
member keyword: "inspect_query", context: "ReadModel", at: "1", named: "", kind: "symbol", required: "false", fills: "mode"
|
|
264
|
+
|
|
265
|
+
end
|
|
266
|
+
end
|
|
267
|
+
end
|