use crate::dto::{prelude::*, rpc::RootRequestMetadata};
#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub enum DelegationAudience {
Canister(Principal),
CanicSubnet(Principal),
Project(String),
}
#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct DelegatedRoleGrant {
pub target: CanisterRole,
pub scopes: Vec<String>,
}
#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub enum RootProof {
IcCanisterSignatureV1(IcCanisterSignatureProofV1),
}
#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub enum IssuerProof {
IcCanisterSignatureV1(IcCanisterSignatureProofV1),
}
#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct IcCanisterSignatureProofV1 {
pub signature_cbor: Vec<u8>,
pub public_key_der: Vec<u8>,
}
#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub enum IssuerProofAlgorithm {
IcCanisterSignatureV1,
}
#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub enum IssuerProofBinding {
IcCanisterSignatureV1 { seed_hash: [u8; 32] },
}
#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct DelegationCert {
pub root_pid: Principal,
pub issuer_pid: Principal,
pub issuer_proof_alg: IssuerProofAlgorithm,
pub issuer_proof_binding_hash: [u8; 32],
pub issuer_proof_binding: IssuerProofBinding,
pub issued_at_ns: u64,
pub not_before_ns: u64,
pub expires_at_ns: u64,
pub max_token_ttl_ns: u64,
pub aud: DelegationAudience,
pub grants: Vec<DelegatedRoleGrant>,
}
#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct DelegationProof {
pub cert: DelegationCert,
pub root_proof: RootProof,
}
#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct ActiveDelegationProof {
pub proof: DelegationProof,
pub cert_hash: [u8; 32],
pub not_before_ns: u64,
pub expires_at_ns: u64,
pub refresh_after_ns: u64,
pub installed_at_ns: u64,
pub installed_by: Principal,
}
#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct InstallActiveDelegationProofRequest {
pub proof: DelegationProof,
}
#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct InstallActiveDelegationProofResponse {
pub active_proof: ActiveDelegationProof,
}
#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub enum ActiveDelegationProofStatus {
Missing,
Valid,
RefreshNeeded,
Expired,
}
#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct ActiveDelegationProofStatusResponse {
pub status: ActiveDelegationProofStatus,
pub root_pid: Option<Principal>,
pub issuer_pid: Option<Principal>,
pub cert_hash: Option<[u8; 32]>,
pub expires_at_ns: Option<u64>,
pub refresh_after_ns: Option<u64>,
}
#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct DelegatedTokenClaims {
pub subject: Principal,
pub issuer_pid: Principal,
pub cert_hash: [u8; 32],
pub issued_at_ns: u64,
pub expires_at_ns: u64,
pub aud: DelegationAudience,
pub grants: Vec<DelegatedRoleGrant>,
pub nonce: [u8; 16],
#[serde(default)]
pub ext: Option<Vec<u8>>,
}
#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct DelegatedToken {
pub claims: DelegatedTokenClaims,
pub proof: DelegationProof,
pub issuer_proof: IssuerProof,
}
#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct AuthRequestMetadata {
pub request_id: [u8; 32],
pub ttl_ns: u64,
}
#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct RootDelegationProofBatchPrepareRequest {
#[serde(default)]
pub metadata: Option<AuthRequestMetadata>,
pub entries: Vec<RootDelegationProofBatchPrepareEntry>,
}
#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct RootDelegationProofBatchPrepareEntry {
pub issuer_pid: Principal,
pub aud: DelegationAudience,
pub grants: Vec<DelegatedRoleGrant>,
pub cert_ttl_ns: u64,
}
#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct RootDelegationProofBatchPrepareResponse {
pub batch_id: [u8; 32],
pub entries: Vec<RootDelegationProofBatchEntry>,
pub retrieval_expires_at_ns: u64,
}
#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct RootDelegationProofBatchEntry {
pub issuer_pid: Principal,
pub cert_hash: [u8; 32],
pub expires_at_ns: u64,
pub refresh_after_ns: u64,
}
#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct RootDelegationProofBatchGetRequest {
pub batch_id: [u8; 32],
pub entries: Vec<RootDelegationProofBatchProofRef>,
}
#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct RootDelegationProofBatchProofRef {
pub issuer_pid: Principal,
pub cert_hash: [u8; 32],
}
#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct RootDelegationProofBatchGetResponse {
pub batch_id: [u8; 32],
pub proofs: Vec<RootDelegationProofBatchProof>,
}
#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct RootDelegationProofBatchProof {
pub issuer_pid: Principal,
pub cert_hash: [u8; 32],
pub proof: DelegationProof,
}
#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct RootDelegationProofBatchInstallRequest {
pub batch_id: [u8; 32],
pub proofs: Vec<RootDelegationProofBatchProof>,
}
#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct RootDelegationProofBatchInstallResponse {
pub batch_id: [u8; 32],
pub outcomes: Vec<RootDelegationProofBatchInstallResult>,
}
#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct RootDelegationProofBatchInstallResult {
pub issuer_pid: Principal,
pub cert_hash: [u8; 32],
pub outcome: RootDelegationProofInstallOutcome,
}
#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub enum RootDelegationProofInstallOutcome {
Installed,
AlreadyInstalled,
RejectedBySigner,
CallFailed,
ProofMismatch,
ExpiredOrSuperseded,
}
#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct RootIssuerPolicyUpsertRequest {
pub issuer_pid: Principal,
pub enabled: bool,
pub allowed_audiences: Vec<DelegationAudience>,
pub allowed_grants: Vec<DelegatedRoleGrant>,
pub max_cert_ttl_ns: u64,
pub refresh_after_ratio_bps: u16,
}
#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct RootIssuerPolicyView {
pub issuer_pid: Principal,
pub enabled: bool,
pub allowed_audiences: Vec<DelegationAudience>,
pub allowed_grants: Vec<DelegatedRoleGrant>,
pub max_cert_ttl_ns: u64,
pub refresh_after_ratio_bps: u16,
}
#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct RootIssuerPolicyResponse {
pub issuer: RootIssuerPolicyView,
}
#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct DelegatedTokenPrepareRequest {
#[serde(default)]
pub metadata: Option<AuthRequestMetadata>,
pub subject: Principal,
pub aud: DelegationAudience,
pub grants: Vec<DelegatedRoleGrant>,
pub ttl_ns: u64,
#[serde(default)]
pub ext: Option<Vec<u8>>,
}
#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct DelegatedTokenPrepareResponse {
pub claims: DelegatedTokenClaims,
pub claims_hash: [u8; 32],
pub retrieval_expires_at_ns: u64,
}
#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct DelegatedTokenGetRequest {
pub claims_hash: [u8; 32],
}
#[derive(CandidType, Clone, Debug, Deserialize)]
pub struct RoleAttestationRequest {
pub subject: Principal,
pub role: CanisterRole,
#[serde(default)]
pub subnet_id: Option<Principal>,
pub audience: Principal,
pub ttl_ns: u64,
pub epoch: u64,
#[serde(default)]
pub metadata: Option<RootRequestMetadata>,
}
#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct RoleAttestation {
pub subject: Principal,
pub role: CanisterRole,
#[serde(default)]
pub subnet_id: Option<Principal>,
pub audience: Principal,
pub issued_at_ns: u64,
pub expires_at_ns: u64,
pub epoch: u64,
}
#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct RoleAttestationPrepareResponse {
pub payload: RoleAttestation,
pub payload_hash: [u8; 32],
pub retrieval_expires_at_ns: u64,
}
#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct RoleAttestationGetRequest {
pub payload_hash: [u8; 32],
}
#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct SignedRoleAttestation {
pub payload: RoleAttestation,
pub root_proof: RootProof,
}
#[cfg(test)]
mod tests {
#[test]
fn auth_dtos_remain_passive_boundary_types() {
let source = include_str!("auth.rs");
let production_source = source
.split("#[cfg(test)]")
.next()
.expect("production source exists");
for marker in [
"impl DelegatedToken",
"impl DelegatedTokenClaims",
"impl RoleAttestation",
"impl SignedRoleAttestation",
"fn verify",
"fn sign",
"fn resolve",
"fn replay",
"fn consume",
"fn policy",
"fn validate",
] {
assert!(
!production_source.contains(marker),
"auth DTOs must stay passive; found marker `{marker}`"
);
}
}
}