Skip to main content

dsfb_densor_runtime/
manifest.rs

1//! The densor manifest — the frozen declaration of which densors + authorities a pipeline run is allowed to use.
2//!
3//! Before executing anything, the runtime loads this manifest and validates it: every entry must be identifiable,
4//! ids must be unique, and the frozen authority set is the allow-list a stage's declared authorities are checked
5//! against. The manifest is data (no behaviour); validation is pure.
6
7use crate::authority::AuthorityHash;
8use crate::densor::DensorKind;
9use crate::errors::RuntimeError;
10use serde::{Deserialize, Serialize};
11
12/// One declared densor in the manifest.
13#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
14pub struct DensorEntry {
15    pub id: String,
16    pub kind: DensorKind,
17    /// The expected 32-byte evidence hash of this densor (checked against the produced object on execution).
18    pub evidence_hash: [u8; 32],
19}
20
21/// A pipeline's frozen manifest: the densors it carries + the authority allow-list its stages may cite.
22#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
23pub struct DensorManifest {
24    pub pipeline_id: String,
25    pub densors: Vec<DensorEntry>,
26    /// The complete frozen set of authorities any stage in this run is permitted to have been built against.
27    pub authorities: Vec<AuthorityHash>,
28}
29
30impl DensorManifest {
31    /// Validate the manifest is well-formed: non-empty pipeline id, every densor identifiable, unique ids, and at
32    /// least one frozen authority (a run with no authority anchor is not admissible). Pure; never mutates.
33    pub fn validate(&self) -> Result<(), RuntimeError> {
34        if self.pipeline_id.trim().is_empty() {
35            return Err(RuntimeError::ManifestInvalid("empty pipeline_id".into()));
36        }
37        if self.authorities.is_empty() {
38            return Err(RuntimeError::ManifestInvalid(
39                "no frozen authorities (a run needs an authority anchor)".into(),
40            ));
41        }
42        let mut seen = std::collections::BTreeSet::new();
43        for d in &self.densors {
44            if d.id.trim().is_empty() {
45                return Err(RuntimeError::ManifestInvalid(
46                    "a densor entry has an empty id".into(),
47                ));
48            }
49            if !seen.insert(d.id.as_str()) {
50                return Err(RuntimeError::ManifestInvalid(format!(
51                    "duplicate densor id '{}'",
52                    d.id
53                )));
54            }
55        }
56        Ok(())
57    }
58
59    /// True iff `authority` is in the manifest's frozen allow-list (matched by name AND digest).
60    pub fn permits_authority(&self, authority: &AuthorityHash) -> bool {
61        self.authorities
62            .iter()
63            .any(|a| a.name == authority.name && a.hash == authority.hash)
64    }
65}