Skip to main content

ic_memory/
policy.rs

1use crate::{key::StableKey, slot::MemoryManagerSlot};
2use serde::Serialize;
3
4///
5/// PolicyIdentity
6///
7/// Host-issued token binding one prepared runtime bootstrap policy configuration.
8///
9/// All 32-byte values are valid. Hosts choose a stable token and change it when
10/// policy semantics or effective configuration change. Names, versions, hashing
11/// and fallible configuration preparation stay with the host. The token is an
12/// equality binding, not authentication or proof that a policy is correct.
13/// It is retained in memory and serialized for diagnostics, never persisted
14/// in the allocation ledger. Diagnostic JSON contains a 32-element byte array.
15///
16
17#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize)]
18#[serde(transparent)]
19pub struct PolicyIdentity([u8; 32]);
20
21impl PolicyIdentity {
22    /// Construct a token from the host's complete policy identity bytes.
23    #[must_use]
24    pub const fn new(bytes: [u8; 32]) -> Self {
25        Self(bytes)
26    }
27
28    /// Borrow the exact identity bytes used for equality and diagnostics.
29    #[must_use]
30    pub const fn as_bytes(&self) -> &[u8; 32] {
31        &self.0
32    }
33}
34
35///
36/// RuntimeBootstrapPolicy
37///
38/// Host policy for recovered admission, allocation checks and runtime identity.
39///
40/// The runtime admits host grants and pool eligibility before calling the
41/// allocation check for each external declaration. Governance stays private;
42/// historical ownership checks still apply to every declaration.
43///
44/// [`crate::MemoryRuntime`] binds its successful bootstrap to this identity.
45/// Repeated bootstrap is idempotent only when the caller supplies the same
46/// sealed declaration snapshot and the same policy identity. Implementations
47/// should change the identity whenever policy configuration or semantics
48/// change. Hosts derive the token from all effective configuration and prepare
49/// any fallible policy setup before calling the runtime. Labels, versions and
50/// hashing algorithms belong to the host; this crate compares the token bytes.
51///
52
53pub trait RuntimeBootstrapPolicy {
54    /// Policy error type.
55    type Error;
56
57    /// Validate one resolved stable-key and allocation-slot claim.
58    /// The runtime checks host grants and pool eligibility before this callback;
59    /// historical ownership checks follow it. Governance bypasses this callback.
60    fn validate_allocation(
61        &self,
62        key: &StableKey,
63        slot: &MemoryManagerSlot,
64    ) -> Result<(), Self::Error>;
65
66    /// Admit recovered identity and complete declarations before resolution.
67    ///
68    /// Runs once per cold bootstrap attempt after validated recovery. Warm
69    /// bootstrap/adoption does not replay it. The default selects no historical
70    /// keys. Hosts compose generated consumers here under their existing policy
71    /// and bucket profile. Include these semantics in the policy identity.
72    fn prepare_bootstrap(
73        &self,
74        _admission: &mut crate::BootstrapAdmission<'_>,
75    ) -> Result<(), Self::Error> {
76        Ok(())
77    }
78
79    /// Return the host-issued token for this prepared policy configuration.
80    fn runtime_bootstrap_identity(&self) -> PolicyIdentity;
81}
82
83#[cfg(test)]
84mod tests {
85    use super::*;
86
87    #[test]
88    fn policy_token_preserves_all_bytes_in_equality_and_diagnostics() {
89        let bytes = std::array::from_fn(|i| u8::try_from(i).unwrap());
90        let identity = PolicyIdentity::new(bytes);
91        assert_eq!(identity.as_bytes(), &bytes);
92        assert_eq!(
93            serde_json::to_value(identity).unwrap(),
94            serde_json::json!(bytes)
95        );
96        for index in 0..32 {
97            let mut changed = bytes;
98            changed[index] ^= 1;
99            assert_ne!(identity, PolicyIdentity::new(changed));
100        }
101    }
102}