Skip to main content

ic_backup/model/operation_plan/context/
mod.rs

1//! Canonical declared network, caller and release context; no fresh permission.
2
3use super::OperationPlanError;
4use crate::model::artifacts::canonical_hash;
5use serde::{Deserialize, Serialize};
6
7/// Passive integration-owned exact execution context declarations.
8#[derive(Clone, Debug)]
9pub struct PlanContextRequest {
10    /// Qualified network fingerprint digest, not an endpoint label.
11    pub network: String,
12    /// Exact selected caller principal; credentials are excluded.
13    pub caller: String,
14    /// Exact opaque release evidence digest supplied by its owner.
15    pub release: String,
16}
17/// Immutable canonical declared context shared by every operation in one plan.
18#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
19#[serde(try_from = "ContextFields")]
20pub struct PlanContextRecord {
21    network: String,
22    caller: String,
23    release: String,
24}
25#[derive(Deserialize)]
26#[serde(deny_unknown_fields)]
27struct ContextFields {
28    network: String,
29    caller: String,
30    release: String,
31}
32impl TryFrom<ContextFields> for PlanContextRecord {
33    type Error = OperationPlanError;
34    fn try_from(fields: ContextFields) -> Result<Self, Self::Error> {
35        Self::new(&PlanContextRequest {
36            network: fields.network,
37            caller: fields.caller,
38            release: fields.release,
39        })
40    }
41}
42impl PlanContextRecord {
43    /// Canonicalize exact declarations without IO or fresh authorization.
44    ///
45    /// # Errors
46    /// Rejects malformed principal or SHA-256 digest fields.
47    pub fn new(request: &PlanContextRequest) -> Result<Self, OperationPlanError> {
48        Ok(Self {
49            network: canonical_hash(&request.network)?,
50            caller: crate::model::principal::canonical_text(&request.caller)
51                .ok_or(OperationPlanError::InvalidPrincipal("caller"))?,
52            release: canonical_hash(&request.release)?,
53        })
54    }
55    /// Read the declared canonical network fingerprint.
56    #[must_use]
57    pub fn network(&self) -> &str {
58        &self.network
59    }
60    /// Read the exact canonical selected caller.
61    #[must_use]
62    pub fn caller(&self) -> &str {
63        &self.caller
64    }
65    /// Read the integration-owned release evidence digest.
66    #[must_use]
67    pub fn release(&self) -> &str {
68        &self.release
69    }
70}