pub struct LineageHeadReceipt {
pub receipt_version: String,
pub registry_did: String,
pub lineage_id: LineageId,
pub head_ctx_id: CtxId,
pub head_version: u32,
pub head_status: String,
pub as_of: DateTime<Utc>,
pub signature: Signature,
}Expand description
A registry-signed lineage-head receipt (RFC-ACDP-0011): the
registry’s attestation that, as of as_of, the head of lineage_id
was head_ctx_id at head_version with head_status.
CLOSED schema (acdp-lineage-head-receipt.schema.json,
additionalProperties: false): every member is signed, so an
unknown member changes the preimage and is rejected at parse time.
The signing construction reuses RFC-ACDP-0010 §5 verbatim — JCS of
the object minus signature, SHA-256, signature over the ASCII
bytes of "sha256:<hex>" — with receipt_version acting as the
in-preimage domain separator.
Unlike RegistryReceipt, head receipts are ephemeral: the
head moves on every supersession, so a registry mints a fresh
receipt (fresh as_of) per /current response (RFC-ACDP-0011 §6).
Fields§
§receipt_version: StringMUST be exactly LINEAGE_HEAD_RECEIPT_VERSION ("acdp-lhr/1").
registry_did: StringThe attesting registry’s DID — did:web:<authority> where
<authority> is the registry’s serving authority
(RFC-ACDP-0011 §4, did:web-only as RFC-ACDP-0010 §4).
lineage_id: LineageIdThe attested lineage (RFC-ACDP-0001 §5.6).
head_ctx_id: CtxIdThe ctx_id of the head version. Its authority MUST equal the
method-specific identifier of registry_did (lineages are
single-registry, RFC-ACDP-0004 §5.3).
head_version: u32The head’s body.version (≥ 1).
head_status: StringThe head’s registry-derived status at as_of (RFC-ACDP-0004
§4). Never superseded — a superseded version is never the
head — and never retracted (RFC-ACDP-0013 §8.3: a retracted
version is never served as head); in practice active or
expired. Kept as the raw wire string so byte-for-byte
comparison with the served registry_state.status is exact
(RFC-ACDP-0011 §7 step 5).
as_of: DateTime<Utc>Registry response-time clock when the head claim was evaluated. Canonical millisecond-precision RFC 3339 UTC, always serialized with exactly three fractional digits (RFC-ACDP-0001 §5.3).
signature: SignatureRegistry signature over the receipt preimage — same envelope and same receipt signing key as RFC-ACDP-0010 §4/§5.
Implementations§
Source§impl LineageHeadReceipt
impl LineageHeadReceipt
Sourcepub fn from_value(value: &Value) -> Result<Self, AcdpError>
pub fn from_value(value: &Value) -> Result<Self, AcdpError>
Parse a head receipt from the JSON value carried in
crate::body::FullContext::lineage_head_receipt, enforcing
the closed schema plus the RFC-ACDP-0011 §4 semantic invariants
(§7 step 1): exact receipt_version, head_version ≥ 1,
head_status pattern and never superseded, did:web-only
registry_did, canonical millisecond as_of byte form.
Sourcepub fn preimage_hash_of_value(value: &Value) -> Result<ContentHash, AcdpError>
pub fn preimage_hash_of_value(value: &Value) -> Result<ContentHash, AcdpError>
Compute the preimage hash from the RAW wire JSON of a head
receipt (the value minus signature, canonicalized as
received). Verifiers MUST hash the receipt exactly as received —
same raw-JSON rule as RegistryReceipt::preimage_hash_of_value.
Sourcepub fn validate_as_of_form(value: &Value) -> Result<(), AcdpError>
pub fn validate_as_of_form(value: &Value) -> Result<(), AcdpError>
Validate the §4 byte form of the raw as_of: canonical
millisecond-precision RFC 3339 UTC with exactly three fractional
digits and a literal Z.
Sourcepub fn preimage_hash(&self) -> Result<ContentHash, AcdpError>
pub fn preimage_hash(&self) -> Result<ContentHash, AcdpError>
Compute the receipt’s signature preimage hash from the struct.
Used at MINT time; verifiers should prefer
Self::preimage_hash_of_value over the raw wire JSON.
Sourcepub fn verify_signature_with_key(
&self,
registry_pub_ed25519: Option<&[u8; 32]>,
registry_pub_p256_sec1: Option<&[u8]>,
) -> Result<(), AcdpError>
pub fn verify_signature_with_key( &self, registry_pub_ed25519: Option<&[u8; 32]>, registry_pub_p256_sec1: Option<&[u8]>, ) -> Result<(), AcdpError>
Verify the receipt signature against a known registry public key
(pure — no DID resolution; the client feature’s
verify_lineage_head_receipt_value resolves the registry DID and
calls this).
Sourcepub fn verify_signature_against_hash(
&self,
hash: &ContentHash,
registry_pub_ed25519: Option<&[u8; 32]>,
registry_pub_p256_sec1: Option<&[u8]>,
) -> Result<(), AcdpError>
pub fn verify_signature_against_hash( &self, hash: &ContentHash, registry_pub_ed25519: Option<&[u8; 32]>, registry_pub_p256_sec1: Option<&[u8]>, ) -> Result<(), AcdpError>
Like Self::verify_signature_with_key but over an
already-computed preimage hash — pair with
Self::preimage_hash_of_value for raw-JSON verification.
Sourcepub fn cross_check_registry_binding(
&self,
serving_authority: &str,
capabilities_registry_did: &str,
) -> Result<(), AcdpError>
pub fn cross_check_registry_binding( &self, serving_authority: &str, capabilities_registry_did: &str, ) -> Result<(), AcdpError>
RFC-ACDP-0011 §7 step 3 — registry binding (pure):
registry_didequalsdid:web:<serving_authority>— the authority the response was actually fetched from;registry_didequalscapabilities.registry_did;- the DID portion of
signature.key_idequalsregistry_did; - the authority component of
head_ctx_idequals the method-specific identifier ofregistry_did(lineages are single-registry).
Sourcepub fn cross_check_lineage(
&self,
requested: &LineageId,
) -> Result<(), AcdpError>
pub fn cross_check_lineage( &self, requested: &LineageId, ) -> Result<(), AcdpError>
RFC-ACDP-0011 §7 step 4 — lineage binding: lineage_id MUST
equal the lineage the consumer requested (on /current) or the
accompanying body.lineage_id (on full retrieval), byte-for-byte.
Sourcepub fn cross_check_head(
&self,
served_ctx_id: &CtxId,
served_version: u32,
served_status: &Status,
on_current_endpoint: bool,
) -> Result<(), AcdpError>
pub fn cross_check_head( &self, served_ctx_id: &CtxId, served_version: u32, served_status: &Status, on_current_endpoint: bool, ) -> Result<(), AcdpError>
RFC-ACDP-0011 §7 steps 5 / 5b — head binding against the accompanying response.
on_current_endpoint = true for GET /lineages/{id}/current,
where the receipt MUST describe the very head being served
(step 5 byte-match, fixture lhr-002). On full retrieval the
step-5 match applies when head_ctx_id equals the retrieved
ctx_id; otherwise the receipt claims the retrieved context is
stale and step 5b’s consistency rule applies (head_version
strictly greater, served status superseded — or retracted
on a registry also advertising acdp-registry-lifecycle, per
the RFC-ACDP-0013 §7.2 precedence).
Sourcepub fn check_as_of_skew(
&self,
now: DateTime<Utc>,
max_clock_skew: Duration,
) -> Result<(), AcdpError>
pub fn check_as_of_skew( &self, now: DateTime<Utc>, max_clock_skew: Duration, ) -> Result<(), AcdpError>
RFC-ACDP-0011 §7 step 6 — as_of sanity against the consumer’s
clock: millisecond-truncated (RFC-ACDP-0001 §5.3) and not in the
future beyond max_clock_skew (RECOMMENDED 120 s). A
future-dated as_of is a forged freshness claim (fixture
lhr-004).
Note this is the verification half only. Staleness (an old but
honest as_of) is consumer freshness policy (§6) — evaluate it
separately via Self::age_at.
Trait Implementations§
Source§impl Clone for LineageHeadReceipt
impl Clone for LineageHeadReceipt
Source§fn clone(&self) -> LineageHeadReceipt
fn clone(&self) -> LineageHeadReceipt
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more