hecks 2.7.0 → 2.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/exe/hecks +11 -0
- data/lib/hecks/adapters/driven/claude_code.rb +4 -104
- data/lib/hecks/adapters/driven/d1.rb +44 -237
- data/lib/hecks/adapters/driven/folder.rb +17 -76
- data/lib/hecks/adapters/driven/google_authentication.rb +15 -49
- data/lib/hecks/adapters/driven/governance_authorization.rb +23 -70
- data/lib/hecks/adapters/driven/heki/journal.rb +8 -41
- data/lib/hecks/adapters/driven/heki/saga_store.rb +12 -54
- data/lib/hecks/adapters/driven/heki/snapshot.rb +4 -12
- data/lib/hecks/adapters/driven/heki.rb +13 -42
- data/lib/hecks/adapters/driven/identity_registry.rb +3 -14
- data/lib/hecks/adapters/driven/in_memory_ordering.rb +9 -26
- data/lib/hecks/adapters/driven/in_process_key_vault.rb +2 -14
- data/lib/hecks/adapters/driven/lambda/client.rb +10 -51
- data/lib/hecks/adapters/driven/lambda.rb +10 -84
- data/lib/hecks/adapters/driven/local_storage.rb +5 -40
- data/lib/hecks/adapters/driven/memory.rb +18 -99
- data/lib/hecks/adapters/driven/mock_stripe_adapter.rb +5 -21
- data/lib/hecks/adapters/driven/postgres/codec.rb +6 -28
- data/lib/hecks/adapters/driven/postgres/outbox.rb +3 -12
- data/lib/hecks/adapters/driven/postgres/reconnect.rb +4 -30
- data/lib/hecks/adapters/driven/postgres/schema_builder.rb +34 -108
- data/lib/hecks/adapters/driven/postgres.rb +145 -134
- data/lib/hecks/adapters/driven/postgres_era.adapter +4 -15
- data/lib/hecks/adapters/driven/prism.rb +7 -30
- data/lib/hecks/adapters/driven/sql_query_builder.rb +21 -121
- data/lib/hecks/adapters/driven/sqlite/codec.rb +8 -40
- data/lib/hecks/adapters/driven/sqlite/projection.rb +26 -82
- data/lib/hecks/adapters/driven/sqlite/schema_builder.rb +40 -84
- data/lib/hecks/adapters/driven/sqlite.rb +128 -65
- data/lib/hecks/adapters/driven/tenant_provisioner.rb +15 -37
- data/lib/hecks/adapters/driven.rb +5 -36
- data/lib/hecks/adapters/driving/github_webhook.rb +8 -76
- data/lib/hecks/behaviors/dsl.rb +7 -25
- data/lib/hecks/behaviors/expectations.rb +32 -142
- data/lib/hecks/behaviors/ir.rb +7 -20
- data/lib/hecks/behaviors/rspec.rb +6 -17
- data/lib/hecks/behaviors/runner.rb +10 -34
- data/lib/hecks/behaviors.rb +4 -8
- data/lib/hecks/bluebook/aggregate.rb +9 -75
- data/lib/hecks/bluebook/assembly/aggregate_assembly.rb +9 -38
- data/lib/hecks/bluebook/assembly/build.rb +4 -15
- data/lib/hecks/bluebook/assembly/contract.rb +15 -136
- data/lib/hecks/bluebook/assembly/contracts.rb +54 -174
- data/lib/hecks/bluebook/assembly/marks.rb +31 -223
- data/lib/hecks/bluebook/assembly/specializer.rb +6 -52
- data/lib/hecks/bluebook/assembly.rb +6 -45
- data/lib/hecks/bluebook/attribute.rb +12 -61
- data/lib/hecks/bluebook/behaviour/aggregate.rb +10 -39
- data/lib/hecks/bluebook/behaviour/attribute.rb +3 -14
- data/lib/hecks/bluebook/behaviour/chapter.rb +17 -42
- data/lib/hecks/bluebook/behaviour/command.rb +14 -66
- data/lib/hecks/bluebook/behaviour/domain_port.rb +4 -20
- data/lib/hecks/bluebook/behaviour/entity.rb +7 -27
- data/lib/hecks/bluebook/behaviour/hexagon.rb +23 -41
- data/lib/hecks/bluebook/behaviour/lifecycle.rb +15 -40
- data/lib/hecks/bluebook/behaviour/policy.rb +23 -52
- data/lib/hecks/bluebook/behaviour/process_manager.rb +30 -57
- data/lib/hecks/bluebook/behaviour/read_model.rb +38 -26
- data/lib/hecks/bluebook/behaviour/traits.rb +27 -64
- data/lib/hecks/bluebook/behaviour/value_object.rb +5 -24
- data/lib/hecks/bluebook/capabilities.rb +17 -49
- data/lib/hecks/bluebook/chapter.rb +10 -48
- data/lib/hecks/bluebook/command.rb +23 -81
- data/lib/hecks/bluebook/domain_port.rb +14 -63
- data/lib/hecks/bluebook/dsl/aggregate_builder/sealing.rb +50 -229
- data/lib/hecks/bluebook/dsl/aggregate_builder.rb +50 -377
- data/lib/hecks/bluebook/dsl/attribute_collector.rb +33 -204
- data/lib/hecks/bluebook/dsl/binding_proxy.rb +17 -65
- data/lib/hecks/bluebook/dsl/bluebook_builder/validation.rb +86 -708
- data/lib/hecks/bluebook/dsl/bluebook_builder.rb +56 -170
- data/lib/hecks/bluebook/dsl/bootstrap_table.rb +1 -0
- data/lib/hecks/bluebook/dsl/command_builder.rb +74 -546
- data/lib/hecks/bluebook/dsl/const_shim.rb +8 -41
- data/lib/hecks/bluebook/dsl/domain_port_builder.rb +12 -87
- data/lib/hecks/bluebook/dsl/entity_builder.rb +44 -330
- data/lib/hecks/bluebook/dsl/generic_dispatch.rb +20 -269
- data/lib/hecks/bluebook/dsl/hecksagon_builder.rb +26 -189
- data/lib/hecks/bluebook/dsl/identity_declaration.rb +13 -88
- data/lib/hecks/bluebook/dsl/lifecycle_builder.rb +6 -20
- data/lib/hecks/bluebook/dsl/policy_builder.rb +16 -88
- data/lib/hecks/bluebook/dsl/port_builder.rb +2 -6
- data/lib/hecks/bluebook/dsl/port_operation_builder.rb +22 -96
- data/lib/hecks/bluebook/dsl/process_manager_builder.rb +31 -184
- data/lib/hecks/bluebook/dsl/query_builder.rb +11 -42
- data/lib/hecks/bluebook/dsl/read_model_builder.rb +75 -201
- data/lib/hecks/bluebook/dsl/rule_reference.rb +22 -163
- data/lib/hecks/bluebook/dsl/translation_builder.rb +28 -114
- data/lib/hecks/bluebook/dsl/value_object_builder.rb +10 -124
- data/lib/hecks/bluebook/dsl/word_gate.rb +16 -162
- data/lib/hecks/bluebook/dsl/world_builder.rb +19 -106
- data/lib/hecks/bluebook/entity.rb +13 -71
- data/lib/hecks/bluebook/expression/ast_json.rb +24 -190
- data/lib/hecks/bluebook/expression/ast_reader.rb +12 -54
- data/lib/hecks/bluebook/expression/canonical_form.rb +11 -88
- data/lib/hecks/bluebook/expression/evaluator.rb +47 -295
- data/lib/hecks/bluebook/expression/resolver/block_predicates.rb +30 -147
- data/lib/hecks/bluebook/expression/resolver.rb +37 -660
- data/lib/hecks/bluebook/hexagon.rb +5 -28
- data/lib/hecks/bluebook/lifecycle.rb +5 -16
- data/lib/hecks/bluebook/meta_validator/adapter_judge.rb +1 -7
- data/lib/hecks/bluebook/meta_validator/judge.rb +111 -361
- data/lib/hecks/bluebook/meta_validator/plan.rb +33 -162
- data/lib/hecks/bluebook/meta_validator/port_judge.rb +2 -7
- data/lib/hecks/bluebook/meta_validator/readings.rb +56 -342
- data/lib/hecks/bluebook/meta_validator/reconstruction.rb +24 -176
- data/lib/hecks/bluebook/meta_validator/shapes.rb +54 -268
- data/lib/hecks/bluebook/meta_validator/syntax_boot.rb +47 -308
- data/lib/hecks/bluebook/meta_validator/translation_judge.rb +7 -43
- data/lib/hecks/bluebook/meta_validator/world_judge.rb +6 -18
- data/lib/hecks/bluebook/meta_validator.rb +79 -349
- data/lib/hecks/bluebook/model_check/client_profile.rb +10 -91
- data/lib/hecks/bluebook/model_check.rb +102 -600
- data/lib/hecks/bluebook/pattern_subset.rb +11 -69
- data/lib/hecks/bluebook/process_manager.rb +13 -83
- data/lib/hecks/bluebook/project_loader.rb +3 -39
- data/lib/hecks/bluebook/project_register.rb +12 -60
- data/lib/hecks/bluebook/query.rb +9 -48
- data/lib/hecks/bluebook/read_model.rb +57 -81
- data/lib/hecks/bluebook/reference.rb +7 -41
- data/lib/hecks/bluebook/smoke_test.rb +8 -98
- data/lib/hecks/bluebook/synthesizer.rb +13 -62
- data/lib/hecks/bluebook/translation.rb +26 -62
- data/lib/hecks/bluebook/value_object.rb +11 -36
- data/lib/hecks/bluebook.rb +5 -22
- data/lib/hecks/cache_dir.rb +84 -0
- data/lib/hecks/cli/document.rb +86 -0
- data/lib/hecks/cli/ir.rb +45 -0
- data/lib/hecks/cli/mcp.rb +31 -0
- data/lib/hecks/cli/mcp_door.rb +366 -0
- data/lib/hecks/cli/model_check.rb +203 -0
- data/lib/hecks/cli/project_cli.rb +90 -0
- data/lib/hecks/cli/project_diagrams.rb +36 -0
- data/lib/hecks/cli/run.rb +173 -0
- data/lib/hecks/cli/smoke_test.rb +45 -0
- data/lib/hecks/cli/stores.rb +53 -0
- data/lib/hecks/cli.rb +160 -0
- data/lib/hecks/construct.rb +8 -34
- data/lib/hecks/deploy/bluebook/deploy.bluebook +33 -142
- data/lib/hecks/deploy/bluebook/deploy.hecksagon +2 -9
- data/lib/hecks/embryonaut_bluebook/lock.rb +3 -35
- data/lib/hecks/embryonaut_bluebook/shape.rb +1 -17
- data/lib/hecks/embryonaut_bluebook/vendor.rb +8 -53
- data/lib/hecks/embryonaut_bluebook/vendor_cli.rb +4 -19
- data/lib/hecks/embryonaut_bluebook.rb +4 -71
- data/lib/hecks/facade/cli_door.rb +24 -106
- data/lib/hecks/facade/cli_runner.rb +28 -172
- data/lib/hecks/facade/command_request.rb +13 -33
- data/lib/hecks/facade/handle.rb +34 -121
- data/lib/hecks/facade/json_door.rb +31 -146
- data/lib/hecks/facade/surface/aggregate_door.rb +39 -104
- data/lib/hecks/facade/surface/chapter.rb +10 -54
- data/lib/hecks/facade/surface.rb +8 -23
- data/lib/hecks/facade.rb +10 -25
- data/lib/hecks/forms/app.rb +15 -70
- data/lib/hecks/forms/command_form_renderer.rb +10 -29
- data/lib/hecks/forms/field_renderer.rb +17 -156
- data/lib/hecks/forms/field_shape.rb +30 -222
- data/lib/hecks/forms/html.rb +12 -47
- data/lib/hecks/forms/index_renderer.rb +1 -4
- data/lib/hecks/forms/page.rb +3 -9
- data/lib/hecks/forms/params.rb +14 -60
- data/lib/hecks/forms/port_argument.rb +2 -19
- data/lib/hecks/forms/query_form_renderer.rb +4 -79
- data/lib/hecks/forms/record_renderer.rb +8 -75
- data/lib/hecks/forms/record_table.rb +7 -50
- data/lib/hecks/forms/reference_options.rb +3 -30
- data/lib/hecks/forms/value_object_shape.rb +8 -35
- data/lib/hecks/forms.rb +5 -33
- data/lib/hecks/fqn.rb +5 -12
- data/lib/hecks/framework/bluebook/compliance.bluebook +16 -65
- data/lib/hecks/framework/bluebook/console_settings.bluebook +47 -134
- data/lib/hecks/framework/bluebook/framework.hecksagon +5 -14
- data/lib/hecks/framework/bluebook/governance.bluebook +13 -34
- data/lib/hecks/framework/bluebook/identity.bluebook +11 -26
- data/lib/hecks/framework/bluebook/privacy.bluebook +8 -33
- data/lib/hecks/framework.rb +11 -80
- data/lib/hecks/freezer.rb +5 -39
- data/lib/hecks/grammar/expression.bluebook +15 -40
- data/lib/hecks/grammar/translation.bluebook +3 -6
- data/lib/hecks/grammar.rb +16 -41
- data/lib/hecks/ir.rb +14 -83
- data/lib/hecks/language/adapter.bluebook +2 -7
- data/lib/hecks/language/bluebook/aggregate.bluebook +56 -221
- data/lib/hecks/language/bluebook/attaches/paging.bluebook +6 -15
- data/lib/hecks/language/bluebook/bluebook.bluebook +15 -83
- data/lib/hecks/language/bluebook/bluebook.hecksagon +3 -15
- data/lib/hecks/language/bluebook/command.bluebook +27 -144
- data/lib/hecks/language/bluebook/entity.bluebook +24 -97
- data/lib/hecks/language/bluebook/policy.bluebook +16 -67
- data/lib/hecks/language/bluebook/process_manager.bluebook +28 -151
- data/lib/hecks/language/bluebook/projection.bluebook +126 -60
- data/lib/hecks/language/bluebook/query.bluebook +12 -43
- data/lib/hecks/language/bluebook/shape.bluebook +23 -73
- data/lib/hecks/language/bluebook/syntax.bluebook +51 -262
- data/lib/hecks/language/bluebook/vocabulary.bluebook +98 -197
- data/lib/hecks/language/hecksagon/adapter_binding.bluebook +3 -10
- data/lib/hecks/language/hecksagon/domain_port.bluebook +4 -19
- data/lib/hecks/language/hecksagon/hecksagon.bluebook +6 -25
- data/lib/hecks/language/hecksagon/port_operation.bluebook +3 -14
- data/lib/hecks/language/oidc.json +35 -0
- data/lib/hecks/language/port.bluebook +4 -17
- data/lib/hecks/language/translation/translation.bluebook +3 -9
- data/lib/hecks/language/translation/translation_aggregate.bluebook +5 -24
- data/lib/hecks/language/world/wiring.bluebook +1 -3
- data/lib/hecks/language/world/world.bluebook +5 -7
- data/lib/hecks/literal.rb +8 -50
- data/lib/hecks/mcp_door_scope.rb +95 -0
- data/lib/hecks/mcp_stdio_guard.rb +4 -41
- data/lib/hecks/naming.rb +29 -137
- data/lib/hecks/ports/access_control.rb +7 -23
- data/lib/hecks/ports/agent/answers.rb +5 -23
- data/lib/hecks/ports/agent.rb +47 -172
- data/lib/hecks/ports/authentication.rb +12 -39
- data/lib/hecks/ports/authorization.rb +16 -43
- data/lib/hecks/ports/clock.rb +5 -45
- data/lib/hecks/ports/extraction.rb +7 -12
- data/lib/hecks/ports/identity_assignment.rb +8 -29
- data/lib/hecks/ports/identity_generation.rb +6 -29
- data/lib/hecks/ports/identity_resolution.rb +2 -10
- data/lib/hecks/ports/key_vault.rb +9 -45
- data/lib/hecks/ports/persistence/append_only.rb +62 -65
- data/lib/hecks/ports/persistence/binding_policy.rb +4 -14
- data/lib/hecks/ports/persistence/codec_boundary.rb +20 -80
- data/lib/hecks/ports/persistence/null_saga_store.rb +4 -20
- data/lib/hecks/ports/persistence/plugin.rb +13 -42
- data/lib/hecks/ports/persistence/plugins/era/era_check.rb +38 -141
- data/lib/hecks/ports/persistence/plugins/era/era_guard/shape_diff.rb +15 -115
- data/lib/hecks/ports/persistence/plugins/era/era_guard.rb +16 -84
- data/lib/hecks/ports/persistence/plugins/era/era_tamper.rb +7 -26
- data/lib/hecks/ports/persistence/plugins/era/expected_era.rb +3 -22
- data/lib/hecks/ports/persistence/plugins/era/lineage.rb +55 -181
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/events.rb +77 -0
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/era_store.rb +12 -122
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/field_cache.rb +28 -128
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/head_compiler.rb +73 -474
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/mint_transaction.rb +31 -124
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/provisioning.rb +45 -219
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/resumable_backfill.rb +13 -108
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/tail_merge.rb +18 -75
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/transform_installer.rb +9 -49
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage.rb +6 -123
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/coverage_check.rb +23 -55
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/era_resolver.rb +14 -72
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/merge_coordinator.rb +7 -16
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/minter.rb +14 -115
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager.rb +13 -45
- data/lib/hecks/ports/persistence/plugins/era/postgres_era.rb +127 -554
- data/lib/hecks/ports/persistence/plugins/era/storage_shape.rb +13 -63
- data/lib/hecks/ports/persistence/plugins/era/translation/audit/approval_digest.rb +2 -17
- data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_one.rb +3 -14
- data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_two.rb +13 -58
- data/lib/hecks/ports/persistence/plugins/era/translation/audit/unfed_report.rb +3 -17
- data/lib/hecks/ports/persistence/plugins/era/translation/audit.rb +9 -26
- data/lib/hecks/ports/persistence/plugins/era/translation/reattest.rb +9 -25
- data/lib/hecks/ports/persistence/plugins/era/translation/rule_compiler.rb +22 -122
- data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/differ.rb +34 -123
- data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/renderer.rb +5 -12
- data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/writer.rb +3 -9
- data/lib/hecks/ports/persistence/plugins/era/translation/scaffold.rb +2 -14
- data/lib/hecks/ports/persistence/plugins/era.rb +4 -23
- data/lib/hecks/ports/persistence/postgres_dump/connection.rb +7 -23
- data/lib/hecks/ports/persistence/postgres_dump.rb +4 -35
- data/lib/hecks/ports/persistence/remote_runtime.rb +2 -24
- data/lib/hecks/ports/persistence/repository_factory.rb +8 -27
- data/lib/hecks/ports/persistence/state_codec.rb +23 -103
- data/lib/hecks/ports/persistence.rb +7 -14
- data/lib/hecks/ports/projection.rb +42 -84
- data/lib/hecks/ports/query/in_memory.rb +10 -58
- data/lib/hecks/ports/query/ordering.rb +11 -32
- data/lib/hecks/ports/query.rb +14 -37
- data/lib/hecks/ports.rb +2 -8
- data/lib/hecks/projections/bootstrap_table.rb +11 -43
- data/lib/hecks/projections/deploy/fargate/assembly.rb +2 -15
- data/lib/hecks/projections/deploy/fargate/cdn.rb +1 -48
- data/lib/hecks/projections/deploy/fargate/cdn_default.rb +2 -11
- data/lib/hecks/projections/deploy/fargate/check.rb +5 -14
- data/lib/hecks/projections/deploy/fargate/containers.rb +3 -78
- data/lib/hecks/projections/deploy/fargate/extras.rb +3 -44
- data/lib/hecks/projections/deploy/fargate/monitoring.rb +0 -44
- data/lib/hecks/projections/deploy/fargate/settings.rb +2 -54
- data/lib/hecks/projections/deploy/fargate/yaml.rb +13 -58
- data/lib/hecks/projections/deploy/fargate.rb +35 -202
- data/lib/hecks/projections/deploy/lambda.rb +151 -679
- data/lib/hecks/projections/deploy/preview/access_yaml.rb +1 -33
- data/lib/hecks/projections/deploy/preview/containers.rb +6 -111
- data/lib/hecks/projections/deploy/preview/routing_yaml.rb +4 -56
- data/lib/hecks/projections/deploy/preview/script.rb +2 -14
- data/lib/hecks/projections/deploy/preview/settings.rb +3 -33
- data/lib/hecks/projections/deploy/preview/task_yaml.rb +2 -38
- data/lib/hecks/projections/deploy/preview/template.rb +2 -58
- data/lib/hecks/projections/deploy/preview.rb +2 -67
- data/lib/hecks/projections/deploy/scripts/settings.rb +3 -25
- data/lib/hecks/projections/deploy/scripts.rb +4 -57
- data/lib/hecks/projections/deploy/shared.rb +47 -146
- data/lib/hecks/projections/deploy/smoke.rb +4 -61
- data/lib/hecks/projections/deploy/template_diff/comparer.rb +3 -25
- data/lib/hecks/projections/deploy/template_diff/loader.rb +2 -11
- data/lib/hecks/projections/deploy/template_diff.rb +5 -57
- data/lib/hecks/projections/diagrams.rb +20 -582
- data/lib/hecks/projections/glossary/html.rb +14 -130
- data/lib/hecks/projections/glossary/markdown.rb +8 -69
- data/lib/hecks/projections/glossary/mermaid.rb +9 -66
- data/lib/hecks/projections/glossary/sensitivity.rb +5 -34
- data/lib/hecks/projections/glossary/sentences.rb +14 -159
- data/lib/hecks/projections/glossary.rb +30 -222
- data/lib/hecks/projections/ir.rb +3 -10
- data/lib/hecks/projections/model/deviations.rb +15 -42
- data/lib/hecks/projections/model.rb +12 -51
- data/lib/hecks/projections/oidc.rb +12 -56
- data/lib/hecks/projections/parser_table.rb +9 -28
- data/lib/hecks/projections/reference.rb +9 -16
- data/lib/hecks/projections/rust_vocabulary.rb +12 -250
- data/lib/hecks/projections/shape.rb +3 -29
- data/lib/hecks/projections/statements.rb +7 -86
- data/lib/hecks/projections/vocabulary.rb +6 -22
- data/lib/hecks/projections.rb +2 -16
- data/lib/hecks/projector/cli_projector.rb +60 -375
- data/lib/hecks/projector/docs_projector.rb +10 -201
- data/lib/hecks/projector/exporter.rb +46 -138
- data/lib/hecks/projector/ir_projector.rb +2 -9
- data/lib/hecks/projector/narrate_projector.rb +15 -189
- data/lib/hecks/projector/target.rb +13 -76
- data/lib/hecks/projector.rb +30 -121
- data/lib/hecks/query_specification/common/comparators.rb +5 -26
- data/lib/hecks/query_specification/common/comparison.rb +35 -143
- data/lib/hecks/query_specification/common/dsl.rb +8 -24
- data/lib/hecks/query_specification/common/null_policy.rb +20 -70
- data/lib/hecks/query_specification/common/options.rb +2 -6
- data/lib/hecks/query_specification/common/where_clause.rb +2 -10
- data/lib/hecks/query_specification/field_path.rb +37 -77
- data/lib/hecks/query_specification/hop_path.rb +12 -76
- data/lib/hecks/release/gem_pin.rb +2 -26
- data/lib/hecks/release/runner/ci_publisher.rb +93 -0
- data/lib/hecks/release/runner/commands.rb +66 -0
- data/lib/hecks/release/runner/console.rb +52 -0
- data/lib/hecks/release/runner/gem_publisher.rb +43 -0
- data/lib/hecks/release/runner/git.rb +48 -0
- data/lib/hecks/release/runner/npm_publisher.rb +75 -0
- data/lib/hecks/release/runner/preflight.rb +104 -0
- data/lib/hecks/release/runner/published.rb +55 -0
- data/lib/hecks/release/runner/tagger.rb +80 -0
- data/lib/hecks/release/runner.rb +215 -0
- data/lib/hecks/rendering.rb +4 -26
- data/lib/hecks/router/namespace_installer.rb +12 -36
- data/lib/hecks/router.rb +4 -8
- data/lib/hecks/runtime/aggregate_lock.rb +8 -33
- data/lib/hecks/runtime/boot_gates.rb +3 -18
- data/lib/hecks/runtime/caller.rb +19 -59
- data/lib/hecks/runtime/capability_graph.rb +5 -21
- data/lib/hecks/runtime/command_interpreter/argument_gate.rb +16 -78
- data/lib/hecks/runtime/command_interpreter/mutation_applier.rb +23 -160
- data/lib/hecks/runtime/command_interpreter.rb +125 -307
- data/lib/hecks/runtime/command_rules/admissibility.rb +95 -366
- data/lib/hecks/runtime/command_rules/arithmetic.rb +66 -196
- data/lib/hecks/runtime/command_rules/authorization.rb +13 -45
- data/lib/hecks/runtime/command_rules/emission.rb +8 -21
- data/lib/hecks/runtime/command_rules/references.rb +23 -202
- data/lib/hecks/runtime/dependency_planning.rb +30 -102
- data/lib/hecks/runtime/dispatcher.rb +82 -241
- data/lib/hecks/runtime/entity_element.rb +40 -462
- data/lib/hecks/runtime/entity_interpreter.rb +65 -220
- data/lib/hecks/runtime/errors.rb +32 -115
- data/lib/hecks/runtime/event.rb +3 -25
- data/lib/hecks/runtime/identity.rb +18 -154
- data/lib/hecks/runtime/instance.rb +18 -150
- data/lib/hecks/runtime/interpreting.rb +11 -70
- data/lib/hecks/runtime/invocation.rb +28 -164
- data/lib/hecks/runtime/loader.rb +48 -186
- data/lib/hecks/runtime/outbox.rb +38 -261
- data/lib/hecks/runtime/policy_interpreter.rb +38 -200
- data/lib/hecks/runtime/port_operation_interpreter.rb +26 -87
- data/lib/hecks/runtime/query_interpreter.rb +45 -187
- data/lib/hecks/runtime/reaction_invocation.rb +36 -138
- data/lib/hecks/runtime/read_model_interpreter.rb +139 -208
- data/lib/hecks/runtime/rebuild_sweep.rb +8 -54
- data/lib/hecks/runtime/reference_hop.rb +8 -81
- data/lib/hecks/runtime/refusal_wording.rb +8 -89
- data/lib/hecks/runtime/registry/saga_persistence.rb +10 -102
- data/lib/hecks/runtime/registry/verification.rb +52 -225
- data/lib/hecks/runtime/registry/world_defaults.rb +4 -53
- data/lib/hecks/runtime/registry.rb +103 -244
- data/lib/hecks/runtime/remote_dispatcher.rb +37 -152
- data/lib/hecks/runtime/routing.rb +4 -15
- data/lib/hecks/runtime/saga_interpreter/correlation.rb +14 -61
- data/lib/hecks/runtime/saga_interpreter.rb +79 -263
- data/lib/hecks/runtime/saga_pending_dispatch.rb +2 -43
- data/lib/hecks/runtime/tenant_check.rb +6 -68
- data/lib/hecks/runtime/tenant_scope.rb +3 -28
- data/lib/hecks/runtime/value/admission.rb +16 -67
- data/lib/hecks/runtime/value/coercion.rb +155 -641
- data/lib/hecks/runtime/value/entity_list_coercion.rb +26 -219
- data/lib/hecks/runtime/value.rb +12 -84
- data/lib/hecks/runtime.rb +17 -65
- data/lib/hecks/storehouse.rb +146 -567
- data/lib/hecks/tenancy/bluebook/tenancy.bluebook +8 -32
- data/lib/hecks/tenancy/bluebook/tenancy.hecksagon +6 -23
- data/lib/hecks/vendoring/git_environment.rb +2 -8
- data/lib/hecks/vendoring/git_source.rb +4 -10
- data/lib/hecks/vendoring.rb +7 -46
- data/lib/hecks/version.rb +3 -14
- data/lib/hecks/vocabulary.rb +5 -0
- data/lib/hecks.rb +32 -82
- data/lib/rubocop/cop/hecks/fallback_hash_lookup.rb +8 -46
- data/lib/rubocop/cop/hecks/sequential_hash_rename_in_loop.rb +11 -80
- data/lib/rubocop/cop/hecks/thread_shared_ivar_mutation.rb +10 -99
- metadata +30 -59
- data/lib/hecks/bench/cli.rb +0 -74
- data/lib/hecks/bench/environment.rb +0 -100
- data/lib/hecks/bench/postgres_probe.rb +0 -41
- data/lib/hecks/bench/report.rb +0 -116
- data/lib/hecks/bench/ruby_runner.rb +0 -151
- data/lib/hecks/bench/run.rb +0 -55
- data/lib/hecks/bench/rust_runner.rb +0 -165
- data/lib/hecks/bench/stats.rb +0 -75
- data/lib/hecks/bench/suite.rb +0 -172
- data/lib/hecks/bench/workload.rb +0 -137
- data/lib/hecks/bench.rb +0 -28
- data/lib/hecks/codemod.rb +0 -443
- data/lib/hecks/corpus.rb +0 -479
- data/lib/hecks/doc/reference.rb +0 -585
- data/lib/hecks/fuzzing/bounded_exhaustive_expressions.rb +0 -684
- data/lib/hecks/fuzzing/combination_miner.rb +0 -178
- data/lib/hecks/fuzzing/concurrent_dispatch.rb +0 -469
- data/lib/hecks/fuzzing/coverage_campaign.rb +0 -161
- data/lib/hecks/fuzzing/differential.rb +0 -192
- data/lib/hecks/fuzzing/domain_generator.rb +0 -871
- data/lib/hecks/fuzzing/era_boundary.rb +0 -154
- data/lib/hecks/fuzzing/form_census.rb +0 -285
- data/lib/hecks/fuzzing/generated_domain_check.rb +0 -171
- data/lib/hecks/fuzzing/invalid_value_generator.rb +0 -125
- data/lib/hecks/fuzzing/isolated_boot.rb +0 -658
- data/lib/hecks/fuzzing/nondeterministic.rb +0 -79
- data/lib/hecks/fuzzing/persistence_parity.rb +0 -253
- data/lib/hecks/fuzzing/properties/corrections.rb +0 -125
- data/lib/hecks/fuzzing/properties/dispatch_and_mutations.rb +0 -688
- data/lib/hecks/fuzzing/properties/guards.rb +0 -398
- data/lib/hecks/fuzzing/properties/invariants_and_aggregation.rb +0 -399
- data/lib/hecks/fuzzing/properties/lifecycle_and_replay.rb +0 -137
- data/lib/hecks/fuzzing/properties/outbox.rb +0 -180
- data/lib/hecks/fuzzing/properties/querying.rb +0 -260
- data/lib/hecks/fuzzing/properties.rb +0 -267
- data/lib/hecks/fuzzing/qa_settings.rb +0 -164
- data/lib/hecks/fuzzing/replay.rb +0 -930
- data/lib/hecks/fuzzing/rotation_priority.rb +0 -114
- data/lib/hecks/fuzzing/rust_gap_manifest.rb +0 -139
- data/lib/hecks/fuzzing/self_consistency.rb +0 -825
- data/lib/hecks/fuzzing/sequence_generator/adversary.rb +0 -532
- data/lib/hecks/fuzzing/sequence_generator/catalog.rb +0 -171
- data/lib/hecks/fuzzing/sequence_generator/outcome_tracker.rb +0 -127
- data/lib/hecks/fuzzing/sequence_generator/picker.rb +0 -116
- data/lib/hecks/fuzzing/sequence_generator/query_binding.rb +0 -138
- data/lib/hecks/fuzzing/sequence_generator/step_builder.rb +0 -344
- data/lib/hecks/fuzzing/sequence_generator.rb +0 -311
- data/lib/hecks/fuzzing/shrinker.rb +0 -309
- data/lib/hecks/fuzzing/structural_skips.rb +0 -53
- data/lib/hecks/fuzzing/sweep_depth.rb +0 -61
- data/lib/hecks/fuzzing/target_capabilities.rb +0 -255
- data/lib/hecks/fuzzing/value_generator.rb +0 -340
- data/lib/hecks/fuzzing.rb +0 -23
- data/lib/hecks/grammar/evolve.rb +0 -524
- data/lib/hecks/query_ir.rb +0 -482
|
@@ -2,27 +2,12 @@ require_relative "../runtime/registry"
|
|
|
2
2
|
|
|
3
3
|
module Hecks
|
|
4
4
|
module Ports
|
|
5
|
-
# The OIDC handshake
|
|
6
|
-
#
|
|
7
|
-
# claims (`issuer`, `subject`, `email`, `email_verified`). Resolved the same way every
|
|
8
|
-
# other port here resolves its adapter: one adapter registry-wide
|
|
9
|
-
# answers this, not a per-aggregate binding, since a domain has no
|
|
10
|
-
# reason to want a different sign-in provider per aggregate.
|
|
11
|
-
#
|
|
12
|
-
# The other half of "who is this" — what a verified pair means to
|
|
13
|
-
# this app, whether it resolves to an existing Identity — is
|
|
14
|
-
# `Ports::IdentityResolution`'s job, not this one's. This port only
|
|
15
|
-
# ever talks to the external provider; it never touches the
|
|
16
|
-
# registry's own Identity/Governance data (it takes `registry`
|
|
17
|
-
# purely to resolve which adapter answers it, same as every port
|
|
18
|
-
# here already does).
|
|
5
|
+
# The OIDC handshake: builds the provider URL and turns the returned code into verified claims.
|
|
6
|
+
# One adapter registry-wide answers it; it never touches the registry's Identity data.
|
|
19
7
|
module Authentication
|
|
20
8
|
NAME = "authentication".freeze
|
|
21
9
|
|
|
22
|
-
# A sign-in that could not be verified
|
|
23
|
-
# exchange, a missing or invalid ID token. An adapter wraps its own
|
|
24
|
-
# libraries' errors into this, so a caller rescues one class whichever
|
|
25
|
-
# provider answers the port.
|
|
10
|
+
# A sign-in that could not be verified (state mismatch, failed code exchange, bad ID token).
|
|
26
11
|
class ValidationError < StandardError
|
|
27
12
|
end
|
|
28
13
|
|
|
@@ -30,17 +15,13 @@ module Hecks
|
|
|
30
15
|
|
|
31
16
|
# Builds the provider URL that starts a sign-in, with the CSRF state minted for it.
|
|
32
17
|
#
|
|
33
|
-
# The caller keeps the state
|
|
34
|
-
# as `expected_state`.
|
|
18
|
+
# The caller keeps the state and hands it back to `verify` as `expected_state`.
|
|
35
19
|
#
|
|
36
20
|
# @param registry [Runtime::Registry] the booted registry to resolve the adapter against
|
|
37
21
|
# @return [Array(String, String)] the URL to send the browser to, then the fresh
|
|
38
22
|
# `state` value embedded in it
|
|
39
23
|
# @raise [Runtime::WiringError] if this port does not resolve to exactly one adapter
|
|
40
|
-
# (see `adapter`)
|
|
41
24
|
# @raise [KeyError] if the adapter's required configuration is unset
|
|
42
|
-
# (`GoogleAuthentication` reads `GOOGLE_CLIENT_ID`, `GOOGLE_CLIENT_SECRET` and
|
|
43
|
-
# `GOOGLE_REDIRECT_URI` with no defaults)
|
|
44
25
|
def authorization_url(registry)
|
|
45
26
|
adapter(registry).authorization_url
|
|
46
27
|
end
|
|
@@ -50,28 +31,20 @@ module Hecks
|
|
|
50
31
|
# @param registry [Runtime::Registry] the booted registry to resolve the adapter against
|
|
51
32
|
# @param code [String] the authorization code the provider sent back
|
|
52
33
|
# @param state [String, nil] the state parameter the provider returned; nil is refused
|
|
53
|
-
# @param expected_state [String, nil] the state `authorization_url`
|
|
54
|
-
#
|
|
55
|
-
#
|
|
56
|
-
#
|
|
57
|
-
#
|
|
58
|
-
# @raise [Ports::Authentication::ValidationError] if either state is nil or the two
|
|
59
|
-
# differ, the code exchange fails, the response has no ID token, or the ID token
|
|
60
|
-
# does not verify
|
|
34
|
+
# @param expected_state [String, nil] the state `authorization_url` returned; nil is refused
|
|
35
|
+
# @return [Hash{Symbol => Object}] the verified claims: `issuer:`, `subject:`, `email:`
|
|
36
|
+
# (nil if the token carries none) and `email_verified:` -- never the raw token
|
|
37
|
+
# @raise [Ports::Authentication::ValidationError] if a state is nil or they differ, the
|
|
38
|
+
# code exchange fails, or the ID token is missing or does not verify
|
|
61
39
|
# @raise [Runtime::WiringError] if this port does not resolve to exactly one adapter
|
|
62
|
-
#
|
|
63
|
-
# @raise [KeyError] if the adapter's required configuration is unset, or a verified
|
|
64
|
-
# token lacks an `iss` or `sub` claim
|
|
40
|
+
# @raise [KeyError] if required configuration is unset, or the token lacks `iss`/`sub`
|
|
65
41
|
def verify(registry, code:, state:, expected_state:)
|
|
66
42
|
adapter(registry).verify(code: code, state: state, expected_state: expected_state)
|
|
67
43
|
end
|
|
68
44
|
|
|
69
|
-
# Finds the single adapter bound to this port
|
|
45
|
+
# Finds the single adapter bound to this port.
|
|
70
46
|
#
|
|
71
|
-
# @
|
|
72
|
-
# @return [Module] the adapter module or class implementing this port
|
|
73
|
-
# @raise [Runtime::WiringError] if no adapter, or more than one, implements this port,
|
|
74
|
-
# or the one that does has no Ruby implementation under `Hecks::Adapters`
|
|
47
|
+
# @raise [Runtime::WiringError] if none, or more than one, implements this port
|
|
75
48
|
def adapter(registry)
|
|
76
49
|
implementations = registry.adapters.values.select { |a| a.port == NAME }
|
|
77
50
|
|
|
@@ -2,28 +2,8 @@ require_relative "../runtime/registry"
|
|
|
2
2
|
|
|
3
3
|
module Hecks
|
|
4
4
|
module Ports
|
|
5
|
-
#
|
|
6
|
-
#
|
|
7
|
-
# resolves its own adapter: one adapter registry-wide answers this
|
|
8
|
-
# port, not a per-aggregate binding, since a domain has no reason to
|
|
9
|
-
# want a different authorization source per aggregate. What answers
|
|
10
|
-
# it is deliberately not named here — the governance-backed adapter
|
|
11
|
-
# is one implementation, not the only possible one, the same way
|
|
12
|
-
# `SequentialIdentity` and `SecureRandomIdentity` are two
|
|
13
|
-
# implementations of `identity_generation`.
|
|
14
|
-
#
|
|
15
|
-
# A caller decides what to do with the answer — dispatch under that
|
|
16
|
-
# role, refuse, log, prefer it over some other fallback value — this
|
|
17
|
-
# only answers the question asked. Nothing here binds a
|
|
18
|
-
# `Runtime::Caller`.
|
|
19
|
-
#
|
|
20
|
-
# `CommandRules::Authorization#refuse_role_mismatch` calls `holds_role?`
|
|
21
|
-
# directly, once a caller binds an `actor_id` and the command's domain
|
|
22
|
-
# has Governance attached (see that rule's own header). `spec/
|
|
23
|
-
# act_as_spec.rb` remains the precedent for the other shape — two
|
|
24
|
-
# separate registries, queried directly by name — for whenever
|
|
25
|
-
# Governance is not in the same boot as the caller; this port is the
|
|
26
|
-
# same questions asked through one adapter when it is.
|
|
5
|
+
# Role questions an application asks before binding a caller. One adapter registry-wide
|
|
6
|
+
# answers them; it only answers, and never binds a `Runtime::Caller`.
|
|
27
7
|
module Authorization
|
|
28
8
|
NAME = "authorization".freeze
|
|
29
9
|
|
|
@@ -35,15 +15,11 @@ module Hecks
|
|
|
35
15
|
# @param actor_id [String] the actor whose grants are checked
|
|
36
16
|
# @param role [String, Symbol] the role name to look for, compared as a String
|
|
37
17
|
# @param as_of [Integer, nil] Unix epoch seconds (from `Ports::Clock.now`); a grant whose
|
|
38
|
-
# `starts_at` is later, or does not parse as a time, does not count. nil skips the
|
|
39
|
-
#
|
|
40
|
-
# @
|
|
41
|
-
#
|
|
42
|
-
#
|
|
43
|
-
# `as_of` and `scope` checks
|
|
44
|
-
# @raise [Runtime::WiringError] if this port does not resolve to exactly one adapter
|
|
45
|
-
# (see `adapter`), or the governance-backed adapter finds no single loaded chapter
|
|
46
|
-
# providing `"authorization"`
|
|
18
|
+
# `starts_at` is later, or does not parse as a time, does not count. nil skips the check
|
|
19
|
+
# @param scope [String, nil] only a grant made for this scope counts; nil counts any scope
|
|
20
|
+
# @return [Boolean] true if at least one live grant of `role` to `actor_id` passes
|
|
21
|
+
# @raise [Runtime::WiringError] if this port does not resolve to exactly one adapter,
|
|
22
|
+
# or the governance-backed adapter finds no single chapter providing `"authorization"`
|
|
47
23
|
def holds_role?(registry, actor_id:, role:, as_of: nil, scope: nil)
|
|
48
24
|
adapter(registry).holds_role?(registry, actor_id: actor_id, role: role, as_of: as_of, scope: scope)
|
|
49
25
|
end
|
|
@@ -56,32 +32,29 @@ module Hecks
|
|
|
56
32
|
# String
|
|
57
33
|
# @return [Boolean] true if a live (not ended) allowance lets `from_role` act as
|
|
58
34
|
# `to_role`
|
|
59
|
-
# @raise [Runtime::WiringError] if this port does not resolve to exactly one adapter
|
|
60
|
-
#
|
|
61
|
-
#
|
|
35
|
+
# @raise [Runtime::WiringError] if this port does not resolve to exactly one adapter,
|
|
36
|
+
# or the governance-backed adapter finds no single loaded chapter providing
|
|
37
|
+
# `"authorization"`
|
|
62
38
|
def authorized_as?(registry, from_role:, to_role:)
|
|
63
39
|
adapter(registry).authorized_as?(registry, from_role: from_role, to_role: to_role)
|
|
64
40
|
end
|
|
65
41
|
|
|
66
|
-
# Looks up the role an actor holds right now
|
|
42
|
+
# Looks up the role an actor holds right now.
|
|
67
43
|
#
|
|
68
44
|
# @param registry [Runtime::Registry] the booted registry to resolve the adapter against
|
|
69
45
|
# @param actor_id [String] the actor to look up
|
|
70
46
|
# @return [String, nil] the role name of the actor's first live (not ended) grant, or
|
|
71
47
|
# nil if it has none; the caller supplies any fallback
|
|
72
|
-
# @raise [Runtime::WiringError] if this port does not resolve to exactly one adapter
|
|
73
|
-
#
|
|
74
|
-
#
|
|
48
|
+
# @raise [Runtime::WiringError] if this port does not resolve to exactly one adapter,
|
|
49
|
+
# or the governance-backed adapter finds no single loaded chapter providing
|
|
50
|
+
# `"authorization"`
|
|
75
51
|
def live_role_for(registry, actor_id:)
|
|
76
52
|
adapter(registry).live_role_for(registry, actor_id: actor_id)
|
|
77
53
|
end
|
|
78
54
|
|
|
79
|
-
# Finds the single adapter bound to this port
|
|
55
|
+
# Finds the single adapter bound to this port.
|
|
80
56
|
#
|
|
81
|
-
# @
|
|
82
|
-
# @return [Module] the adapter module or class implementing this port
|
|
83
|
-
# @raise [Runtime::WiringError] if no adapter, or more than one, implements this port,
|
|
84
|
-
# or the one that does has no Ruby implementation under `Hecks::Adapters`
|
|
57
|
+
# @raise [Runtime::WiringError] if none, or more than one, implements this port
|
|
85
58
|
def adapter(registry)
|
|
86
59
|
implementations = registry.adapters.values.select { |a| a.port == NAME }
|
|
87
60
|
|
data/lib/hecks/ports/clock.rb
CHANGED
|
@@ -2,42 +2,8 @@ require_relative "../runtime/registry"
|
|
|
2
2
|
|
|
3
3
|
module Hecks
|
|
4
4
|
module Ports
|
|
5
|
-
# What time it is
|
|
6
|
-
#
|
|
7
|
-
# Resolved exactly the way `Ports::IdentityGeneration` resolves its own
|
|
8
|
-
# adapter: one adapter registry-wide implements this, not a per-aggregate
|
|
9
|
-
# binding, because two aggregates in one running app have no real reason to
|
|
10
|
-
# disagree about the time.
|
|
11
|
-
#
|
|
12
|
-
# ## Why a port and not `Time.now`
|
|
13
|
-
#
|
|
14
|
-
# A staleness rule — "another agent may take this claim after fifteen
|
|
15
|
-
# minutes" — is untestable against the real clock: a spec for it would
|
|
16
|
-
# either sleep for fifteen minutes or never run at all. Bound to a fixed
|
|
17
|
-
# adapter, the same rule is three lines. That is the whole argument, and
|
|
18
|
-
# it is the same one `SequentialIdentity` makes next door.
|
|
19
|
-
#
|
|
20
|
-
# ## Why a predicate still can't ask the time
|
|
21
|
-
#
|
|
22
|
-
# The expression sublanguage has no clock and should not: a `given` that
|
|
23
|
-
# read the time would evaluate differently on two runs over the same
|
|
24
|
-
# record, and every replay, audit and fuzz oracle in this repository
|
|
25
|
-
# assumes it does not. So `now` remains an argument the predicate merely
|
|
26
|
-
# reads, and this port is what lets a caller stop typing it — the door
|
|
27
|
-
# fills it in, the value is baked into the dispatch, and the recorded
|
|
28
|
-
# step carries the concrete number forever after.
|
|
29
|
-
#
|
|
30
|
-
# ## Why the runtime never calls this directly
|
|
31
|
-
#
|
|
32
|
-
# `IdentityGeneration`'s own note works through the replay question for
|
|
33
|
-
# a minted uuid and lands on "the value gets baked into the caller's
|
|
34
|
-
# args at the first live dispatch". A clock consulted inside the
|
|
35
|
-
# interpreter would not have that property: a recorded corpus step
|
|
36
|
-
# replayed tomorrow would silently get tomorrow's time, and the
|
|
37
|
-
# fuzzer's oracle and the adapter-agreement gate both compare runs of
|
|
38
|
-
# exactly that shape. So the filling happens at the door, where a
|
|
39
|
-
# human or an agent is typing, and never on the dispatch path a replay
|
|
40
|
-
# uses.
|
|
5
|
+
# What time it is, as one registry-wide adapter answers it.
|
|
6
|
+
# Predicates cannot read the clock (replays must be deterministic), so the door fills `now`.
|
|
41
7
|
module Clock
|
|
42
8
|
NAME = "clock".freeze
|
|
43
9
|
|
|
@@ -45,23 +11,17 @@ module Hecks
|
|
|
45
11
|
|
|
46
12
|
# Reads the current time from the bound clock adapter.
|
|
47
13
|
#
|
|
48
|
-
#
|
|
49
|
-
# arithmetic on. `claimed_at.value + window.value <= now.value` is
|
|
50
|
-
# addition and comparison — the only two things it has — and a Time
|
|
14
|
+
# Integer seconds, because the expression sublanguage can add and compare but a Time
|
|
51
15
|
# object supports neither.
|
|
52
16
|
#
|
|
53
17
|
# @param registry [Runtime::Registry] the booted registry to resolve the adapter against
|
|
54
18
|
# @return [Integer] the current time, in Unix epoch seconds
|
|
55
19
|
# @raise [Runtime::WiringError] if this port does not resolve to exactly one adapter
|
|
56
|
-
# (see `adapter`)
|
|
57
20
|
def now(registry) = adapter(registry).now
|
|
58
21
|
|
|
59
|
-
# Finds the single adapter bound to this port
|
|
22
|
+
# Finds the single adapter bound to this port.
|
|
60
23
|
#
|
|
61
|
-
# @
|
|
62
|
-
# @return [Module] the adapter module or class implementing this port
|
|
63
|
-
# @raise [Runtime::WiringError] if no adapter, or more than one, implements this port,
|
|
64
|
-
# or the one that does has no Ruby implementation under `Hecks::Adapters`
|
|
24
|
+
# @raise [Runtime::WiringError] if none, or more than one, implements this port
|
|
65
25
|
def adapter(registry)
|
|
66
26
|
implementations = registry.adapters.values.select { |a| a.port == NAME }
|
|
67
27
|
|
|
@@ -2,10 +2,8 @@ require_relative "../runtime/registry"
|
|
|
2
2
|
|
|
3
3
|
module Hecks
|
|
4
4
|
module Ports
|
|
5
|
-
#
|
|
6
|
-
#
|
|
7
|
-
# directly rather than taking a registry argument, since extraction only
|
|
8
|
-
# ever happens while a bluebook is loading, never after boot.
|
|
5
|
+
# Resolves the adapter that recovers a predicate's own source (`canonical`).
|
|
6
|
+
# Reads `Hecks.current_registry`, since extraction only happens while a bluebook loads.
|
|
9
7
|
module Extraction
|
|
10
8
|
NAME = "extraction".freeze
|
|
11
9
|
|
|
@@ -16,19 +14,16 @@ module Hecks
|
|
|
16
14
|
# @param block [Proc] a block written in a bluebook file, such as a `given` predicate
|
|
17
15
|
# or an `identified_by` path
|
|
18
16
|
# @return [String, nil] the block body's source, normalised by
|
|
19
|
-
# `Bluebook::Expression::CanonicalForm
|
|
20
|
-
#
|
|
21
|
-
# the block has an empty body
|
|
17
|
+
# `Bluebook::Expression::CanonicalForm`; nil if the block's file cannot be read, no
|
|
18
|
+
# block starts on its line, or the block has an empty body
|
|
22
19
|
# @raise [Runtime::WiringError] if called outside a boot, or this port does not resolve
|
|
23
|
-
# to exactly one adapter
|
|
20
|
+
# to exactly one adapter
|
|
24
21
|
def canonical(block) = adapter.canonical(block)
|
|
25
22
|
|
|
26
23
|
# Finds the single adapter bound to this port in the registry currently booting.
|
|
27
24
|
#
|
|
28
|
-
# @
|
|
29
|
-
#
|
|
30
|
-
# boot), if no adapter, or more than one, implements this port, or if the one that
|
|
31
|
-
# does has no Ruby implementation under `Hecks::Adapters`
|
|
25
|
+
# @raise [Runtime::WiringError] if called outside a boot, or none, or more than one,
|
|
26
|
+
# implements this port
|
|
32
27
|
def adapter
|
|
33
28
|
registry = Hecks.current_registry
|
|
34
29
|
unless registry
|
|
@@ -2,21 +2,8 @@ require_relative "../runtime/registry"
|
|
|
2
2
|
|
|
3
3
|
module Hecks
|
|
4
4
|
module Ports
|
|
5
|
-
# Which value a creating command's
|
|
6
|
-
#
|
|
7
|
-
# mechanically answers it — a driving app's own console, say,
|
|
8
|
-
# falls back to this when a collection's identity strategy names
|
|
9
|
-
# "port" rather than "slug"/"sequence" (both of those stay pure
|
|
10
|
-
# config-driven mechanics, computed by whoever is dispatching,
|
|
11
|
-
# never by this port).
|
|
12
|
-
#
|
|
13
|
-
# Pure delegation, same as every sibling port (AccessControl,
|
|
14
|
-
# IdentityGeneration): an app's own domain declares what "port"
|
|
15
|
-
# actually means for it — mint a real UUID via
|
|
16
|
-
# Ports::IdentityGeneration, derive something else entirely — this
|
|
17
|
-
# port just resolves the one adapter that domain wired and calls
|
|
18
|
-
# it, the same "one adapter registry-wide, refuse if zero or many"
|
|
19
|
-
# resolution every other port here already uses.
|
|
5
|
+
# Which value a creating command's identity field gets when its strategy names "port".
|
|
6
|
+
# Delegates to the one adapter the domain wired.
|
|
20
7
|
module IdentityAssignment
|
|
21
8
|
NAME = "identity_assignment".freeze
|
|
22
9
|
|
|
@@ -24,29 +11,21 @@ module Hecks
|
|
|
24
11
|
|
|
25
12
|
# Asks the domain's adapter which value a creating command's identity field gets.
|
|
26
13
|
#
|
|
27
|
-
#
|
|
28
|
-
# shape below other than `registry` is adapter-defined: the port forwards it untouched.
|
|
14
|
+
# Every argument other than `registry` is adapter-defined and forwarded untouched.
|
|
29
15
|
#
|
|
30
16
|
# @param registry [Runtime::Registry] the booted registry to resolve the adapter against
|
|
31
|
-
# @param agg_name [Object] adapter-defined
|
|
32
|
-
#
|
|
33
|
-
# @param
|
|
34
|
-
# field
|
|
35
|
-
# @param args [Object] adapter-defined, forwarded unchanged; the creating command's own
|
|
36
|
-
# arguments
|
|
17
|
+
# @param agg_name [Object] adapter-defined; names the aggregate being assigned
|
|
18
|
+
# @param field_name [Object] adapter-defined; names the identity field
|
|
19
|
+
# @param args [Object] adapter-defined; the creating command's own arguments
|
|
37
20
|
# @return [Object] adapter-defined value to assign as the identity
|
|
38
21
|
# @raise [Runtime::WiringError] if this port does not resolve to exactly one adapter
|
|
39
|
-
# (see `adapter`)
|
|
40
22
|
def assign(registry, agg_name:, field_name:, args:)
|
|
41
23
|
adapter(registry).assign(registry, agg_name: agg_name, field_name: field_name, args: args)
|
|
42
24
|
end
|
|
43
25
|
|
|
44
|
-
# Finds the single adapter bound to this port
|
|
26
|
+
# Finds the single adapter bound to this port.
|
|
45
27
|
#
|
|
46
|
-
# @
|
|
47
|
-
# @return [Module] the adapter module or class implementing this port
|
|
48
|
-
# @raise [Runtime::WiringError] if no adapter, or more than one, implements this port,
|
|
49
|
-
# or the one that does has no Ruby implementation under `Hecks::Adapters`
|
|
28
|
+
# @raise [Runtime::WiringError] if none, or more than one, implements this port
|
|
50
29
|
def adapter(registry)
|
|
51
30
|
implementations = registry.adapters.values.select { |a| a.port == NAME }
|
|
52
31
|
|
|
@@ -2,27 +2,9 @@ require_relative "../runtime/registry"
|
|
|
2
2
|
|
|
3
3
|
module Hecks
|
|
4
4
|
module Ports
|
|
5
|
-
#
|
|
6
|
-
#
|
|
7
|
-
#
|
|
8
|
-
# adapter registry-wide implements this port, not a per-aggregate
|
|
9
|
-
# binding the way persistence needs — different aggregates have no
|
|
10
|
-
# real reason to want different id-generation strategies within
|
|
11
|
-
# one running app).
|
|
12
|
-
#
|
|
13
|
-
# Replay needs no suppression here, on purpose. A UUID minted for a
|
|
14
|
-
# creating command's identity gets baked into that step's own args
|
|
15
|
-
# — an ordinary string value — the moment it's generated, by
|
|
16
|
-
# whoever issues the first, live dispatch. A recorded corpus
|
|
17
|
-
# script or a captured fuzz-replay step already holds that
|
|
18
|
-
# concrete value; replaying it calls `dispatch` with the same
|
|
19
|
-
# args, and this module is never consulted again, for the same
|
|
20
|
-
# reason `SecureRandom.uuid` never runs twice for one
|
|
21
|
-
# already-recorded step today. `Event#occurred_at`
|
|
22
|
-
# (`command_rules/emission.rb`) is the one other "environmental
|
|
23
|
-
# fact, not caller-supplied" this codebase has, and it's handled
|
|
24
|
-
# the identical way: it fires on every dispatch, replay included,
|
|
25
|
-
# and comparison simply excludes it.
|
|
5
|
+
# Supplies the identity for a creating command with no natural key.
|
|
6
|
+
# One adapter registry-wide implements it. Replay never calls it: the minted value is
|
|
7
|
+
# already baked into the recorded step's args.
|
|
26
8
|
module IdentityGeneration
|
|
27
9
|
NAME = "identity_generation".freeze
|
|
28
10
|
|
|
@@ -32,18 +14,13 @@ module Hecks
|
|
|
32
14
|
#
|
|
33
15
|
# @param registry [Runtime::Registry] the booted registry to resolve the adapter against
|
|
34
16
|
# @return [String] a newly minted identity: a random UUID from `SecureRandomIdentity`,
|
|
35
|
-
# or a decimal counter
|
|
36
|
-
# spec double — unique per adapter, not guaranteed UUID-shaped
|
|
17
|
+
# or a decimal counter from the deterministic `SequentialIdentity` spec double
|
|
37
18
|
# @raise [Runtime::WiringError] if this port does not resolve to exactly one adapter
|
|
38
|
-
# (see `adapter`)
|
|
39
19
|
def uuid(registry) = adapter(registry).uuid
|
|
40
20
|
|
|
41
|
-
# Finds the single adapter bound to this port
|
|
21
|
+
# Finds the single adapter bound to this port.
|
|
42
22
|
#
|
|
43
|
-
# @
|
|
44
|
-
# @return [Module] the adapter module or class implementing this port
|
|
45
|
-
# @raise [Runtime::WiringError] if no adapter, or more than one, implements this port,
|
|
46
|
-
# or the one that does has no Ruby implementation under `Hecks::Adapters`
|
|
23
|
+
# @raise [Runtime::WiringError] if none, or more than one, implements this port
|
|
47
24
|
def adapter(registry)
|
|
48
25
|
implementations = registry.adapters.values.select { |a| a.port == NAME }
|
|
49
26
|
|
|
@@ -2,16 +2,8 @@ require_relative "../runtime/registry"
|
|
|
2
2
|
|
|
3
3
|
module Hecks
|
|
4
4
|
module Ports
|
|
5
|
-
#
|
|
6
|
-
#
|
|
7
|
-
# already has for Governance: one adapter registry-wide answers this
|
|
8
|
-
# port, resolved the same zero/one/many way, so an application never
|
|
9
|
-
# has to name `Identity` directly to ask "who is this."
|
|
10
|
-
#
|
|
11
|
-
# Answers `nil` for a pair nothing has linked — the caller decides
|
|
12
|
-
# what that means (refuse, prompt to register, whatever), the same
|
|
13
|
-
# way `Authorization#holds_role?` answering `false` decides nothing
|
|
14
|
-
# on its own.
|
|
5
|
+
# Resolves an authenticated (issuer, subject) pair to a stable identity id.
|
|
6
|
+
# One adapter registry-wide answers this port.
|
|
15
7
|
module IdentityResolution
|
|
16
8
|
NAME = "identity_resolution".freeze
|
|
17
9
|
|
|
@@ -2,55 +2,23 @@ require_relative "../runtime/registry"
|
|
|
2
2
|
|
|
3
3
|
module Hecks
|
|
4
4
|
module Ports
|
|
5
|
-
# A subject's
|
|
6
|
-
#
|
|
7
|
-
# material never being reachable except through this port's opaque
|
|
8
|
-
# reference (see `Privacy::SubjectKey`, `lib/hecks/framework/bluebook/
|
|
9
|
-
# privacy.bluebook`). Resolved the same way `Ports::IdentityGeneration`
|
|
10
|
-
# resolves its own adapter: one adapter registry-wide answers this
|
|
11
|
-
# port, not a per-aggregate binding.
|
|
5
|
+
# A subject's encryption key, one boundary removed from any event or
|
|
6
|
+
# bluebook attribute, so cryptoshredding never exposes key material.
|
|
12
7
|
module KeyVault
|
|
13
8
|
NAME = "key_vault".freeze
|
|
14
9
|
|
|
15
10
|
module_function
|
|
16
11
|
|
|
17
|
-
# Mints a
|
|
18
|
-
#
|
|
19
|
-
# @param registry [Runtime::Registry] the booted registry to resolve the adapter against
|
|
20
|
-
# @param subject_id [String] the data subject the key is being issued for
|
|
21
|
-
# @return [String] an opaque key reference; the key material itself never leaves the
|
|
22
|
-
# bound adapter, and is never suitable to store on an event or a bluebook attribute
|
|
12
|
+
# Mints a per-subject key; the key material itself never leaves the bound adapter.
|
|
23
13
|
def issue(registry, subject_id:) = adapter(registry).issue(subject_id: subject_id)
|
|
24
14
|
|
|
25
|
-
# Irrevocably destroys a key
|
|
26
|
-
#
|
|
27
|
-
# Ciphertext produced under `key_reference` becomes permanently unrecoverable the
|
|
28
|
-
# moment this returns — the mechanism a right-to-erasure request satisfies without
|
|
29
|
-
# rewriting or deleting any event.
|
|
30
|
-
#
|
|
31
|
-
# @param registry [Runtime::Registry] the booted registry to resolve the adapter against
|
|
32
|
-
# @param key_reference [String] the opaque reference {#issue} returned
|
|
33
|
-
# @return [Boolean] true when a live key was destroyed; false when this reference was
|
|
34
|
-
# already destroyed, or was never issued
|
|
15
|
+
# Irrevocably destroys a key; ciphertext under it becomes unrecoverable at once —
|
|
16
|
+
# how a right-to-erasure request is satisfied without rewriting or deleting events.
|
|
35
17
|
def destroy(registry, key_reference:) = adapter(registry).destroy(key_reference: key_reference)
|
|
36
18
|
|
|
37
|
-
#
|
|
38
|
-
#
|
|
39
|
-
#
|
|
40
|
-
# allow. `Privacy::SubjectKey.Shred`'s own lifecycle guard (`from: "active"`) still
|
|
41
|
-
# refuses a raw double-dispatch; this is what closes the gap one level up, where the
|
|
42
|
-
# danger isn't a duplicate `Shred` but `Shred` running *before* {#destroy} does.
|
|
43
|
-
#
|
|
44
|
-
# Idempotent: a subject with no live `SubjectKey` record, or one already shredded,
|
|
45
|
-
# is left alone and answered `false` — a retried erasure request never re-destroys
|
|
46
|
-
# an already-gone key or double-dispatches `Shred`.
|
|
47
|
-
#
|
|
48
|
-
# @param dispatcher [Runtime::Dispatcher, Runtime::RemoteDispatcher] the booted
|
|
49
|
-
# dispatcher both the lookup query and the `Shred` dispatch run through
|
|
50
|
-
# @param domain [String] the subject's own domain FQN, e.g. `"Site::Registration"`
|
|
51
|
-
# @param subject_id [String] the data subject to erase
|
|
52
|
-
# @return [Boolean] true when a live key was found and shredded by this call; false
|
|
53
|
-
# when no `SubjectKey` record exists for this subject, or it was already shredded
|
|
19
|
+
# Destroys the subject's key, then dispatches Shred, in that fixed order — never the
|
|
20
|
+
# reverse, so Shred cannot be dispatched before the key is actually gone. Idempotent:
|
|
21
|
+
# a subject with no live key, or one already shredded, is left alone and returns false.
|
|
54
22
|
def shred!(dispatcher, domain:, subject_id:) # rubocop:disable Naming/PredicateMethod
|
|
55
23
|
record = dispatcher.query("Privacy::SubjectKey.ForSubject", domain: domain, subject_id: subject_id).first
|
|
56
24
|
return false unless record
|
|
@@ -61,11 +29,7 @@ module Hecks
|
|
|
61
29
|
true
|
|
62
30
|
end
|
|
63
31
|
|
|
64
|
-
#
|
|
65
|
-
#
|
|
66
|
-
# @param registry [Runtime::Registry] the booted registry to search
|
|
67
|
-
# @return [Module] the adapter module or class implementing this port
|
|
68
|
-
# @raise [Runtime::WiringError] if no adapter, or more than one, implements this port
|
|
32
|
+
# Refuses an ambiguous wiring rather than choosing an adapter arbitrarily.
|
|
69
33
|
def adapter(registry)
|
|
70
34
|
implementations = registry.adapters.values.select { |a| a.port == NAME }
|
|
71
35
|
|