1use crate::dto::{prelude::*, rpc::RootRequestMetadata};
2
3#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
8pub enum DelegationAudience {
9 Canister(Principal),
10 CanicSubnet(Principal),
11 Project(String),
12}
13
14#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
19pub struct DelegatedRoleGrant {
20 pub target: CanisterRole,
21 pub scopes: Vec<String>,
22}
23
24#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
29pub enum RootProof {
30 IcCanisterSignatureV1(IcCanisterSignatureProofV1),
31}
32
33#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
38pub enum IssuerProof {
39 IcCanisterSignatureV1(IcCanisterSignatureProofV1),
40}
41
42#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
47pub struct IcCanisterSignatureProofV1 {
48 pub signature_cbor: Vec<u8>,
49 pub public_key_der: Vec<u8>,
50}
51
52#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
57pub enum IssuerProofAlgorithm {
58 IcCanisterSignatureV1,
59}
60
61#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
66pub enum IssuerProofBinding {
67 IcCanisterSignatureV1 { seed_hash: [u8; 32] },
68}
69
70#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
75pub struct DelegationCert {
76 pub root_pid: Principal,
77 pub issuer_pid: Principal,
78 pub issuer_proof_alg: IssuerProofAlgorithm,
79 pub issuer_proof_binding_hash: [u8; 32],
80 pub issuer_proof_binding: IssuerProofBinding,
81 pub issued_at_ns: u64,
82 pub not_before_ns: u64,
83 pub expires_at_ns: u64,
84 pub max_token_ttl_ns: u64,
85 pub aud: DelegationAudience,
86 pub grants: Vec<DelegatedRoleGrant>,
87}
88
89#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
94pub struct DelegationProof {
95 pub cert: DelegationCert,
96 pub root_proof: RootProof,
97}
98
99#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
104pub struct ActiveDelegationProof {
105 pub proof: DelegationProof,
106 pub cert_hash: [u8; 32],
107 pub not_before_ns: u64,
108 pub expires_at_ns: u64,
109 pub refresh_after_ns: u64,
110 pub installed_at_ns: u64,
111 pub installed_by: Principal,
112}
113
114#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
119pub struct InstallActiveDelegationProofRequest {
120 pub proof: DelegationProof,
121}
122
123#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
128pub struct InstallActiveDelegationProofResponse {
129 pub active_proof: ActiveDelegationProof,
130}
131
132#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
137pub enum ActiveDelegationProofStatus {
138 Missing,
139 Valid,
140 RefreshNeeded,
141 Expired,
142}
143
144#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
149pub struct ActiveDelegationProofStatusResponse {
150 pub status: ActiveDelegationProofStatus,
151 pub root_pid: Option<Principal>,
152 pub issuer_pid: Option<Principal>,
153 pub cert_hash: Option<[u8; 32]>,
154 pub expires_at_ns: Option<u64>,
155 pub refresh_after_ns: Option<u64>,
156}
157
158#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
163pub struct DelegatedTokenClaims {
164 pub subject: Principal,
165 pub issuer_pid: Principal,
166 pub cert_hash: [u8; 32],
167 pub issued_at_ns: u64,
168 pub expires_at_ns: u64,
169 pub aud: DelegationAudience,
170 pub grants: Vec<DelegatedRoleGrant>,
171 pub nonce: [u8; 16],
172 #[serde(default)]
173 pub ext: Option<Vec<u8>>,
174}
175
176#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
181pub struct DelegatedToken {
182 pub claims: DelegatedTokenClaims,
183 pub proof: DelegationProof,
184 pub issuer_proof: IssuerProof,
185}
186
187#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
192pub struct AuthRequestMetadata {
193 pub request_id: [u8; 32],
194 pub ttl_ns: u64,
195}
196
197#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
202pub struct RootDelegationProofBatchPrepareRequest {
203 #[serde(default)]
204 pub metadata: Option<AuthRequestMetadata>,
205 pub entries: Vec<RootDelegationProofBatchPrepareEntry>,
206}
207
208#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
213pub struct RootDelegationProofBatchPrepareEntry {
214 pub issuer_pid: Principal,
215 pub aud: DelegationAudience,
216 pub grants: Vec<DelegatedRoleGrant>,
217 pub cert_ttl_ns: u64,
218}
219
220#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
225pub struct RootDelegationProofBatchPrepareResponse {
226 pub batch_id: [u8; 32],
227 pub entries: Vec<RootDelegationProofBatchEntry>,
228 pub retrieval_expires_at_ns: u64,
229}
230
231#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
236pub struct RootDelegationProofBatchEntry {
237 pub issuer_pid: Principal,
238 pub cert_hash: [u8; 32],
239 pub expires_at_ns: u64,
240 pub refresh_after_ns: u64,
241}
242
243#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
248pub struct RootDelegationProofBatchGetRequest {
249 pub batch_id: [u8; 32],
250 pub entries: Vec<RootDelegationProofBatchProofRef>,
251}
252
253#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
258pub struct RootDelegationProofBatchProofRef {
259 pub issuer_pid: Principal,
260 pub cert_hash: [u8; 32],
261}
262
263#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
268pub struct RootDelegationProofBatchGetResponse {
269 pub batch_id: [u8; 32],
270 pub proofs: Vec<RootDelegationProofBatchProof>,
271}
272
273#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
278pub struct RootDelegationProofBatchProof {
279 pub issuer_pid: Principal,
280 pub cert_hash: [u8; 32],
281 pub proof: DelegationProof,
282}
283
284#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
289pub struct RootDelegationProofBatchInstallRequest {
290 pub batch_id: [u8; 32],
291 pub proofs: Vec<RootDelegationProofBatchProof>,
292}
293
294#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
299pub struct RootDelegationProofBatchInstallResponse {
300 pub batch_id: [u8; 32],
301 pub outcomes: Vec<RootDelegationProofBatchInstallResult>,
302}
303
304#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
309pub struct RootDelegationProofBatchInstallResult {
310 pub issuer_pid: Principal,
311 pub cert_hash: [u8; 32],
312 pub outcome: RootDelegationProofInstallOutcome,
313}
314
315#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
320pub enum RootDelegationProofInstallOutcome {
321 Installed,
322 AlreadyInstalled,
323 RejectedBySigner,
324 CallFailed,
325 ProofMismatch,
326 ExpiredOrSuperseded,
327}
328
329#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
334pub struct RootIssuerPolicyUpsertRequest {
335 pub issuer_pid: Principal,
336 pub enabled: bool,
337 pub allowed_audiences: Vec<DelegationAudience>,
338 pub allowed_grants: Vec<DelegatedRoleGrant>,
339 pub max_cert_ttl_ns: u64,
340 pub refresh_after_ratio_bps: u16,
341}
342
343#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
348pub struct RootIssuerPolicyView {
349 pub issuer_pid: Principal,
350 pub enabled: bool,
351 pub allowed_audiences: Vec<DelegationAudience>,
352 pub allowed_grants: Vec<DelegatedRoleGrant>,
353 pub max_cert_ttl_ns: u64,
354 pub refresh_after_ratio_bps: u16,
355}
356
357#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
362pub struct RootIssuerPolicyResponse {
363 pub issuer: RootIssuerPolicyView,
364}
365
366#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
371pub struct DelegatedTokenPrepareRequest {
372 #[serde(default)]
373 pub metadata: Option<AuthRequestMetadata>,
374 pub subject: Principal,
375 pub aud: DelegationAudience,
376 pub grants: Vec<DelegatedRoleGrant>,
377 pub ttl_ns: u64,
378 #[serde(default)]
379 pub ext: Option<Vec<u8>>,
380}
381
382#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
387pub struct DelegatedTokenPrepareResponse {
388 pub claims: DelegatedTokenClaims,
389 pub claims_hash: [u8; 32],
390 pub retrieval_expires_at_ns: u64,
391}
392
393#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
398pub struct DelegatedTokenGetRequest {
399 pub claims_hash: [u8; 32],
400}
401
402#[derive(CandidType, Clone, Debug, Deserialize)]
407pub struct RoleAttestationRequest {
408 pub subject: Principal,
409 pub role: CanisterRole,
410 #[serde(default)]
411 pub subnet_id: Option<Principal>,
412 pub audience: Principal,
413 pub ttl_ns: u64,
414 pub epoch: u64,
415 #[serde(default)]
416 pub metadata: Option<RootRequestMetadata>,
417}
418
419#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
424pub struct RoleAttestation {
425 pub subject: Principal,
426 pub role: CanisterRole,
427 #[serde(default)]
428 pub subnet_id: Option<Principal>,
429 pub audience: Principal,
430 pub issued_at_ns: u64,
431 pub expires_at_ns: u64,
432 pub epoch: u64,
433}
434
435#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
440pub struct RoleAttestationPrepareResponse {
441 pub payload: RoleAttestation,
442 pub payload_hash: [u8; 32],
443 pub retrieval_expires_at_ns: u64,
444}
445
446#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
451pub struct RoleAttestationGetRequest {
452 pub payload_hash: [u8; 32],
453}
454
455#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
460pub struct SignedRoleAttestation {
461 pub payload: RoleAttestation,
462 pub root_proof: RootProof,
463}
464
465#[cfg(test)]
470mod tests {
471 #[test]
472 fn auth_dtos_remain_passive_boundary_types() {
473 let source = include_str!("auth.rs");
474 let production_source = source
475 .split("#[cfg(test)]")
476 .next()
477 .expect("production source exists");
478
479 for marker in [
480 "impl DelegatedToken",
481 "impl DelegatedTokenClaims",
482 "impl RoleAttestation",
483 "impl SignedRoleAttestation",
484 "fn verify",
485 "fn sign",
486 "fn resolve",
487 "fn replay",
488 "fn consume",
489 "fn policy",
490 "fn validate",
491 ] {
492 assert!(
493 !production_source.contains(marker),
494 "auth DTOs must stay passive; found marker `{marker}`"
495 );
496 }
497 }
498}