nixfleet_proto/
evidence_signing.rs

1//! Shared signing-payload shapes for host event-stream payloads. Adding a
2//! field invalidates existing signatures - bump signing version.
3
4use chrono::{DateTime, Utc};
5use serde::Serialize;
6
7#[derive(Debug, Clone, Serialize)]
8#[serde(rename_all = "camelCase")]
9pub struct ActivationFailedSignedPayload<'a> {
10    pub hostname: &'a str,
11    pub rollout: Option<&'a str>,
12    pub phase: &'a str,
13    pub exit_code: Option<i32>,
14    /// SHA-256 of the JCS bytes of `stderr_tail`.
15    pub stderr_tail_sha256: String,
16}
17
18#[derive(Debug, Clone, Serialize)]
19#[serde(rename_all = "camelCase")]
20pub struct RollbackTriggeredSignedPayload<'a> {
21    pub hostname: &'a str,
22    pub rollout: Option<&'a str>,
23    pub reason: &'a str,
24}
25
26/// Soak-state attestation, bound to (hostname, rollout) so a stale signature
27/// can't replay across rollouts. Without this signature CP cannot trust the
28/// agent's claimed confirmation time (replay would short-circuit the soak gate).
29/// Verified against `hosts.<hostname>.pubkey` from fleet.resolved.
30#[derive(Debug, Clone, Serialize)]
31#[serde(rename_all = "camelCase")]
32pub struct LastConfirmedAtSignedPayload<'a> {
33    pub hostname: &'a str,
34    pub rollout_id: &'a str,
35    pub last_confirmed_at: DateTime<Utc>,
36}
37
38#[derive(Debug, Clone, Serialize)]
39#[serde(rename_all = "camelCase")]
40pub struct RealiseFailedSignedPayload<'a> {
41    pub hostname: &'a str,
42    pub rollout: Option<&'a str>,
43    pub closure_hash: &'a str,
44    pub reason: &'a str,
45}
46
47#[derive(Debug, Clone, Serialize)]
48#[serde(rename_all = "camelCase")]
49pub struct VerifyMismatchSignedPayload<'a> {
50    pub hostname: &'a str,
51    pub rollout: Option<&'a str>,
52    pub expected: &'a str,
53    pub actual: &'a str,
54}
55
56#[derive(Debug, Clone, Serialize)]
57#[serde(rename_all = "camelCase")]
58pub struct ClosureSignatureMismatchSignedPayload<'a> {
59    pub hostname: &'a str,
60    pub rollout: Option<&'a str>,
61    pub closure_hash: &'a str,
62    /// SHA-256 of the JCS bytes of `stderr_tail`.
63    pub stderr_tail_sha256: String,
64}
65
66#[derive(Debug, Clone, Serialize)]
67#[serde(rename_all = "camelCase")]
68pub struct StaleTargetSignedPayload<'a> {
69    pub hostname: &'a str,
70    pub rollout: Option<&'a str>,
71    pub closure_hash: &'a str,
72    pub channel_ref: &'a str,
73    pub signed_at: DateTime<Utc>,
74    pub freshness_window_secs: u32,
75    pub age_secs: i64,
76}
77
78/// Agent could not load + parse the advertised rollout manifest.
79#[derive(Debug, Clone, Serialize)]
80#[serde(rename_all = "camelCase")]
81pub struct ManifestMissingSignedPayload<'a> {
82    pub hostname: &'a str,
83    pub rollout: Option<&'a str>,
84    pub rollout_id: &'a str,
85    pub reason: &'a str,
86}
87
88/// Manifest signature didn't verify against trust roots.
89#[derive(Debug, Clone, Serialize)]
90#[serde(rename_all = "camelCase")]
91pub struct ManifestVerifyFailedSignedPayload<'a> {
92    pub hostname: &'a str,
93    pub rollout: Option<&'a str>,
94    pub rollout_id: &'a str,
95    pub reason: &'a str,
96}
97
98/// Manifest signed but agent's content-bound checks failed (hash, host_set
99/// membership, or pinned-bytes drift).
100#[derive(Debug, Clone, Serialize)]
101#[serde(rename_all = "camelCase")]
102pub struct ManifestMismatchSignedPayload<'a> {
103    pub hostname: &'a str,
104    pub rollout: Option<&'a str>,
105    pub rollout_id: &'a str,
106    pub reason: &'a str,
107}