pub struct Anchor {
pub version: u8,
pub epoch: u32,
pub count: u64,
pub head_hex: String,
pub written_at: u64,
pub orphaned_since: Option<u64>,
}Expand description
A per-file downgrade-resistance record, stored as an age-vault secret keyed by
anchor_key.
Authenticity comes entirely from the vault’s own AEAD encryption — the anchor carries no MAC of its own, since an attacker who cannot decrypt the vault cannot forge or delete an entry either way.
Fields§
§version: u8Format version, for forward compatibility.
epoch: u32The finalizing key epoch (cross-check + operator diagnostics only — not required to match on read, since a legitimately re-keyed file may resolve under a different epoch).
count: u64Total on-disk entry count at the time this anchor was written.
head_hex: StringThe verified chain head at exactly count entries, hex-encoded.
written_at: u64Wall-clock milliseconds at write time, embedded inside this AEAD-protected value so
it is unforgeable by a file-write-only attacker (unlike filesystem mtime, which such an
attacker can freely rewrite via utimensat). Used by the session-anchor reconcile-and-cap
sweep to select the true oldest anchor for eviction (issue #6449 rev2 critic S3) — eviction
ordering must never depend on an attacker-controlled signal.
orphaned_since: Option<u64>Wall-clock milliseconds at which the reconcile-and-cap sweep first observed this anchor’s
backing file/session-directory absent. None while the file exists. Set on the first
sweep that finds the file gone, cleared if the file reappears before the grace window
elapses (self-heal), and used to gate orphan reap behind a grace window so a
delete→wait-out-a-sweep→recreate-forged-legacy sequence cannot make the sweep delete the
anchor on the attacker’s behalf (issue #6462). #[serde(default)] means pre-existing
persisted anchors deserialize with None, no vault migration needed;
skip_serializing_if keeps steady-state (never-orphaned) anchors byte-identical to their
pre-#6462 serialization.
Implementations§
Source§impl Anchor
impl Anchor
Sourcepub fn new(epoch: u32, count: u64, head: ChainHash) -> Self
pub fn new(epoch: u32, count: u64, head: ChainHash) -> Self
Construct a new anchor for a file finalized with epoch/count/head, stamping
Self::written_at with the current wall-clock time.
Sourcepub fn head(&self) -> Result<ChainHash, AnchorError>
pub fn head(&self) -> Result<ChainHash, AnchorError>
Parse Self::head_hex back into a ChainHash.
§Errors
Returns AnchorError::Malformed if the stored hex is not a valid chain hash — this can
only happen if the vault entry was corrupted or hand-edited by the age-key holder, not by
a file-write-only attacker.