Skip to main content

zenkey_fleet/report/
registry.rs

1//! The registry plane (RFC 08 §5/§6): a served slice against a local one,
2//! per producer and in aggregate.
3
4use serde::Serialize;
5
6/// One producer, as the bus serves it versus as the checkout declares it
7/// (issue #50). A `None` version means "not present on that side", which is a
8/// fact with two very different explanations — the findings say which.
9#[derive(Debug, Clone, Serialize)]
10pub struct ProducerDiff {
11    pub producer: String,
12    #[serde(skip_serializing_if = "Option::is_none")]
13    pub served_version: Option<String>,
14    #[serde(skip_serializing_if = "Option::is_none")]
15    pub local_version: Option<String>,
16    /// RFC 08 §6 findings, rendered. Empty = the two agree.
17    pub findings: Vec<String>,
18}
19
20/// `zenctl registry diff` (issue #50).
21#[derive(Debug, Clone, Serialize)]
22pub struct RegistryDiff {
23    pub producers: Vec<ProducerDiff>,
24}
25
26impl RegistryDiff {
27    /// Producers whose two sides disagree.
28    pub fn disagreeing(&self) -> usize {
29        self.producers
30            .iter()
31            .filter(|p| !p.findings.is_empty())
32            .count()
33    }
34}
35
36/// One producer where the served slice and the on-disk slice disagree.
37///
38/// A disagreement is **data**, not an error: served wins in the union (the
39/// bus is the runtime truth, RFC 08 §6.1), and the difference is retained for
40/// `doctor` to report instead of being silently overwritten.
41#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize)]
42pub struct SliceDisagreement {
43    pub producer: String,
44    pub bus_version: String,
45    pub dirs_version: String,
46    /// Whether anything beyond the version string differs (subjects,
47    /// procedures, blob tiers).
48    pub shape_differs: bool,
49}