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,88 @@
|
|
|
1
|
+
require_relative "../../../runtime/value"
|
|
2
|
+
|
|
3
|
+
module Hecks
|
|
4
|
+
module Adapters
|
|
5
|
+
class Postgres
|
|
6
|
+
# How a state crosses the column boundary: which fields persist, and
|
|
7
|
+
# how each one encodes into (and decodes out of) its column. Same
|
|
8
|
+
# SHAPE as Sqlite::Codec (one column per attribute, JSON for
|
|
9
|
+
# nested/list) — not its mechanics. Sqlite's own columns carry no
|
|
10
|
+
# type affinity worth trusting on the way back out (SQLite gives it
|
|
11
|
+
# back typed anyway via the driver), but `pg` hands every column
|
|
12
|
+
# back as TEXT unless a type map says otherwise, so a real `bigint`/
|
|
13
|
+
# `double precision` column needs its OWN coercion on decode that
|
|
14
|
+
# Sqlite never had to write.
|
|
15
|
+
module Codec
|
|
16
|
+
private
|
|
17
|
+
|
|
18
|
+
def persisted_fields
|
|
19
|
+
fields = @aggregate.attributes.reject { |attribute| attribute.name == :id }.map do |attribute|
|
|
20
|
+
{ name: attribute.name, attribute: attribute, sql_type: sql_type(attribute) }
|
|
21
|
+
end
|
|
22
|
+
lifecycle = @aggregate.lifecycle
|
|
23
|
+
fields << { name: lifecycle.field, attribute: nil, sql_type: "text" } if lifecycle && !fields.any? { |field| field[:name] == lifecycle.field }
|
|
24
|
+
# `projects` FIELDS (S12, ADR 0025) ARE A LOCAL COLUMN TOO — see
|
|
25
|
+
# Sqlite::Codec#persisted_fields' own comment; identical reasoning,
|
|
26
|
+
# `text` to match this file's own lowercase SQL type spelling.
|
|
27
|
+
@aggregate.projected_fields.each do |field|
|
|
28
|
+
next if fields.any? { |f| f[:name] == field.name }
|
|
29
|
+
|
|
30
|
+
fields << { name: field.name, attribute: nil, sql_type: "text" }
|
|
31
|
+
end
|
|
32
|
+
fields
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def encode(attr, value)
|
|
36
|
+
# NEVER SET IS NOT EMPTY — same reasoning as Sqlite::Codec's own
|
|
37
|
+
# comment: a list attribute nothing has ever appended to has to
|
|
38
|
+
# stay NULL to answer the same as Memory does, not become `[]`
|
|
39
|
+
# invented by this adapter's own storage.
|
|
40
|
+
return (value.nil? ? nil : JSON.generate(value)) if attr.list?
|
|
41
|
+
return JSON.generate(value) if value.is_a?(Hash) || value.is_a?(Runtime::Value)
|
|
42
|
+
|
|
43
|
+
value
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def encode_field(field, value)
|
|
47
|
+
return value unless field[:attribute]
|
|
48
|
+
|
|
49
|
+
encode(field[:attribute], value)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def decode(row)
|
|
53
|
+
persisted_fields.each_with_object({}) do |field, state|
|
|
54
|
+
attr = field[:attribute]
|
|
55
|
+
unless attr
|
|
56
|
+
state[field[:name]] = row[field[:name].to_s]
|
|
57
|
+
next
|
|
58
|
+
end
|
|
59
|
+
raw = row[attr.name.to_s]
|
|
60
|
+
state[attr.name] =
|
|
61
|
+
if attr.list? || value_object?(attr)
|
|
62
|
+
raw ? JSON.parse(raw, symbolize_names: true) : nil
|
|
63
|
+
else
|
|
64
|
+
coerce_scalar(attr, raw)
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# `pg` returns every column as a Ruby String by default (no type
|
|
70
|
+
# map installed) — a `bigint`/`double precision` column has to be
|
|
71
|
+
# coerced back on the way out, unlike Sqlite3's own driver, which
|
|
72
|
+
# already types a row by the column's declared affinity. Mirrors
|
|
73
|
+
# SQL_TYPES' own mapping: whatever gets a real numeric column here
|
|
74
|
+
# gets converted back here, everything else (String, references,
|
|
75
|
+
# enums, ...) passes through as the text it already is.
|
|
76
|
+
def coerce_scalar(attr, raw)
|
|
77
|
+
return nil if raw.nil?
|
|
78
|
+
|
|
79
|
+
case attr.type
|
|
80
|
+
when "Integer" then raw.to_i
|
|
81
|
+
when "Float" then raw.to_f
|
|
82
|
+
else raw
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
require "digest"
|
|
2
|
+
|
|
3
|
+
module Hecks
|
|
4
|
+
module Adapters
|
|
5
|
+
class Postgres
|
|
6
|
+
# The DDL: one table per aggregate, a real column per attribute (a
|
|
7
|
+
# jsonb column per nested/list attribute), an append-only entry
|
|
8
|
+
# table beside it, the shared events/saga tables — and the automatic
|
|
9
|
+
# indexing this adapter carries that `PostgresEra` does not (see
|
|
10
|
+
# docs/implemented/postgres-era-adapter-split-plan.md, governing principle 3:
|
|
11
|
+
# every field a declared query filters or sorts on is safe to index
|
|
12
|
+
# directly here, since there is no `head_view` reduction to route
|
|
13
|
+
# around the way `PostgresEra`'s own cache-table story exists for).
|
|
14
|
+
module SchemaBuilder
|
|
15
|
+
private
|
|
16
|
+
|
|
17
|
+
def create_aggregate_table!
|
|
18
|
+
columns = persisted_fields.map { |field| "#{quote_ident(field[:name])} #{field[:sql_type]}" }
|
|
19
|
+
@db.exec(
|
|
20
|
+
"CREATE TABLE IF NOT EXISTS #{quoted_table} (id text PRIMARY KEY#{columns.empty? ? '' : ', '}#{columns.join(', ')})"
|
|
21
|
+
)
|
|
22
|
+
# SELF-HEALING, SAME IDIOM AS `ensure_indexes!` BELOW —
|
|
23
|
+
# `CREATE TABLE IF NOT EXISTS` above does NOT retroactively add a
|
|
24
|
+
# column to an already-existing table (a committed database from
|
|
25
|
+
# before optimistic-concurrency CAS existed), so this runs
|
|
26
|
+
# unconditionally on every boot and no-ops once the column is
|
|
27
|
+
# there. ADAPTER BOOKKEEPING ONLY — never listed in
|
|
28
|
+
# `persisted_fields` (Codec), so it never appears in `decode`'s
|
|
29
|
+
# domain-state hash or `Instance#to_h`.
|
|
30
|
+
@db.exec("ALTER TABLE #{quoted_table} ADD COLUMN IF NOT EXISTS hecks_version bigint NOT NULL DEFAULT 1")
|
|
31
|
+
# RIGHT HERE, NOT A SEPARATE STEP IN `Postgres#initialize` —
|
|
32
|
+
# same idiom Sqlite::SchemaBuilder's own `create_aggregate_table!`
|
|
33
|
+
# uses: index creation runs unconditionally, right after the
|
|
34
|
+
# table it indexes exists, the same self-healing shape
|
|
35
|
+
# `ensure_head_snapshot!`/`ensure_first_head!` already use on
|
|
36
|
+
# `PostgresEra`'s side.
|
|
37
|
+
ensure_indexes!
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def create_entry_table!
|
|
41
|
+
@db.exec(<<~SQL)
|
|
42
|
+
CREATE TABLE IF NOT EXISTS #{quoted_entry_table} (
|
|
43
|
+
sequence bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
|
44
|
+
aggregate_id text NOT NULL,
|
|
45
|
+
operation text NOT NULL DEFAULT 'save',
|
|
46
|
+
state jsonb NOT NULL,
|
|
47
|
+
mirrors jsonb
|
|
48
|
+
)
|
|
49
|
+
SQL
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Same DDL as `PostgresEra`'s own — not lineage-specific, copied
|
|
53
|
+
# verbatim (see docs/implemented/postgres-era-adapter-split-plan.md).
|
|
54
|
+
def create_event_table!
|
|
55
|
+
@db.exec(<<~SQL)
|
|
56
|
+
CREATE TABLE IF NOT EXISTS events (
|
|
57
|
+
id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
|
58
|
+
name text NOT NULL,
|
|
59
|
+
aggregate text NOT NULL,
|
|
60
|
+
aggregate_id text NOT NULL,
|
|
61
|
+
payload jsonb,
|
|
62
|
+
occurred_at text
|
|
63
|
+
)
|
|
64
|
+
SQL
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Same DDL as `PostgresEra`'s own — not lineage-specific, copied
|
|
68
|
+
# verbatim (see docs/implemented/postgres-era-adapter-split-plan.md).
|
|
69
|
+
def create_saga_table!
|
|
70
|
+
@db.exec(<<~SQL)
|
|
71
|
+
CREATE TABLE IF NOT EXISTS hecks_saga_instances (
|
|
72
|
+
domain text NOT NULL,
|
|
73
|
+
process_manager text NOT NULL,
|
|
74
|
+
correlation text NOT NULL,
|
|
75
|
+
state text NOT NULL,
|
|
76
|
+
memory jsonb NOT NULL,
|
|
77
|
+
completed_compensations jsonb NOT NULL DEFAULT '[]'::jsonb,
|
|
78
|
+
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
79
|
+
PRIMARY KEY (domain, process_manager, correlation)
|
|
80
|
+
)
|
|
81
|
+
SQL
|
|
82
|
+
# `CREATE TABLE IF NOT EXISTS` above is a no-op against a table
|
|
83
|
+
# this same domain already created before this column existed
|
|
84
|
+
# — the same idiom `rust/host/src/journal.rs`'s own
|
|
85
|
+
# `sagas_backfilled` column addition already uses, for the
|
|
86
|
+
# identical reason.
|
|
87
|
+
@db.exec("ALTER TABLE hecks_saga_instances ADD COLUMN IF NOT EXISTS completed_compensations jsonb NOT NULL DEFAULT '[]'::jsonb")
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def sql_type(attr)
|
|
91
|
+
return "jsonb" if attr.list? || value_object?(attr)
|
|
92
|
+
|
|
93
|
+
SQL_TYPES.fetch(attr.type, "text")
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# ── automatic indexing ───────────────────────────────────────
|
|
97
|
+
#
|
|
98
|
+
# Derived from every declared query's `where`/`order_by` fields —
|
|
99
|
+
# no bluebook author opts in, matching every other self-healing
|
|
100
|
+
# schema move this adapter makes. Walks the aggregate's own
|
|
101
|
+
# queries AND each entity's own queries — the same enumeration
|
|
102
|
+
# `dsl/aggregate_builder.rb`'s own `query_surfaces` walks at
|
|
103
|
+
# declaration-seal time — but an entity's own fields never
|
|
104
|
+
# produce an index below: an entity has no table of its own, its
|
|
105
|
+
# rows live inside a LIST-typed attribute on the AGGREGATE's own
|
|
106
|
+
# table (`QueryInterpreter#entity_rows` resolves it that way, and
|
|
107
|
+
# answers an entity query entirely in memory over `repository.all`
|
|
108
|
+
# — it never reaches this adapter's own `query` method at all).
|
|
109
|
+
# Every list-typed attribute is excluded below regardless (see
|
|
110
|
+
# `index_field!`), so an entity's own field would always resolve
|
|
111
|
+
# to "skip" anyway. Walked explicitly rather than silently
|
|
112
|
+
# dropped, so a reader can see entities were considered here, not
|
|
113
|
+
# forgotten.
|
|
114
|
+
def ensure_indexes!
|
|
115
|
+
query_surfaces.each do |owner, queries|
|
|
116
|
+
next unless owner.equal?(@aggregate)
|
|
117
|
+
|
|
118
|
+
queries.each { |query| index_query!(query) }
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def query_surfaces
|
|
123
|
+
[[@aggregate, @aggregate.queries]] +
|
|
124
|
+
@aggregate.entities.map { |entity| [entity, entity.queries] }
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def index_query!(query)
|
|
128
|
+
query.wheres.each { |clause| index_field!(clause.field) }
|
|
129
|
+
index_field!(query.order_by.field) if query.order_by
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# A `list_of` attribute is never indexed here — this adapter's
|
|
133
|
+
# own `contains` on a list field compiles to `EXISTS (SELECT 1
|
|
134
|
+
# FROM jsonb_array_elements(...) ...)` (see `list_contains_clause`
|
|
135
|
+
# below), a SQL shape neither a plain btree on the raw jsonb
|
|
136
|
+
# column nor even a GIN jsonb index (`@>`, `?`) accelerates —
|
|
137
|
+
# Postgres's own GIN jsonb operators match a DIFFERENT SQL shape
|
|
138
|
+
# than the `EXISTS` + `jsonb_array_elements` this codebase always
|
|
139
|
+
# compiles a list `contains` to. An index here would be dead
|
|
140
|
+
# weight, not free correctness, so none is attempted.
|
|
141
|
+
def index_field!(field)
|
|
142
|
+
# A HOP PATH ("owner/field" — `Bluebook::AggregateBuilder`'s own
|
|
143
|
+
# convention for a field reached by crossing a reference,
|
|
144
|
+
# `aggregate_builder.rb`'s own `field.to_s.include?("/")`
|
|
145
|
+
# checks) IS NEVER INDEXED HERE — same reasoning as `list_of`
|
|
146
|
+
# below: `query_expression`/`nested_expression` below have no
|
|
147
|
+
# dialect for this shape at all (they'd compile the whole
|
|
148
|
+
# "owner/field" string as one bare column/jsonb-path segment,
|
|
149
|
+
# which is not a real column and errors PG::UndefinedColumn on
|
|
150
|
+
# `CREATE INDEX`, discovered fuzzing a real Postgres boot of
|
|
151
|
+
# `examples/banking` — Account's own `projects :customer_status,
|
|
152
|
+
# from: :"customer.status"` compiles to exactly this shape).
|
|
153
|
+
# Skipping the index is always safe, the same way skipping a
|
|
154
|
+
# `list_of` index is: an index is a perf optimization, not
|
|
155
|
+
# correctness, so "never built" beats "built wrong." Whether a
|
|
156
|
+
# hop-path field can be QUERIED at all against this adapter is
|
|
157
|
+
# a separate, still-open question this skip does not answer —
|
|
158
|
+
# see docs/future-features.md's fuzzer-adapter entry, and
|
|
159
|
+
# docs/1.0-readiness.md item 2 for this gap's OTHER two
|
|
160
|
+
# independent failure points (Postgres querying, Rust codegen's
|
|
161
|
+
# `OpenForSuspendedCustomers` — bin/rust_coverage's own
|
|
162
|
+
# allowlist) — tracked together, not as three unrelated bugs.
|
|
163
|
+
return if field.to_s.include?("/")
|
|
164
|
+
|
|
165
|
+
name, *_path = field.to_s.split(".")
|
|
166
|
+
attribute = @aggregate.attribute(name)
|
|
167
|
+
return if attribute&.list?
|
|
168
|
+
|
|
169
|
+
# THE SAME EXPRESSION THE QUERY ITSELF COMPILES TO — calling
|
|
170
|
+
# `query_expression`/`plain_column`, the real dialect methods,
|
|
171
|
+
# rather than a second, hand-rolled derivation of the same
|
|
172
|
+
# path that could silently drift from it. An index whose
|
|
173
|
+
# expression doesn't match the planner's own candidate
|
|
174
|
+
# expression byte-for-byte is invisible to the planner,
|
|
175
|
+
# created or not.
|
|
176
|
+
expression = query_expression(field.to_s)
|
|
177
|
+
if expression == plain_column(name)
|
|
178
|
+
create_plain_index!(name)
|
|
179
|
+
else
|
|
180
|
+
create_expression_index!(expression, field.to_s)
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
def create_plain_index!(column)
|
|
185
|
+
name = index_name(column.to_s)
|
|
186
|
+
@db.exec("CREATE INDEX IF NOT EXISTS #{quote_ident(name)} ON #{quoted_table} (#{quote_ident(column)})")
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
def create_expression_index!(expression, field)
|
|
190
|
+
name = index_name(field)
|
|
191
|
+
@db.exec("CREATE INDEX IF NOT EXISTS #{quote_ident(name)} ON #{quoted_table} ((#{expression}))")
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
# Postgres identifiers cap at 63 bytes. Hashing TABLE + FIELD
|
|
195
|
+
# together keeps every generated index name well under that no
|
|
196
|
+
# matter how long an aggregate or attribute name gets, and keeps
|
|
197
|
+
# two distinct fields — on the same table or different ones —
|
|
198
|
+
# from ever colliding, or truncating into the same name the way
|
|
199
|
+
# a naive `"idx_#{table}_#{field}"` could once either got long
|
|
200
|
+
# enough.
|
|
201
|
+
def index_name(field)
|
|
202
|
+
"hecks_idx_#{Digest::SHA256.hexdigest("#{table}:#{field}")[0, 40]}"
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
end
|
|
207
|
+
end
|