hecks 2.8.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 +4 -6
- 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 +17 -98
- 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 +5 -48
- 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 +31 -141
- 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 +14 -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 +25 -31
- data/lib/hecks/bluebook/behaviour/traits.rb +27 -64
- data/lib/hecks/bluebook/behaviour/value_object.rb +5 -24
- data/lib/hecks/bluebook/capabilities.rb +17 -49
- data/lib/hecks/bluebook/chapter.rb +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 +16 -69
- 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 -194
- 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 -111
- data/lib/hecks/bluebook/entity.rb +13 -71
- data/lib/hecks/bluebook/expression/ast_json.rb +24 -190
- data/lib/hecks/bluebook/expression/ast_reader.rb +12 -54
- data/lib/hecks/bluebook/expression/canonical_form.rb +11 -88
- data/lib/hecks/bluebook/expression/evaluator.rb +47 -295
- data/lib/hecks/bluebook/expression/resolver/block_predicates.rb +30 -147
- data/lib/hecks/bluebook/expression/resolver.rb +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 +53 -267
- data/lib/hecks/bluebook/meta_validator/syntax_boot.rb +43 -305
- 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 +6 -21
- data/lib/hecks/bluebook/model_check.rb +100 -597
- 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 +4 -23
- data/lib/hecks/cli/document.rb +3 -21
- data/lib/hecks/cli/ir.rb +3 -5
- data/lib/hecks/cli/mcp.rb +2 -3
- data/lib/hecks/cli/mcp_door.rb +19 -114
- data/lib/hecks/cli/model_check.rb +18 -85
- data/lib/hecks/cli/project_cli.rb +7 -40
- data/lib/hecks/cli/project_diagrams.rb +0 -7
- data/lib/hecks/cli/run.rb +12 -58
- data/lib/hecks/cli/smoke_test.rb +2 -16
- data/lib/hecks/cli/stores.rb +1 -2
- data/lib/hecks/cli.rb +18 -24
- 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 +82 -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 +9 -90
- 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 +61 -64
- data/lib/hecks/ports/persistence/binding_policy.rb +4 -14
- data/lib/hecks/ports/persistence/codec_boundary.rb +20 -80
- data/lib/hecks/ports/persistence/null_saga_store.rb +4 -20
- data/lib/hecks/ports/persistence/plugin.rb +13 -42
- data/lib/hecks/ports/persistence/plugins/era/era_check.rb +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 +6 -25
- 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 +18 -124
- data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/differ.rb +34 -123
- data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/renderer.rb +5 -12
- data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/writer.rb +3 -9
- data/lib/hecks/ports/persistence/plugins/era/translation/scaffold.rb +2 -14
- data/lib/hecks/ports/persistence/plugins/era.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 +150 -678
- 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 +2 -15
- 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 +42 -134
- data/lib/hecks/projector/ir_projector.rb +2 -9
- data/lib/hecks/projector/narrate_projector.rb +15 -189
- data/lib/hecks/projector/target.rb +13 -76
- data/lib/hecks/projector.rb +30 -121
- data/lib/hecks/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 +3 -6
- data/lib/hecks/release/runner/commands.rb +2 -4
- data/lib/hecks/release/runner/gem_publisher.rb +2 -3
- data/lib/hecks/release/runner/npm_publisher.rb +6 -20
- data/lib/hecks/release/runner/preflight.rb +4 -19
- data/lib/hecks/release/runner/tagger.rb +2 -9
- data/lib/hecks/release/runner.rb +3 -32
- 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 +124 -306
- data/lib/hecks/runtime/command_rules/admissibility.rb +95 -366
- data/lib/hecks/runtime/command_rules/arithmetic.rb +66 -196
- data/lib/hecks/runtime/command_rules/authorization.rb +13 -45
- data/lib/hecks/runtime/command_rules/emission.rb +8 -21
- data/lib/hecks/runtime/command_rules/references.rb +23 -202
- data/lib/hecks/runtime/dependency_planning.rb +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 +64 -219
- data/lib/hecks/runtime/errors.rb +32 -115
- data/lib/hecks/runtime/event.rb +3 -25
- data/lib/hecks/runtime/identity.rb +18 -154
- data/lib/hecks/runtime/instance.rb +18 -150
- data/lib/hecks/runtime/interpreting.rb +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 +117 -208
- data/lib/hecks/runtime/rebuild_sweep.rb +8 -54
- data/lib/hecks/runtime/reference_hop.rb +8 -81
- data/lib/hecks/runtime/refusal_wording.rb +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 +99 -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 +141 -568
- 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.rb +26 -81
- 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 +3 -2
data/lib/hecks/forms.rb
CHANGED
|
@@ -1,41 +1,13 @@
|
|
|
1
|
-
# The forms surface: `expose
|
|
2
|
-
# `
|
|
3
|
-
# command-form-and-query-form-bluebook.md), the IR->HTML renderers, and
|
|
4
|
-
# the Rack app that content-negotiates between them and a plain JSON
|
|
5
|
-
# reading of the same dispatch. Not required by `require "hecks"`
|
|
6
|
-
# itself — a project that never boots this file never pays for `rack`,
|
|
7
|
-
# the same lazy-dependency discipline the Gemfile's own comment already
|
|
8
|
-
# holds `pg`/`oauth2`/`aws-sdk-lambda` to.
|
|
9
|
-
#
|
|
10
|
-
# See docs/command-form-and-query-form-bluebook.md for the design this
|
|
11
|
-
# implements and what it deliberately leaves for later.
|
|
1
|
+
# The forms surface: `expose`, the HTML renderers and the Rack app serving them.
|
|
2
|
+
# Not loaded by `require "hecks"`, so `rack` stays a lazy dependency.
|
|
12
3
|
require "hecks"
|
|
13
4
|
require_relative "forms/app"
|
|
14
5
|
|
|
15
6
|
module Hecks
|
|
16
|
-
# Per-
|
|
17
|
-
# by the Rack app at request time (`.config`) to decide which chapters'
|
|
18
|
-
# forms are switched on at all — see the file header above for what
|
|
19
|
-
# `expose` deliberately does and does not cover.
|
|
7
|
+
# Per-app `expose` configuration, looked up by the Rack app at request time.
|
|
20
8
|
module Forms
|
|
21
|
-
#
|
|
22
|
-
#
|
|
23
|
-
# `Hecks.hecksagon`, ...) and outside `Runtime::Registry` entirely, on
|
|
24
|
-
# purpose: a real language word goes through `syntax.bluebook` and
|
|
25
|
-
# `MetaValidator` (see docs/implemented/guides/extending-hecks.md, "a new word is a
|
|
26
|
-
# declared row before it is a line of Ruby") and is judged by
|
|
27
|
-
# spec/syntax_conformance_spec.rb + spec/dsl_coverage_spec.rb — gates
|
|
28
|
-
# this construct has not earned yet. An ordinary Ruby DSL, one level of
|
|
29
|
-
# module state, no different in kind from a project's own initializer —
|
|
30
|
-
# see docs/command-form-and-query-form-bluebook.md, "why this isn't
|
|
31
|
-
# syntax.bluebook yet".
|
|
32
|
-
#
|
|
33
|
-
# One `expose` grants a whole chapter, not a command or a query
|
|
34
|
-
# individually — the future `command_form.bluebook`/`query_form.bluebook`
|
|
35
|
-
# words are per-declaration (one command, one query, its own form/view,
|
|
36
|
-
# possibly its own overrides), which `expose` doesn't do today and was
|
|
37
|
-
# never trying to; it's the coarse "turn this chapter's forms on at
|
|
38
|
-
# all" switch those finer words will eventually sit inside.
|
|
9
|
+
# The chapters one app exposes. Plain module state, outside `syntax.bluebook` and
|
|
10
|
+
# the registry; one `expose` switches on a whole chapter, not a single command or query.
|
|
39
11
|
class Config
|
|
40
12
|
attr_reader :name, :exposes
|
|
41
13
|
|
data/lib/hecks/fqn.rb
CHANGED
|
@@ -24,10 +24,9 @@ module Hecks
|
|
|
24
24
|
new(realm: realm, domain: domain, version: version, aggregate: aggregate, verb: command, kind: :command)
|
|
25
25
|
end
|
|
26
26
|
|
|
27
|
-
# Builds the FQN of one query,
|
|
27
|
+
# Builds the FQN of one query, on an aggregate or domain-level.
|
|
28
28
|
#
|
|
29
|
-
# @param realm [String, nil] deployment identity from the world, or nil
|
|
30
|
-
# unrealmed address
|
|
29
|
+
# @param realm [String, nil] deployment identity from the world, or nil if unrealmed
|
|
31
30
|
# @param domain [String] the domain name
|
|
32
31
|
# @param query [String] the query's snake_case verb
|
|
33
32
|
# @param aggregate [String, nil] the aggregate the query belongs to, or nil for
|
|
@@ -41,12 +40,8 @@ module Hecks
|
|
|
41
40
|
new(realm: realm, domain: domain, version: version, aggregate: aggregate, verb: query, kind: :query)
|
|
42
41
|
end
|
|
43
42
|
|
|
44
|
-
#
|
|
45
|
-
# on
|
|
46
|
-
# field validate -> construct. Each step consumes locals (segments, verb,
|
|
47
|
-
# kind) the step before it derived; splitting would mean threading all of
|
|
48
|
-
# them back out as parameters/returns between new methods, for no
|
|
49
|
-
# readability gain over reading the pipeline top to bottom once.
|
|
43
|
+
# Parses a `Realm::Domain@version::Aggregate.verb` address.
|
|
44
|
+
# One method on purpose: each step consumes locals the step before it derived.
|
|
50
45
|
#
|
|
51
46
|
# @param text [String] a `Realm::Domain::Aggregate.verb` address, with domain
|
|
52
47
|
# optionally `@version`-pinned and aggregate optional for a domain-level query
|
|
@@ -65,9 +60,7 @@ module Hecks
|
|
|
65
60
|
|
|
66
61
|
realm, domain_spec, aggregate = case segments.length
|
|
67
62
|
when 3 then segments
|
|
68
|
-
#
|
|
69
|
-
# public realm/domain form for a
|
|
70
|
-
# domain-level read model.
|
|
63
|
+
# realm::domain.query is a domain-level read model
|
|
71
64
|
when 2 then query_name?(verb) ? [segments[0], segments[1], nil] : [nil, *segments]
|
|
72
65
|
else [nil, segments.first, nil]
|
|
73
66
|
end
|
|
@@ -2,46 +2,16 @@ Hecks.bluebook "Compliance" do
|
|
|
2
2
|
vision "Something elsewhere already acted to contain a risk; this domain tracks the human review that decides what happens next."
|
|
3
3
|
supporting
|
|
4
4
|
|
|
5
|
-
#
|
|
6
|
-
#
|
|
7
|
-
#
|
|
8
|
-
#
|
|
9
|
-
# PROCESS), Compliance genuinely supports BOTH modes from the same
|
|
10
|
-
# source: a domain that wants Review handled locally can
|
|
11
|
-
# `uses_framework "Compliance"` exactly like those two; a domain that
|
|
12
|
-
# wants it as a real, separately-deployed service — Banking's own
|
|
13
|
-
# choice, examples/compliance/ — reaches it through `across
|
|
14
|
-
# "Compliance"` on a policy instead, genuine cross-Lambda delivery.
|
|
15
|
-
# Nothing about this bluebook's own declarations changes between the
|
|
16
|
-
# two; only whether the CONSUMER merges it in or deploys it apart.
|
|
5
|
+
# Supports both modes from one source: `uses_framework "Compliance"` merges it in-process,
|
|
6
|
+
# or a separately deployed service is reached with `across "Compliance"` on a policy.
|
|
7
|
+
# examples/compliance/bluebook/compliance.bluebook symlinks here, since a symlink pointing
|
|
8
|
+
# outside lib/ does not survive `gem build`.
|
|
17
9
|
#
|
|
18
|
-
#
|
|
19
|
-
#
|
|
20
|
-
# 1.5.0) — a symlink pointing outside lib/ never survives `gem
|
|
21
|
-
# build` (RubyGems drops it, warning "not supported on all
|
|
22
|
-
# platforms"), so the real content has to live in the tree the
|
|
23
|
-
# gemspec actually packages.
|
|
10
|
+
# Contain first, investigate second: the containing action (a freeze, a box surrender) has
|
|
11
|
+
# already happened elsewhere. This domain is told the fact and records the review after it.
|
|
24
12
|
#
|
|
25
|
-
#
|
|
26
|
-
#
|
|
27
|
-
# directly and synchronously in three places (Customer.Suspend/
|
|
28
|
-
# Reinstate, Account.Freeze/Unfreeze, OnboardingCase.Clear/Decline) —
|
|
29
|
-
# this domain is deliberately NOT a fourth. By the time either
|
|
30
|
-
# aggregate below is opened, the containing action (a freeze, a box
|
|
31
|
-
# surrender) has ALREADY happened, unilaterally, elsewhere; this
|
|
32
|
-
# domain never asks permission, it is TOLD a fact and gives the same
|
|
33
|
-
# officer a place to record what they decided about it afterward.
|
|
34
|
-
#
|
|
35
|
-
# TWO AGGREGATES, NOT ONE — found live, designing this: Banking's own
|
|
36
|
-
# `ReviewOnFreeze`/`ReviewOnBoxSurrender` policies forward their
|
|
37
|
-
# triggering event's payload VERBATIM (neither declares a `with:`
|
|
38
|
-
# projection, which policies have gained since), and the two events
|
|
39
|
-
# carry genuinely different fields (`AccountFrozen`: `number`;
|
|
40
|
-
# `BoxSurrendered`: `branch_code` + `box_number`). One shared
|
|
41
|
-
# aggregate would need an artificial union of both shapes — and while
|
|
42
|
-
# `with:` could now reshape either side into it, that would be
|
|
43
|
-
# inventing a sameness the domain does not have. Two small aggregates,
|
|
44
|
-
# each identified by its own subject's own natural key, need neither.
|
|
13
|
+
# One aggregate per triggering event: the events carry different fields, so a shared
|
|
14
|
+
# aggregate would need an artificial union of the shapes.
|
|
45
15
|
|
|
46
16
|
aggregate "AccountFreezeReview" do
|
|
47
17
|
description "The compliance review a frozen account gets, opened the moment Banking::Account.Freeze already happened."
|
|
@@ -60,12 +30,8 @@ Hecks.bluebook "Compliance" do
|
|
|
60
30
|
transition "Escalate" => "escalated", from: "open"
|
|
61
31
|
end
|
|
62
32
|
|
|
63
|
-
#
|
|
64
|
-
# field
|
|
65
|
-
# the ONLY field this ever receives (ReviewOnFreeze's own `on
|
|
66
|
-
# "Account.AccountFrozen"`), so this declares exactly that and
|
|
67
|
-
# nothing more; an unrecognized field would refuse at the JSON
|
|
68
|
-
# boundary rather than silently drop it.
|
|
33
|
+
# System-triggered. Takes only `number`, the one field `AccountFrozen` carries; an
|
|
34
|
+
# unrecognized field is refused at the JSON boundary rather than dropped.
|
|
69
35
|
command "Open" do
|
|
70
36
|
role "System"
|
|
71
37
|
goal "Register that a frozen account needs compliance review"
|
|
@@ -117,9 +83,7 @@ Hecks.bluebook "Compliance" do
|
|
|
117
83
|
transition "Escalate" => "escalated", from: "open"
|
|
118
84
|
end
|
|
119
85
|
|
|
120
|
-
#
|
|
121
|
-
# (`ReviewOnBoxSurrender`'s own `on SafeDepositBox::BoxSurrendered`) — the same
|
|
122
|
-
# discipline `AccountFreezeReview.Open` holds itself to, above.
|
|
86
|
+
# Takes exactly the fields `BoxSurrendered` carries, as `AccountFreezeReview.Open` does.
|
|
123
87
|
command "Open" do
|
|
124
88
|
role "System"
|
|
125
89
|
goal "Register that a surrendered box needs compliance review"
|
|
@@ -149,18 +113,9 @@ Hecks.bluebook "Compliance" do
|
|
|
149
113
|
end
|
|
150
114
|
end
|
|
151
115
|
|
|
152
|
-
# A
|
|
153
|
-
#
|
|
154
|
-
#
|
|
155
|
-
# neither `AccountFrozen` (`number`) nor `BoxSurrendered`
|
|
156
|
-
# (`branch_code`/`box_number`), so this gets its own aggregate rather
|
|
157
|
-
# than an artificial union.
|
|
158
|
-
#
|
|
159
|
-
# REACHED VIA `translates`, NOT a `policy` this bluebook declares —
|
|
160
|
-
# which foreign domain's event a consumer conforms to is a wiring
|
|
161
|
-
# decision (see `HecksagonBuilder#translates`'s own header), so the
|
|
162
|
-
# reaction lives in whichever `.hecksagon` attaches both Privacy and
|
|
163
|
-
# Compliance, not here.
|
|
116
|
+
# A third shape, not a union of the other two: `Privacy::Marking`'s `Marked` event carries
|
|
117
|
+
# `domain`/`attribute_path`. Reached via `translates` in whichever `.hecksagon` attaches
|
|
118
|
+
# both Privacy and Compliance, since which foreign event to conform to is wiring.
|
|
164
119
|
aggregate "PrivacyReview" do
|
|
165
120
|
description "The compliance review a newly marked sensitive field gets, opened the moment Privacy::Marking.Mark already happened."
|
|
166
121
|
|
|
@@ -184,12 +139,8 @@ Hecks.bluebook "Compliance" do
|
|
|
184
139
|
transition "Escalate" => "escalated", from: "open"
|
|
185
140
|
end
|
|
186
141
|
|
|
187
|
-
#
|
|
188
|
-
#
|
|
189
|
-
# just `domain`/`attribute_path`, the same restraint
|
|
190
|
-
# `AccountFreezeReview.Open`/`BoxSurrenderReview.Open` already hold
|
|
191
|
-
# themselves to above; `category`/`readable_by` stay on the
|
|
192
|
-
# marking itself, not duplicated here.
|
|
142
|
+
# System-triggered. Takes only `Marking`'s identity fields; `category`/`readable_by` stay
|
|
143
|
+
# on the marking.
|
|
193
144
|
command "Open" do
|
|
194
145
|
role "System"
|
|
195
146
|
goal "Register that a newly marked sensitive field needs compliance review"
|
|
@@ -2,80 +2,38 @@ Hecks.bluebook "ConsoleSettings" do
|
|
|
2
2
|
vision "A generic admin console's own curated UI facts — nav, columns, state tones, which rows a detail panel shows — as real dispatched data instead of a hand-rewritten YAML file. A UI opinion the DOMAIN it's pointed at has no way to answer, never a business record; see the console app's own presentation_config.rb for the fuller story."
|
|
3
3
|
supporting
|
|
4
4
|
|
|
5
|
-
# A
|
|
6
|
-
# `uses_framework "ConsoleSettings"` in the consuming app's own
|
|
7
|
-
#
|
|
8
|
-
|
|
9
|
-
#
|
|
10
|
-
#
|
|
11
|
-
#
|
|
12
|
-
|
|
13
|
-
#
|
|
14
|
-
#
|
|
15
|
-
#
|
|
16
|
-
#
|
|
17
|
-
# NOT named "Forms" — Hecks::Forms (lib/hecks/forms/) already
|
|
18
|
-
# names a different, real thing: a dormant prototype (the working half
|
|
19
|
-
# of command_form.bluebook/query_form.bluebook, see docs/command-form-
|
|
20
|
-
# and-query-form-bluebook.md) that renders raw forms/query views
|
|
21
|
-
# straight off any IR, zero config. This chapter is the opposite kind
|
|
22
|
-
# of surface — a CURATED, hand-authored dashboard's own settings — and
|
|
23
|
-
# picks a name that doesn't read as the same one.
|
|
24
|
-
#
|
|
25
|
-
# SCOPE: everything presentation.yml carries EXCEPT a collection's own
|
|
26
|
-
# `after_create` (a dispatch chain with a literal-or-$field-or-
|
|
27
|
-
# count_query arg shape — a harder design problem that shouldn't gate
|
|
28
|
-
# everything else; Ruby-side PresentationConfig keeps validating it,
|
|
29
|
-
# same as always, with nowhere yet to persist it). `overview.stats`
|
|
30
|
-
# (Overview, below) and every `extra_json`/`identity_extra_json`
|
|
31
|
-
# field throughout this chapter were BOTH originally scoped out on an
|
|
32
|
-
# "confirmed unused in any real presentation.yml" basis that turned
|
|
33
|
-
# out to be checked against the wrong file — the console app's own
|
|
34
|
-
# fixture, never this app's actual, live one. Migrating the real file
|
|
35
|
-
# found both very much in use.
|
|
5
|
+
# A framework member like Identity/Governance: attach with
|
|
6
|
+
# `uses_framework "ConsoleSettings"` in the consuming app's own `.hecksagon`,
|
|
7
|
+
# plus a `Hecks.hecksagon "ConsoleSettings" do ... end` persistence binding.
|
|
8
|
+
|
|
9
|
+
# Named ConsoleSettings, not "Forms" — Hecks::Forms (lib/hecks/forms/) names a
|
|
10
|
+
# different thing, a raw form/query renderer straight off any IR. This chapter
|
|
11
|
+
# is a curated, hand-authored dashboard's own settings.
|
|
12
|
+
|
|
13
|
+
# Scopes everything presentation.yml carries except a collection's own
|
|
14
|
+
# `after_create` dispatch chain (a harder arg shape, still validated in Ruby).
|
|
15
|
+
# `overview.stats` and the `extra_json`/`identity_extra_json` fields below are
|
|
16
|
+
# real, in-use fields, confirmed against the app's actual presentation.yml.
|
|
36
17
|
|
|
37
18
|
aggregate "StateStyle" do
|
|
38
19
|
description "One aggregate's one lifecycle state, styled — a tone and whether it needs attention. Every real state gets a row, even a bare one (PresentationConfig's own missing_state_entries! check), so Declare and the two Set commands are separate: a bare row is a real, valid thing to have."
|
|
39
20
|
|
|
40
21
|
# `agg`, not `aggregate` — the bluebook DSL's own word for what's being
|
|
41
|
-
# declared
|
|
42
|
-
#
|
|
43
|
-
# (see [[project_generic_founder_app]]) already had to work around
|
|
44
|
-
# once for `id`.
|
|
22
|
+
# declared; an attribute of that name would shadow it, the same collision
|
|
23
|
+
# ui_schema.rb already had to work around once for `id`.
|
|
45
24
|
attribute :agg, StateStyleText
|
|
46
25
|
attribute :state, StateStyleText
|
|
47
26
|
attribute :tone, one_of("good", "warn", "danger", "muted", "accent"), optional: true
|
|
48
27
|
|
|
49
28
|
identified_by :agg, :state
|
|
50
|
-
# `Flag
|
|
51
|
-
#
|
|
52
|
-
# on an aggregate/command attribute
|
|
53
|
-
# - `TrueClass`/`FalseClass` are real, pre-existing Ruby constants,
|
|
54
|
-
# so writing them here resolves through NORMAL Ruby constant
|
|
55
|
-
# lookup rather than ever reaching the DSL's own ConstShim (unlike
|
|
56
|
-
# a bareword like `Flag`, which has no such constant and so DOES
|
|
57
|
-
# reach it) — the meta-validator has no separate case for the
|
|
58
|
-
# literal class objects, so it goes looking for a declared value
|
|
59
|
-
# object named "TrueClass" and fails. `Attribute::PRIMITIVES`
|
|
60
|
-
# lists them, but no real bluebook in this codebase spells one.
|
|
61
|
-
# - A bare primitive (`String`, `Integer`) directly on an
|
|
62
|
-
# AGGREGATE or COMMAND attribute fails the identical way — every
|
|
63
|
-
# real example in this codebase only ever uses `String`/`Integer`
|
|
64
|
-
# INSIDE a `value_object do...end` block, never as a top-level
|
|
65
|
-
# attribute's own type; reproduced with a 4-line isolated bluebook
|
|
66
|
-
# before trusting it as a real rule, not a guess.
|
|
67
|
-
# PresentationConfig's own Ruby glue converts "true"/"false" at the
|
|
68
|
-
# boundary.
|
|
29
|
+
# `Flag` wraps "true"/"false" as a value object: `TrueClass` resolves as a
|
|
30
|
+
# real Ruby constant rather than reaching ConstShim, and a bare `String`/
|
|
31
|
+
# `Integer` fails the same way directly on an aggregate/command attribute.
|
|
69
32
|
attribute :attention, Flag, optional: true
|
|
70
33
|
|
|
71
|
-
#
|
|
72
|
-
#
|
|
73
|
-
#
|
|
74
|
-
# real, in-use fields this schema didn't model. Serialized, not
|
|
75
|
-
# decomposed — the same verified-then-opaque reasoning Overview's
|
|
76
|
-
# own `where_json` already documents: PresentationConfig's own
|
|
77
|
-
# reshape/write is where the real key set is enumerated and
|
|
78
|
-
# subtracted from, in Ruby, not here.
|
|
34
|
+
# Carries whatever a state entry has beyond tone/attention (e.g. a display
|
|
35
|
+
# `label` or a `note`) — serialized, not decomposed; PresentationConfig's
|
|
36
|
+
# own reshape/write enumerates the real key set in Ruby, not here.
|
|
79
37
|
attribute :extra_json, StateStyleExtra, optional: true
|
|
80
38
|
|
|
81
39
|
value_object "StateStyleText" do
|
|
@@ -87,10 +45,8 @@ Hecks.bluebook "ConsoleSettings" do
|
|
|
87
45
|
attribute :value, String
|
|
88
46
|
end
|
|
89
47
|
|
|
90
|
-
#
|
|
91
|
-
#
|
|
92
|
-
# reason) — this wraps extra_json's own opaque JSON text the same
|
|
93
|
-
# way every other scalar field in this chapter already wraps one.
|
|
48
|
+
# Wraps extra_json's opaque JSON text — a bare `String` fails directly on
|
|
49
|
+
# an aggregate/command attribute (see the `Flag` comment above).
|
|
94
50
|
value_object "StateStyleExtra" do
|
|
95
51
|
attribute :value, String
|
|
96
52
|
end
|
|
@@ -158,23 +114,17 @@ Hecks.bluebook "ConsoleSettings" do
|
|
|
158
114
|
attribute :identity_strategy, one_of("slug", "sequence", "port"), optional: true
|
|
159
115
|
attribute :identity_source, SettingsText, optional: true
|
|
160
116
|
attribute :identity_prefix, SettingsText, optional: true
|
|
161
|
-
# `pad` (a sequence strategy's
|
|
162
|
-
#
|
|
163
|
-
#
|
|
164
|
-
# aren't a closed set either: whatever a real identity rule carries
|
|
165
|
-
# beyond field/strategy/source/prefix, opaque, same as extra_json
|
|
166
|
-
# below.
|
|
117
|
+
# `pad` (a sequence strategy's zero-padding width, e.g. "C-004" vs "C-4")
|
|
118
|
+
# is real but unmodeled here, same as identity_source/identity_prefix —
|
|
119
|
+
# carried opaquely in identity_extra_json below.
|
|
167
120
|
attribute :identity_extra_json, CollectionExtra, optional: true
|
|
168
121
|
attribute :columns, list_of(Column)
|
|
169
122
|
attribute :detail_fields, list_of(DetailField)
|
|
170
123
|
attribute :detail_field_columns, list_of(DetailFieldColumn)
|
|
171
124
|
attribute :preconditions, list_of(Precondition)
|
|
172
125
|
attribute :field_formats, list_of(FieldFormat)
|
|
173
|
-
#
|
|
174
|
-
# `
|
|
175
|
-
# in-use fields this schema didn't model (10/8/2 real occurrences
|
|
176
|
-
# respectively). Same verified-then-opaque reasoning as StateStyle's
|
|
177
|
-
# own extra_json.
|
|
126
|
+
# Carries real, in-use fields this schema doesn't model (e.g. `noun_sing`,
|
|
127
|
+
# `create_label`, `nav_group`) — opaque, same as StateStyle's extra_json.
|
|
178
128
|
attribute :extra_json, CollectionExtra, optional: true
|
|
179
129
|
|
|
180
130
|
value_object "SettingsText" do
|
|
@@ -186,21 +136,15 @@ Hecks.bluebook "ConsoleSettings" do
|
|
|
186
136
|
attribute :value, Integer
|
|
187
137
|
end
|
|
188
138
|
|
|
189
|
-
#
|
|
190
|
-
#
|
|
191
|
-
# identity_extra_json; both are opaque JSON text, no reason for two
|
|
192
|
-
# separate wrapper types.
|
|
139
|
+
# Shared by extra_json and identity_extra_json — both opaque JSON text, no
|
|
140
|
+
# reason for two wrapper types. A bare `String` fails on an attribute directly.
|
|
193
141
|
value_object "CollectionExtra" do
|
|
194
142
|
attribute :value, String
|
|
195
143
|
end
|
|
196
144
|
|
|
197
|
-
# A list/table column. `sortable`/`sort_default` are optional
|
|
198
|
-
#
|
|
199
|
-
#
|
|
200
|
-
# enough (and PresentationConfig.validate! already checks it in
|
|
201
|
-
# Ruby) that a dedicated `one_of: [...]` (S3, ADR 0025 — the field's
|
|
202
|
-
# own keyword now, no sibling value object or `admits:` indirection
|
|
203
|
-
# needed) still isn't worth it for this one field.
|
|
145
|
+
# A list/table column. `sortable`/`sort_default` are optional (most columns
|
|
146
|
+
# take the frontend's default). `sort_default` stays a plain String rather
|
|
147
|
+
# than a closed `one_of` (ADR 0025) — PresentationConfig.validate! checks it.
|
|
204
148
|
value_object "Column" do
|
|
205
149
|
attribute :field, String
|
|
206
150
|
attribute :sortable, String, optional: true # "true"/"false" — see StateStyle.attention's own comment
|
|
@@ -211,14 +155,9 @@ Hecks.bluebook "ConsoleSettings" do
|
|
|
211
155
|
attribute :extra_json, String, optional: true
|
|
212
156
|
end
|
|
213
157
|
|
|
214
|
-
# One field the detail panel shows. `state_filter` only
|
|
215
|
-
#
|
|
216
|
-
#
|
|
217
|
-
# here refuses a state_filter on the wrong shape of field, since that
|
|
218
|
-
# check needs the APP's own live IR, which this domain can't see; it
|
|
219
|
-
# stays a Ruby-side PresentationConfig.validate! check, same as always.
|
|
220
|
-
# `display` is a plain String for the same nested-`one_of` collision
|
|
221
|
-
# reason `sort_default` is, above.
|
|
158
|
+
# One field the detail panel shows. `state_filter` only applies to an
|
|
159
|
+
# entity-backed rows field; nothing here enforces that, since it needs the
|
|
160
|
+
# app's own live IR — PresentationConfig.validate! checks it in Ruby.
|
|
222
161
|
value_object "DetailField" do
|
|
223
162
|
attribute :field, String
|
|
224
163
|
attribute :display, String, optional: true
|
|
@@ -229,10 +168,9 @@ Hecks.bluebook "ConsoleSettings" do
|
|
|
229
168
|
attribute :extra_json, String, optional: true
|
|
230
169
|
end
|
|
231
170
|
|
|
232
|
-
# A rows-shaped detail field's
|
|
233
|
-
#
|
|
234
|
-
#
|
|
235
|
-
# Query::AskOption already uses for a compound option's own parts.
|
|
171
|
+
# A rows-shaped detail field's sub-column filter, flattened to one row per
|
|
172
|
+
# (field, column) pair and grouped back by `field` on the way out — the
|
|
173
|
+
# same flattening Query::AskOption uses for a compound option's parts.
|
|
236
174
|
value_object "DetailFieldColumn" do
|
|
237
175
|
attribute :field, String
|
|
238
176
|
attribute :column, String
|
|
@@ -397,15 +335,9 @@ Hecks.bluebook "ConsoleSettings" do
|
|
|
397
335
|
end
|
|
398
336
|
end
|
|
399
337
|
|
|
400
|
-
#
|
|
401
|
-
#
|
|
402
|
-
#
|
|
403
|
-
# whole console. `attribute :key, OverviewKey` holds a literal constant
|
|
404
|
-
# ("overview") rather than anything a person chooses — the same reason
|
|
405
|
-
# a creating command needs SOME identity to hydrate against (hydrate's
|
|
406
|
-
# own "an identity that is invented is neither derived from the record
|
|
407
|
-
# nor permanently associated with it" comment), just with the value
|
|
408
|
-
# fixed instead of derived from what's being declared.
|
|
338
|
+
# Domain-wide, not per-aggregate: exactly one row, ever, for the whole
|
|
339
|
+
# console. `key` holds a literal constant ("overview") rather than anything
|
|
340
|
+
# chosen, since a creating command still needs some identity to hydrate against.
|
|
409
341
|
aggregate "Overview" do
|
|
410
342
|
description "The console's own dashboard stat cards, whole. One row, ever — `key` is always the literal 'overview', never chosen. Every stat gets replaced as a whole list on save, the same 'replace whole, never patch one' convention Collection's own columns/detail_fields/preconditions/field_formats already use."
|
|
411
343
|
|
|
@@ -420,20 +352,9 @@ Hecks.bluebook "ConsoleSettings" do
|
|
|
420
352
|
invariant("is the one true singleton key") { value == "overview" }
|
|
421
353
|
end
|
|
422
354
|
|
|
423
|
-
# `where_json` carries the stat's
|
|
424
|
-
#
|
|
425
|
-
#
|
|
426
|
-
# serialized, not decomposed into the bluebook's own closed
|
|
427
|
-
# attribute grammar. That tree is genuinely open-ended (arbitrary
|
|
428
|
-
# nesting depth via `not:`, an arbitrary literal attribute name as
|
|
429
|
-
# a where key for anything that isn't `state`), and hecks's
|
|
430
|
-
# attribute types have no way to express "arbitrary nested map" at
|
|
431
|
-
# all — the same reason `sort_default`/`display`/`format` above stay
|
|
432
|
-
# plain Strings rather than a nested `one_of`. PresentationConfig's
|
|
433
|
-
# own `validate_where!`/`validate_has_related!` still walk and check
|
|
434
|
-
# the REAL structure, in Ruby, against the app's own live IR, before
|
|
435
|
-
# this is ever serialized and dispatched — this field is the
|
|
436
|
-
# verified-then-opaque storage, not an unchecked one.
|
|
355
|
+
# `where_json` carries the stat's recursive filter expression, serialized
|
|
356
|
+
# rather than decomposed — the tree is open-ended and hecks's attribute
|
|
357
|
+
# types can't express it. PresentationConfig.validate_where! checks it in Ruby.
|
|
437
358
|
value_object "Stat" do
|
|
438
359
|
attribute :label, String
|
|
439
360
|
attribute :collection, String
|
|
@@ -464,17 +385,9 @@ Hecks.bluebook "ConsoleSettings" do
|
|
|
464
385
|
end
|
|
465
386
|
end
|
|
466
387
|
|
|
467
|
-
#
|
|
468
|
-
#
|
|
469
|
-
#
|
|
470
|
-
# `group_by`'s own reference doc). PresentationConfig.rb's own read
|
|
471
|
-
# side (`reshape_states`/`reshape_collections`) dispatches these
|
|
472
|
-
# instead of hand-rolling the unwrap/grouping in Ruby — see its own
|
|
473
|
-
# header for what's still Ruby (the detail_field_columns/detail_fields
|
|
474
|
-
# join, which isn't a report concern at all — two list attributes on
|
|
475
|
-
# the SAME record, not two aggregates — and Overview's own stat cards,
|
|
476
|
-
# which are read straight off Overview.find, a singleton needing
|
|
477
|
-
# neither grouping nor unwrapping either).
|
|
388
|
+
# Both read models are rootless (bulk, no id at dispatch) and grouped by an
|
|
389
|
+
# aggregate's full identity, so each leaf is exactly one row. Dispatched from
|
|
390
|
+
# PresentationConfig's read side rather than hand-rolled in Ruby.
|
|
478
391
|
read_model "Styles" do
|
|
479
392
|
description "Every StateStyle row, nested by the aggregate and state it styles."
|
|
480
393
|
include StateStyle
|
|
@@ -1,21 +1,13 @@
|
|
|
1
|
-
# The framework members
|
|
2
|
-
# `Hecks.boot("lib/hecks/framework")`
|
|
3
|
-
# another domain attached with `uses_framework`.
|
|
4
|
-
#
|
|
5
|
-
# `uses_framework` does NOT read this file (Framework.load! loads a
|
|
6
|
-
# member's bluebook and nothing else, deliberately — see framework.rb),
|
|
7
|
-
# so an attaching domain still declares its own binding for these
|
|
8
|
-
# aggregates, exactly as before. This only answers the case where the
|
|
9
|
-
# framework is the domain being booted.
|
|
1
|
+
# The framework members bound to Memory so they can boot standing alone with
|
|
2
|
+
# `Hecks.boot("lib/hecks/framework")`. `uses_framework` does not read this file.
|
|
10
3
|
Hecks.hecksagon "Compliance" do
|
|
11
|
-
# Every command
|
|
12
|
-
# access control once Governance can check it against something (S8).
|
|
4
|
+
# Every command declares `role "Compliance officer"`; the role check needs Governance.
|
|
13
5
|
uses_framework "Governance"
|
|
14
6
|
persisted_by "Memory"
|
|
15
7
|
end
|
|
16
8
|
|
|
17
9
|
Hecks.hecksagon "ConsoleSettings" do
|
|
18
|
-
# Same reason as Compliance
|
|
10
|
+
# Same reason as Compliance.
|
|
19
11
|
uses_framework "Governance"
|
|
20
12
|
persisted_by "Memory"
|
|
21
13
|
end
|
|
@@ -25,8 +17,7 @@ Hecks.hecksagon "Governance" do
|
|
|
25
17
|
end
|
|
26
18
|
|
|
27
19
|
Hecks.hecksagon "Identity" do
|
|
28
|
-
# `Identity
|
|
29
|
-
# same reason as Compliance/ConsoleSettings, above — S8.
|
|
20
|
+
# `Identity.Register` declares `role "Identity registrar"`; same reason as Compliance.
|
|
30
21
|
uses_framework "Governance"
|
|
31
22
|
persisted_by "Memory"
|
|
32
23
|
end
|
|
@@ -2,10 +2,9 @@ Hecks.bluebook "Governance" do
|
|
|
2
2
|
vision "Organizational authority is explicit, reviewable, and historically explainable."
|
|
3
3
|
supporting
|
|
4
4
|
|
|
5
|
-
#
|
|
6
|
-
#
|
|
7
|
-
#
|
|
8
|
-
# three verbs from here, rather than recognising "Governance" by name.
|
|
5
|
+
# What this chapter answers for every attaching domain: the role check at dispatch, boot's
|
|
6
|
+
# refusal of an ungoverned `role`, the authorization adapter and the fuzzer's grant
|
|
7
|
+
# steering read these three verbs from here rather than recognising "Governance" by name.
|
|
9
8
|
provides "authorization",
|
|
10
9
|
assignments: "RoleAssignment.AssignmentsForActor",
|
|
11
10
|
grant: "RoleAssignment.Assign",
|
|
@@ -14,12 +13,9 @@ Hecks.bluebook "Governance" do
|
|
|
14
13
|
aggregate "RoleAssignment" do
|
|
15
14
|
description "One actor holding one role, over one scope, from one point in time — revoked by setting when it ended, never deleted."
|
|
16
15
|
|
|
17
|
-
#
|
|
18
|
-
#
|
|
19
|
-
#
|
|
20
|
-
# adapter exists yet in this codebase to mint a synthetic id, and none
|
|
21
|
-
# is needed: `starts_at` already makes "this actor started holding this
|
|
22
|
-
# role at this time" unique on its own.
|
|
16
|
+
# The identity is the event, not the (actor, role) pair: an actor can hold a role again
|
|
17
|
+
# after a prior assignment ended, and that is a second assignment. `starts_at` makes each
|
|
18
|
+
# one unique.
|
|
23
19
|
attribute :actor_id, IdentityId
|
|
24
20
|
attribute :role_name, RoleName
|
|
25
21
|
attribute :scope, Scope
|
|
@@ -78,21 +74,10 @@ Hecks.bluebook "Governance" do
|
|
|
78
74
|
end
|
|
79
75
|
end
|
|
80
76
|
|
|
81
|
-
#
|
|
82
|
-
#
|
|
83
|
-
#
|
|
84
|
-
#
|
|
85
|
-
# revocation, no delete — and, like RoleAssignment, THE IDENTITY IS THE
|
|
86
|
-
# GRANT, not the (from_role, to_role) pair. `starts_at` used to be
|
|
87
|
-
# missing from here — the one field RoleAssignment's own identity adds
|
|
88
|
-
# beyond its own (actor, role) pair specifically so a second, later
|
|
89
|
-
# assignment is a SECOND real record rather than a collision. Without
|
|
90
|
-
# it, `identified_by :from_role, :to_role` alone made a revoked pair's
|
|
91
|
-
# own identity permanently occupied: `Grant` is a creating command, the
|
|
92
|
-
# same (from_role, to_role) pair is the SAME id forever, and a repeat
|
|
93
|
-
# `Grant` after a `Revoke` was refused as `AlreadyExists` no matter how
|
|
94
|
-
# long ago the prior grant ended — an absorbing "revoked" state this
|
|
95
|
-
# very comment already claimed didn't exist.
|
|
77
|
+
# Whether role X may act as role Y, which `act_as` needs before a caller dispatches under a
|
|
78
|
+
# role it does not hold. Same event-log shape as RoleAssignment, and the identity is the
|
|
79
|
+
# grant: without `starts_at`, a revoked pair would occupy its id forever and a repeat
|
|
80
|
+
# `Grant` would be refused as `AlreadyExists`.
|
|
96
81
|
aggregate "RoleTransition" do
|
|
97
82
|
description "Role X is authorized to act as role Y, from one point in time — until revoked, and grantable again afterward, exactly like RoleAssignment."
|
|
98
83
|
|
|
@@ -135,15 +120,9 @@ Hecks.bluebook "Governance" do
|
|
|
135
120
|
emits RoleTransitionRevoked
|
|
136
121
|
end
|
|
137
122
|
|
|
138
|
-
#
|
|
139
|
-
# `
|
|
140
|
-
#
|
|
141
|
-
# answers with every row and the CALLER reads `ends_at` to tell a
|
|
142
|
-
# live grant from a revoked one, exactly as it already must for
|
|
143
|
-
# every assignment. Can answer MORE than one row now that `starts_at`
|
|
144
|
-
# is part of the identity — a pair granted again after a revocation is
|
|
145
|
-
# a SECOND row, not an overwrite of the first, the same way a
|
|
146
|
-
# re-assigned actor/role is for RoleAssignment.
|
|
123
|
+
# Every grant of this pair, current or historical: `where` cannot ask "ends_at is absent",
|
|
124
|
+
# so the caller reads `ends_at` to tell a live grant from a revoked one. A pair granted
|
|
125
|
+
# again after a revocation is a second row.
|
|
147
126
|
query "Allowed" do
|
|
148
127
|
description "Every role transition granted for this exact pair, current or historical."
|
|
149
128
|
attribute :from_role, RoleName
|