1use crate::{
2 dto::{prelude::*, rpc::RootRequestMetadata},
3 ids::BuildNetwork,
4};
5
6#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
11pub enum DelegationAudience {
12 Canister(Principal),
13 CanicSubnet(Principal),
14 Project(String),
15}
16
17#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
22pub struct DelegatedRoleGrant {
23 pub target: CanisterRole,
24 pub scopes: Vec<String>,
25}
26
27#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
32pub enum RootProof {
33 IcChainKeyBatchSignatureV1(IcChainKeyBatchSignatureProofV1),
34}
35
36#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
41pub enum RootProofMode {
42 ChainKeyBatch,
43}
44
45#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
50pub enum IssuerProof {
51 IcCanisterSignatureV1(IcCanisterSignatureProofV1),
52}
53
54#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
59pub struct IcCanisterSignatureProofV1 {
60 pub signature_cbor: Vec<u8>,
61 pub public_key_der: Vec<u8>,
62}
63
64#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
69pub enum ChainKeyAlgorithm {
70 EcdsaSecp256k1,
71}
72
73#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
78pub struct ChainKeyKeyId {
79 pub name: String,
80}
81
82#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
87pub struct RootKeyPolicyV1 {
88 pub root_canister_id: Principal,
89 pub proof_mode: RootProofMode,
90 pub algorithm: ChainKeyAlgorithm,
91 pub key_id: ChainKeyKeyId,
92 pub derivation_path_hash: [u8; 32],
93 pub public_key: Vec<u8>,
94 pub key_version: u64,
95 pub min_accepted_key_version: u64,
96 pub min_accepted_proof_epoch: u64,
97 pub min_accepted_registry_epoch: u64,
98 pub max_revocation_latency_ns: u64,
99 pub valid_from_ns: u64,
100 pub accept_until_ns: u64,
101 pub build_network: BuildNetwork,
102}
103
104#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
109pub struct DelegatedAuthRegistrySnapshotV1 {
110 pub schema_version: u16,
111 pub root_canister_id: Principal,
112 pub registry_epoch: u64,
113 pub proof_mode: RootProofMode,
114 pub root_key_policy_hash: [u8; 32],
115 pub issuer_policies: Vec<DelegatedAuthIssuerPolicySnapshotV1>,
116}
117
118#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
123pub struct DelegatedAuthIssuerPolicySnapshotV1 {
124 pub issuer_canister_id: Principal,
125 pub enabled: bool,
126 pub preferred_proof_mode: RootProofMode,
127 pub allowed_audiences: Vec<DelegationAudience>,
128 pub allowed_grants: Vec<DelegatedRoleGrant>,
129 pub max_root_proof_ttl_ns: u64,
130 pub max_token_ttl_ns: u64,
131 pub issuer_proof_algorithm: IssuerProofAlgorithm,
132 pub issuer_proof_binding_hash: [u8; 32],
133 pub renewal_template_hash: [u8; 32],
134}
135
136#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
141pub struct IcChainKeyBatchSignatureProofV1 {
142 pub header: ChainKeyBatchHeaderV1,
143 pub delegation_cert: ChainKeyDelegationCertV1,
144 pub issuer_witness: ChainKeyBatchWitnessV1,
145 pub signature: ChainKeyRootSignatureV1,
146}
147
148#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
153pub struct ChainKeyBatchHeaderV1 {
154 pub schema_version: u16,
155 pub root_canister_id: Principal,
156 pub batch_id: [u8; 32],
157 pub proof_epoch: u64,
158 pub registry_epoch: u64,
159 pub registry_hash: [u8; 32],
160 pub tree_root: [u8; 32],
161 pub not_before_ns: u64,
162 pub expires_at_ns: u64,
163 pub algorithm: ChainKeyAlgorithm,
164 pub key_id: ChainKeyKeyId,
165 pub derivation_path_hash: [u8; 32],
166 pub key_version: u64,
167}
168
169#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
174pub struct ChainKeyDelegationCertV1 {
175 pub root_canister_id: Principal,
176 pub issuer_canister_id: Principal,
177 pub proof_epoch: u64,
178 pub issuer_proof_algorithm: IssuerProofAlgorithm,
179 pub issuer_proof_binding_hash: [u8; 32],
180 pub issuer_proof_binding: IssuerProofBinding,
181 pub max_token_ttl_ns: u64,
182 pub audience: DelegationAudience,
183 pub grants: Vec<DelegatedRoleGrant>,
184 pub not_before_ns: u64,
185 pub expires_at_ns: u64,
186 pub registry_epoch: u64,
187 pub registry_hash: [u8; 32],
188}
189
190#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
195pub struct ChainKeyRootSignatureV1 {
196 pub algorithm: ChainKeyAlgorithm,
197 pub key_id: ChainKeyKeyId,
198 pub derivation_path: Vec<Vec<u8>>,
199 pub public_key: Vec<u8>,
200 pub signature: Vec<u8>,
201}
202
203#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
208pub struct ChainKeyBatchWitnessV1 {
209 pub steps: Vec<ChainKeyBatchWitnessStepV1>,
210}
211
212#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
217pub enum ChainKeyBatchWitnessStepV1 {
218 LeftSibling([u8; 32]),
219 RightSibling([u8; 32]),
220}
221
222#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
227pub enum IssuerProofAlgorithm {
228 IcCanisterSignatureV1,
229}
230
231#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
236pub enum IssuerProofBinding {
237 IcCanisterSignatureV1 { seed_hash: [u8; 32] },
238}
239
240#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
245pub struct DelegationCert {
246 pub root_pid: Principal,
247 pub issuer_pid: Principal,
248 pub issuer_proof_alg: IssuerProofAlgorithm,
249 pub issuer_proof_binding_hash: [u8; 32],
250 pub issuer_proof_binding: IssuerProofBinding,
251 pub issued_at_ns: u64,
252 pub not_before_ns: u64,
253 pub expires_at_ns: u64,
254 pub max_token_ttl_ns: u64,
255 pub aud: DelegationAudience,
256 pub grants: Vec<DelegatedRoleGrant>,
257}
258
259#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
264pub struct DelegationProof {
265 pub cert: DelegationCert,
266 pub root_proof: RootProof,
267}
268
269#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
274pub struct ActiveDelegationProof {
275 pub proof: DelegationProof,
276 pub cert_hash: [u8; 32],
277 pub not_before_ns: u64,
278 pub expires_at_ns: u64,
279 pub refresh_after_ns: u64,
280 pub installed_at_ns: u64,
281 pub installed_by: Principal,
282}
283
284#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
289pub struct InstallActiveDelegationProofRequest {
290 pub proof: DelegationProof,
291}
292
293#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
298pub struct InstallActiveDelegationProofResponse {
299 pub active_proof: ActiveDelegationProof,
300}
301
302#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
307pub enum ActiveDelegationProofStatus {
308 Missing,
309 Valid,
310 RefreshNeeded,
311 Expired,
312}
313
314#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
319pub struct ActiveDelegationProofStatusResponse {
320 pub status: ActiveDelegationProofStatus,
321 pub root_pid: Option<Principal>,
322 pub issuer_pid: Option<Principal>,
323 pub cert_hash: Option<[u8; 32]>,
324 pub expires_at_ns: Option<u64>,
325 pub refresh_after_ns: Option<u64>,
326}
327
328#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
333pub struct DelegatedTokenClaims {
334 pub subject: Principal,
335 pub issuer_pid: Principal,
336 pub cert_hash: [u8; 32],
337 pub issued_at_ns: u64,
338 pub expires_at_ns: u64,
339 pub aud: DelegationAudience,
340 pub grants: Vec<DelegatedRoleGrant>,
341 pub nonce: [u8; 16],
342 #[serde(default)]
343 pub ext: Option<Vec<u8>>,
344}
345
346#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
351pub struct DelegatedToken {
352 pub claims: DelegatedTokenClaims,
353 pub proof: DelegationProof,
354 pub issuer_proof: IssuerProof,
355}
356
357#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
362pub struct AuthRequestMetadata {
363 pub request_id: [u8; 32],
364 pub ttl_ns: u64,
365}
366
367#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
372pub struct RootDelegationProofBatchProofRef {
373 pub issuer_pid: Principal,
374 pub cert_hash: [u8; 32],
375}
376
377#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
382pub struct RootDelegationProofBatchProof {
383 pub issuer_pid: Principal,
384 pub cert_hash: [u8; 32],
385 pub proof: DelegationProof,
386}
387
388#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
393pub struct RootDelegationProofBatchInstallRequest {
394 pub batch_id: [u8; 32],
395 pub proofs: Vec<RootDelegationProofBatchProof>,
396}
397
398#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
403pub enum RootDelegationProofInstallOutcome {
404 Installed,
405 AlreadyInstalled,
406 RejectedBySigner,
407 CallFailed,
408 ProofMismatch,
409 ExpiredOrSuperseded,
410}
411
412#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
417pub struct RootIssuerPolicyUpsertRequest {
418 pub issuer_pid: Principal,
419 pub enabled: bool,
420 pub allowed_audiences: Vec<DelegationAudience>,
421 pub allowed_grants: Vec<DelegatedRoleGrant>,
422 pub max_cert_ttl_ns: u64,
423 pub refresh_after_ratio_bps: u16,
424}
425
426#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
431pub struct RootIssuerPolicyView {
432 pub issuer_pid: Principal,
433 pub enabled: bool,
434 pub allowed_audiences: Vec<DelegationAudience>,
435 pub allowed_grants: Vec<DelegatedRoleGrant>,
436 pub max_cert_ttl_ns: u64,
437 pub refresh_after_ratio_bps: u16,
438}
439
440#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
445pub struct RootIssuerPolicyResponse {
446 pub issuer: RootIssuerPolicyView,
447}
448
449#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
454pub struct RootIssuerRenewalTemplateUpsertRequest {
455 pub issuer_pid: Principal,
456 pub enabled: bool,
457 pub aud: DelegationAudience,
458 pub grants: Vec<DelegatedRoleGrant>,
459 pub cert_ttl_ns: u64,
460}
461
462#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
467pub struct RootIssuerRenewalTemplateView {
468 pub issuer_pid: Principal,
469 pub enabled: bool,
470 pub aud: DelegationAudience,
471 pub grants: Vec<DelegatedRoleGrant>,
472 pub cert_ttl_ns: u64,
473}
474
475#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
480pub struct RootIssuerRenewalTemplateResponse {
481 pub template: RootIssuerRenewalTemplateView,
482}
483
484#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
489pub struct RootIssuerRenewalStatusRequest {
490 pub issuer_pid: Principal,
491}
492
493#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
498pub enum RootIssuerRenewalOutcome {
499 AlreadyInstalled,
500 DriftDetected,
501 InstallDeadlineExpired,
502 Installed,
503 IssuerCallFailed,
504 NeverRun,
505 PolicyRejected,
506 ProofMismatch,
507 QuotaExceeded,
508 RejectedByIssuer,
509 RetrievalExpired,
510 TemplateChanged,
511 TemplateDisabled,
512}
513
514#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
519pub enum RootIssuerRenewalAttemptStatus {
520 Prepared,
521 Installing,
522 Installed,
523 FailedRetryable,
524 FailedTerminal,
525 Disabled,
526 Expired,
527}
528
529#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
534pub struct RootIssuerRenewalAttemptView {
535 pub attempt_id: [u8; 32],
536 pub issuer_pid: Principal,
537 pub template_fingerprint: [u8; 32],
538 pub batch_id: [u8; 32],
539 pub proof_ref: RootDelegationProofBatchProofRef,
540 pub status: RootIssuerRenewalAttemptStatus,
541 pub prepared_at_ns: u64,
542 pub retrieval_expires_at_ns: u64,
543 pub install_deadline_ns: u64,
544 pub prepared_cert_hash: [u8; 32],
545 pub prepared_expires_at_ns: u64,
546 pub prepared_refresh_after_ns: u64,
547 pub failure: Option<RootIssuerRenewalOutcome>,
548}
549
550#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
555pub struct RootIssuerRenewalStateView {
556 pub issuer_pid: Principal,
557 pub template_fingerprint: [u8; 32],
558 pub last_installed_cert_hash: Option<[u8; 32]>,
559 pub last_installed_expires_at_ns: Option<u64>,
560 pub last_installed_refresh_after_ns: Option<u64>,
561 pub active_attempt_id: Option<[u8; 32]>,
562 pub last_outcome: RootIssuerRenewalOutcome,
563 pub consecutive_failures: u32,
564 pub next_attempt_after_ns: u64,
565 pub updated_at_ns: u64,
566}
567
568#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
573pub struct RootIssuerRenewalStatusResponse {
574 pub template: Option<RootIssuerRenewalTemplateView>,
575 pub state: Option<RootIssuerRenewalStateView>,
576 pub active_attempt: Option<RootIssuerRenewalAttemptView>,
577}
578
579#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
584pub struct DelegatedTokenPrepareRequest {
585 #[serde(default)]
586 pub metadata: Option<AuthRequestMetadata>,
587 pub subject: Principal,
588 pub aud: DelegationAudience,
589 pub grants: Vec<DelegatedRoleGrant>,
590 pub ttl_ns: u64,
591 #[serde(default)]
592 pub ext: Option<Vec<u8>>,
593}
594
595#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
600pub struct DelegatedTokenPrepareResponse {
601 pub claims: DelegatedTokenClaims,
602 pub claims_hash: [u8; 32],
603 pub retrieval_expires_at_ns: u64,
604}
605
606#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
611pub struct DelegatedTokenGetRequest {
612 pub claims_hash: [u8; 32],
613}
614
615#[derive(CandidType, Clone, Debug, Deserialize)]
620pub struct RoleAttestationRequest {
621 pub subject: Principal,
622 pub role: CanisterRole,
623 #[serde(default)]
624 pub subnet_id: Option<Principal>,
625 pub audience: Principal,
626 pub ttl_ns: u64,
627 pub epoch: u64,
628 #[serde(default)]
629 pub metadata: Option<RootRequestMetadata>,
630}
631
632#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
637pub struct RoleAttestation {
638 pub subject: Principal,
639 pub role: CanisterRole,
640 #[serde(default)]
641 pub subnet_id: Option<Principal>,
642 pub audience: Principal,
643 pub issued_at_ns: u64,
644 pub expires_at_ns: u64,
645 pub epoch: u64,
646}
647
648#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
653pub enum RoleAttestationRootProof {
654 IcCanisterSignatureV1(IcCanisterSignatureProofV1),
655}
656
657#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
662pub struct RoleAttestationPrepareResponse {
663 pub payload: RoleAttestation,
664 pub payload_hash: [u8; 32],
665 pub retrieval_expires_at_ns: u64,
666}
667
668#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
673pub struct RoleAttestationGetRequest {
674 pub payload_hash: [u8; 32],
675}
676
677#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
682pub struct SignedRoleAttestation {
683 pub payload: RoleAttestation,
684 pub root_proof: RoleAttestationRootProof,
685}
686
687#[cfg(test)]
692mod tests {
693 #[test]
694 fn auth_dtos_remain_passive_boundary_types() {
695 let source = include_str!("auth.rs");
696 let production_source = source
697 .split("#[cfg(test)]")
698 .next()
699 .expect("production source exists");
700
701 for marker in [
702 "impl DelegatedToken",
703 "impl DelegatedTokenClaims",
704 "impl RoleAttestation",
705 "impl SignedRoleAttestation",
706 "fn verify",
707 "fn sign",
708 "fn resolve",
709 "fn replay",
710 "fn consume",
711 "fn policy",
712 "fn validate",
713 ] {
714 assert!(
715 !production_source.contains(marker),
716 "auth DTOs must stay passive; found marker `{marker}`"
717 );
718 }
719 }
720}