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
|
@@ -1,23 +1,5 @@
|
|
|
1
|
-
#
|
|
2
|
-
#
|
|
3
|
-
# boots this directory directly (Ports::Loading.bootstrap + load_domain,
|
|
4
|
-
# the same pipeline lib/hecks/runtime/loader.rb uses, minus a
|
|
5
|
-
# `.world`/`.hecksagon` this domain has no need for) and dispatches one
|
|
6
|
-
# command against it before generating anything from a domain's own
|
|
7
|
-
# `deployed_to("AwsLambda")` settings.
|
|
8
|
-
#
|
|
9
|
-
# WHY THIS EXISTS: `world.bluebook`'s `Wiring`/`Setting` is a DELIBERATELY
|
|
10
|
-
# open, untyped map — "a verb's schema is not even contained in the file
|
|
11
|
-
# being parsed" (syntax.bluebook's own header on this). That's the right
|
|
12
|
-
# call for `Wiring` itself (an adapter verb's shape genuinely isn't the
|
|
13
|
-
# world language's business), but it leaves `deployed_to`'s ACTUAL shape
|
|
14
|
-
# validated nowhere — `bin/project_deploy` used to check it by hand
|
|
15
|
-
# (`deploy_settings[:adapter] == "AwsLambda" or abort ...`,
|
|
16
|
-
# `fetch(:region) { abort ... }`), the exact raw-Ruby-refusal pattern
|
|
17
|
-
# every other kind of bluebook mistake in this codebase does NOT use.
|
|
18
|
-
# This closes that gap the same way any other rule gets enforced here:
|
|
19
|
-
# as a real command, real invariants, a real corpus-testable refusal —
|
|
20
|
-
# not a hand-written abort string discovered only by running the script.
|
|
1
|
+
# Tooling-internal domain `bin/project_deploy` boots directly; never attached via `uses_framework`.
|
|
2
|
+
# It validates the `deployed_to` shape that `world.bluebook`'s untyped `Setting` map leaves open.
|
|
21
3
|
Hecks.bluebook "Deploy" do
|
|
22
4
|
aggregate "LambdaTarget" do
|
|
23
5
|
description "One domain's validated AWS Lambda deploy target — what deployed_to(\"AwsLambda\") must resolve to before bin/project_deploy generates anything from it."
|
|
@@ -41,77 +23,39 @@ Hecks.bluebook "Deploy" do
|
|
|
41
23
|
invariant("a region is named") { !value.to_s.empty? }
|
|
42
24
|
end
|
|
43
25
|
|
|
44
|
-
# "Postgres" (
|
|
45
|
-
#
|
|
46
|
-
#
|
|
47
|
-
#
|
|
48
|
-
#
|
|
49
|
-
# v2, Postgres-compatible — the SAME `Adapters::Postgres`/
|
|
50
|
-
# `tokio_postgres` code on both the Ruby and rust/host sides
|
|
51
|
-
# either way; this only changes which CloudFormation resource
|
|
52
|
-
# bin/project_deploy emits, never a runtime adapter).
|
|
53
|
-
# "Shared" — no RDS/VPC of this domain's own at all; it borrows
|
|
54
|
-
# another already-deployed domain's instance instead (the
|
|
55
|
-
# storehouse), isolated from that domain's own data by a native
|
|
56
|
-
# Postgres SCHEMA (this domain's own lowercase name), not a
|
|
57
|
-
# separate database. Requires a sibling `owner "OtherDomain"`
|
|
58
|
-
# setting inside the SAME deployed_to("AwsLambda") block, naming
|
|
59
|
-
# which already-deployed domain owns the shared instance —
|
|
60
|
-
# bin/project_deploy checks for that setting itself (Ruby-level,
|
|
61
|
-
# the same as `pg_version`/`google_oauth_present` below it), not
|
|
62
|
-
# here: which domain owns the instance is a deploy-time fact, not
|
|
63
|
-
# a business invariant this validated aggregate's job to hold.
|
|
26
|
+
# "Postgres" (plain RDS, the default when `deployed_to` names none) or "Aurora"
|
|
27
|
+
# (Serverless v2);
|
|
28
|
+
# only the emitted CloudFormation resource differs, never the runtime adapter. "Shared" borrows
|
|
29
|
+
# another domain's instance under its own Postgres schema and needs an `owner` setting, which
|
|
30
|
+
# `bin/project_deploy` checks, since the owning domain is a deploy-time fact.
|
|
64
31
|
value_object "Database" do
|
|
65
32
|
attribute :value, String, one_of: ["Postgres", "Aurora", "Shared"]
|
|
66
33
|
end
|
|
67
34
|
|
|
68
|
-
# "None" (the
|
|
69
|
-
#
|
|
70
|
-
#
|
|
71
|
-
# web UI in-process (rust/host/src/web.rs), reading HECKS_IR_PATH
|
|
72
|
-
# (a plain-JSON sidecar bin/project_wasm writes beside the .wasm
|
|
73
|
-
# artifact) and dispatching through the SAME in-process
|
|
74
|
-
# dispatch::handle/read the internal {"verb"}/{"read"} path already
|
|
75
|
-
# uses — no second Lambda, no VPC Interface Endpoint, no Ruby.
|
|
76
|
-
# Deliberately NOT "Ruby" as a third member here: a Ruby WebFunction
|
|
77
|
-
# is the pre-existing, SEPARATE `lambda_handler.rb`-file-presence
|
|
78
|
-
# mechanism (Embryonaut's own), untouched by this attribute —
|
|
79
|
-
# bin/project_deploy refuses generation outright if a domain
|
|
80
|
-
# declares `web "Rust"` AND has a `lambda_handler.rb`, rather than
|
|
81
|
-
# silently picking one.
|
|
35
|
+
# "None" (default) or "Rust": the domain's own Lambda (rust/host) also serves a public web UI
|
|
36
|
+
# in-process (rust/host/src/web.rs). "Ruby" is not a member: a Ruby WebFunction comes from a
|
|
37
|
+
# `lambda_handler.rb` file, and `bin/project_deploy` refuses `web "Rust"` alongside one.
|
|
82
38
|
value_object "Web" do
|
|
83
39
|
attribute :value, String, one_of: ["None", "Rust"]
|
|
84
40
|
end
|
|
85
41
|
|
|
86
|
-
# 128-10240 MB
|
|
87
|
-
# number this domain invented. A typo here used to fail deep inside
|
|
88
|
-
# a real `sam deploy`, sometimes minutes in; now it refuses before
|
|
89
|
-
# a single file is generated.
|
|
42
|
+
# 128-10240 MB, AWS Lambda's own floor and ceiling.
|
|
90
43
|
value_object "Memory" do
|
|
91
44
|
attribute :value, Integer
|
|
92
45
|
invariant("memory is at least 128 MB") { value >= 128 }
|
|
93
46
|
invariant("memory is at most 10240 MB") { value <= 10240 }
|
|
94
47
|
end
|
|
95
48
|
|
|
96
|
-
#
|
|
49
|
+
# Lambda's own ceiling of 900s.
|
|
97
50
|
value_object "Timeout" do
|
|
98
51
|
attribute :value, Integer
|
|
99
52
|
invariant("a timeout is positive") { value.positive? }
|
|
100
53
|
invariant("a timeout fits Lambda's own 900s ceiling") { value <= 900 }
|
|
101
54
|
end
|
|
102
55
|
|
|
103
|
-
#
|
|
104
|
-
#
|
|
105
|
-
# `
|
|
106
|
-
# `next unless normalized.key?(attribute.name)` skips coercion
|
|
107
|
-
# entirely for an absent key, so a command-level `default:` is
|
|
108
|
-
# honored ONLY at the JSON/Rust-codegen boundary (`scalar_from_json_
|
|
109
|
-
# expr`'s own domain), never by Ruby's own direct dispatch — a
|
|
110
|
-
# `default:` here would be quietly false advertising. "What memory
|
|
111
|
-
# defaults to when unspecified" stays exactly where it already
|
|
112
|
-
# lived (bin/project_deploy's own `fetch(:memory, 512)`); this
|
|
113
|
-
# command validates a FULLY-RESOLVED target, and bin/project_deploy
|
|
114
|
-
# resolves the default before ever dispatching.
|
|
56
|
+
# All required, no `default:`: command-level defaults apply only at the JSON/Rust-codegen
|
|
57
|
+
# boundary, not Ruby's direct dispatch (interpreting.rb `normalize_args`). Defaults are
|
|
58
|
+
# resolved by `bin/project_deploy` before it dispatches.
|
|
115
59
|
command "Declare" do
|
|
116
60
|
goal "Validate one domain's AwsLambda deploy target before anything is generated from it"
|
|
117
61
|
|
|
@@ -133,11 +77,8 @@ Hecks.bluebook "Deploy" do
|
|
|
133
77
|
end
|
|
134
78
|
end
|
|
135
79
|
|
|
136
|
-
# A sibling of `LambdaTarget
|
|
137
|
-
#
|
|
138
|
-
# `DomainName`/`Realm`/`Schema` below already make the same point), so
|
|
139
|
-
# this aggregate carries its own copies of `DomainName`/`Region`/
|
|
140
|
-
# `Database`/`Web` rather than reaching into `LambdaTarget`'s.
|
|
80
|
+
# A sibling of `LambdaTarget` with its own value objects, since value objects are not
|
|
81
|
+
# shared across aggregates.
|
|
141
82
|
aggregate "FargateTarget" do
|
|
142
83
|
description "One domain's validated AWS Fargate deploy target — what deployed_to(\"AwsFargate\") must resolve to before bin/project_deploy generates anything from it."
|
|
143
84
|
|
|
@@ -161,60 +102,40 @@ Hecks.bluebook "Deploy" do
|
|
|
161
102
|
invariant("a region is named") { !value.to_s.empty? }
|
|
162
103
|
end
|
|
163
104
|
|
|
164
|
-
#
|
|
165
|
-
#
|
|
166
|
-
# are a pairing `ECS` itself enforces at deploy time; encoding that
|
|
167
|
-
# whole table here would duplicate AWS's own rules for no benefit
|
|
168
|
-
# this generator needs. This only catches a typo (zero, negative)
|
|
169
|
-
# before a single file is generated, the same floor `Memory`/`Port`
|
|
170
|
-
# below hold for their own ranges.
|
|
105
|
+
# Positive only: ECS enforces AWS's cpu/memory pairings at deploy time, so this just
|
|
106
|
+
# catches a typo.
|
|
171
107
|
value_object "Cpu" do
|
|
172
108
|
attribute :value, Integer
|
|
173
109
|
invariant("cpu is positive") { value.positive? }
|
|
174
110
|
end
|
|
175
111
|
|
|
176
|
-
# Fargate's own
|
|
177
|
-
#
|
|
178
|
-
# that aggregate alone, so this is a distinct value object under the
|
|
179
|
-
# same name rather than a shared one. A plain sanity floor and
|
|
180
|
-
# ceiling, not AWS's own cpu-paired table (see `Cpu`'s own comment).
|
|
112
|
+
# Fargate's own range, not Lambda's 128-10240 MB. A sanity floor and ceiling, not AWS's
|
|
113
|
+
# cpu-paired table (see `Cpu`).
|
|
181
114
|
value_object "Memory" do
|
|
182
115
|
attribute :value, Integer
|
|
183
116
|
invariant("memory is positive") { value.positive? }
|
|
184
117
|
invariant("memory is at most 122880 MB") { value <= 122880 }
|
|
185
118
|
end
|
|
186
119
|
|
|
187
|
-
#
|
|
188
|
-
# "Postgres"/"Aurora" provision this domain's own RDS instance;
|
|
189
|
-
# "Shared" borrows another already-deployed domain's instance,
|
|
190
|
-
# isolated by a native Postgres schema. See that value object's own
|
|
191
|
-
# comment for the full reasoning; it applies unchanged here.
|
|
120
|
+
# As `LambdaTarget`'s `Database`.
|
|
192
121
|
value_object "Database" do
|
|
193
122
|
attribute :value, String, one_of: ["Postgres", "Aurora", "Shared"]
|
|
194
123
|
end
|
|
195
124
|
|
|
196
|
-
#
|
|
197
|
-
# means the domain's own task also serves its public web UI
|
|
198
|
-
# in-process, over the port this aggregate's own `Port` attribute
|
|
199
|
-
# declares.
|
|
125
|
+
# As `LambdaTarget`'s `Web`; "Rust" serves the web UI in-process on this aggregate's `Port`.
|
|
200
126
|
value_object "Web" do
|
|
201
127
|
attribute :value, String, one_of: ["None", "Rust"]
|
|
202
128
|
end
|
|
203
129
|
|
|
204
|
-
# The container port the task listens on and the target group
|
|
205
|
-
# routes to — a real TCP port, not an arbitrary integer.
|
|
130
|
+
# The container port the task listens on and the target group routes to.
|
|
206
131
|
value_object "Port" do
|
|
207
132
|
attribute :value, Integer
|
|
208
133
|
invariant("a port is at least 1") { value >= 1 }
|
|
209
134
|
invariant("a port is at most 65535") { value <= 65535 }
|
|
210
135
|
end
|
|
211
136
|
|
|
212
|
-
# All seven required
|
|
213
|
-
#
|
|
214
|
-
# comment on `normalize_args`/`coerce_declared_arguments`. This
|
|
215
|
-
# validates a fully-resolved target, after `bin/project_deploy`'s own
|
|
216
|
-
# defaulting (`cpu`/`memory`/`port` each fall back to a Ruby-side
|
|
217
|
-
# default before this ever dispatches), not instead of it.
|
|
137
|
+
# All seven required for the same reason as `LambdaTarget.Declare`; this validates a
|
|
138
|
+
# target already resolved by `bin/project_deploy`'s defaults.
|
|
218
139
|
command "Declare" do
|
|
219
140
|
goal "Validate one domain's AwsFargate deploy target before anything is generated from it"
|
|
220
141
|
|
|
@@ -238,24 +159,8 @@ Hecks.bluebook "Deploy" do
|
|
|
238
159
|
end
|
|
239
160
|
end
|
|
240
161
|
|
|
241
|
-
# `bin/project_tenant
|
|
242
|
-
#
|
|
243
|
-
# script GENERATES/ACTS (writes `environments/<slug>.world`, ensures
|
|
244
|
-
# the Postgres schema, boots once to prove it). Deliberately NOT a
|
|
245
|
-
# saga/process manager with durable runtime state — every step
|
|
246
|
-
# `bin/project_tenant` takes is already idempotent by construction
|
|
247
|
-
# (`CREATE SCHEMA IF NOT EXISTS` — PostgresEra#connect_for's own,
|
|
248
|
-
# File.write of the overlay — a plain overwrite, `Hecks.boot` itself),
|
|
249
|
-
# the same "generator script, not a business process" shape
|
|
250
|
-
# `bin/project_deploy` already is; a saga's own resumability earns
|
|
251
|
-
# its cost coordinating a real distributed transaction across
|
|
252
|
-
# multiple ports with real failure boundaries (Payments::Payment's
|
|
253
|
-
# own PaymentGateway, say) — three local, idempotent, single-process
|
|
254
|
-
# steps have no such boundary to resume across. A durable, reactable
|
|
255
|
-
# RUNTIME fact ("this tenant exists, is active, is suspended") is a
|
|
256
|
-
# different, later, business-facing thing — deliberately not built
|
|
257
|
-
# here, and deliberately not named Deploy::Tenant to avoid colliding
|
|
258
|
-
# with this validation-only aggregate should it ever land.
|
|
162
|
+
# The validated shape of `bin/project_tenant`, which does the generating and provisioning.
|
|
163
|
+
# Not a saga: each of its steps is idempotent and local, so there is nothing to resume.
|
|
259
164
|
aggregate "Tenant" do
|
|
260
165
|
description "One tenant's validated identity — which realm and Postgres schema `bin/project_tenant` provisions before booting a domain directory under Runtime.boot's own `environment:` overlay for it."
|
|
261
166
|
|
|
@@ -266,11 +171,8 @@ Hecks.bluebook "Deploy" do
|
|
|
266
171
|
attribute :realm, Realm
|
|
267
172
|
attribute :schema, Schema
|
|
268
173
|
|
|
269
|
-
#
|
|
270
|
-
#
|
|
271
|
-
# `schema` is its own, separately-declared field precisely so a
|
|
272
|
-
# tenant CAN choose a different schema name than its slug)
|
|
273
|
-
# ordinarily the schema name too.
|
|
174
|
+
# Lowercase, no spaces: a slug becomes the `environments/<slug>.world` filename and, by
|
|
175
|
+
# convention only, the schema name (`schema` is separate so a tenant can differ).
|
|
274
176
|
value_object "Slug" do
|
|
275
177
|
attribute :value, String, pattern: '^[a-z][a-z0-9_]*$'
|
|
276
178
|
invariant("a tenant slug is named") { !value.to_s.empty? }
|
|
@@ -286,20 +188,9 @@ Hecks.bluebook "Deploy" do
|
|
|
286
188
|
invariant("a tenant realm is named") { !value.to_s.empty? }
|
|
287
189
|
end
|
|
288
190
|
|
|
289
|
-
#
|
|
290
|
-
#
|
|
291
|
-
#
|
|
292
|
-
# NOT a byte-length ceiling too (Postgres's own real 63-byte
|
|
293
|
-
# NAMEDATALEN limit) — the expression grammar invariants compile
|
|
294
|
-
# through admits a narrow arithmetic/comparison subset, not
|
|
295
|
-
# arbitrary method dispatch (`bytesize` included; found live,
|
|
296
|
-
# writing this: `Bluebook::Expression::Evaluator` tries to resolve
|
|
297
|
-
# a dotted chain as a FIELD lookup, not a method call, the same
|
|
298
|
-
# "admits + but not -, no parentheses" narrowness
|
|
299
|
-
# embryonaut_bluebooks/payments' own Refund command already
|
|
300
|
-
# documents). Postgres itself refuses a too-long identifier loudly
|
|
301
|
-
# on its own; not worth fighting the expression grammar for a
|
|
302
|
-
# corner case this rare.
|
|
191
|
+
# Lowercase, letters/digits/underscores, starting with a letter. Postgres's 63-byte
|
|
192
|
+
# identifier limit is not checked: the invariant expression grammar has no `bytesize`, and
|
|
193
|
+
# Postgres refuses a too-long identifier itself.
|
|
303
194
|
value_object "Schema" do
|
|
304
195
|
attribute :value, String, pattern: '^[a-z][a-z0-9_]*$'
|
|
305
196
|
invariant("a schema is named") { !value.to_s.empty? }
|
|
@@ -2,15 +2,8 @@
|
|
|
2
2
|
Hecks.hecksagon "Deploy" do
|
|
3
3
|
persisted_by "Memory"
|
|
4
4
|
|
|
5
|
-
#
|
|
6
|
-
#
|
|
7
|
-
# the request; `TenantProvisioner` (lib/hecks/adapters/driven/
|
|
8
|
-
# tenant_provisioner.rb) writes the overlay file and answers or
|
|
9
|
-
# refuses. `database`/`adapter`/`directory` are declared here, not on
|
|
10
|
-
# `Tenant` itself — CLI-only facts this validated request never
|
|
11
|
-
# needed to hold as its own state. `directory` is the real
|
|
12
|
-
# filesystem path being provisioned — NOT re-derivable from `Tenant`'s
|
|
13
|
-
# own `domain` (its declared NAME, e.g. "Scratch", never a path).
|
|
5
|
+
# `bin/project_tenant` dispatches this after `Tenant.Declare` validates; `directory` is a real
|
|
6
|
+
# filesystem path, which `Tenant`'s declared `domain` name cannot supply.
|
|
14
7
|
Deploy::Tenant.port "TenantProvisioning" do
|
|
15
8
|
asks "Provision", to: Tenant do
|
|
16
9
|
attribute :database, DatabaseName
|
|
@@ -2,31 +2,10 @@ require "digest"
|
|
|
2
2
|
|
|
3
3
|
module Hecks
|
|
4
4
|
module EmbryonautBluebook
|
|
5
|
-
#
|
|
6
|
-
#
|
|
7
|
-
#
|
|
8
|
-
# ## File format
|
|
9
|
-
#
|
|
10
|
-
# One `key: value` line each for `package`, `version`, `tag`, `commit`
|
|
11
|
-
# and `digest`, then one `shape: <Domain> <label>` line per domain:
|
|
12
|
-
#
|
|
13
|
-
# package: payments
|
|
14
|
-
# version: 1.2.0
|
|
15
|
-
# tag: payments-v1.2.0
|
|
16
|
-
# commit: <full commit id the tag points at>
|
|
17
|
-
# digest: <sha256 of the vendored *.bluebook files>
|
|
18
|
-
# shape: Payments d33c23
|
|
19
|
-
#
|
|
20
|
-
# The digest is the sha256 of the `<sha256> <name>` lines of every
|
|
21
|
-
# top-level `*.bluebook` file, sorted by name. The source repository's own
|
|
22
|
-
# `bin/bluebook_digest` prints the same number for the tagged release, which
|
|
23
|
-
# is how a vendored copy is proven to be exactly what it claims to be.
|
|
5
|
+
# The digest here must match the source repo's own bin/bluebook_digest
|
|
6
|
+
# output for the same tag, or a vendored copy cannot be trusted.
|
|
24
7
|
Lock = Struct.new(:package, :version, :tag, :commit, :digest, :shape, keyword_init: true) do
|
|
25
|
-
#
|
|
26
|
-
#
|
|
27
|
-
# @param dir [String] the directory to measure
|
|
28
|
-
# @return [String, nil] 64 lowercase hex characters, nil when the directory holds
|
|
29
|
-
# no bluebook file
|
|
8
|
+
# Sorted by name so the digest never depends on directory listing order.
|
|
30
9
|
def self.digest_of(dir)
|
|
31
10
|
names = Dir.children(dir).select { |name| name.end_with?(".bluebook") }.sort
|
|
32
11
|
return nil if names.empty?
|
|
@@ -35,20 +14,12 @@ module Hecks
|
|
|
35
14
|
Digest::SHA256.hexdigest(lines.join)
|
|
36
15
|
end
|
|
37
16
|
|
|
38
|
-
# Reads a lock file.
|
|
39
|
-
#
|
|
40
|
-
# @param path [String] the `bluebook.lock` path
|
|
41
|
-
# @return [Lock, nil] the parsed lock, nil when the file does not exist
|
|
42
17
|
def self.read(path)
|
|
43
18
|
return nil unless File.file?(path)
|
|
44
19
|
|
|
45
20
|
parse(File.read(path))
|
|
46
21
|
end
|
|
47
22
|
|
|
48
|
-
# Parses a lock's text.
|
|
49
|
-
#
|
|
50
|
-
# @param text [String] the file's content
|
|
51
|
-
# @return [Lock] the lock, with `shape` as an Array of lines (empty when none)
|
|
52
23
|
def self.parse(text)
|
|
53
24
|
fields = { shape: [] }
|
|
54
25
|
text.each_line do |line|
|
|
@@ -60,9 +31,6 @@ module Hecks
|
|
|
60
31
|
new(**fields.slice(*members))
|
|
61
32
|
end
|
|
62
33
|
|
|
63
|
-
# Renders the lock as the text written to `bluebook.lock`.
|
|
64
|
-
#
|
|
65
|
-
# @return [String] the lines described above, newline terminated
|
|
66
34
|
def to_s
|
|
67
35
|
header = %i[package version tag commit digest].map { |key| "#{key}: #{self[key]}\n" }
|
|
68
36
|
(header + Array(shape).map { |line| "shape: #{line}\n" }).join
|
|
@@ -2,21 +2,10 @@ require_relative "../ports/persistence/plugins/era/storage_shape"
|
|
|
2
2
|
|
|
3
3
|
module Hecks
|
|
4
4
|
module EmbryonautBluebook
|
|
5
|
-
#
|
|
6
|
-
#
|
|
7
|
-
# A label is what `PostgresEra` mints an era from, so a vendored package
|
|
8
|
-
# whose label changed is one whose next deploy mints a new era. This reads
|
|
9
|
-
# the files the way the era guard reads a held era's text: parse only, no
|
|
10
|
-
# boot, no wiring, no database, each file loaded into a scratch registry.
|
|
5
|
+
# A label change here means a vendored package's next deploy mints a new PostgresEra.
|
|
11
6
|
module Shape
|
|
12
7
|
module_function
|
|
13
8
|
|
|
14
|
-
# Measures every domain a directory's bluebook files declare.
|
|
15
|
-
#
|
|
16
|
-
# @param dir [String] a directory holding `*.bluebook` files
|
|
17
|
-
# @return [Array<String>] one `"<Domain> <label>"` line per domain, sorted by domain name
|
|
18
|
-
# @raise [Vendoring::Error] if the directory holds no bluebook file, or the files do
|
|
19
|
-
# not load, the refusal a boot would raise
|
|
20
9
|
def labels(dir)
|
|
21
10
|
files = Dir[File.join(dir, "*.bluebook")]
|
|
22
11
|
raise Vendoring::Error, "no *.bluebook files in #{dir}" if files.empty?
|
|
@@ -26,11 +15,6 @@ module Hecks
|
|
|
26
15
|
end
|
|
27
16
|
end
|
|
28
17
|
|
|
29
|
-
# Loads bluebook files into a registry of their own.
|
|
30
|
-
#
|
|
31
|
-
# @param files [Array<String>] absolute bluebook file paths, in load order
|
|
32
|
-
# @return [Runtime::Registry] the scratch registry holding what the files declared
|
|
33
|
-
# @raise [Vendoring::Error] if any file fails to load
|
|
34
18
|
def load_all(files)
|
|
35
19
|
scratch = Runtime::Registry.new
|
|
36
20
|
library = Ports::Loading.bootstrap
|
|
@@ -5,32 +5,8 @@ require_relative "shape"
|
|
|
5
5
|
|
|
6
6
|
module Hecks
|
|
7
7
|
module EmbryonautBluebook
|
|
8
|
-
#
|
|
9
|
-
#
|
|
10
|
-
# ## What it does
|
|
11
|
-
#
|
|
12
|
-
# Pins the package's top-level `bluebook/*.bluebook` files from one commit
|
|
13
|
-
# of a local source repository into
|
|
14
|
-
# `<root>/vendor/embryonaut_bluebooks/<name>/bluebook/`, where `load!`
|
|
15
|
-
# resolves them. Only bluebook files are taken: a `.hecksagon`, `.port` or
|
|
16
|
-
# `.adapter` is a wiring decision for whoever deploys, never part of the
|
|
17
|
-
# vendored package.
|
|
18
|
-
#
|
|
19
|
-
# ## Releases and bare commits
|
|
20
|
-
#
|
|
21
|
-
# The source repository tags each release `<name>-v<X.Y.Z>` on a commit
|
|
22
|
-
# whose `<name>/bluebook.yml` says that version. A release pin (`ref` nil for
|
|
23
|
-
# the newest tag, `"1.2.0"`, or the tag name) also writes `bluebook.lock`,
|
|
24
|
-
# which records version, tag, commit, content digest and storage shape, and
|
|
25
|
-
# holds two refusals, because a production project is bound to `PostgresEra`:
|
|
26
|
-
#
|
|
27
|
-
# - a version lower than the vendored one, unless `allow_downgrade`;
|
|
28
|
-
# - a storage-shape change that does not raise the version by at least a
|
|
29
|
-
# minor, so a new era shows in the version number and not only in a hash.
|
|
30
|
-
#
|
|
31
|
-
# Any other commit-ish pins that commit and writes only the marker, with no
|
|
32
|
-
# lock and no version checks. Either way nothing on disk changes when a
|
|
33
|
-
# pin is refused or its files do not load.
|
|
8
|
+
# Pins a package's `bluebook/*.bluebook` files from a source repo commit; a
|
|
9
|
+
# release pin also refuses a downgrade or an era-breaking storage-shape change.
|
|
34
10
|
class Vendor
|
|
35
11
|
# A release version, `X.Y.Z`.
|
|
36
12
|
VERSION = /\A\d+\.\d+\.\d+\z/
|
|
@@ -38,33 +14,17 @@ module Hecks
|
|
|
38
14
|
# A package name is a directory name and a bluebook name stem.
|
|
39
15
|
NAME = /\A[a-z][a-z0-9_]*\z/
|
|
40
16
|
|
|
41
|
-
# What a vendoring changed
|
|
42
|
-
#
|
|
43
|
-
# @!attribute [r] previous_version
|
|
44
|
-
# @return [String, nil] the version recorded before, nil when there was none
|
|
45
|
-
# @!attribute [r] previous_shape
|
|
46
|
-
# @return [Array<String>, nil] the shape lines measured before, nil when there was
|
|
47
|
-
# no earlier copy
|
|
17
|
+
# What a vendoring changed; previous_version/previous_shape are nil when
|
|
18
|
+
# there was no earlier vendored copy.
|
|
48
19
|
Result = Struct.new(:package, :commit, :version, :tag, :digest, :shape,
|
|
49
20
|
:previous_version, :previous_shape, :dir, keyword_init: true) do
|
|
50
|
-
# Says whether this was a release pin, which writes a lock.
|
|
51
|
-
#
|
|
52
|
-
# @return [Boolean] true for a release, false for a bare commit
|
|
53
21
|
def release? = !tag.nil?
|
|
54
22
|
|
|
55
|
-
# Says whether the storage shape moved since the earlier copy.
|
|
56
|
-
#
|
|
57
|
-
# @return [Boolean] true when an earlier copy existed and its shape differs
|
|
58
23
|
def shape_changed? = !previous_shape.nil? && previous_shape != shape
|
|
59
24
|
end
|
|
60
25
|
|
|
61
|
-
#
|
|
62
|
-
#
|
|
63
|
-
# @param ref [String, nil] `X.Y.Z`, a release tag name, any commit-ish, or nil for the
|
|
64
|
-
# newest release
|
|
65
|
-
# @param root [String] the consuming project's root
|
|
66
|
-
# @param allow_downgrade [Boolean] whether a release older than the vendored one is allowed
|
|
67
|
-
# @raise [Vendoring::Error] if the name is not a plain package name
|
|
26
|
+
# `ref` accepts `X.Y.Z`, a release tag name, any commit-ish, or nil for
|
|
27
|
+
# the newest release.
|
|
68
28
|
def initialize(name, from:, root:, ref: nil, allow_downgrade: false)
|
|
69
29
|
@name = name.to_s
|
|
70
30
|
raise Vendoring::Error, "#{name.inspect} is not a package name" unless @name.match?(NAME)
|
|
@@ -76,10 +36,6 @@ module Hecks
|
|
|
76
36
|
end
|
|
77
37
|
|
|
78
38
|
# Pins the package and reports what changed.
|
|
79
|
-
#
|
|
80
|
-
# @return [Result] the commit, version and shape now vendored
|
|
81
|
-
# @raise [Vendoring::Error] if the release or commit is not found, the tagged commit
|
|
82
|
-
# disagrees with its own version, the files do not load, or a refusal above applies
|
|
83
39
|
def call
|
|
84
40
|
tag, version = release
|
|
85
41
|
previous_version, previous_shape = existing
|
|
@@ -99,9 +55,8 @@ module Hecks
|
|
|
99
55
|
|
|
100
56
|
def package_dir = File.join(@root, "vendor", "embryonaut_bluebooks", @name)
|
|
101
57
|
|
|
102
|
-
# Resolves what `ref` asks for into a release tag and its version
|
|
103
|
-
#
|
|
104
|
-
# @return [Array(String, String), nil] tag and version for a release, nil for a bare commit
|
|
58
|
+
# Resolves what `ref` asks for into a release tag and its version, or nil
|
|
59
|
+
# for a bare commit.
|
|
105
60
|
def release
|
|
106
61
|
tag = release_tag
|
|
107
62
|
return nil unless tag
|
|
@@ -3,21 +3,10 @@ require_relative "vendor"
|
|
|
3
3
|
|
|
4
4
|
module Hecks
|
|
5
5
|
module EmbryonautBluebook
|
|
6
|
-
# The command line behind `bin/vendor_bluebook
|
|
6
|
+
# The command line behind `bin/vendor_bluebook`; lives in the gem so a
|
|
7
|
+
# consuming project reaches it through its own bundle, no script to copy.
|
|
7
8
|
#
|
|
8
|
-
#
|
|
9
|
-
# through its own bundle without a copy of the script:
|
|
10
|
-
#
|
|
11
|
-
# bundle exec ruby -rhecks \
|
|
12
|
-
# -e 'exit Hecks::EmbryonautBluebook::VendorCli.run(ARGV)' payments@1.2.0
|
|
13
|
-
#
|
|
14
|
-
# ## Usage
|
|
15
|
-
#
|
|
16
|
-
# vendor_bluebook <package>[@<version-or-commit>] [--from <path>] [--root <path>]
|
|
17
|
-
#
|
|
18
|
-
# `--from` defaults to `$EMBRYONAUT_BLUEBOOKS_SRC` and `--root` to the current
|
|
19
|
-
# directory. `ALLOW_DOWNGRADE=1` in the environment permits a release older
|
|
20
|
-
# than the vendored one.
|
|
9
|
+
# vendor_bluebook <package>[@<version-or-commit>] [--from path] [--root path]
|
|
21
10
|
module VendorCli
|
|
22
11
|
USAGE = "usage: vendor_bluebook <package>[@<version-or-commit>] [--from PATH] [--root PATH]".freeze
|
|
23
12
|
|
|
@@ -44,11 +33,7 @@ module Hecks
|
|
|
44
33
|
1
|
|
45
34
|
end
|
|
46
35
|
|
|
47
|
-
#
|
|
48
|
-
#
|
|
49
|
-
# @param argv [Array<String>] the command-line arguments
|
|
50
|
-
# @param options [Hash{Symbol => String}] receives `:from` and `:root` when given
|
|
51
|
-
# @return [String, nil] the one positional argument, nil unless exactly one was given
|
|
36
|
+
# nil unless argv held exactly one positional argument.
|
|
52
37
|
def self.parse(argv, options)
|
|
53
38
|
parser = OptionParser.new
|
|
54
39
|
parser.on("--from PATH") { |path| options[:from] = path }
|
|
@@ -1,75 +1,6 @@
|
|
|
1
1
|
module Hecks
|
|
2
|
-
# A vendored, external bluebook
|
|
3
|
-
#
|
|
4
|
-
# ## What it is
|
|
5
|
-
#
|
|
6
|
-
# Same shape as Framework (framework.rb), for members that don't ship
|
|
7
|
-
# inside hecks's own lib/ at all: a separate, independently-versioned
|
|
8
|
-
# package (github.com/chrisyoung/embryonaut_bluebooks) that a consuming
|
|
9
|
-
# project vendors into its own checkout, the same way a project already
|
|
10
|
-
# vendors hecks itself (bin/vendor_hecks, vendor/hecks/).
|
|
11
|
-
#
|
|
12
|
-
# ## Recovered, not rebuilt
|
|
13
|
-
#
|
|
14
|
-
# This module and its `uses_embryonaut_bluebook`
|
|
15
|
-
# DSL word (hecksagon_builder.rb) were built on a prior commit of this
|
|
16
|
-
# repo (933d1dd), vendored out to a real consumer (a client site's domain,
|
|
17
|
-
# for embryonaut_bluebooks/payments), and then lost from this repo's own
|
|
18
|
-
# reachable history — a hard reset or rebase left no branch containing
|
|
19
|
-
# that commit. The consumer's vendor snapshot (a `git archive` of that
|
|
20
|
-
# commit, committed into their repo) was the only surviving copy; this
|
|
21
|
-
# file is ported forward from it, checked against current `main`'s own
|
|
22
|
-
# conventions rather than copied wholesale, since the two trees had
|
|
23
|
-
# otherwise diverged for weeks in both directions.
|
|
24
|
-
#
|
|
25
|
-
# ## Resolution
|
|
26
|
-
#
|
|
27
|
-
# Resolved from the consuming registry's own root, not this gem's
|
|
28
|
-
# __dir__ — Framework::ROOT can be a fixed, `__dir__`-relative constant
|
|
29
|
-
# because framework members ship inside this gem; an embryonaut bluebook
|
|
30
|
-
# ships inside the consumer's own checkout instead, at
|
|
31
|
-
# `<registry.root>/vendor/embryonaut_bluebooks/<name>/bluebook/`. There
|
|
32
|
-
# is no fixed answer until a registry (and its root) actually exists, so
|
|
33
|
-
# this resolves lazily, per call — the same reason `uses_framework`
|
|
34
|
-
# itself only runs at hecksagon-build time, when a real registry is
|
|
35
|
-
# current.
|
|
36
|
-
#
|
|
37
|
-
# ## Load order
|
|
38
|
-
#
|
|
39
|
-
# Every `.bluebook` file in the package, sorted — not just one. Unlike a
|
|
40
|
-
# framework member (one file, named by its own stem), a vendored package
|
|
41
|
-
# can span several bluebook files that reopen the same `Hecks.bluebook`
|
|
42
|
-
# (embryonaut_bluebooks/payments/bluebook/{payment,payments,policies}
|
|
43
|
-
# .bluebook all reopen "Payments"). Load order matters — policies
|
|
44
|
-
# .bluebook names `Payment::Succeed` and needs the aggregate already
|
|
45
|
-
# built — and a plain alphabetical sort already gives the right order:
|
|
46
|
-
# payment < payments < policies, the same reason that package's own
|
|
47
|
-
# files are named to fall in that order in the first place.
|
|
48
|
-
#
|
|
49
|
-
# ## Scope
|
|
50
|
-
#
|
|
51
|
-
# Only the bluebook files — same restriction Framework draws, same
|
|
52
|
-
# reason: a `.hecksagon`/`.port`/`.adapter` is a wiring decision
|
|
53
|
-
# (persistence, which processor adapter is bound) that belongs to
|
|
54
|
-
# whoever is deploying, never baked into the vendored package itself.
|
|
55
|
-
# embryonaut_bluebooks/payments ships its own mock `.hecksagon` for its
|
|
56
|
-
# own spec suite; a consumer declares its own separate
|
|
57
|
-
# `Hecks.hecksagon "Payments" do ... end` to bind real storage/adapters
|
|
58
|
-
# — see Framework's own comment for the fuller reasoning, identical here.
|
|
59
|
-
#
|
|
60
|
-
# ## Idempotency
|
|
61
|
-
#
|
|
62
|
-
# Idempotent the same way `Framework.load!` is — checked against the
|
|
63
|
-
# bluebook this package actually declares (`Naming.pascal("payments")`
|
|
64
|
-
# => "Payments"), not a separate ledger. A vendored package's directory
|
|
65
|
-
# name and its declared `Hecks.bluebook` name are the one convention
|
|
66
|
-
# this reuses from Framework rather than reinventing.
|
|
67
|
-
#
|
|
68
|
-
# ## Vendoring
|
|
69
|
-
#
|
|
70
|
-
# `vendor!` is the other direction: it pins a package from a local checkout
|
|
71
|
-
# of the registry into a consuming project's own `vendor/` tree, and is the
|
|
72
|
-
# one implementation behind `bin/vendor_bluebook` (see Vendoring and Vendor).
|
|
2
|
+
# A vendored, external bluebook: same shape as Framework, but for a
|
|
3
|
+
# package that ships outside hecks's own lib/ (see .load! and .vendor!).
|
|
73
4
|
module EmbryonautBluebook
|
|
74
5
|
autoload :Lock, File.join(__dir__, "embryonaut_bluebook/lock")
|
|
75
6
|
autoload :Shape, File.join(__dir__, "embryonaut_bluebook/shape")
|
|
@@ -103,6 +34,8 @@ module Hecks
|
|
|
103
34
|
"vendor it with bin/vendor_bluebook #{name}"
|
|
104
35
|
end
|
|
105
36
|
|
|
37
|
+
# Loaded in the glob's alphabetical order; a package with several
|
|
38
|
+
# files that reopen the same bluebook is named to rely on that.
|
|
106
39
|
files.each { |file| Kernel.load(file) }
|
|
107
40
|
end
|
|
108
41
|
|