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,392 @@
|
|
|
1
|
+
Hecks.bluebook "Bluebook" do
|
|
2
|
+
aggregate "Entity" do
|
|
3
|
+
description "One entity inside an aggregate — an element with its own identity, state machine, commands and queries. Its own root because it repeats the aggregate's whole shape one level down."
|
|
4
|
+
|
|
5
|
+
reference_to Aggregate
|
|
6
|
+
|
|
7
|
+
# THE AGGREGATE IT IS IN, AND ITS NAME. Note this is the identity of the RECORD
|
|
8
|
+
# describing a piece, which is a different thing from the identity that piece
|
|
9
|
+
# itself declares (`identified_by`, the list below).
|
|
10
|
+
identified_by :aggregate, :name
|
|
11
|
+
|
|
12
|
+
attribute :owner, EntityText
|
|
13
|
+
attribute :name, EntityName
|
|
14
|
+
attribute :description, EntityName
|
|
15
|
+
# SEVERAL PATHS, joined — a piece spells an identity exactly as a head does,
|
|
16
|
+
# which is the whole point of it being its own root.
|
|
17
|
+
attribute :identified_by, list_of(IdentityPath)
|
|
18
|
+
attribute :attributes, list_of(PieceField)
|
|
19
|
+
# ADR 0028 — A PRECONDITION SHARED ACROSS THIS PIECE'S OWN COMMANDS,
|
|
20
|
+
# DECLARED ONCE — the SAME Rule shape Aggregate's own `preconditions`
|
|
21
|
+
# already carries (that file's own comment on why it's declared
|
|
22
|
+
# again here rather than shared: a value object is aggregate-scoped
|
|
23
|
+
# in this self-hosting domain).
|
|
24
|
+
attribute :preconditions, list_of(Rule)
|
|
25
|
+
# A PIECE'S OWN SHAPE RULE — the SAME Rule shape, checked (round 7)
|
|
26
|
+
# against EVERY INSTANCE this piece's own aggregate holds, not the
|
|
27
|
+
# aggregate's own flat state — `ValueObject#invariants`'s own
|
|
28
|
+
# relationship to ITS OWN instances, one construct over.
|
|
29
|
+
attribute :invariants, list_of(Rule)
|
|
30
|
+
attribute :state_field, EntityText, optional: true
|
|
31
|
+
attribute :state_start, EntityText, optional: true
|
|
32
|
+
attribute :transitions, list_of(PieceTransition)
|
|
33
|
+
|
|
34
|
+
value_object "EntityName" do
|
|
35
|
+
attribute :value, String
|
|
36
|
+
invariant("an entity is named") { !value.to_s.empty? }
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
value_object "EntityText" do
|
|
40
|
+
attribute :value, String
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# See Aggregate's own "Rule" value object — the identical shape,
|
|
44
|
+
# declared again here rather than shared (that file's own comment
|
|
45
|
+
# on why).
|
|
46
|
+
value_object "Rule" do
|
|
47
|
+
attribute :description, String
|
|
48
|
+
attribute :canonical, String
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# A piece's identity is made of parts the same way a head's is, so it holds
|
|
52
|
+
# the same shape. Declared here rather than shared because a value object
|
|
53
|
+
# belongs to the aggregate that uses it.
|
|
54
|
+
value_object "IdentityPath" do
|
|
55
|
+
attribute :value, String
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
value_object "PieceField" do
|
|
59
|
+
attribute :name, String
|
|
60
|
+
attribute :type, String
|
|
61
|
+
attribute :list, String
|
|
62
|
+
attribute :optional, String, optional: true
|
|
63
|
+
attribute :pattern, String, optional: true
|
|
64
|
+
attribute :default, String
|
|
65
|
+
# The closed set this value must belong to — see Aggregate::Field.
|
|
66
|
+
attribute :admits, String, optional: true
|
|
67
|
+
attribute :relationship, String, optional: true
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
value_object "PieceTransition" do
|
|
71
|
+
attribute :command, String
|
|
72
|
+
attribute :from_state, String
|
|
73
|
+
attribute :to_state, String
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# The way back: everything DECLARED IN the aggregate above. The parent
|
|
77
|
+
# reference IS the query.
|
|
78
|
+
# WHERE IT SITS AMONG ITS SIBLINGS. Declaration order is a FACT ABOUT THE
|
|
79
|
+
# SOURCE — the IR is a contract read straight from this file,
|
|
80
|
+
# field for field AND INDEX FOR INDEX. So the language HOLDS it, instead of
|
|
81
|
+
# inheriting it from whatever order a store happens to iterate: an ask that
|
|
82
|
+
# does not say how it is ordered is answered in identity order, which is
|
|
83
|
+
# right for every other ask and fatal for the one that is the SOURCE.
|
|
84
|
+
value_object "Position" do
|
|
85
|
+
attribute :value, Integer
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
attribute :position, Position
|
|
89
|
+
|
|
90
|
+
query "DeclaredIn" do
|
|
91
|
+
attribute :aggregate, EntityText
|
|
92
|
+
where(aggregate: :aggregate)
|
|
93
|
+
order_by :position
|
|
94
|
+
end
|
|
95
|
+
command "Declare" do
|
|
96
|
+
role "Language"
|
|
97
|
+
goal "Open an entity inside an aggregate"
|
|
98
|
+
|
|
99
|
+
reference_to Aggregate
|
|
100
|
+
attribute :owner, EntityText
|
|
101
|
+
attribute :name, EntityName
|
|
102
|
+
attribute :description, EntityName, optional: true
|
|
103
|
+
|
|
104
|
+
attribute :position, Position, optional: true
|
|
105
|
+
sets :aggregate
|
|
106
|
+
sets :owner
|
|
107
|
+
sets :name
|
|
108
|
+
sets :description
|
|
109
|
+
sets :position
|
|
110
|
+
emits PieceDeclared
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# ONE PART OF THE PIECE'S IDENTITY, attached exactly as an aggregate's is.
|
|
114
|
+
#
|
|
115
|
+
# A PIECE MUST SAY WHAT IT IS KNOWN BY — the rule, where the language keeps
|
|
116
|
+
# its rules. An entity is an element with an identity of ITS OWN ; that is
|
|
117
|
+
# the whole difference between a piece and a value object, so a command
|
|
118
|
+
# acting on one must be able to say which one. Undeclared, every reader
|
|
119
|
+
# has to invent its own answer — fall through to nothing, or assume
|
|
120
|
+
# `id` — and inventions agree only because every entity in the corpus happened
|
|
121
|
+
# to declare it: a divergence the
|
|
122
|
+
# declaration was masking. Requiring it removes the default there was to
|
|
123
|
+
# disagree about. That requirement now sits on Seal, where a whole-document
|
|
124
|
+
# rule belongs ; what stays here is the shape of each part.
|
|
125
|
+
command "Identify" do
|
|
126
|
+
role "Language"
|
|
127
|
+
goal "Attach one part of the entity's identity"
|
|
128
|
+
|
|
129
|
+
attribute :path, IdentityPath
|
|
130
|
+
|
|
131
|
+
# See Aggregate.Identify, where the same rule is written out in full —
|
|
132
|
+
# the builder resolves the real shape (dotted-unwrap, reference, or
|
|
133
|
+
# bare scalar) before a part ever reaches here.
|
|
134
|
+
given("an identity part names something") { !path.value.to_s.empty? }
|
|
135
|
+
|
|
136
|
+
sets :identified_by, append: { value: :path }
|
|
137
|
+
emits PieceIdentified
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
command "Seal" do
|
|
141
|
+
role "Language"
|
|
142
|
+
goal "Close an entity — the checks that need every declaration present"
|
|
143
|
+
|
|
144
|
+
# A piece gets the whole-document shape a head has, for the same reason :
|
|
145
|
+
# "it said SOMETHING" cannot be asked while the parts are still arriving.
|
|
146
|
+
|
|
147
|
+
given("an entity says what it is known by") { !identified_by.empty? }
|
|
148
|
+
|
|
149
|
+
emits PieceSealed
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
command "Attribute" do
|
|
153
|
+
role "Language"
|
|
154
|
+
goal "Attach one attribute to the entity"
|
|
155
|
+
|
|
156
|
+
# THE TYPE IS A REFERENCE TO THE VALUE OBJECT IT NAMES — the same rule
|
|
157
|
+
# Aggregate.Attribute enforces one construct over (see that command's own
|
|
158
|
+
# comment). An entity declares no value objects of its own (Entity never
|
|
159
|
+
# answers `value_object` — entity.rb's own comment says why); its
|
|
160
|
+
# attributes read the SAME pool its enclosing aggregate declares, so this
|
|
161
|
+
# still resolves as a reference, not free text. An entity attribute naming
|
|
162
|
+
# an undeclared value object failed to fail: `type` rode as plain text, so
|
|
163
|
+
# reference resolution never ran and a typo'd or invented type boots clean.
|
|
164
|
+
reference_to ValueObject, as: :type
|
|
165
|
+
attribute :name, EntityText
|
|
166
|
+
attribute :list, EntityText
|
|
167
|
+
attribute :optional, EntityText, optional: true
|
|
168
|
+
attribute :pattern, EntityText, optional: true
|
|
169
|
+
attribute :default, EntityText, optional: true
|
|
170
|
+
attribute :admits, EntityText, optional: true
|
|
171
|
+
attribute :relationship, EntityText, optional: true
|
|
172
|
+
|
|
173
|
+
sets :attributes, append: { name: :name, type: :type, list: :list, default: :default, optional: :optional, pattern: :pattern, admits: :admits, relationship: :relationship }
|
|
174
|
+
|
|
175
|
+
emits PieceAttributeAttached
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
# An attribute that points at ANOTHER AGGREGATE'S HEAD — the SAME
|
|
179
|
+
# construct Aggregate.Reference is, one level down (see that
|
|
180
|
+
# command's own comment for why the type cannot be text): `belongs_to`/
|
|
181
|
+
# `has_one`/`has_many`/`reference_to` are declared on an entity by the
|
|
182
|
+
# same DSL (`EntityBuilder`/`AttributeCollector`) an aggregate uses,
|
|
183
|
+
# and a real fixture already exercises it (`spec/relationship_
|
|
184
|
+
# declaration_spec.rb`'s "uses the same relationship declarations on
|
|
185
|
+
# an entity", `docs/reference/entity.md`). Without this verb such an
|
|
186
|
+
# attribute fell to the SAME `Attribute` verb above, which reads
|
|
187
|
+
# `type` as a value-object reference — so a cross-aggregate reference
|
|
188
|
+
# declared on a piece failed reference resolution against the wrong
|
|
189
|
+
# pool the moment entity attributes started being checked at all.
|
|
190
|
+
command "Reference" do
|
|
191
|
+
role "Language"
|
|
192
|
+
goal "Attach an attribute that points at another aggregate's head"
|
|
193
|
+
|
|
194
|
+
reference_to Aggregate, as: :points_at
|
|
195
|
+
attribute :name, EntityText
|
|
196
|
+
attribute :list, EntityText
|
|
197
|
+
attribute :optional, EntityText, optional: true
|
|
198
|
+
attribute :pattern, EntityText, optional: true
|
|
199
|
+
attribute :default, EntityText, optional: true
|
|
200
|
+
attribute :admits, EntityText, optional: true
|
|
201
|
+
attribute :relationship, EntityText, optional: true
|
|
202
|
+
|
|
203
|
+
sets :attributes, append: { name: :name, type: :points_at, list: :list, default: :default, optional: :optional, pattern: :pattern, admits: :admits, relationship: :relationship }
|
|
204
|
+
|
|
205
|
+
emits PieceReferenceAttached
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
# An attribute whose type names a PIECE NESTED INSIDE THIS ONE — the
|
|
209
|
+
# SAME construct Aggregate.Holds is, one level down (see that
|
|
210
|
+
# command's own comment): `attribute :dispatches, list_of(Dispatch)`
|
|
211
|
+
# inside `entity "Handler"` (S17, ADR 0026's own two-level chain) is
|
|
212
|
+
# exactly `Account#ledger` one level further in. Without this verb
|
|
213
|
+
# such an attribute fell to the SAME `Attribute` verb above, which
|
|
214
|
+
# reads `type` as a value-object reference — so a piece nested inside
|
|
215
|
+
# a piece failed reference resolution against the wrong pool the
|
|
216
|
+
# moment entity attributes started being checked at all (found live:
|
|
217
|
+
# the meta-grammar's own `Handler.dispatches` naming `Dispatch`,
|
|
218
|
+
# nested inside Handler itself).
|
|
219
|
+
command "Holds" do
|
|
220
|
+
role "Language"
|
|
221
|
+
goal "Attach an attribute whose type is a piece nested inside this one"
|
|
222
|
+
|
|
223
|
+
reference_to Entity, as: :holds
|
|
224
|
+
attribute :name, EntityText
|
|
225
|
+
attribute :list, EntityText
|
|
226
|
+
attribute :optional, EntityText, optional: true
|
|
227
|
+
attribute :pattern, EntityText, optional: true
|
|
228
|
+
attribute :default, EntityText, optional: true
|
|
229
|
+
attribute :admits, EntityText, optional: true
|
|
230
|
+
attribute :relationship, EntityText, optional: true
|
|
231
|
+
|
|
232
|
+
sets :attributes, append: { name: :name, type: :holds, list: :list, default: :default, optional: :optional, pattern: :pattern, admits: :admits, relationship: :relationship }
|
|
233
|
+
|
|
234
|
+
emits PieceHeld
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
# A PRECONDITION SHARED ACROSS THIS PIECE'S OWN COMMANDS, DECLARED
|
|
239
|
+
# ONCE (ADR 0028) — see Aggregate.Precondition, the identical shape
|
|
240
|
+
# one level down: the piece's own named `given`, referenced back by
|
|
241
|
+
# one of its own commands rather than re-typed.
|
|
242
|
+
command "Precondition" do
|
|
243
|
+
role "Language"
|
|
244
|
+
goal "Declare one precondition this piece's own commands can reference by name"
|
|
245
|
+
|
|
246
|
+
attribute :description, EntityText, optional: true
|
|
247
|
+
attribute :canonical, EntityText
|
|
248
|
+
|
|
249
|
+
given("a rule says what it means") { !description.value.to_s.empty? }
|
|
250
|
+
given("a rule survives extraction") { !canonical.value.to_s.empty? }
|
|
251
|
+
|
|
252
|
+
sets :preconditions, append: { description: :description, canonical: :canonical }
|
|
253
|
+
|
|
254
|
+
emits PiecePreconditionAttached
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
# A PIECE'S OWN SHAPE RULE, DECLARED ONCE (round 7) — see
|
|
258
|
+
# Aggregate.Invariant, the identical shape one level down: checked
|
|
259
|
+
# against every instance of this piece, not this ONE aggregate's
|
|
260
|
+
# own flat state.
|
|
261
|
+
command "Invariant" do
|
|
262
|
+
role "Language"
|
|
263
|
+
goal "Attach one shape rule this piece's own instances must hold"
|
|
264
|
+
|
|
265
|
+
attribute :description, EntityText, optional: true
|
|
266
|
+
attribute :canonical, EntityText
|
|
267
|
+
|
|
268
|
+
given("a rule says what it means") { !description.value.to_s.empty? }
|
|
269
|
+
given("a rule survives extraction") { !canonical.value.to_s.empty? }
|
|
270
|
+
|
|
271
|
+
sets :invariants, append: { description: :description, canonical: :canonical }
|
|
272
|
+
|
|
273
|
+
emits PieceInvariantAttached
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
command "Lifecycle" do
|
|
277
|
+
role "Language"
|
|
278
|
+
goal "Name the field this entity's state machine runs on"
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
sets :state_field
|
|
282
|
+
sets :state_start
|
|
283
|
+
|
|
284
|
+
emits PieceLifecycleNamed
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
command "Transition" do
|
|
288
|
+
role "Language"
|
|
289
|
+
goal "Attach one transition to the entity's state machine"
|
|
290
|
+
|
|
291
|
+
attribute :command, EntityText
|
|
292
|
+
attribute :from_state, EntityText, optional: true
|
|
293
|
+
attribute :to_state, EntityText
|
|
294
|
+
|
|
295
|
+
sets :transitions, append: { command: :command, from_state: :from_state, to_state: :to_state }
|
|
296
|
+
|
|
297
|
+
emits PieceTransitionAttached
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
# HOW ENTITY IS SPELLED. These rows live with the concept
|
|
301
|
+
# they describe; SyntaxBoot discovers every aggregate-local seed table.
|
|
302
|
+
# Contexts represented here: Entity.
|
|
303
|
+
value_object "KeywordSeed" do
|
|
304
|
+
attribute :word, String
|
|
305
|
+
attribute :context, String, admits: "Syntax::Context"
|
|
306
|
+
attribute :body, String, admits: "Syntax::Body"
|
|
307
|
+
attribute :inner, String
|
|
308
|
+
attribute :opens, String
|
|
309
|
+
attribute :fills, String
|
|
310
|
+
attribute :status, String, default: "admitted", admits: "Syntax::Status"
|
|
311
|
+
attribute :was, String
|
|
312
|
+
attribute :resolves_via, String, default: "", admits: "Syntax::ResolutionScope"
|
|
313
|
+
attribute :disambiguator, String, default: "", admits: "Syntax::Disambiguator"
|
|
314
|
+
|
|
315
|
+
member word: "description", context: "Entity", body: "none", inner: "", opens: "", fills: "description"
|
|
316
|
+
member word: "identified_by", context: "Entity", body: "keywords", inner: "ValueObject", opens: "ValueObject", fills: "identified_by", calls: "identified_by_impl"
|
|
317
|
+
member word: "identified_by", context: "Entity", body: "none", inner: "", opens: "", fills: "identified_by", calls: "identified_by_impl"
|
|
318
|
+
member word: "given", context: "Entity", body: "source", inner: "", opens: "", fills: "preconditions", resolves_via: "owner_keyed", disambiguator: "declared_by", calls: "given_impl"
|
|
319
|
+
member word: "invariant", context: "Entity", body: "source", inner: "", opens: "", fills: "invariants", calls: "invariant_impl"
|
|
320
|
+
member word: "command", context: "Entity", body: "keywords", inner: "Command", opens: "Command", fills: "", calls: "command_impl"
|
|
321
|
+
member word: "query", context: "Entity", body: "keywords", inner: "Query", opens: "Query", fills: "", calls: "query_impl"
|
|
322
|
+
member word: "lifecycle", context: "Entity", body: "keywords", inner: "Lifecycle", opens: "", fills: "state_field", calls: "lifecycle_impl"
|
|
323
|
+
member word: "attribute", context: "Entity", body: "none", inner: "", opens: "", fills: "attributes", calls: "attribute_impl"
|
|
324
|
+
member word: "reference_to", context: "Entity", body: "none", inner: "", opens: "", fills: "attributes", calls: "reference_to_impl"
|
|
325
|
+
member word: "has_many", context: "Entity", body: "none", inner: "", opens: "", fills: "attributes", calls: "has_many_impl"
|
|
326
|
+
member word: "has_one", context: "Entity", body: "none", inner: "", opens: "", fills: "attributes", calls: "has_one_impl"
|
|
327
|
+
member word: "belongs_to", context: "Entity", body: "none", inner: "", opens: "", fills: "attributes", calls: "belongs_to_impl"
|
|
328
|
+
member word: "entity", context: "Entity", body: "keywords", inner: "Entity", opens: "Entity", fills: "", calls: "entity_impl"
|
|
329
|
+
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
value_object "ArgumentSeed" do
|
|
333
|
+
attribute :keyword, String
|
|
334
|
+
attribute :context, String, admits: "Syntax::Context"
|
|
335
|
+
attribute :at, String
|
|
336
|
+
attribute :named, String
|
|
337
|
+
attribute :kind, String, admits: "Syntax::ArgumentKind"
|
|
338
|
+
attribute :required, String
|
|
339
|
+
attribute :fills, String
|
|
340
|
+
attribute :selects, String
|
|
341
|
+
attribute :pair_key_fills, String
|
|
342
|
+
attribute :pair_value_fills, String
|
|
343
|
+
attribute :pairs_shape, String, admits: "Syntax::PairsShape"
|
|
344
|
+
attribute :status, String, default: "admitted", admits: "Syntax::Status"
|
|
345
|
+
attribute :variadic, String
|
|
346
|
+
attribute :minimum, String
|
|
347
|
+
attribute :coerce, String
|
|
348
|
+
attribute :blank_message, String
|
|
349
|
+
|
|
350
|
+
member keyword: "description", context: "Entity", at: "1", named: "", kind: "text", required: "true", fills: "description", coerce: "false"
|
|
351
|
+
member keyword: "given", context: "Entity", at: "1", named: "", kind: "text", required: "true", fills: "description"
|
|
352
|
+
# PLAIN TEXT, not `kind: "constant"` — unlike `Aggregate`'s own
|
|
353
|
+
# `declared_by:` (which names a real aggregate constant), a piece
|
|
354
|
+
# has no first-class, independently-addressable reference anywhere
|
|
355
|
+
# in this language. "AggregateName.EntityName" ships as a string,
|
|
356
|
+
# the same way `admits:` shipped textual before its own
|
|
357
|
+
# constant-bridge existed — see `EntityBuilder#given_impl`'s own
|
|
358
|
+
# comment for why this is a deliberate, not temporary-by-oversight,
|
|
359
|
+
# divergence.
|
|
360
|
+
member keyword: "given", context: "Entity", at: "", named: "declared_by", kind: "text", required: "false", fills: "declared_by"
|
|
361
|
+
member keyword: "invariant", context: "Entity", at: "1", named: "", kind: "text", required: "true", fills: "description"
|
|
362
|
+
member keyword: "identified_by", context: "Entity", at: "1", named: "", kind: "symbol", required: "false", fills: "identified_by", variadic: "true", minimum: "2"
|
|
363
|
+
member keyword: "identified_by", context: "Entity", at: "1", named: "", kind: "constant", required: "false", fills: "type"
|
|
364
|
+
member keyword: "identified_by", context: "Entity", at: "", named: "as", kind: "symbol", required: "false", fills: "name"
|
|
365
|
+
member keyword: "command", context: "Entity", at: "1", named: "", kind: "text", required: "true", fills: "name"
|
|
366
|
+
member keyword: "command", context: "Entity", at: "", named: "from", kind: "literal", required: "false", fills: "from"
|
|
367
|
+
member keyword: "query", context: "Entity", at: "1", named: "", kind: "text", required: "true", fills: "name"
|
|
368
|
+
member keyword: "entity", context: "Entity", at: "1", named: "", kind: "text", required: "true", fills: "name"
|
|
369
|
+
member keyword: "lifecycle", context: "Entity", at: "1", named: "", kind: "symbol", required: "true", fills: "state_field"
|
|
370
|
+
member keyword: "lifecycle", context: "Entity", at: "", named: "default", kind: "literal", required: "true", fills: "state_start"
|
|
371
|
+
member keyword: "attribute", context: "Entity", at: "1", named: "", kind: "symbol", required: "true", fills: "name"
|
|
372
|
+
member keyword: "attribute", context: "Entity", at: "2", named: "", kind: "constant", required: "true", fills: "type"
|
|
373
|
+
member keyword: "attribute", context: "Entity", at: "", named: "default", kind: "literal", required: "false", fills: "default"
|
|
374
|
+
member keyword: "attribute", context: "Entity", at: "", named: "optional", kind: "flag", required: "false", fills: "optional"
|
|
375
|
+
member keyword: "attribute", context: "Entity", at: "", named: "pattern", kind: "text", required: "false", fills: "pattern"
|
|
376
|
+
member keyword: "attribute", context: "Entity", at: "", named: "admits", kind: "text", required: "false", fills: "admits"
|
|
377
|
+
member keyword: "attribute", context: "Entity", at: "", named: "one_of", kind: "list", required: "false", fills: "one_of"
|
|
378
|
+
member keyword: "reference_to", context: "Entity", at: "1", named: "", kind: "constant", required: "true", fills: "type"
|
|
379
|
+
member keyword: "reference_to", context: "Entity", at: "", named: "as", kind: "symbol", required: "false", fills: "name"
|
|
380
|
+
member keyword: "reference_to", context: "Entity", at: "", named: "optional", kind: "flag", required: "false", fills: "optional"
|
|
381
|
+
member keyword: "has_many", context: "Entity", at: "1", named: "", kind: "constant", required: "true", fills: "type"
|
|
382
|
+
member keyword: "has_many", context: "Entity", at: "", named: "as", kind: "symbol", required: "false", fills: "name"
|
|
383
|
+
member keyword: "has_one", context: "Entity", at: "1", named: "", kind: "constant", required: "true", fills: "type"
|
|
384
|
+
member keyword: "has_one", context: "Entity", at: "", named: "as", kind: "symbol", required: "false", fills: "name"
|
|
385
|
+
member keyword: "has_one", context: "Entity", at: "", named: "optional", kind: "flag", required: "false", fills: "optional"
|
|
386
|
+
member keyword: "belongs_to", context: "Entity", at: "1", named: "", kind: "constant", required: "true", fills: "type"
|
|
387
|
+
member keyword: "belongs_to", context: "Entity", at: "", named: "as", kind: "symbol", required: "false", fills: "name"
|
|
388
|
+
member keyword: "belongs_to", context: "Entity", at: "", named: "optional", kind: "flag", required: "false", fills: "optional"
|
|
389
|
+
|
|
390
|
+
end
|
|
391
|
+
end
|
|
392
|
+
end
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
Hecks.bluebook "Bluebook" do
|
|
2
|
+
aggregate "Policy" do
|
|
3
|
+
description "One policy — the event it watches, the command it fires, and the domain that command belongs to."
|
|
4
|
+
|
|
5
|
+
reference_to Bluebook
|
|
6
|
+
|
|
7
|
+
# THE CHAPTER IT IS IN, AND ITS NAME. A policy hangs off the chapter rather
|
|
8
|
+
# than an aggregate, so the chapter is the part above it.
|
|
9
|
+
identified_by :bluebook, :name
|
|
10
|
+
|
|
11
|
+
attribute :name, PolicyName
|
|
12
|
+
# WHICH HEAD DECLARED IT, empty for a reaction the chapter owns.
|
|
13
|
+
#
|
|
14
|
+
# A policy written inside an aggregate is hoisted onto the chapter by the
|
|
15
|
+
# builder, and the chapter is where the runtime reads it — so nothing was ever
|
|
16
|
+
# lost at runtime. What was lost is where it was WRITTEN, which is a fact about
|
|
17
|
+
# the source, and facts about the source are what this language holds.
|
|
18
|
+
# `Aggregate#to_h` does not carry it and does not need to: the wire format is
|
|
19
|
+
# a contract, and the language may hold more than it.
|
|
20
|
+
attribute :aggregate, PolicyText
|
|
21
|
+
attribute :on_event, PolicyText
|
|
22
|
+
attribute :trigger_command, PolicyText
|
|
23
|
+
attribute :target_domain, PolicyText
|
|
24
|
+
# THE GUARD, CARRIED AS TEXT — same discipline `Command.givens`
|
|
25
|
+
# already holds: the block that wrote it is never called at
|
|
26
|
+
# runtime, only its EXTRACTED SOURCE is (Ports::Extraction), so
|
|
27
|
+
# what the language holds is the string, not a live Proc no wire
|
|
28
|
+
# format could carry. Optional — most policies fire unconditionally.
|
|
29
|
+
attribute :where, PolicyText, optional: true
|
|
30
|
+
# THE FAN-OUT SOURCE — a query verb ("Aggregate.query_name" or
|
|
31
|
+
# "Domain::Aggregate.query_name"), same text shape as
|
|
32
|
+
# `trigger_command`/`target_domain` beside it. Optional — most
|
|
33
|
+
# policies fire once, not once per row.
|
|
34
|
+
attribute :for_each, PolicyText, optional: true
|
|
35
|
+
# WHAT THE TRIGGER IS GIVEN, when the event's own shape is not it.
|
|
36
|
+
# Empty means the whole payload forwards verbatim — what every policy
|
|
37
|
+
# did before this existed, and still the right default for a trigger
|
|
38
|
+
# shaped like its event.
|
|
39
|
+
#
|
|
40
|
+
# The same `Binding` list a saga's own `Dispatch` carries, for the
|
|
41
|
+
# same reason: a reaction crosses an aggregate boundary, and the
|
|
42
|
+
# event on one side is under no obligation to be shaped like the
|
|
43
|
+
# command on the other. Without it the target has to declare every
|
|
44
|
+
# field the event happens to carry — banking's own `FreezeAccount`
|
|
45
|
+
# grew an attribute it never reads, and Account grew two duplicated
|
|
46
|
+
# value objects to type it, before this word existed.
|
|
47
|
+
attribute :with_spec, list_of(Binding)
|
|
48
|
+
|
|
49
|
+
value_object "PolicyName" do
|
|
50
|
+
attribute :value, String
|
|
51
|
+
invariant("a policy is named") { !value.to_s.empty? }
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
value_object "PolicyText" do
|
|
55
|
+
attribute :value, String
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# DECLARED HERE RATHER THAN SHARED WITH `Dispatch`'s own — a value
|
|
59
|
+
# object belongs to the aggregate that uses it, and everything that
|
|
60
|
+
# walks an aggregate's own scope has nowhere else to look.
|
|
61
|
+
value_object "Binding" do
|
|
62
|
+
attribute :key, String
|
|
63
|
+
attribute :value, String
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# The way back: everything DECLARED IN the chapter above. The parent
|
|
67
|
+
# reference IS the query.
|
|
68
|
+
# WHERE IT SITS AMONG ITS SIBLINGS. Declaration order is a FACT ABOUT THE
|
|
69
|
+
# SOURCE — the IR is a contract read straight from this file,
|
|
70
|
+
# field for field AND INDEX FOR INDEX. So the language HOLDS it, instead of
|
|
71
|
+
# inheriting it from whatever order a store happens to iterate: an ask that
|
|
72
|
+
# does not say how it is ordered is answered in identity order, which is
|
|
73
|
+
# right for every other ask and fatal for the one that is the SOURCE.
|
|
74
|
+
value_object "Position" do
|
|
75
|
+
attribute :value, Integer
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
attribute :position, Position
|
|
79
|
+
|
|
80
|
+
query "DeclaredIn" do
|
|
81
|
+
attribute :bluebook, PolicyText
|
|
82
|
+
where(bluebook: :bluebook)
|
|
83
|
+
order_by :position
|
|
84
|
+
end
|
|
85
|
+
command "Declare" do
|
|
86
|
+
role "Language"
|
|
87
|
+
goal "Declare a policy on a chapter"
|
|
88
|
+
|
|
89
|
+
reference_to Bluebook
|
|
90
|
+
attribute :name, PolicyName
|
|
91
|
+
attribute :aggregate, PolicyText, optional: true
|
|
92
|
+
attribute :on_event, PolicyText
|
|
93
|
+
attribute :trigger_command, PolicyText
|
|
94
|
+
attribute :target_domain, PolicyText, optional: true
|
|
95
|
+
attribute :where, PolicyText, optional: true
|
|
96
|
+
attribute :for_each, PolicyText, optional: true
|
|
97
|
+
|
|
98
|
+
attribute :position, Position, optional: true
|
|
99
|
+
sets :bluebook
|
|
100
|
+
sets :name
|
|
101
|
+
sets :aggregate
|
|
102
|
+
sets :on_event
|
|
103
|
+
sets :trigger_command
|
|
104
|
+
sets :target_domain
|
|
105
|
+
sets :where
|
|
106
|
+
sets :for_each
|
|
107
|
+
sets :position
|
|
108
|
+
emits ReactionDeclared
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
command "Bind" do
|
|
112
|
+
role "Language"
|
|
113
|
+
goal "Bind one argument of the triggered command"
|
|
114
|
+
|
|
115
|
+
attribute :key, PolicyText
|
|
116
|
+
attribute :value, PolicyText
|
|
117
|
+
|
|
118
|
+
sets :with_spec, append: { key: :key, value: :value }
|
|
119
|
+
|
|
120
|
+
emits TriggerBindingAttached
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
# HOW POLICY IS SPELLED. These rows live with the concept
|
|
124
|
+
# they describe; SyntaxBoot discovers every aggregate-local seed table.
|
|
125
|
+
# Contexts represented here: Policy.
|
|
126
|
+
#
|
|
127
|
+
# `on`'s ArgumentSeed gained a `kind: "constant"` row alongside its
|
|
128
|
+
# existing `kind: "text"` one (ADR 0025, S6 — "events first-class"),
|
|
129
|
+
# same shape `trigger`'s own pair already carries — `on
|
|
130
|
+
# Account::AccountFrozen`, a bare constant, now parses the same way
|
|
131
|
+
# `trigger Account::Debit` does. `calls: "on_impl"` routes the word
|
|
132
|
+
# through a hand-written method (`PolicyBuilder#on_impl`) instead of
|
|
133
|
+
# the generic single-fill coercion, mirroring `trigger`'s own
|
|
134
|
+
# `calls: "trigger_impl"` on the row below. UNLIKE `trigger`,
|
|
135
|
+
# `on_impl` does NOT refuse the quoted-text form outside
|
|
136
|
+
# `shadow_parse` — command references were safe to refuse that way
|
|
137
|
+
# only because they're 100% migrated across the live corpus; event
|
|
138
|
+
# names (`emits`/`on`) are not (only Account's `AccountFrozen` is,
|
|
139
|
+
# this pass), so refusing the old spelling here would break every
|
|
140
|
+
# live `.bluebook` site this pass didn't touch. Both forms stay
|
|
141
|
+
# admitted until a full corpus migration lands.
|
|
142
|
+
value_object "KeywordSeed" do
|
|
143
|
+
attribute :word, String
|
|
144
|
+
attribute :context, String, admits: "Syntax::Context"
|
|
145
|
+
attribute :body, String, admits: "Syntax::Body"
|
|
146
|
+
attribute :inner, String
|
|
147
|
+
attribute :opens, String
|
|
148
|
+
attribute :fills, String
|
|
149
|
+
attribute :status, String, default: "admitted", admits: "Syntax::Status"
|
|
150
|
+
attribute :was, String
|
|
151
|
+
attribute :resolves_via, String, default: "", admits: "Syntax::ResolutionScope"
|
|
152
|
+
attribute :disambiguator, String, default: "", admits: "Syntax::Disambiguator"
|
|
153
|
+
|
|
154
|
+
member word: "on", context: "Policy", body: "none", inner: "", opens: "", fills: "on_event", calls: "on_impl"
|
|
155
|
+
member word: "trigger", context: "Policy", body: "none", inner: "", opens: "", fills: "trigger_command", calls: "trigger_impl"
|
|
156
|
+
member word: "across", context: "Policy", body: "none", inner: "", opens: "", fills: "target_domain"
|
|
157
|
+
member word: "where", context: "Policy", body: "source", inner: "", opens: "", fills: "where"
|
|
158
|
+
member word: "for_each", context: "Policy", body: "none", inner: "", opens: "", fills: "for_each"
|
|
159
|
+
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
value_object "ArgumentSeed" do
|
|
163
|
+
attribute :keyword, String
|
|
164
|
+
attribute :context, String, admits: "Syntax::Context"
|
|
165
|
+
attribute :at, String
|
|
166
|
+
attribute :named, String
|
|
167
|
+
attribute :kind, String, admits: "Syntax::ArgumentKind"
|
|
168
|
+
attribute :required, String
|
|
169
|
+
attribute :fills, String
|
|
170
|
+
attribute :selects, String
|
|
171
|
+
attribute :pair_key_fills, String
|
|
172
|
+
attribute :pair_value_fills, String
|
|
173
|
+
attribute :pairs_shape, String, admits: "Syntax::PairsShape"
|
|
174
|
+
attribute :status, String, default: "admitted", admits: "Syntax::Status"
|
|
175
|
+
attribute :variadic, String
|
|
176
|
+
attribute :coerce, String
|
|
177
|
+
attribute :blank_message, String
|
|
178
|
+
|
|
179
|
+
member keyword: "on", context: "Policy", at: "1", named: "", kind: "constant", required: "true", fills: "on_event"
|
|
180
|
+
member keyword: "on", context: "Policy", at: "1", named: "", kind: "text", required: "true", fills: "on_event"
|
|
181
|
+
member keyword: "trigger", context: "Policy", at: "1", named: "", kind: "constant", required: "true", fills: "trigger_command"
|
|
182
|
+
member keyword: "trigger", context: "Policy", at: "1", named: "", kind: "text", required: "true", fills: "trigger_command"
|
|
183
|
+
member keyword: "across", context: "Policy", at: "1", named: "", kind: "text", required: "true", fills: "target_domain"
|
|
184
|
+
member keyword: "for_each", context: "Policy", at: "1", named: "", kind: "text", required: "true", fills: "for_each"
|
|
185
|
+
member keyword: "trigger", context: "Policy", at: "", named: "with", kind: "pairs", required: "false", fills: "with_spec", pairs_shape: "verbatim"
|
|
186
|
+
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
end
|