Invariants / DC-NODE-15

DC-NODE-15

DC derived enforced

Forge admissibility requires the durable servable tip to equal the followed peer tip. A --mode node forge is admissible ONLY when durable_servable_tip == followed_peer_tip (hash AND block_no); otherwise it fails closed with a typed structured refusal ForgeRefused::NotCaughtUp { local_servable_tip, followed_peer_tip, reason } -- no forge, no state transition, tip unchanged (distinct from a forge Failed). The recovered anchor (recovered.tip) is NEVER a forge base. The followed-peer-tip signal is a forge-ADMISSIBILITY input only: it may PREVENT a forge but may not select, replace, reorder, or prefer chains (it never reaches select_best_chain / chain_selector / fork_choice).

Source

docs/clusters/PHASE4-N-AE/cluster.md; docs/clusters/PHASE4-N-AE/slices/AE.A.md; docs/planning/phase4-n-ae-slice-a-invariants.md

Introduced in
PHASE4-N-AE

Enforcement trace

Tests 3

  • forge_refused_not_caught_up
  • forge_base_falls_back_to_snapshot_anchor
  • forge_on_followed_tip_proceeds_with_parent_byte_equal

Cross-references

Strengthened in

Evidence notes

PHASE4-N-AE.A (2026-06-06). ENFORCED. The --mode node ForgeTick recovered.tip forge-base fallback (node_lifecycle.rs:1102 None => act.recovered.tip.clone()) is removed: the forge base is the durable servable tip (ChainDb::tip(); the recovered snapshot anchor is never a forge base). A closed GREEN classifier forge_followed_tip_admission(durable_servable_tip, followed_peer_tip) returns CaughtUp iff BOTH tips are present AND hash AND block_no are equal, else NotCaughtUp{reason} (NoFollowedPeerTip | NoDurableServableTip | TipMismatch). On the recovered/following path the ForgeTick arm calls the classifier BEFORE the single fenced forge_one_from_recovered; NotCaughtUp records a typed ForgeRefused::NotCaughtUp{local_servable_tip, followed_peer_tip, reason} into ForgeActivation.last_forge_refused (a structured LOCAL observation, never a log-string-only path) and the forge does not fire (no state transition, tip unchanged) -- mechanically distinct from a forge Failed. The followed-peer-tip signal (FollowedPeerTipSignal) is sourced from the SAME run_admission_wire_pump stream (the AdmissionPeerEvent::TipUpdate events NodeBlockSource skips for sync are recorded as a write-only side effect); it is a forge-ADMISSIBILITY input only and never reaches select_best_chain/chain_selector/fork_choice (gate (d) static-grep enforced). The from-genesis cold-start (recovered.tip None) is upstream of the gate (DC-NODE-08). Gate: ci_check_forge_followed_tip_admission.sh.