Module: Hecks::Runtime::EraCheck
- Defined in:
- lib/hecks/ports/persistence/plugins/era/era_check.rb
Overview
The boot-time era gate, run for the adapters that HAVE eras — the lineage-capable ones. An era is a fact about stored data that some adapter can carry across a shape change; an adapter that cannot translate has no era to hold, and holding one for it would record history about data nothing can act on.
The whole domain is handed to the capable adapter's own era check (Postgres: hold, recognize, mint, or refuse toward the scaffold), which keeps its era facts as rows BESIDE its data. That co-location is load-bearing — a watermark only means something against the journal it was cut from, and an approval recorded anywhere but the reviewed database binds to nothing.
The capability is asked of the adapter, never of its name: a second adapter that grows an era story declares lineage_capable? and era_check! and needs no change here.
Detection and identity are separate jobs: this check never hashes anything — era names come from the store, already minted (by the scaffold) or absent. Refusal wordings are contract, pinned by the corpus.
Class Method Summary collapse
- .adapter_for(registry, domain, aggregate) ⇒ Object
-
.check!(registry, directory) ⇒ Object
EACH BLUEBOOK'S OWN SOURCE, not one file read once and reused for every bluebook in the registry — true as long as a domain directory only ever held exactly one, and silently wrong the moment
uses_frameworkmade a second, differently-sourced bluebook (Governance, Identity —lib/hecks/framework/bluebook/, not the domain's own directory) share a boot with the first. - .check_bluebook!(registry, bluebook, current_text, directory: nil) ⇒ Object
-
.check_compute_rules!(registry, bluebook) ⇒ Object
The per-rule capability gate — NOT an era fact, and so it survives on every adapter: a compute rule's SQL is its only implementation, so an aggregate carrying one cannot boot anywhere but Postgres, whatever any shape comparison would say.
-
.check_compute_rules_for_registry!(registry) ⇒ Object
The domain-agnostic half, split out for ADR 0031's boot-gate registry: a compute rule requires Postgres whatever adapter is actually bound, so this must run for EVERY registry, the same way
registry.verify!does — it is not conditional on any adapter being lineage-capable, and must never be skipped bycheck_lineage!'s own capability gate below. -
.check_lineage!(registry, directory) ⇒ Object
The capability-gated half — ADR 0031's registered
:era_checkgate. -
.lineage_capable?(registry, adapter_name) ⇒ Boolean
The capability idiom: an adapter CLASS that answers lineage_capable? with true carries eras and may act on drift (translate, fork, merge).
-
.lineage_capable_registry?(registry) ⇒ Boolean
The
:era_checkgate's own registration predicate: true iff at least one bluebook's own anchor (first) aggregate resolves to a lineage-capable adapter — mirrorscheck_bluebook!'s existing per-bluebook anchor check, just asked once, up front, of the whole registry, so a registry with nothing lineage-capable bound anywhere never registers the gate at all. -
.source_text_for(bluebook, directory) ⇒ Object
The domain's own directory first, matched by name — a real app's directory may hold more than one file once
uses_frameworkexists, so ".first" alone can no longer be trusted, the exact way it silently wasn't the day this was found: three domains booted together, one real source text read once (the domain's own, ".first"'d), and every OTHER domain's era-1 held THAT text under its own name — a later shadow-parse of it reconstructs a completely different shape, and every boot after the first refuses toward a scaffold that was never the real drift.
Class Method Details
.adapter_for(registry, domain, aggregate) ⇒ Object
153 154 155 |
# File 'lib/hecks/ports/persistence/plugins/era/era_check.rb', line 153 def adapter_for(registry, domain, aggregate) Ports::Persistence::BindingPolicy.resolve(registry, domain, aggregate).adapter end |
.check!(registry, directory) ⇒ Object
EACH BLUEBOOK'S OWN SOURCE, not one file read once and reused
for every bluebook in the registry — true as long as a domain
directory only ever held exactly one, and silently wrong the
moment uses_framework made a second, differently-sourced
bluebook (Governance, Identity — lib/hecks/framework/bluebook/,
not the domain's own directory) share a boot with the first.
Caught the hard way: three domains booted together, one real
source text (the domain's own), and every OTHER domain's era-1
held THAT text under its own name — a shadow-parse of it later
reconstructs a completely different shape, and every boot after
the first refuses toward a scaffold that was never the real
drift.
46 47 48 49 |
# File 'lib/hecks/ports/persistence/plugins/era/era_check.rb', line 46 def check!(registry, directory) check_compute_rules_for_registry!(registry) check_lineage!(registry, directory) end |
.check_bluebook!(registry, bluebook, current_text, directory: nil) ⇒ Object
117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
# File 'lib/hecks/ports/persistence/plugins/era/era_check.rb', line 117 def check_bluebook!(registry, bluebook, current_text, directory: nil) first = bluebook.aggregates.first return unless first adapter_name = adapter_for(registry, bluebook.name, first) return unless lineage_capable?(registry, adapter_name) unless current_text raise WiringError, "cannot boot #{bluebook.name}: bound to a lineage-capable adapter, but no source file for " \ "it could be found (checked #{directory.inspect} and the framework registry)" end settings = registry.world(bluebook.name)&.for_binding(Ports::Persistence::VERB, adapter_name) || {} registry.adapter_class(adapter_name).era_check!( registry: registry, bluebook: bluebook, current_text: current_text, settings: settings, directory: directory ) end |
.check_compute_rules!(registry, bluebook) ⇒ Object
The per-rule capability gate — NOT an era fact, and so it survives on every adapter: a compute rule's SQL is its only implementation, so an aggregate carrying one cannot boot anywhere but Postgres, whatever any shape comparison would say.
141 142 143 144 145 146 147 148 149 150 151 |
# File 'lib/hecks/ports/persistence/plugins/era/era_check.rb', line 141 def check_compute_rules!(registry, bluebook) bluebook.aggregates.each do |aggregate| lineage = Ports::Persistence::Lineage.for(registry, bluebook.name, aggregate) next unless lineage&.computes? adapter = adapter_for(registry, bluebook.name, aggregate) next if lineage_capable?(registry, adapter) raise WiringError, "compute rules require the Postgres adapter; #{aggregate.name} is bound to #{adapter}" end end |
.check_compute_rules_for_registry!(registry) ⇒ Object
The domain-agnostic half, split out for ADR 0031's boot-gate
registry: a compute rule requires Postgres whatever adapter is
actually bound, so this must run for EVERY registry, the same way
registry.verify! does — it is not conditional on any adapter
being lineage-capable, and must never be skipped by
check_lineage!'s own capability gate below.
57 58 59 |
# File 'lib/hecks/ports/persistence/plugins/era/era_check.rb', line 57 def check_compute_rules_for_registry!(registry) registry.bluebooks.each_value { |bluebook| check_compute_rules!(registry, bluebook) } end |
.check_lineage!(registry, directory) ⇒ Object
The capability-gated half — ADR 0031's registered :era_check
gate. Registration is conditional on lineage_capable_registry?;
check_bluebook! below still carries its own per-bluebook
lineage_capable? return-early, unchanged, for a registry with a
mix of lineage-capable and plain-adapter bluebooks.
66 67 68 69 70 |
# File 'lib/hecks/ports/persistence/plugins/era/era_check.rb', line 66 def check_lineage!(registry, directory) registry.bluebooks.each_value do |bluebook| check_bluebook!(registry, bluebook, source_text_for(bluebook, directory), directory: directory) end end |
.lineage_capable?(registry, adapter_name) ⇒ Boolean
The capability idiom: an adapter CLASS that answers lineage_capable? with true carries eras and may act on drift (translate, fork, merge). Postgres alone does today; the seam is what lets a second one arrive without touching this file.
161 162 163 164 165 166 |
# File 'lib/hecks/ports/persistence/plugins/era/era_check.rb', line 161 def lineage_capable?(registry, adapter_name) adapter_class = registry.adapters[adapter_name] && registry.adapter_class(adapter_name) adapter_class.respond_to?(:lineage_capable?) && adapter_class.lineage_capable? rescue StandardError false end |
.lineage_capable_registry?(registry) ⇒ Boolean
The :era_check gate's own registration predicate: true iff at
least one bluebook's own anchor (first) aggregate resolves to a
lineage-capable adapter — mirrors check_bluebook!'s existing
per-bluebook anchor check, just asked once, up front, of the
whole registry, so a registry with nothing lineage-capable bound
anywhere never registers the gate at all.
78 79 80 81 82 83 84 85 |
# File 'lib/hecks/ports/persistence/plugins/era/era_check.rb', line 78 def lineage_capable_registry?(registry) registry.bluebooks.each_value.any? do |bluebook| first = bluebook.aggregates.first next false unless first lineage_capable?(registry, adapter_for(registry, bluebook.name, first)) end end |
.source_text_for(bluebook, directory) ⇒ Object
The domain's own directory first, matched by name — a real app's
directory may hold more than one file once uses_framework
exists, so ".first" alone can no longer be trusted, the exact
way it silently wasn't the day this was found: three domains
booted together, one real source text read once (the domain's
own, ".first"'d), and every OTHER domain's era-1 held THAT text
under its own name — a later shadow-parse of it reconstructs a
completely different shape, and every boot after the first
refuses toward a scaffold that was never the real drift.
A single-file directory whose one file names something ELSE
falls back to it anyway (a fixture may legitimately name its
file differently from the Hecks.bluebook it declares) — UNLESS
this bluebook is a known framework member, in which case that
one file is certainly some OTHER domain's, not this one's, and
the framework registry is asked instead — the only other place a
bluebook in this registry could have come from, per
uses_framework.
105 106 107 108 109 110 111 112 113 114 115 |
# File 'lib/hecks/ports/persistence/plugins/era/era_check.rb', line 105 def source_text_for(bluebook, directory) domain_files = Dir[File.join(directory, "*.bluebook")] own = domain_files.select do |path| File.foreach(path, encoding: "UTF-8").any? { |line| line.match?(/\A\s*Hecks\.bluebook\s+#{Regexp.escape(bluebook.name.inspect)}/) } end own = domain_files if own.empty? && domain_files.size == 1 && !Framework.members.key?(bluebook.name) own = [Framework.members[bluebook.name]].compact if own.empty? return if own.empty? own.map { |path| File.read(path, encoding: "UTF-8") }.join("\n") end |