hecks 3.10.0 → 3.12.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/examples/pizzas/bluebook/pizzas.bluebook +29 -0
- data/examples/pizzas/bluebook/pizzas.hecksagon +7 -0
- data/exe/hecks +4 -4
- data/lib/hecks/adapters/driven/d1.rb +2 -10
- data/lib/hecks/adapters/driven/heki.adapter +1 -1
- data/lib/hecks/adapters/driven/heki.rb +2 -12
- data/lib/hecks/adapters/driven/lambda.adapter +1 -1
- data/lib/hecks/adapters/driven/lambda.rb +3 -18
- data/lib/hecks/adapters/driven/postgres.rb +4 -11
- data/lib/hecks/adapters/driven/sqlite.adapter +1 -1
- data/lib/hecks/adapters/driven/sqlite.rb +2 -10
- data/lib/hecks/adapters/driving/admission.rb +46 -0
- data/lib/hecks/adapters/driving/cli/nesting.rb +36 -0
- data/lib/hecks/adapters/driving/cli/shorthand.rb +88 -0
- data/lib/hecks/adapters/driving/cli.rb +127 -0
- data/lib/hecks/adapters/driving/cli_runner/answers.rb +160 -0
- data/lib/hecks/adapters/driving/cli_runner/resolution.rb +158 -0
- data/lib/hecks/adapters/driving/cli_runner/settling.rb +120 -0
- data/lib/hecks/adapters/driving/cli_runner/streaming.rb +93 -0
- data/lib/hecks/adapters/driving/cli_runner/suggestions.rb +47 -0
- data/lib/hecks/adapters/driving/cli_runner.rb +70 -0
- data/lib/hecks/adapters/driving/command_request.rb +121 -0
- data/lib/hecks/adapters/driving/handle.rb +214 -0
- data/lib/hecks/adapters/driving/json.rb +136 -0
- data/lib/hecks/adapters/driving/launcher_options.rb +267 -0
- data/lib/hecks/adapters/driving/mcp/properties.rb +49 -0
- data/lib/hecks/adapters/driving/mcp/tool_calls.rb +116 -0
- data/lib/hecks/adapters/driving/mcp/tool_definitions/auditing.rb +53 -0
- data/lib/hecks/adapters/driving/mcp/tool_definitions/calling.rb +71 -0
- data/lib/hecks/adapters/driving/mcp/tool_definitions/reading.rb +99 -0
- data/lib/hecks/adapters/driving/mcp/tool_definitions.rb +18 -0
- data/lib/hecks/adapters/driving/mcp.rb +159 -0
- data/lib/hecks/adapters/driving/mcp_guide_cache.rb +78 -0
- data/lib/hecks/adapters/driving/mcp_scope/argument_policy.rb +97 -0
- data/lib/hecks/adapters/driving/mcp_scope/env_problems.rb +69 -0
- data/lib/hecks/adapters/driving/mcp_scope/presenter.rb +83 -0
- data/lib/hecks/adapters/driving/mcp_scope.rb +213 -0
- data/lib/hecks/adapters/driving/newcomer.rb +50 -0
- data/lib/hecks/adapters/driving/ruby/aggregate_module.rb +171 -0
- data/lib/hecks/adapters/driving/ruby/chapter.rb +91 -0
- data/lib/hecks/adapters/driving/ruby.rb +83 -0
- data/lib/hecks/adapters/driving/usage_cache.rb +144 -0
- data/lib/hecks/{doors.rb → adapters/driving.rb} +10 -6
- data/lib/hecks/behaviors/expectations/boot.rb +1 -1
- data/lib/hecks/bench/ruby_runner.rb +1 -1
- data/lib/hecks/bluebook/ask_resolution.rb +130 -0
- data/lib/hecks/bluebook/assembly/aggregate_assembly.rb +8 -2
- data/lib/hecks/bluebook/assembly/contracts/read_models.rb +1 -1
- data/lib/hecks/bluebook/assembly/contracts/rules.rb +4 -2
- data/lib/hecks/bluebook/assembly/contracts/structure.rb +3 -1
- data/lib/hecks/bluebook/assembly/marks.rb +4 -15
- data/lib/hecks/bluebook/assembly/scalars.rb +39 -0
- data/lib/hecks/bluebook/attribute.rb +1 -1
- data/lib/hecks/bluebook/behaviour/command.rb +13 -8
- data/lib/hecks/bluebook/behaviour/policy.rb +30 -0
- data/lib/hecks/bluebook/capabilities/attribute_values.rb +72 -0
- data/lib/hecks/bluebook/capabilities.rb +91 -9
- data/lib/hecks/bluebook/domain_port.rb +16 -4
- data/lib/hecks/bluebook/dsl/adapter_builder.rb +18 -6
- data/lib/hecks/bluebook/dsl/binding_proxy.rb +13 -0
- data/lib/hecks/bluebook/dsl/bluebook_builder/validation/computed_sources.rb +98 -0
- data/lib/hecks/bluebook/dsl/bluebook_builder/validation/fan_out_rows.rb +42 -0
- data/lib/hecks/bluebook/dsl/bluebook_builder/validation/projected_fields.rb +14 -2
- data/lib/hecks/bluebook/dsl/bluebook_builder/validation/provisions.rb +69 -3
- data/lib/hecks/bluebook/dsl/bluebook_builder/validation/with_projections.rb +17 -10
- data/lib/hecks/bluebook/dsl/bluebook_builder/validation.rb +5 -0
- data/lib/hecks/bluebook/dsl/bootstrap_table.rb +2 -0
- data/lib/hecks/bluebook/dsl/command_builder/mutations.rb +8 -1
- data/lib/hecks/bluebook/dsl/command_builder/operands.rb +121 -0
- data/lib/hecks/bluebook/dsl/command_builder.rb +2 -0
- data/lib/hecks/bluebook/dsl/hecksagon_builder.rb +10 -1
- data/lib/hecks/bluebook/dsl/lifecycle_builder.rb +45 -2
- data/lib/hecks/bluebook/dsl/policy_builder.rb +47 -10
- data/lib/hecks/bluebook/dsl/rule_reference.rb +7 -4
- data/lib/hecks/bluebook/dsl/world_builder.rb +1 -1
- data/lib/hecks/bluebook/expression/ast_json/emitters.rb +6 -0
- data/lib/hecks/bluebook/expression/ast_json.rb +9 -6
- data/lib/hecks/bluebook/expression/ast_reader.rb +14 -9
- data/lib/hecks/bluebook/expression/projection.json +36 -0
- data/lib/hecks/bluebook/expression/resolver/operations.rb +31 -0
- data/lib/hecks/bluebook/expression/resolver/parsing.rb +38 -5
- data/lib/hecks/bluebook/expression/resolver/scanning.rb +22 -5
- data/lib/hecks/bluebook/expression/resolver/values.rb +10 -0
- data/lib/hecks/bluebook/expression/resolver.rb +20 -1
- data/lib/hecks/bluebook/hecksagon.rb +23 -3
- data/lib/hecks/bluebook/lifecycle.rb +22 -3
- data/lib/hecks/bluebook/meta_validator/adapter_judge.rb +13 -1
- data/lib/hecks/bluebook/meta_validator/modes.rb +4 -1
- data/lib/hecks/bluebook/meta_validator/readings.rb +24 -1
- data/lib/hecks/bluebook/meta_validator/reconstruction/heads.rb +2 -1
- data/lib/hecks/bluebook/meta_validator/reconstruction.rb +6 -3
- data/lib/hecks/bluebook/meta_validator/shapes.rb +5 -0
- data/lib/hecks/bluebook/meta_validator/verdict_cache.rb +1 -1
- data/lib/hecks/bluebook/meta_validator.rb +12 -12
- data/lib/hecks/bluebook/model_check/ask_checks.rb +71 -0
- data/lib/hecks/bluebook/model_check/policy_checks.rb +2 -1
- data/lib/hecks/bluebook/model_check/reference_checks.rb +70 -0
- data/lib/hecks/bluebook/model_check.rb +8 -2
- data/lib/hecks/bluebook/policy.rb +4 -2
- data/lib/hecks/bluebook/smoke_test.rb +1 -1
- data/lib/hecks/bluebook/synthesizer.rb +2 -0
- data/lib/hecks/bluebook.rb +2 -0
- data/lib/hecks/cli/command_table.rb +1 -1
- data/lib/hecks/cli/console.rb +2 -1
- data/lib/hecks/cli/document.rb +1 -1
- data/lib/hecks/cli/launcher_words.rb +4 -4
- data/lib/hecks/cli/mcp.rb +4 -4
- data/lib/hecks/cli/project_cli/launcher_source.rb +2 -2
- data/lib/hecks/cli/project_cli/templates.rb +5 -5
- data/lib/hecks/cli/project_cli.rb +9 -6
- data/lib/hecks/cli/run.rb +2 -2
- data/lib/hecks/cli/smoke_http/checks.rb +4 -1
- data/lib/hecks/cli/smoke_http/transport.rb +3 -3
- data/lib/hecks/cli/smoke_http.rb +3 -0
- data/lib/hecks/codemod.rb +5 -2
- data/lib/hecks/corpus/routes.rb +7 -0
- data/lib/hecks/corpus/rust.rb +3 -2
- data/lib/hecks/deploy/bluebook/deploy.bluebook +34 -4
- data/lib/hecks/doc/reference/rendering.rb +6 -3
- data/lib/hecks/forms/app/commands.rb +8 -7
- data/lib/hecks/forms/app/queries.rb +2 -1
- data/lib/hecks/forms/app.rb +1 -1
- data/lib/hecks/forms/record_renderer.rb +1 -1
- data/lib/hecks/framework/bluebook/privacy.bluebook +11 -0
- data/lib/hecks/fuzzing/concurrent_dispatch.rb +4 -1
- data/lib/hecks/fuzzing/failure_triage.rb +2 -1
- data/lib/hecks/fuzzing/mutation/run.rb +11 -4
- data/lib/hecks/fuzzing/properties/catalog.rb +6 -4
- data/lib/hecks/fuzzing/properties/guaranteed_by_construction.rb +18 -11
- data/lib/hecks/fuzzing/properties/guards.rb +1 -1
- data/lib/hecks/fuzzing/self_consistency/saga_redelivery.rb +1 -1
- data/lib/hecks/fuzzing/self_consistency.rb +6 -2
- data/lib/hecks/fuzzing/shrinker.rb +3 -1
- data/lib/hecks/fuzzing/value_generator.rb +19 -5
- data/lib/hecks/gate/stages.yml +33 -7
- data/lib/hecks/grammar/evolve.rb +1 -1
- data/lib/hecks/grammar/expression_operators.json +372 -0
- data/lib/hecks/grammar/operators.rb +3 -1
- data/lib/hecks/hecks/adapters/codebase/corpus_tasks.rb +10 -10
- data/lib/hecks/hecks/adapters/codebase/inspection/rubycritic.rb +35 -0
- data/lib/hecks/hecks/adapters/codebase/inspection.rb +104 -0
- data/lib/hecks/hecks/adapters/codebase/publishing.rb +2 -1
- data/lib/hecks/hecks/adapters/codebase/release_facts.rb +12 -2
- data/lib/hecks/hecks/adapters/codebase/source_tree.rb +2 -1
- data/lib/hecks/hecks/adapters/codebase/test_runner.rb +1 -1
- data/lib/hecks/hecks/adapters/cost_explorer.rb +8 -5
- data/lib/hecks/hecks/adapters/deploy_toolchain/statuses.rb +2 -1
- data/lib/hecks/hecks/adapters/finding_github.rb +13 -6
- data/lib/hecks/hecks/adapters/first_admin.rb +2 -2
- data/lib/hecks/hecks/adapters/github_rulesets.rb +6 -3
- data/lib/hecks/hecks/adapters/in_process_boot.rb +1 -1
- data/lib/hecks/hecks/adapters/journal_store/compaction.rb +1 -1
- data/lib/hecks/hecks/adapters/journal_store/edge_audit.rb +10 -20
- data/lib/hecks/hecks/adapters/journal_store/held_domain.rb +28 -5
- data/lib/hecks/hecks/adapters/local_files.rb +2 -2
- data/lib/hecks/hecks/adapters/rehearsal/audit_report.rb +107 -0
- data/lib/hecks/hecks/adapters/rehearsal/census.rb +71 -0
- data/lib/hecks/hecks/adapters/rehearsal/declaration.rb +133 -0
- data/lib/hecks/hecks/adapters/rehearsal/environment.rb +83 -0
- data/lib/hecks/hecks/adapters/rehearsal/inquiry.rb +142 -0
- data/lib/hecks/hecks/adapters/rehearsal/memory_store.rb +96 -0
- data/lib/hecks/hecks/adapters/rehearsal/postgres_census.rb +100 -0
- data/lib/hecks/hecks/adapters/rehearsal/postgres_reading.rb +69 -0
- data/lib/hecks/hecks/adapters/rehearsal/postgres_store.rb +133 -0
- data/lib/hecks/hecks/adapters/rehearsal/rows.rb +41 -0
- data/lib/hecks/hecks/adapters/rehearsal/rust_audit.rb +83 -0
- data/lib/hecks/hecks/adapters/rehearsal/subject.rb +104 -0
- data/lib/hecks/hecks/adapters/rehearsal.rb +54 -0
- data/lib/hecks/hecks/adapters/rehearsal_store.adapter +7 -0
- data/lib/hecks/hecks/adapters/rehearsal_store.rb +81 -0
- data/lib/hecks/hecks/adapters/terminal.rb +13 -11
- data/lib/hecks/hecks/codebase.behaviors +13 -1
- data/lib/hecks/hecks/codebase.bluebook +239 -5
- data/lib/hecks/hecks/custodian.behaviors +24 -6
- data/lib/hecks/hecks/custodian.bluebook +6 -1227
- data/lib/hecks/hecks/deploy.behaviors +1 -1
- data/lib/hecks/hecks/deploy.world +1 -3
- data/lib/hecks/hecks/hecks.behaviors +1 -1
- data/lib/hecks/hecks/hecks.hecksagon +53 -18
- data/lib/hecks/hecks/hecks.world +13 -10
- data/lib/hecks/hecks/rehearsal.bluebook +477 -0
- data/lib/hecks/hecks/site.behaviors +1 -1
- data/lib/hecks/hecks/site.world +0 -1
- data/lib/hecks/hecks/tooling.bluebook +1238 -0
- data/lib/hecks/indifferent_key.rb +20 -0
- data/lib/hecks/language/adapter.bluebook +13 -3
- data/lib/hecks/language/bluebook/aggregate.bluebook +23 -0
- data/lib/hecks/language/bluebook/bluebook.behaviors +23 -0
- data/lib/hecks/language/bluebook/bluebook.bluebook +15 -0
- data/lib/hecks/language/bluebook/entity.bluebook +18 -0
- data/lib/hecks/language/bluebook/policy.behaviors +19 -0
- data/lib/hecks/language/bluebook/policy.bluebook +9 -1
- data/lib/hecks/language/bluebook/query.bluebook +1 -1
- data/lib/hecks/language/bluebook/vocabulary.bluebook +63 -4
- data/lib/hecks/language/hecksagon/domain_port.bluebook +1 -1
- data/lib/hecks/language/hecksagon/hecksagon.bluebook +22 -0
- data/lib/hecks/language/oidc.json +10 -0
- data/lib/hecks/language/port.bluebook +4 -4
- data/lib/hecks/literal.rb +12 -3
- data/lib/hecks/ports/key_vault.rb +7 -2
- data/lib/hecks/ports/persistence/plugins/era/era_check.rb +21 -10
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/boot.rb +4 -2
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/era_resolver.rb +2 -1
- data/lib/hecks/ports/persistence/repository_factory.rb +6 -3
- data/lib/hecks/projection_files/expression_tables.rb +7 -2
- data/lib/hecks/projections/deploy/box/compose.rb +6 -4
- data/lib/hecks/projections/deploy/box/edge.rb +62 -0
- data/lib/hecks/projections/deploy/box/logging.rb +99 -0
- data/lib/hecks/projections/deploy/box/roll_scripts.rb +16 -8
- data/lib/hecks/projections/deploy/box/settings/cdn.rb +40 -0
- data/lib/hecks/projections/deploy/box/settings/logs.rb +40 -0
- data/lib/hecks/projections/deploy/box/settings/patterns.rb +11 -0
- data/lib/hecks/projections/deploy/box/settings/types.rb +16 -1
- data/lib/hecks/projections/deploy/box/settings.rb +6 -2
- data/lib/hecks/projections/deploy/box/stack_yaml.rb +5 -2
- data/lib/hecks/projections/deploy/box/templates/Makefile.tmpl +16 -0
- data/lib/hecks/projections/deploy/box/templates/box.yaml.tmpl +8 -4
- data/lib/hecks/projections/deploy/box/templates/deploy-box.sh.tmpl +32 -0
- data/lib/hecks/projections/deploy/box/templates/deploy-service.sh.tmpl +1 -1
- data/lib/hecks/projections/deploy/box/templates/edge.mk.tmpl +17 -0
- data/lib/hecks/projections/deploy/box/templates/edge.yaml.tmpl +65 -0
- data/lib/hecks/projections/deploy/box/templates/log-group.yaml.tmpl +12 -0
- data/lib/hecks/projections/deploy/box/templates/log-policy.yaml.tmpl +7 -0
- data/lib/hecks/projections/deploy/box/templates/render-compose-taskdef.sh.tmpl +5 -4
- data/lib/hecks/projections/deploy/box/templates/render-compose.sh.tmpl +5 -4
- data/lib/hecks/projections/deploy/box.rb +15 -3
- data/lib/hecks/projections/deploy/preview/preview.sh.erb +1 -1
- data/lib/hecks/projections/deploy/shared.rb +5 -2
- data/lib/hecks/projections/model/deviations.rb +2 -2
- data/lib/hecks/projections/model.rb +2 -2
- data/lib/hecks/projections/oidc.rb +13 -1
- data/lib/hecks/projections/shape.rb +5 -2
- data/lib/hecks/projections/site/cms_editor/attributes.rb +26 -6
- data/lib/hecks/projections/site/cms_editor/blocks.rb +157 -0
- data/lib/hecks/projections/site/cms_editor/checks.rb +14 -1
- data/lib/hecks/projections/site/cms_editor/clearing.rb +70 -0
- data/lib/hecks/projections/site/cms_editor/color.rb +124 -0
- data/lib/hecks/projections/site/cms_editor/composition.rb +42 -0
- data/lib/hecks/projections/site/cms_editor/destructive.rb +61 -0
- data/lib/hecks/projections/site/cms_editor/drafts.rb +102 -0
- data/lib/hecks/projections/site/cms_editor/hints.rb +74 -0
- data/lib/hecks/projections/site/cms_editor/icons.rb +86 -0
- data/lib/hecks/projections/site/cms_editor/key_kinds.rb +31 -0
- data/lib/hecks/projections/site/cms_editor/limits.rb +72 -0
- data/lib/hecks/projections/site/cms_editor/media.rb +1 -1
- data/lib/hecks/projections/site/cms_editor/moment.rb +34 -0
- data/lib/hecks/projections/site/cms_editor/palette.rb +115 -0
- data/lib/hecks/projections/site/cms_editor/pickers.rb +85 -0
- data/lib/hecks/projections/site/cms_editor/preview.rb +91 -0
- data/lib/hecks/projections/site/cms_editor/relations.rb +92 -0
- data/lib/hecks/projections/site/cms_editor/scale_checks.rb +66 -0
- data/lib/hecks/projections/site/cms_editor/scheduling.rb +150 -0
- data/lib/hecks/projections/site/cms_editor/schema.rb +96 -19
- data/lib/hecks/projections/site/cms_editor/setting.rb +52 -9
- data/lib/hecks/projections/site/cms_editor/targets.rb +86 -0
- data/lib/hecks/projections/site/cms_editor/templates/package.json.tmpl +18 -1
- data/lib/hecks/projections/site/cms_editor/templates/src/app.ts.tmpl +251 -57
- data/lib/hecks/projections/site/cms_editor/templates/src/assets.ts.tmpl +98 -0
- data/lib/hecks/projections/site/cms_editor/templates/src/auth/membership.ts.tmpl +32 -24
- data/lib/hecks/projections/site/cms_editor/templates/src/browser/app.css.tmpl +412 -0
- data/lib/hecks/projections/site/cms_editor/templates/src/browser/autosave.js.tmpl +144 -0
- data/lib/hecks/projections/site/cms_editor/templates/src/browser/blocks.js.tmpl +500 -0
- data/lib/hecks/projections/site/cms_editor/templates/src/browser/body_doc.js.tmpl +175 -0
- data/lib/hecks/projections/site/cms_editor/templates/src/browser/body_editor.js.tmpl +418 -0
- data/lib/hecks/projections/site/cms_editor/templates/src/browser/epoch.js.tmpl +61 -0
- data/lib/hecks/projections/site/cms_editor/templates/src/browser/forms.js.tmpl +210 -0
- data/lib/hecks/projections/site/cms_editor/templates/src/browser/lists.js.tmpl +40 -0
- data/lib/hecks/projections/site/cms_editor/templates/src/browser/main.js.tmpl +26 -0
- data/lib/hecks/projections/site/cms_editor/templates/src/browser/media_picker.js.tmpl +232 -0
- data/lib/hecks/projections/site/cms_editor/templates/src/browser/moments.js.tmpl +73 -0
- data/lib/hecks/projections/site/cms_editor/templates/src/browser/pickers.js.tmpl +152 -0
- data/lib/hecks/projections/site/cms_editor/templates/src/browser/preview.js.tmpl +98 -0
- data/lib/hecks/projections/site/cms_editor/templates/src/browser/shell.js.tmpl +140 -0
- data/lib/hecks/projections/site/cms_editor/templates/src/browser/toast.js.tmpl +66 -0
- data/lib/hecks/projections/site/cms_editor/templates/src/choices.ts.tmpl +99 -0
- data/lib/hecks/projections/site/cms_editor/templates/src/commands.ts.tmpl +78 -24
- data/lib/hecks/projections/site/cms_editor/templates/src/config.ts.tmpl +6 -0
- data/lib/hecks/projections/site/cms_editor/templates/src/flash.ts.tmpl +52 -0
- data/lib/hecks/projections/site/cms_editor/templates/src/host.ts.tmpl +19 -2
- data/lib/hecks/projections/site/cms_editor/templates/src/media/handler.ts.tmpl +31 -8
- data/lib/hecks/projections/site/cms_editor/templates/src/names.ts.tmpl +36 -0
- data/lib/hecks/projections/site/cms_editor/templates/src/schema.ts.tmpl +131 -2
- data/lib/hecks/projections/site/cms_editor/templates/src/ui/availability.ts.tmpl +15 -0
- data/lib/hecks/projections/site/cms_editor/templates/src/ui/block_list.js.tmpl +213 -0
- data/lib/hecks/projections/site/cms_editor/templates/src/ui/blocks.ts.tmpl +275 -0
- data/lib/hecks/projections/site/cms_editor/templates/src/ui/body_model.js.tmpl +8 -5
- data/lib/hecks/projections/site/cms_editor/templates/src/ui/detail.ts.tmpl +88 -0
- data/lib/hecks/projections/site/cms_editor/templates/src/ui/dialogs.ts.tmpl +43 -0
- data/lib/hecks/projections/site/cms_editor/templates/src/ui/fields.ts.tmpl +229 -34
- data/lib/hecks/projections/site/cms_editor/templates/src/ui/html.ts.tmpl +40 -81
- data/lib/hecks/projections/site/cms_editor/templates/src/ui/icons.ts.tmpl +15 -0
- data/lib/hecks/projections/site/cms_editor/templates/src/ui/input.ts.tmpl +29 -12
- data/lib/hecks/projections/site/cms_editor/templates/src/ui/links.ts.tmpl +100 -0
- data/lib/hecks/projections/site/cms_editor/templates/src/ui/moments.ts.tmpl +44 -0
- data/lib/hecks/projections/site/cms_editor/templates/src/ui/outline.ts.tmpl +53 -17
- data/lib/hecks/projections/site/cms_editor/templates/src/ui/pages.ts.tmpl +178 -88
- data/lib/hecks/projections/site/cms_editor/templates/src/ui/paging.ts.tmpl +82 -0
- data/lib/hecks/projections/site/cms_editor/templates/src/ui/pickers.ts.tmpl +110 -0
- data/lib/hecks/projections/site/cms_editor/templates/src/ui/preview.ts.tmpl +87 -0
- data/lib/hecks/projections/site/cms_editor/templates/src/ui/related.ts.tmpl +97 -0
- data/lib/hecks/projections/site/cms_editor/templates/src/ui/schedule.ts.tmpl +160 -0
- data/lib/hecks/projections/site/cms_editor/templates/src/ui/shell.ts.tmpl +211 -0
- data/lib/hecks/projections/site/cms_editor/templates/src/ui/table.ts.tmpl +151 -0
- data/lib/hecks/projections/site/cms_editor/templates/src/ui/theme.js.tmpl +16 -0
- data/lib/hecks/projections/site/cms_editor/templates/src/ui/values.ts.tmpl +69 -0
- data/lib/hecks/projections/site/cms_editor/templates/src/ui/words.ts.tmpl +97 -0
- data/lib/hecks/projections/site/cms_editor/templates/src/ui/world.ts.tmpl +35 -0
- data/lib/hecks/projections/site/cms_editor/templates/tsconfig.json.tmpl +2 -1
- data/lib/hecks/projections/site/cms_editor/theme.rb +29 -0
- data/lib/hecks/projections/site/cms_editor/theme_checks.rb +57 -0
- data/lib/hecks/projections/site/cms_editor.rb +49 -23
- data/lib/hecks/projections/site/role_probe.rb +2 -0
- data/lib/hecks/projections/site/site_root/workflow.rb +5 -0
- data/lib/hecks/projector/cli_audience.rb +22 -1
- data/lib/hecks/projector/cli_projector/listing.rb +1 -1
- data/lib/hecks/projector/cli_projector/option_specs.rb +1 -1
- data/lib/hecks/projector/cli_projector/usage.rb +15 -4
- data/lib/hecks/projector/docs_projector/closing.rb +1 -1
- data/lib/hecks/projector/docs_projector.rb +1 -1
- data/lib/hecks/projector/exporter/bindings.rb +40 -10
- data/lib/hecks/projector/exporter/capability_values.rb +55 -0
- data/lib/hecks/projector/narrate_projector/reactions.rb +1 -1
- data/lib/hecks/projector/target.rb +11 -0
- data/lib/hecks/projector.rb +32 -5
- data/lib/hecks/quality_control/adapters/github_checks.rb +12 -8
- data/lib/hecks/quality_control/adapters/github_issues.rb +8 -4
- data/lib/hecks/quality_control/cli/qa_open_pr.rb +2 -2
- data/lib/hecks/quality_control/cli/qa_sweep/checks/shrinking.rb +1 -1
- data/lib/hecks/quality_control/cli/qa_sweep/finding_report.rb +1 -1
- data/lib/hecks/quality_control/cli/qa_sweep.rb +1 -1
- data/lib/hecks/quality_control/quality_control.bluebook +6 -2
- data/lib/hecks/release/approval.rb +64 -0
- data/lib/hecks/router/{door.rb → aggregate_reader.rb} +5 -4
- data/lib/hecks/router/namespace_installer.rb +16 -16
- data/lib/hecks/router.rb +1 -1
- data/lib/hecks/runtime/best_effort.rb +22 -0
- data/lib/hecks/runtime/command_interpreter/mutation_applier.rb +12 -2
- data/lib/hecks/runtime/command_interpreter.rb +3 -2
- data/lib/hecks/runtime/command_rules/emission.rb +1 -1
- data/lib/hecks/runtime/dispatcher.rb +4 -4
- data/lib/hecks/runtime/entity_element/location.rb +1 -1
- data/lib/hecks/runtime/event.rb +5 -0
- data/lib/hecks/runtime/identity.rb +7 -6
- data/lib/hecks/runtime/interpreting.rb +2 -1
- data/lib/hecks/runtime/invocation_builder.rb +1 -1
- data/lib/hecks/runtime/loader/boot_steps.rb +8 -5
- data/lib/hecks/runtime/loader.rb +10 -10
- data/lib/hecks/runtime/policy_interpreter/arguments.rb +7 -4
- data/lib/hecks/runtime/policy_interpreter/fan_out.rb +3 -3
- data/lib/hecks/runtime/policy_interpreter.rb +6 -6
- data/lib/hecks/runtime/port_operation_interpreter.rb +1 -1
- data/lib/hecks/runtime/reaction_invocation.rb +1 -1
- data/lib/hecks/runtime/rebuild_sweep.rb +11 -1
- data/lib/hecks/runtime/registry/ask_verification.rb +35 -0
- data/lib/hecks/runtime/registry/hecksagon_rules.rb +10 -0
- data/lib/hecks/runtime/registry/merging.rb +1 -1
- data/lib/hecks/runtime/registry/providers.rb +16 -0
- data/lib/hecks/runtime/registry/read_repository.rb +6 -4
- data/lib/hecks/runtime/registry/verification.rb +4 -1
- data/lib/hecks/runtime/registry/world_defaults.rb +29 -0
- data/lib/hecks/runtime/registry.rb +1 -1
- data/lib/hecks/runtime/saga_interpreter/compensation.rb +1 -1
- data/lib/hecks/runtime/saga_interpreter/delivery.rb +4 -4
- data/lib/hecks/runtime/saga_interpreter/transitions.rb +1 -1
- data/lib/hecks/runtime/saga_interpreter.rb +3 -3
- data/lib/hecks/runtime/tenant_check.rb +5 -4
- data/lib/hecks/runtime/value/coercion.rb +2 -2
- data/lib/hecks/runtime/value/validation.rb +16 -4
- data/lib/hecks/runtime.rb +9 -9
- data/lib/hecks/rust_build/host.rb +11 -4
- data/lib/hecks/rust_build/prebuilt_binary.rb +101 -0
- data/lib/hecks/rust_build/project_rust/target_ir.rb +1 -1
- data/lib/hecks/rust_build/wasm.rb +1 -1
- data/lib/hecks/rust_build/wasm_browser.rb +1 -1
- data/lib/hecks/rust_build.rb +11 -0
- data/lib/hecks/served_options.rb +53 -0
- data/lib/hecks/site/bluebook/site.bluebook +1 -0
- data/lib/hecks/storehouse/audit.rb +1 -1
- data/lib/hecks/storehouse/dispatching.rb +8 -6
- data/lib/hecks/storehouse/introspection.rb +2 -2
- data/lib/hecks/storehouse/querying.rb +6 -4
- data/lib/hecks/storehouse.rb +4 -4
- data/lib/hecks/tools/ci_gate_decision.rb +35 -0
- data/lib/hecks/tools/ci_gates.rb +20 -1
- data/lib/hecks/tools/comment_style/source_file.rb +4 -1
- data/lib/hecks/tools/deploy_recipe_lint/fixtures.rb +4 -1
- data/lib/hecks/tools/lanes/files.rb +8 -0
- data/lib/hecks/tools/lanes/prebuilt_workflow.rb +81 -0
- data/lib/hecks/tools/lanes/rows.rb +6 -0
- data/lib/hecks/tools/lanes.rb +1 -0
- data/lib/hecks/tools/oidc_manifests.rb +4 -5
- data/lib/hecks/tools/regeneration_run.rb +11 -4
- data/lib/hecks/tools/release_only.rb +111 -0
- data/lib/hecks/tools/site_routes/editor_files.rb +12 -5
- data/lib/hecks/tools/tenant_provisioning.rb +2 -2
- data/lib/hecks/tools/tools_doc.rb +4 -4
- data/lib/hecks/version.rb +1 -1
- data/lib/hecks/vocabulary.rb +19 -5
- data/lib/hecks.rb +15 -15
- data/lib/rubocop/cop/hecks/env_dump.rb +69 -0
- data/lib/rubocop/cop/hecks/monotonic_duration.rb +53 -0
- data/lib/rubocop/cop/hecks/no_wall_clock_in_runtime.rb +34 -0
- data/lib/rubocop/cop/hecks/raw_shell_interpolation.rb +79 -0
- data/lib/rubocop/cop/hecks/sleep_in_spec.rb +34 -0
- data/lib/rubocop/cop/hecks/swallowed_rescue.rb +37 -0
- data/lib/rubocop/cop/hecks/symbol_string_key_mix.rb +50 -0
- data/lib/rubocop/cop/hecks/untyped_raise.rb +37 -0
- data/prebuilt/9ee54e2f0d4d6d3fe046827779b221e02de665fba911a048ae5dd8b8fbfb7d90.marshal +0 -0
- data/prebuilt/d74a00e996222c1d8b676d5959092effc46b4dc59e0555f3bf9554ac58e3094a.marshal +0 -0
- data/prebuilt/verdicts-df19f35868d3284a70f55e42dcef87ef4e65e6a678e5135f72e1f6cff4c1357b.json +1 -0
- data/rust/.gitignore +6 -0
- data/rust/Cargo.toml +6 -0
- data/rust/build/src/binding_pass.rs +103 -0
- data/rust/build/src/cargo_sync.rs +6 -0
- data/rust/build/src/lineage_pass.rs +3 -3
- data/rust/build/src/main.rs +17 -5
- data/rust/build/src/pipeline.rs +48 -5
- data/rust/build/src/seams_pass.rs +123 -0
- data/rust/build/src/translation_pass.rs +167 -0
- data/rust/codegen/src/asks.rs +103 -0
- data/rust/codegen/src/commands.rs +13 -8
- data/rust/codegen/src/constraints.rs +25 -0
- data/rust/codegen/src/domain_generator.rs +2 -0
- data/rust/codegen/src/expr_emitter.rs +13 -0
- data/rust/codegen/src/json_codec.rs +54 -15
- data/rust/codegen/src/main.rs +1 -0
- data/rust/codegen/src/mutations.rs +128 -3
- data/rust/codegen/src/queries.rs +11 -2
- data/rust/codegen/src/reactions.rs +1 -1
- data/rust/codegen/src/types.rs +166 -8
- data/rust/host/HECKS_RELEASE +1 -1
- data/rust/host/src/api.rs +4 -4
- data/rust/host/src/bin/validate_harness.rs +43 -0
- data/rust/host/src/boundary_fuzz/expr_json.rs +2 -2
- data/rust/host/src/boundary_fuzz/ir.rs +1 -0
- data/rust/host/src/boundary_fuzz/server.rs +1 -1
- data/rust/host/src/checkout.rs +35 -19
- data/rust/host/src/commerce_ir.rs +408 -2
- data/rust/host/src/expr_json.rs +118 -0
- data/rust/host/src/extension.rs +13 -1
- data/rust/host/src/lib.rs +1 -0
- data/rust/host/src/mint.rs +1 -1
- data/rust/host/src/payments/tests.rs +27 -1
- data/rust/host/src/payments.rs +12 -4
- data/rust/host/src/platform_signin/attack_tests.rs +1100 -0
- data/rust/host/src/platform_signin/config.rs +512 -0
- data/rust/host/src/platform_signin/cookie.rs +237 -0
- data/rust/host/src/platform_signin/extension.rs +190 -0
- data/rust/host/src/platform_signin/fetcher.rs +322 -0
- data/rust/host/src/platform_signin/handler.rs +251 -0
- data/rust/host/src/platform_signin/handler_tests.rs +554 -0
- data/rust/host/src/platform_signin/jti.rs +196 -0
- data/rust/host/src/platform_signin/jwks.rs +542 -0
- data/rust/host/src/platform_signin/jws.rs +249 -0
- data/rust/host/src/platform_signin/known_answer_tests.rs +237 -0
- data/rust/host/src/platform_signin/mapping_tests.rs +254 -0
- data/rust/host/src/platform_signin/mod.rs +75 -0
- data/rust/host/src/platform_signin/mode_tests.rs +382 -0
- data/rust/host/src/platform_signin/pages.rs +204 -0
- data/rust/host/src/platform_signin/query.rs +233 -0
- data/rust/host/src/platform_signin/session.rs +151 -0
- data/rust/host/src/platform_signin/settings.rs +385 -0
- data/rust/host/src/platform_signin/strict_json.rs +351 -0
- data/rust/host/src/platform_signin/test_support.rs +235 -0
- data/rust/host/src/platform_signin/ttl_tests.rs +94 -0
- data/rust/host/src/platform_signin/verify.rs +604 -0
- data/rust/host/src/platform_signin/wiring_support.rs +319 -0
- data/rust/host/src/query_step.rs +22 -4
- data/rust/host/src/reference_validate.rs +653 -108
- data/rust/host/src/resend.rs +2 -0
- data/rust/host/src/server.rs +19 -6
- data/rust/host/src/ui_schema.rs +132 -5
- data/rust/host/src/web/newsletter.rs +7 -8
- data/rust/host/src/web/newsletter_send.rs +38 -13
- data/rust/host/src/web/registrations.rs +229 -26
- data/rust/host/src/web.rs +53 -9
- data/rust/parser/src/emit.rs +38 -6
- data/rust/parser/src/expr/ast_json.rs +7 -1
- data/rust/parser/src/expr/resolver.rs +171 -6
- data/rust/parser/src/ir.rs +7 -0
- data/rust/parser/src/keywords.rs +24 -0
- data/rust/parser/src/main.rs +3 -0
- data/rust/parser/src/parse/aggregate.rs +2 -1
- data/rust/parser/src/parse/chapter.rs +2 -2
- data/rust/parser/src/parse/command.rs +2 -0
- data/rust/parser/src/parse/hecksagon.rs +5 -2
- data/rust/parser/src/parse/lifecycle.rs +81 -0
- data/rust/parser/src/parse/mod.rs +15 -1
- data/rust/parser/src/parse/policy.rs +13 -2
- data/rust/parser/src/parse/value_object.rs +34 -17
- data/rust/parser/src/ruby_value.rs +1 -1
- data/rust/src/exemplar/commands.rs +4 -4
- data/rust/src/exemplar/constraints.rs +1 -1
- data/rust/src/exemplar/json.rs +43 -1
- data/rust/src/kernel/cli.rs +7 -5
- data/rust/src/kernel/dispatch.rs +2 -2
- data/rust/src/kernel/dispatch_guard_tests.rs +1 -1
- data/rust/src/kernel/expr.rs +66 -3
- data/rust/src/kernel/expression_operators/arithmetic.rs +130 -5
- data/rust/src/kernel/expression_operators/text.rs +26 -2
- data/rust/src/kernel/json.rs +15 -0
- data/rust/src/kernel/mod.rs +1 -1
- data/rust/src/kernel/orchestrate.rs +54 -5
- data/rust/src/kernel/orchestrate_guard_tests.rs +67 -0
- data/rust/src/kernel/pattern.rs +60 -0
- data/rust/src/kernel/reference_lookup.rs +90 -7
- metadata +178 -38
- data/lib/hecks/doors/cli_door/nesting.rb +0 -34
- data/lib/hecks/doors/cli_door/shorthand.rb +0 -85
- data/lib/hecks/doors/cli_door.rb +0 -124
- data/lib/hecks/doors/cli_runner/answers.rb +0 -138
- data/lib/hecks/doors/cli_runner/resolution.rb +0 -146
- data/lib/hecks/doors/cli_runner/settling.rb +0 -115
- data/lib/hecks/doors/cli_runner/streaming.rb +0 -90
- data/lib/hecks/doors/cli_runner/suggestions.rb +0 -43
- data/lib/hecks/doors/cli_runner.rb +0 -66
- data/lib/hecks/doors/command_request.rb +0 -119
- data/lib/hecks/doors/handle.rb +0 -208
- data/lib/hecks/doors/json_door.rb +0 -132
- data/lib/hecks/doors/launcher_options.rb +0 -247
- data/lib/hecks/doors/mcp_door/properties.rb +0 -47
- data/lib/hecks/doors/mcp_door/tool_calls.rb +0 -113
- data/lib/hecks/doors/mcp_door/tool_definitions/auditing.rb +0 -51
- data/lib/hecks/doors/mcp_door/tool_definitions/calling.rb +0 -69
- data/lib/hecks/doors/mcp_door/tool_definitions/reading.rb +0 -97
- data/lib/hecks/doors/mcp_door/tool_definitions.rb +0 -15
- data/lib/hecks/doors/mcp_door.rb +0 -156
- data/lib/hecks/doors/mcp_door_scope/argument_policy.rb +0 -92
- data/lib/hecks/doors/mcp_door_scope/env_problems.rb +0 -55
- data/lib/hecks/doors/mcp_door_scope/presenter.rb +0 -78
- data/lib/hecks/doors/mcp_door_scope.rb +0 -201
- data/lib/hecks/doors/mcp_guide_cache.rb +0 -75
- data/lib/hecks/doors/ruby_door/aggregate_door.rb +0 -162
- data/lib/hecks/doors/ruby_door/chapter.rb +0 -89
- data/lib/hecks/doors/ruby_door.rb +0 -80
- data/lib/hecks/doors/usage_cache.rb +0 -139
- data/lib/hecks/projections/site/cms_editor/templates/src/ui/body_widget.js.tmpl +0 -282
- data/lib/hecks/projections/site/cms_editor/templates/src/ui/media_picker.js.tmpl +0 -109
- data/prebuilt/c28d6d9db14eea3e17161e9d9c262efee30b256cf97693a7cfd552bce24b2f7f.marshal +0 -0
- data/prebuilt/cb375cba61ca0dbe8ddb9739c306510fe05e5f4b7a9b6955caff8224c63ea0e0.marshal +0 -0
- data/prebuilt/verdicts-d6d584ad43b5f3cebf88aafbbdbf024c38574acf18e06adffbc555f7786b1c2f.json +0 -1
|
@@ -20,11 +20,11 @@ module Hecks
|
|
|
20
20
|
|
|
21
21
|
# @param registry [Runtime::Registry] the booted registry whose loaded
|
|
22
22
|
# bluebooks are scanned for candidate policies
|
|
23
|
-
# @param
|
|
23
|
+
# @param dispatcher [Runtime::Dispatcher] the dispatcher reactions re-enter through,
|
|
24
24
|
# and whose reaction-depth guard is checked before each delivery
|
|
25
|
-
def initialize(registry,
|
|
25
|
+
def initialize(registry, dispatcher:)
|
|
26
26
|
@registry = registry
|
|
27
|
-
@
|
|
27
|
+
@dispatcher = dispatcher
|
|
28
28
|
end
|
|
29
29
|
|
|
30
30
|
# Fires every declared policy `event` triggers, recording each outcome on
|
|
@@ -96,15 +96,15 @@ module Hecks
|
|
|
96
96
|
# may go.
|
|
97
97
|
def fire(policy, event, target, record)
|
|
98
98
|
return nil unless where_holds?(policy, event)
|
|
99
|
-
return depth_refusal(record) if @
|
|
99
|
+
return depth_refusal(record) if @dispatcher.reaction_depth_reached?
|
|
100
100
|
|
|
101
101
|
args = trigger_args(policy, event)
|
|
102
|
-
@
|
|
102
|
+
@dispatcher.reenter(target, **reaction_invocation(target, args, policy, event))
|
|
103
103
|
record.merge(delivered: true)
|
|
104
104
|
end
|
|
105
105
|
|
|
106
106
|
def depth_refusal(record)
|
|
107
|
-
record.merge(delivered: false, reason: "reaction depth #{@
|
|
107
|
+
record.merge(delivered: false, reason: "reaction depth #{@dispatcher.max_reaction_depth} reached")
|
|
108
108
|
end
|
|
109
109
|
|
|
110
110
|
# A defect, not a refusal: recorded with `defect: true` and warned, never
|
|
@@ -90,7 +90,7 @@ module Hecks
|
|
|
90
90
|
# @raise [Runtime::UnknownVerb] if `verb` does not resolve (only when `explicit`)
|
|
91
91
|
# @raise [Runtime::TypeMismatch] if no receiver identity resolves for an explicit target
|
|
92
92
|
# @raise [Runtime::UnknownArgument] if an explicit projection has an undeclared fact
|
|
93
|
-
# rubocop:disable-next Metrics/ParameterLists -- the keyword
|
|
93
|
+
# rubocop:disable-next Metrics/ParameterLists -- the keyword entry point both interpreters call
|
|
94
94
|
def build(registry:, verb:, projected:, explicit:, passthrough: [], source_receiver: nil)
|
|
95
95
|
args = projected.transform_keys(&:to_sym)
|
|
96
96
|
return forwarded(registry, verb, args, source_receiver) unless explicit
|
|
@@ -49,7 +49,17 @@ module Hecks
|
|
|
49
49
|
return nil if id.nil?
|
|
50
50
|
|
|
51
51
|
remote = registry.repository(domain, target).find(id.to_s)
|
|
52
|
-
remote&.[](field.remote_field)
|
|
52
|
+
unwrap_single_field(target, field, remote&.[](field.remote_field))
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# A remote field typed by a single-field value object is copied as its one scalar, so the
|
|
56
|
+
# projecting aggregate holds `123`, never `{ value: 123 }`. Any other value is copied as is.
|
|
57
|
+
def unwrap_single_field(target, field, value)
|
|
58
|
+
attribute = target.attribute(field.remote_field)
|
|
59
|
+
sole = attribute && target.value_object(attribute.type)&.sole_attribute
|
|
60
|
+
return value unless sole && !value.nil?
|
|
61
|
+
|
|
62
|
+
value.is_a?(Hash) ? value.fetch(sole.name) { value[sole.name.to_s] } : value[sole.name]
|
|
53
63
|
end
|
|
54
64
|
end
|
|
55
65
|
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
require_relative "../../bluebook/ask_resolution"
|
|
2
|
+
|
|
3
|
+
module Hecks
|
|
4
|
+
module Runtime
|
|
5
|
+
class Registry
|
|
6
|
+
# The boot gate for `ask`: every policy's ask must resolve to one declared port operation,
|
|
7
|
+
# so a name the hecksagon never declared stops the boot instead of firing at nothing.
|
|
8
|
+
# Mixed into {Verification}.
|
|
9
|
+
module AskVerification
|
|
10
|
+
private
|
|
11
|
+
|
|
12
|
+
# A port operation a chapter provides, and an ask a policy makes, each name a port
|
|
13
|
+
# operation the hecksagon declared.
|
|
14
|
+
def refuse_unresolved_ports!
|
|
15
|
+
refuse_unresolved_port_operations!
|
|
16
|
+
refuse_unresolved_asks!
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Binds each ask to the operation it resolves to, refusing the first that resolves to none.
|
|
20
|
+
#
|
|
21
|
+
# @raise [WiringError] naming the policy, the ask and what the hecksagon would need
|
|
22
|
+
def refuse_unresolved_asks!
|
|
23
|
+
@declared.bluebooks.each_value do |chapter|
|
|
24
|
+
chapter.policies.select(&:asks?).each do |policy|
|
|
25
|
+
outcome = Bluebook::AskResolution.call(chapter, policy)
|
|
26
|
+
raise WiringError, outcome.detail unless outcome.resolved?
|
|
27
|
+
|
|
28
|
+
policy.resolve_ask!(outcome.verb)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -27,6 +27,16 @@ module Hecks
|
|
|
27
27
|
"without that it is silent decoration, the exact defect this refusal exists to catch"
|
|
28
28
|
end
|
|
29
29
|
|
|
30
|
+
# `driven_by` names a driving adapter; a name none answers to would silently admit nothing.
|
|
31
|
+
def refuse_unknown_driving!(hecksagon)
|
|
32
|
+
unknown = hecksagon.driving - Bluebook::Hecksagon::DRIVING_ADAPTERS
|
|
33
|
+
return if unknown.empty?
|
|
34
|
+
|
|
35
|
+
raise WiringError,
|
|
36
|
+
"#{hecksagon.domain} is driven_by #{unknown.map(&:inspect).join(", ")}, which no driving " \
|
|
37
|
+
"adapter answers to — the adapters are #{Bluebook::Hecksagon::DRIVING_ADAPTERS.join(", ")}"
|
|
38
|
+
end
|
|
39
|
+
|
|
30
40
|
# `attaches` loads a bounded context; the consumer must declare the sibling hecksagon
|
|
31
41
|
# that is its ACL (Governance/Identity/Privacy already do). A vendored package only
|
|
32
42
|
# loads its `.bluebook` files, so persistence, Governance and the `translates` ACL live
|
|
@@ -17,7 +17,7 @@ module Hecks
|
|
|
17
17
|
def merge_hecksagons(base, overlay)
|
|
18
18
|
# Order-independent: list facts uniq, so loading context_map before or after the
|
|
19
19
|
# domain file yields the same merged hecksagon.
|
|
20
|
-
lists = %i[subscriptions attachments translates].to_h do |facet|
|
|
20
|
+
lists = %i[subscriptions attachments translates driving].to_h do |facet|
|
|
21
21
|
[facet, (base.public_send(facet) + overlay.public_send(facet)).uniq]
|
|
22
22
|
end
|
|
23
23
|
Bluebook::Hecksagon.new(domain: base.domain, binds: base.binds + overlay.binds,
|
|
@@ -101,6 +101,16 @@ module Hecks
|
|
|
101
101
|
vendored_provider_for(domain, Bluebook::Capabilities::PAYMENT_CONNECTION)
|
|
102
102
|
end
|
|
103
103
|
|
|
104
|
+
# The chapter that owns the checkout boundary for `domain` — resolved by what it
|
|
105
|
+
# declares (`provides "checkout"`). Nil when none does.
|
|
106
|
+
#
|
|
107
|
+
# @param domain [String, Symbol] the domain whose checkout chapter is being resolved
|
|
108
|
+
# @return [Bluebook::Chapter, nil] the chapter that owns `domain`'s checkout windows,
|
|
109
|
+
# or nil if none does
|
|
110
|
+
def checkout_provider_for(domain)
|
|
111
|
+
vendored_provider_for(domain, Bluebook::Capabilities::CHECKOUT)
|
|
112
|
+
end
|
|
113
|
+
|
|
104
114
|
# The chapter that takes payments for `domain`: the domain's own chapter, a
|
|
105
115
|
# framework member, or a vendored embryonaut bluebook it attaches, that
|
|
106
116
|
# declares `provides "payments"`.
|
|
@@ -112,6 +122,12 @@ module Hecks
|
|
|
112
122
|
vendored_provider_for(domain, Bluebook::Capabilities::PAYMENTS)
|
|
113
123
|
end
|
|
114
124
|
|
|
125
|
+
# The first loaded chapter that declares `capability`, whichever domain asks.
|
|
126
|
+
#
|
|
127
|
+
# @param capability [String] a `Bluebook::Capabilities` name
|
|
128
|
+
# @return [Bluebook::Chapter, nil] the providing chapter, or nil if none loaded does
|
|
129
|
+
def provider_of(capability) = bluebooks.values.find { |chapter| chapter.provides?(capability) }
|
|
130
|
+
|
|
115
131
|
# The chapter that provides `capability` for `domain`: the domain's own chapter,
|
|
116
132
|
# a framework member its hecksagon attaches, or a vendored embryonaut bluebook
|
|
117
133
|
# it attaches, that declares it.
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
require_relative "../best_effort"
|
|
2
|
+
|
|
1
3
|
module Hecks
|
|
2
4
|
module Runtime
|
|
3
5
|
class Registry
|
|
@@ -37,10 +39,10 @@ module Hecks
|
|
|
37
39
|
# `authoritative`, in the same order; false on any mismatch, or if comparing
|
|
38
40
|
# them raises
|
|
39
41
|
def projection_current?(projection, authoritative)
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
BestEffort.call(false) do
|
|
43
|
+
entries_match?(projection.entries, authoritative.entries) &&
|
|
44
|
+
sorted_rows(projection) == sorted_rows(authoritative)
|
|
45
|
+
end
|
|
44
46
|
end
|
|
45
47
|
|
|
46
48
|
private
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
require_relative "../../bluebook/hecksagon"
|
|
2
2
|
require_relative "hecksagon_rules"
|
|
3
|
+
require_relative "ask_verification"
|
|
3
4
|
require_relative "query_verification"
|
|
4
5
|
require_relative "chapter_verification"
|
|
5
6
|
require_relative "durability_warnings"
|
|
@@ -11,6 +12,7 @@ module Hecks
|
|
|
11
12
|
# port's verb, and every world default is usable. `verify!` runs it all at boot.
|
|
12
13
|
module Verification
|
|
13
14
|
include HecksagonRules
|
|
15
|
+
include AskVerification
|
|
14
16
|
include QueryVerification
|
|
15
17
|
include ChapterVerification
|
|
16
18
|
include DurabilityWarnings
|
|
@@ -24,7 +26,7 @@ module Hecks
|
|
|
24
26
|
refuse_cross_package_bluebook_merge!
|
|
25
27
|
refuse_reserved_chapter_names!
|
|
26
28
|
refuse_membership_without_identity!
|
|
27
|
-
|
|
29
|
+
refuse_unresolved_ports!
|
|
28
30
|
refuse_unanswerable_queries!
|
|
29
31
|
|
|
30
32
|
@declared.hecksagons.each_value { |hecksagon| verify_hecksagon!(hecksagon) }
|
|
@@ -126,6 +128,7 @@ module Hecks
|
|
|
126
128
|
# warnings for its chapter.
|
|
127
129
|
def verify_hecksagon!(hecksagon)
|
|
128
130
|
refuse_ungoverned_roles!(hecksagon)
|
|
131
|
+
refuse_unknown_driving!(hecksagon)
|
|
129
132
|
refuse_unwired_attachments!(hecksagon)
|
|
130
133
|
refuse_bounded_without_acl!(hecksagon)
|
|
131
134
|
hecksagon.binds.each { |bind| verify_bind!(hecksagon, bind) }
|
|
@@ -28,8 +28,37 @@ module Hecks
|
|
|
28
28
|
self
|
|
29
29
|
end
|
|
30
30
|
|
|
31
|
+
# The defaults an adapter's `.adapter` declares for its fields, with each `{name}` or
|
|
32
|
+
# `{storage_name}` in a string filled from `aggregate`. A world's own setting always wins.
|
|
33
|
+
#
|
|
34
|
+
# @param adapter [String, Symbol] the adapter's name
|
|
35
|
+
# @param aggregate [Bluebook::Aggregate] the aggregate the adapter is built for
|
|
36
|
+
# @return [Hash{Symbol => Object}] the defaults, empty when the adapter declares none
|
|
37
|
+
def adapter_defaults(adapter, aggregate)
|
|
38
|
+
declared = @declared.adapters[adapter.to_s]&.declared_defaults || {}
|
|
39
|
+
declared.transform_values { |value| fill_placeholders(value, aggregate) }
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# `settings` laid over the adapter's declared defaults. A field a world gives as `:default`
|
|
43
|
+
# asks for the declared default, so it is left out and the default shows through.
|
|
44
|
+
#
|
|
45
|
+
# @param adapter [String, Symbol] the adapter's name
|
|
46
|
+
# @param aggregate [Bluebook::Aggregate] the aggregate the adapter is built for
|
|
47
|
+
# @param settings [Hash{Symbol => Object}] the settings the world gave
|
|
48
|
+
# @return [Hash{Symbol => Object}] the defaults, overridden by the settings given
|
|
49
|
+
def with_adapter_defaults(adapter, aggregate, settings)
|
|
50
|
+
adapter_defaults(adapter, aggregate).merge(settings.reject { |_, value| value == :default })
|
|
51
|
+
end
|
|
52
|
+
|
|
31
53
|
private
|
|
32
54
|
|
|
55
|
+
# A string default with its placeholders filled from the aggregate; any other value as is.
|
|
56
|
+
def fill_placeholders(value, aggregate)
|
|
57
|
+
return value unless value.is_a?(String)
|
|
58
|
+
|
|
59
|
+
value.gsub(/\{(name|storage_name)\}/) { aggregate.public_send(Regexp.last_match(1)) }
|
|
60
|
+
end
|
|
61
|
+
|
|
33
62
|
# The chapter's own world answers first; the project's world fills the gap.
|
|
34
63
|
def world_default(domain, field)
|
|
35
64
|
world(domain)&.public_send(field) || project_world&.public_send(field)
|
|
@@ -45,7 +45,7 @@ module Hecks
|
|
|
45
45
|
# against; nil for a registry with no such root
|
|
46
46
|
def initialize(root: nil)
|
|
47
47
|
@root = root
|
|
48
|
-
# Recorded at hecksagon-build time (
|
|
48
|
+
# Recorded at hecksagon-build time (AggregateModule#mark_sensitive), Loader.boot's
|
|
49
49
|
# post-dispatch step turns each pending privacy marking into a real Privacy::Marking.Mark,
|
|
50
50
|
# idempotently. `resolved_eras` and `superseded_eras` are eager, not lazy, so no two
|
|
51
51
|
# dispatching threads race to create them; all writes still happen at boot,
|
|
@@ -7,7 +7,7 @@ module Hecks
|
|
|
7
7
|
module Compensation
|
|
8
8
|
private
|
|
9
9
|
|
|
10
|
-
# Recorded before dispatching, not after `@
|
|
10
|
+
# Recorded before dispatching, not after `@dispatcher.reenter` returns —
|
|
11
11
|
# reenter can recursively re-enter this interpreter and refuse
|
|
12
12
|
# before ever returning here, and recording only on success would
|
|
13
13
|
# be too late for that nested refusal to see this leg's own
|
|
@@ -24,7 +24,7 @@ module Hecks
|
|
|
24
24
|
record = { process_manager: process_manager.name, instance: correlation, dispatch: spec.command_name }
|
|
25
25
|
|
|
26
26
|
log_dispatch_inputs(leg, spec, args) unless spec.with_spec.to_a.empty?
|
|
27
|
-
return refuse_at_depth_ceiling(leg, record) if @
|
|
27
|
+
return refuse_at_depth_ceiling(leg, record) if @dispatcher.reaction_depth_reached?
|
|
28
28
|
|
|
29
29
|
attempt_dispatch(leg, spec, args, record)
|
|
30
30
|
end
|
|
@@ -46,7 +46,7 @@ module Hecks
|
|
|
46
46
|
# it unwinds like a refusal rather than stranding the instance.
|
|
47
47
|
def refuse_at_depth_ceiling(leg, record)
|
|
48
48
|
@registry.saga_log << record.merge(delivered: false,
|
|
49
|
-
reason: "reaction depth #{@
|
|
49
|
+
reason: "reaction depth #{@dispatcher.max_reaction_depth} reached")
|
|
50
50
|
unwind(leg)
|
|
51
51
|
end
|
|
52
52
|
|
|
@@ -95,14 +95,14 @@ module Hecks
|
|
|
95
95
|
nil
|
|
96
96
|
end
|
|
97
97
|
|
|
98
|
-
# Dispatches `command_name` through the
|
|
98
|
+
# Dispatches `command_name` through the dispatcher, stamped with this saga's correlation.
|
|
99
99
|
def reenter_command(leg, command_name, projected, explicit:, source_receiver:)
|
|
100
100
|
head = leg.process_manager.correlation_head
|
|
101
101
|
verb = qualified(command_name, leg.domain)
|
|
102
102
|
invocation = ReactionInvocation.build(registry: @registry, verb: verb, projected: projected,
|
|
103
103
|
explicit: explicit, passthrough: [head],
|
|
104
104
|
source_receiver: source_receiver)
|
|
105
|
-
@
|
|
105
|
+
@dispatcher.reenter(verb, saga_correlation: { head.to_s => leg.correlation }, **invocation)
|
|
106
106
|
end
|
|
107
107
|
|
|
108
108
|
# Unlike a refusal, a crash isn't a domain decision, so it
|
|
@@ -21,7 +21,7 @@ module Hecks
|
|
|
21
21
|
|
|
22
22
|
# The mutex covers only the check-mutate-checkpoint step, never the
|
|
23
23
|
# dispatch cascade that follows — `deliver_saga_dispatch`'s
|
|
24
|
-
# `@
|
|
24
|
+
# `@dispatcher.reenter` can recursively re-enter this interpreter on the
|
|
25
25
|
# same thread, and `Mutex` is not reentrant.
|
|
26
26
|
def remembered_leg_taken?(leg)
|
|
27
27
|
leg.instance = @registry.saga_instances[leg.process_manager.name][leg.correlation]
|
|
@@ -55,11 +55,11 @@ module Hecks
|
|
|
55
55
|
|
|
56
56
|
# @param registry [Runtime::Registry] the booted registry whose declared
|
|
57
57
|
# process managers and saga persistence this interpreter runs against
|
|
58
|
-
# @param
|
|
58
|
+
# @param dispatcher [Runtime::Dispatcher] the dispatcher a saga leg's own dispatch
|
|
59
59
|
# re-enters through
|
|
60
|
-
def initialize(registry,
|
|
60
|
+
def initialize(registry, dispatcher:)
|
|
61
61
|
@registry = registry
|
|
62
|
-
@
|
|
62
|
+
@dispatcher = dispatcher
|
|
63
63
|
end
|
|
64
64
|
|
|
65
65
|
# Runs `domain`'s declared process managers against `event`: begins,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
require_relative "../ports/persistence/binding_policy"
|
|
2
|
+
require_relative "best_effort"
|
|
2
3
|
|
|
3
4
|
module Hecks
|
|
4
5
|
module Runtime
|
|
@@ -37,10 +38,10 @@ module Hecks
|
|
|
37
38
|
# Same defensive shape as EraCheck#lineage_capable? — a class that
|
|
38
39
|
# doesn't respond at all, or whose lookup raises, is false, not an error.
|
|
39
40
|
def tenant_capable?(registry, adapter_name)
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
BestEffort.call(false) do
|
|
42
|
+
adapter_class = registry.adapters[adapter_name] && registry.adapter_class(adapter_name)
|
|
43
|
+
adapter_class.respond_to?(:tenant_capable?) && adapter_class.tenant_capable?
|
|
44
|
+
end
|
|
44
45
|
end
|
|
45
46
|
end
|
|
46
47
|
end
|
|
@@ -37,9 +37,9 @@ module Hecks
|
|
|
37
37
|
# Coerces `value` for a single, already-resolved `attribute`, branching on
|
|
38
38
|
# its declared shape (list, reference, composite, or bare scalar).
|
|
39
39
|
#
|
|
40
|
-
# `boundary: false` is the query
|
|
40
|
+
# `boundary: false` is the query entry point, where a declared type documents the
|
|
41
41
|
# argument for callers/generators rather than naming a shape to enforce.
|
|
42
|
-
# `argument: true` is the command/entity/port dispatch
|
|
42
|
+
# `argument: true` is the command/entity/port dispatch entry point, where a nil for
|
|
43
43
|
# a required attribute is a left-empty argument (C3.7), not ordinary state nil.
|
|
44
44
|
#
|
|
45
45
|
# @raise [Runtime::TypeMismatch] if `value` cannot be coerced, or a required
|
|
@@ -34,7 +34,11 @@ module Hecks
|
|
|
34
34
|
fields
|
|
35
35
|
end
|
|
36
36
|
|
|
37
|
-
# Fills every declared attribute `fields` lacks with its own `default
|
|
37
|
+
# Fills every declared attribute `fields` lacks with its own `default:`, and every required
|
|
38
|
+
# list it lacks with an empty one: a list left out reads as no members, the one shape the
|
|
39
|
+
# Rust runtime (a `Vec`) can hold, so a value object built from nothing (a required
|
|
40
|
+
# argument left empty, C3.7) is `{blocks: []}` on both sides rather than `{}` here.
|
|
41
|
+
# An optional list stays absent, and an offered list, empty or not, is kept as offered.
|
|
38
42
|
#
|
|
39
43
|
# @param value_object [Class] the `Bluebook::ValueObject` subclass whose
|
|
40
44
|
# declared defaults are read
|
|
@@ -42,11 +46,11 @@ module Hecks
|
|
|
42
46
|
# @return [Hash{Symbol => Object}] `fields`, with defaults filled in
|
|
43
47
|
def apply_defaults(value_object, fields)
|
|
44
48
|
value_object.attributes.each_with_object(fields) do |attribute, completed|
|
|
45
|
-
completed
|
|
49
|
+
fill_absent(completed, attribute) unless completed.key?(attribute.name)
|
|
46
50
|
end
|
|
47
51
|
end
|
|
48
52
|
|
|
49
|
-
# The full
|
|
53
|
+
# The full entry point a value object's own fields pass through — shared by
|
|
50
54
|
# `build` and `normalize_composite_fields`, so a nested field refuses
|
|
51
55
|
# exactly like the same type declared directly on a command.
|
|
52
56
|
#
|
|
@@ -85,6 +89,13 @@ module Hecks
|
|
|
85
89
|
|
|
86
90
|
private
|
|
87
91
|
|
|
92
|
+
# The default an absent attribute declares, else an empty list for a required list.
|
|
93
|
+
def fill_absent(fields, attribute)
|
|
94
|
+
return fields[attribute.name] = attribute.default unless attribute.default.nil?
|
|
95
|
+
|
|
96
|
+
fields[attribute.name] = [] if attribute.list? && !attribute.optional?
|
|
97
|
+
end
|
|
98
|
+
|
|
88
99
|
def normalize_composite_field(aggregate, attribute, fields)
|
|
89
100
|
# A list member hydrates the same as a top-level list, so a value
|
|
90
101
|
# read back from the store matches the shape a live dispatch wrote.
|
|
@@ -109,7 +120,8 @@ module Hecks
|
|
|
109
120
|
validate_input_list(aggregate, attribute, fields)
|
|
110
121
|
end
|
|
111
122
|
|
|
112
|
-
# Runs each value-object member of an input list through the same
|
|
123
|
+
# Runs each value-object member of an input list through the same entry point a nested
|
|
124
|
+
# single
|
|
113
125
|
# value goes through, so a member's own invariants and nested lists refuse on dispatch
|
|
114
126
|
# exactly as they do when the list sits directly on a command. The members stay as offered.
|
|
115
127
|
def validate_input_list(aggregate, attribute, fields)
|
data/lib/hecks/runtime.rb
CHANGED
|
@@ -42,12 +42,12 @@ module Hecks
|
|
|
42
42
|
#
|
|
43
43
|
# @param path [String] path to a domain directory, or a file inside one
|
|
44
44
|
# @param shared [String, nil] a shared-root override
|
|
45
|
-
# @param
|
|
45
|
+
# @param install_driving [Boolean] whether to install the Ruby facade constants
|
|
46
46
|
# @param environment [String, nil] the environment name for `Adapters::Folder#load_domain`
|
|
47
47
|
# @return [Runtime::Dispatcher, Runtime::RemoteDispatcher] the dispatcher bound
|
|
48
48
|
# to the booted domain
|
|
49
|
-
def boot(path, shared: nil,
|
|
50
|
-
Loader.boot(path, shared: shared,
|
|
49
|
+
def boot(path, shared: nil, install_driving: true, environment: Runtime::Loader::FROM_ENV)
|
|
50
|
+
Loader.boot(path, shared: shared, install_driving: install_driving, environment: environment)
|
|
51
51
|
end
|
|
52
52
|
|
|
53
53
|
# Loads a domain's declarations without binding any adapter. See Loader.describe.
|
|
@@ -63,23 +63,23 @@ module Hecks
|
|
|
63
63
|
# Finishes a boot from declarations `describe` already loaded. See Loader.boot_described.
|
|
64
64
|
#
|
|
65
65
|
# @param described [Runtime::Loader::Described] what `describe` answered
|
|
66
|
-
# @param
|
|
66
|
+
# @param install_driving [Boolean] whether to install the Ruby facade constants
|
|
67
67
|
# @return [Runtime::Dispatcher, Runtime::RemoteDispatcher] the dispatcher bound
|
|
68
68
|
# to the booted domain
|
|
69
|
-
def boot_described(described,
|
|
70
|
-
Loader.boot_described(described,
|
|
69
|
+
def boot_described(described, install_driving: true)
|
|
70
|
+
Loader.boot_described(described, install_driving: install_driving)
|
|
71
71
|
end
|
|
72
72
|
|
|
73
73
|
# Loads only the given files of a domain; otherwise like `boot`. See Loader.boot_files.
|
|
74
74
|
#
|
|
75
75
|
# @param paths [String, Array<String>] one or more file paths within the domain
|
|
76
76
|
# @param shared [String, nil] a shared-root override
|
|
77
|
-
# @param
|
|
77
|
+
# @param install_driving [Boolean] whether to install the Ruby facade constants
|
|
78
78
|
# @param environment [String, nil] the environment name for the selected-file loader
|
|
79
79
|
# @return [Runtime::Dispatcher, Runtime::RemoteDispatcher] the dispatcher bound
|
|
80
80
|
# to the booted domain
|
|
81
|
-
def boot_files(paths, shared: nil,
|
|
82
|
-
Loader.boot_files(paths, shared: shared,
|
|
81
|
+
def boot_files(paths, shared: nil, install_driving: true, environment: Runtime::Loader::FROM_ENV)
|
|
82
|
+
Loader.boot_files(paths, shared: shared, install_driving: install_driving, environment: environment)
|
|
83
83
|
end
|
|
84
84
|
|
|
85
85
|
# Bind the ambient registry for the duration of the block, restoring
|
|
@@ -4,6 +4,7 @@ require "fileutils"
|
|
|
4
4
|
require "open3"
|
|
5
5
|
require_relative "../rust_build"
|
|
6
6
|
require_relative "wasm"
|
|
7
|
+
require_relative "prebuilt_binary"
|
|
7
8
|
|
|
8
9
|
module Hecks
|
|
9
10
|
module RustBuild
|
|
@@ -102,13 +103,19 @@ module Hecks
|
|
|
102
103
|
def compile(target)
|
|
103
104
|
host_dir = File.join(RustBuild.rust_dir, "host")
|
|
104
105
|
target_dir = ENV.fetch("CARGO_TARGET_DIR", File.join(host_dir, "target"))
|
|
106
|
+
binary = File.join(target_dir, target, "release", BINARY)
|
|
107
|
+
return binary if PrebuiltBinary.fetch("host", host_dir, target: target, into: binary)
|
|
108
|
+
|
|
109
|
+
cargo_build(target, host_dir, { "CARGO_TARGET_DIR" => target_dir }.merge(linker_for(target)))
|
|
110
|
+
binary
|
|
111
|
+
rescue Failure => e
|
|
112
|
+
raise Failure, "#{e.message}#{cross_hint(target)}"
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def cargo_build(target, host_dir, env)
|
|
105
116
|
puts "== cargo build --release --target #{target} --bin #{BINARY} (rust/host) =="
|
|
106
|
-
env = { "CARGO_TARGET_DIR" => target_dir }.merge(linker_for(target))
|
|
107
117
|
RustBuild.command!("rustup", "run", TOOLCHAIN, "cargo", "build", "--release", "--target", target,
|
|
108
118
|
"--bin", BINARY, chdir: host_dir, env: env)
|
|
109
|
-
File.join(target_dir, target, "release", BINARY)
|
|
110
|
-
rescue Failure => e
|
|
111
|
-
raise Failure, "#{e.message}#{cross_hint(target)}"
|
|
112
119
|
end
|
|
113
120
|
|
|
114
121
|
def linker_for(target)
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "digest"
|
|
4
|
+
require "fileutils"
|
|
5
|
+
require "net/http"
|
|
6
|
+
require "uri"
|
|
7
|
+
require "hecks/vocabulary"
|
|
8
|
+
|
|
9
|
+
module Hecks
|
|
10
|
+
module RustBuild
|
|
11
|
+
# A binary hecks has already compiled and published, named by what went into it (ADR 0110).
|
|
12
|
+
#
|
|
13
|
+
# The `PrebuiltBinary` rows of the Vocabulary chapter say which binaries are published: the
|
|
14
|
+
# crate to key, the Cargo binary, the target it is built for. A release tagged `<name>-<key>`
|
|
15
|
+
# holds the binary and its `.sha256`; the key is a hash of the crate's build inputs, so the
|
|
16
|
+
# same bytes are the same release, whichever commit they come from. `fetch` downloads it and
|
|
17
|
+
# checks its hash, and answers nil on any miss (not published yet, no network, a hash that
|
|
18
|
+
# does not match) so a caller compiles as it always did. `HECKS_PREBUILT=off` turns the
|
|
19
|
+
# download off.
|
|
20
|
+
module PrebuiltBinary
|
|
21
|
+
# Where releases are published.
|
|
22
|
+
REPOSITORY = "heckslabs/hecks"
|
|
23
|
+
|
|
24
|
+
# Left out of the key: Cargo's own output, and files that are never part of the binary.
|
|
25
|
+
EXCLUDED = %w[target tests .gitignore].freeze
|
|
26
|
+
|
|
27
|
+
MAX_REDIRECTS = 5
|
|
28
|
+
|
|
29
|
+
module_function
|
|
30
|
+
|
|
31
|
+
# @param name [String] a `PrebuiltBinary` row's name
|
|
32
|
+
# @return [Hash{String => String}] the row
|
|
33
|
+
# @raise [KeyError] when no row has the name
|
|
34
|
+
def row(name)
|
|
35
|
+
Hecks::Vocabulary.rows("PrebuiltBinary").find { |found| found["name"] == name } or
|
|
36
|
+
raise KeyError, "no PrebuiltBinary row named #{name.inspect}"
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# @param crate_dir [String] the crate's directory
|
|
40
|
+
# @return [String] a hash of every file that goes into the build: each path and its bytes, in
|
|
41
|
+
# path order, so it does not depend on the checkout it is read from
|
|
42
|
+
def key(crate_dir)
|
|
43
|
+
files = Dir.glob("**/*", File::FNM_DOTMATCH, base: crate_dir).sort.select do |path|
|
|
44
|
+
File.file?(File.join(crate_dir, path)) && !EXCLUDED.include?(path.split("/").first)
|
|
45
|
+
end
|
|
46
|
+
digest = Digest::SHA256.new
|
|
47
|
+
files.each { |path| digest << "#{path}\0#{File.binread(File.join(crate_dir, path))}\0" }
|
|
48
|
+
digest.hexdigest[0, 24]
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# @param name [String] a row's name
|
|
52
|
+
# @param key [String] the crate's key
|
|
53
|
+
# @return [String] the release tag
|
|
54
|
+
def tag(name, key) = "#{name}-#{key}"
|
|
55
|
+
|
|
56
|
+
# @param name [String] a row's name
|
|
57
|
+
# @return [String] the file the release holds the binary as
|
|
58
|
+
def asset(name)
|
|
59
|
+
found = row(name)
|
|
60
|
+
"#{found["executable"]}-#{found["target"]}"
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# @param name [String] a row's name
|
|
64
|
+
# @param crate_dir [String] the crate's directory
|
|
65
|
+
# @param target [String] the triple the caller builds for
|
|
66
|
+
# @param into [String] the file to write the binary to
|
|
67
|
+
# @return [String, nil] `into`, or nil when the binary is not published for this target or
|
|
68
|
+
# could not be fetched and verified
|
|
69
|
+
def fetch(name, crate_dir, target:, into:)
|
|
70
|
+
return if ENV["HECKS_PREBUILT"] == "off" || row(name)["target"] != target
|
|
71
|
+
|
|
72
|
+
body = verified(name, crate_dir) or return
|
|
73
|
+
FileUtils.mkdir_p(File.dirname(into))
|
|
74
|
+
File.binwrite(into, body)
|
|
75
|
+
File.chmod(0o755, into)
|
|
76
|
+
puts "== downloaded the prebuilt #{asset(name)} (#{tag(name, key(crate_dir))}); nothing compiled =="
|
|
77
|
+
into
|
|
78
|
+
rescue SystemCallError, SocketError, Timeout::Error, OpenSSL::SSL::SSLError
|
|
79
|
+
nil
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# @return [String, nil] the published binary, nil unless its bytes hash to the published
|
|
83
|
+
# sha256
|
|
84
|
+
def verified(name, crate_dir)
|
|
85
|
+
base = "https://github.com/#{REPOSITORY}/releases/download/#{tag(name, key(crate_dir))}/#{asset(name)}"
|
|
86
|
+
expected = get("#{base}.sha256")&.split&.first
|
|
87
|
+
body = expected && get(base)
|
|
88
|
+
body if body && Digest::SHA256.hexdigest(body) == expected
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# @return [String, nil] the body at the URL, following redirects, nil unless it answers 200
|
|
92
|
+
def get(url, redirects = MAX_REDIRECTS)
|
|
93
|
+
response = Net::HTTP.get_response(URI(url))
|
|
94
|
+
return response.body if response.is_a?(Net::HTTPSuccess)
|
|
95
|
+
return get(response["location"], redirects - 1) if response.is_a?(Net::HTTPRedirection) && redirects.positive?
|
|
96
|
+
|
|
97
|
+
nil
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
@@ -11,7 +11,7 @@ module Hecks
|
|
|
11
11
|
# The optional attachments `rust/host` reads from `ir.json`, each omitted when nothing
|
|
12
12
|
# attached provides it: exporter method, then the key it is written under.
|
|
13
13
|
SEAMS = %i[authorization membership identity newsletter newsletter_issues payments
|
|
14
|
-
registrations payment_connection].freeze
|
|
14
|
+
registrations payment_connection checkout].freeze
|
|
15
15
|
|
|
16
16
|
# Round-trips a value through JSON so generators see the string-keyed shape a real
|
|
17
17
|
# `ir.json` carries, never live Ruby symbols.
|
|
@@ -60,7 +60,7 @@ module Hecks
|
|
|
60
60
|
end
|
|
61
61
|
|
|
62
62
|
def require_target!
|
|
63
|
-
return if
|
|
63
|
+
return if RustBuild.target_installed?(TARGET)
|
|
64
64
|
|
|
65
65
|
raise Failure, <<~MSG
|
|
66
66
|
#{TARGET} isn't installed for this toolchain. Install it once with:
|
|
@@ -52,7 +52,7 @@ module Hecks
|
|
|
52
52
|
end
|
|
53
53
|
|
|
54
54
|
def require_target!
|
|
55
|
-
return if
|
|
55
|
+
return if RustBuild.target_installed?(TARGET)
|
|
56
56
|
|
|
57
57
|
raise Failure, <<~MSG
|
|
58
58
|
#{TARGET} isn't installed for this toolchain. Install it once with:
|