Skip to main content

ic_auth/portable/
grants.rs

1//! Immutable structural admission for host-selected portable authority grants.
2use crate::certificate_issuance::{GrantValidationError, validate_grants};
3use ic_auth_protocol_types::DelegatedRoleGrant;
4
5/// Owned canonical grants admitted to the portable limits once, before use.
6/// This establishes shape only, never enrollment, provenance or authorization.
7/// Hosts must select the current protected set and advance their generation
8/// atomically with authority changes. Clock, revocation and scope checks still
9/// run for every operation. Construct a fresh value after decoding configuration
10/// or restoring it from storage; this type has no unchecked deserializer.
11///
12/// Read access cannot invalidate admitted ordering or grammar:
13/// ```compile_fail
14/// use ic_auth::portable::ValidatedGrants;
15/// fn change(grants: &mut ValidatedGrants) {
16///     grants.as_slice()[0].scopes.clear();
17/// }
18/// ```
19#[derive(Clone, Debug, Eq, PartialEq)]
20pub struct ValidatedGrants(Vec<DelegatedRoleGrant>);
21
22impl ValidatedGrants {
23    /// Admit nonempty, strictly ordered role/scope grants without normalization.
24    /// Refuse more than 16 roles or 32 scopes per role, empty scope sets and
25    /// invalid scope labels through the canonical grant validator.
26    pub fn new(grants: Vec<DelegatedRoleGrant>) -> Result<Self, GrantValidationError> {
27        validate_grants(
28            &grants,
29            crate::limits::MAX_GRANTS,
30            crate::limits::MAX_SCOPES_PER_GRANT,
31        )?;
32        Ok(Self(grants))
33    }
34
35    pub fn as_slice(&self) -> &[DelegatedRoleGrant] {
36        &self.0
37    }
38
39    /// Consume structural evidence before editing or projecting the raw grants.
40    /// Reconstruct through `new` before using edited grants as authority again.
41    pub fn into_vec(self) -> Vec<DelegatedRoleGrant> {
42        self.0
43    }
44}