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