Skip to main content

ManifestProvenance

Struct ManifestProvenance 

Source
pub struct ManifestProvenance {
    pub build_git_sha: Option<String>,
    pub build_lock_digest: Option<String>,
    pub wire_crate_version: Option<String>,
    pub store_schema_version: Option<String>,
}
Expand description

Build facts a module DECLARES about its own binary at HELLO. The daemon overlays process-identity evidence it alone can attest; the two halves are served together via supervisor.provenance and never merged.

The canonical constructor form is a full 40-character lowercase hexadecimal build_git_sha and a full 64-character lowercase hexadecimal build_lock_digest; abbreviations are not conforming. The daemon’s HELLO decoder intentionally remains lenient enough to relay older declarations, so this construction contract is enforced by build_provenance rather than by wire deserialization.

Honesty contract for constructors (ruled with the first adopters):

  • Every field is a VERIFIED-AT-BUILD claim. No field is required: a module may declare any subset, and omitting an inapplicable field is the honest choice rather than inventing a value to fill it. Populate build_git_sha only from a value injected by the build/release pipeline (CK_BUILD_REV via option_env! guarded by the packaging path, or build.rs equivalent) — never from ambient env at an arbitrary consumer compile, which mints a provenance claim from an accident of whoever ran cargo. A builder that can determine whether the tree was clean may declare the sha regardless of whether a release pipeline exists.
  • Dirty or unstamped builds declare None for the affected fields. A populated field stops the reader asking; absent-and-honest beats present-and-best-effort. Absence is reported at two levels with two distinct words: a module that declared no provenance block at all reads unverifiable, while an omitted field inside a declared block is dropped from the wire and reads unavailable. So omitting a field never costs a module its Reported status – declaration is decided by whether the manifest carried a block, not by which fields it filled.
  • Dirty-tree stamps are not canonical build_git_sha values. A pipeline that emits -dirty must omit the affected field rather than pass that stamp to the canonical constructor. Stricter is better: cerebellum’s build.rs reports the commit ONLY when the tree was clean, on the argument that dirty bytes match no commit and a precise-looking wrong answer beats absence at being believed.
  • Two silent-when-wrong checks for any build-rev embedder (CEREB): does the builder know whether the tree was clean, and can its no-git sentinel (source-tarball builds) escape into a field parsed as a sha? Sentinels render as absence, never as a value.
  • Fill fields FROM THE BUILD only: reading Cargo.lock or the wire crate version inside the manifest constructor describes the source tree sitting beside the running binary, not the binary — the exact claim this struct exists to avoid.
  • Declare what you KNOW, not blanket-None (WERNI): store_schema_version needs no pipeline — any module with a migration list can state its newest migration as fact, and a daemon comparing it against the store’s actual version sees a stale-binary mismatch directly. Blanket None where a field is knowable wastes the field; blanket-fill where it is not mints a lie. Absence also beats sentinel values (CKCRED): omit the FIELD when BUILD_REV reads a builder sentinel (“unknown”, “unavailable”, “none”, any casing) — publishing the sentinel string as a fact is a well-formed lie shape validation cannot catch. Field omission, not block omission, is the target shape for SDK modules: wire_crate_version is a compile-time constant of the linked crate, so a module using the SDK always has at least one honest fact and build_provenance reflects that by never returning an absent block. (Block absence remains meaningful on the wire — it reads unverifiable, the module made no claim — but it is the shape for non-adopters and proxied manifests, not a target for declarers; see #78.) The hazard in one sentence, for every referent and sentinel case alike: A PRESENT, WELL-FORMED FIELD STOPS THE READER ASKING — a value from the wrong domain and a sentinel from the wrong vocabulary are indistinguishable from a correct value to every check that inspects shape rather than meaning.
  • PROXIED MANIFESTS STAY None PERMANENTLY (CALLO): a process that forwards another machine’s manifest cannot observe that build, and a forwarded provenance claim is indistinguishable on the wire from a verified one — filling it launders an unverifiable assertion. Same reasoning as pinning a re-exported module’s trust_tier to Untrusted. Record that at the construction site: injection-wiring sweeps grep for provenance: and the obvious action at a re-export site is the wrong one.

Fields§

§build_git_sha: Option<String>§build_lock_digest: Option<String>§wire_crate_version: Option<String>

REFERENT: the subc-protocol crate version linked into this binary (subc_protocol::SUBC_PROTOCOL_CRATE_VERSION) — the fleet’s shared wire vocabulary, one numbering space for every module. Never a module’s own envelope/payload crate version: that is real information in a different numbering space, and here it scores as a confident wrong answer at any census gate. (QTA’s rule, learned live: a field whose entire content is a referent cannot be documented by its constraints — so the referent is stated here, where readers look.)

§store_schema_version: Option<String>

Implementations§

Trait Implementations§

Source§

impl Clone for ManifestProvenance

Source§

fn clone(&self) -> ManifestProvenance

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for ManifestProvenance

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<'de> Deserialize<'de> for ManifestProvenance

Source§

fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl Eq for ManifestProvenance

Source§

impl PartialEq for ManifestProvenance

Source§

fn eq(&self, other: &ManifestProvenance) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl Serialize for ManifestProvenance

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more
Source§

impl StructuralPartialEq for ManifestProvenance

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.