templar_curator_primitives/auth/
mod.rs

1//! Chain-agnostic authentication and authorization primitives.
2//!
3//! This module provides a pluggable auth surface so curator and strategy vaults
4//! can share the runtime while using different authorization mechanisms.
5//!
6//! The core trait [`AuthAdapter`] allows each chain executor to implement its own
7//! signature verification while sharing the same action kinds and error types.
8
9use templar_vault_kernel::{Address, KernelAction};
10
11/// Shared authorization class for an action.
12#[templar_vault_macros::vault_derive(borsh, serde)]
13#[derive(Clone, Copy, PartialEq, Eq)]
14pub enum AuthPolicyClass {
15    /// User-facing/public action (no special role requirement).
16    Public,
17    /// Sentinel/emergency-governance privileged action.
18    Sentinel,
19    /// Allocator-level privileged action.
20    Allocator,
21    /// Emergency allocator path (allocator + emergency role on some executors).
22    AllocatorEmergency,
23    /// Curator/owner-only privileged action.
24    Curator,
25}
26
27/// Canonical shared policy class for an action.
28#[inline]
29#[must_use]
30pub const fn canonical_policy_class(action: ActionKind) -> AuthPolicyClass {
31    match action {
32        ActionKind::Deposit | ActionKind::RequestWithdraw | ActionKind::AtomicWithdraw => {
33            AuthPolicyClass::Public
34        }
35        ActionKind::ExecuteWithdraw
36        | ActionKind::BeginAllocating
37        | ActionKind::FinishAllocating
38        | ActionKind::SyncExternalAssets
39        | ActionKind::RebalanceWithdraw
40        | ActionKind::BeginRefreshing
41        | ActionKind::FinishRefreshing
42        | ActionKind::SettlePayout
43        | ActionKind::RefreshFees => AuthPolicyClass::Allocator,
44        ActionKind::Pause | ActionKind::SetRestrictions => AuthPolicyClass::Sentinel,
45        ActionKind::AbortAllocating
46        | ActionKind::AbortWithdrawing
47        | ActionKind::AbortRefreshing => AuthPolicyClass::AllocatorEmergency,
48        ActionKind::ManualReconcile | ActionKind::EmergencyReset | ActionKind::PolicyAdmin => {
49            AuthPolicyClass::Curator
50        }
51    }
52}
53
54/// Boundary executor policy class for an action.
55#[inline]
56#[must_use]
57pub const fn boundary_policy_class(action: ActionKind) -> AuthPolicyClass {
58    match action {
59        ActionKind::Deposit | ActionKind::RequestWithdraw | ActionKind::AtomicWithdraw => {
60            AuthPolicyClass::Public
61        }
62        ActionKind::ExecuteWithdraw
63        | ActionKind::BeginAllocating
64        | ActionKind::FinishAllocating
65        | ActionKind::SyncExternalAssets
66        | ActionKind::RebalanceWithdraw
67        | ActionKind::BeginRefreshing
68        | ActionKind::FinishRefreshing
69        | ActionKind::RefreshFees
70        | ActionKind::SettlePayout => AuthPolicyClass::Allocator,
71        ActionKind::Pause | ActionKind::SetRestrictions => AuthPolicyClass::Sentinel,
72        ActionKind::AbortAllocating
73        | ActionKind::AbortWithdrawing
74        | ActionKind::AbortRefreshing => AuthPolicyClass::AllocatorEmergency,
75        ActionKind::ManualReconcile | ActionKind::EmergencyReset | ActionKind::PolicyAdmin => {
76            AuthPolicyClass::Curator
77        }
78    }
79}
80
81/// Kinds of actions that require authorization.
82#[templar_vault_macros::vault_derive(borsh, serde)]
83#[derive(Clone, Copy, PartialEq, Eq)]
84pub enum ActionKind {
85    /// User deposit action.
86    Deposit,
87    /// User withdraw request.
88    RequestWithdraw,
89    /// Execute pending withdrawal.
90    ExecuteWithdraw,
91    /// Pause/unpause the vault.
92    Pause,
93    /// Set kernel restrictions (pause/allowlist/denylist).
94    SetRestrictions,
95    /// Curator-only policy/state administration outside kernel restrictions.
96    PolicyAdmin,
97    /// Begin allocation operation.
98    BeginAllocating,
99    /// Finish allocation operation.
100    FinishAllocating,
101    /// Sync external assets.
102    SyncExternalAssets,
103    RebalanceWithdraw,
104    /// Begin refresh operation.
105    BeginRefreshing,
106    /// Finish refresh operation.
107    FinishRefreshing,
108    /// Abort allocation.
109    AbortAllocating,
110    /// Abort withdrawal.
111    AbortWithdrawing,
112    /// Abort refresh.
113    AbortRefreshing,
114    /// Settle payout.
115    SettlePayout,
116    /// Refresh fees.
117    RefreshFees,
118    /// Privileged manual reconciliation of external assets.
119    ManualReconcile,
120    /// Emergency reset to force-idle a stuck vault.
121    EmergencyReset,
122    /// Atomic withdraw (by assets, idle-only fast path).
123    AtomicWithdraw,
124}
125
126impl ActionKind {
127    /// Returns true if this action requires privileged access under the canonical policy.
128    #[inline]
129    #[must_use]
130    pub const fn is_privileged(&self) -> bool {
131        !matches!(canonical_policy_class(*self), AuthPolicyClass::Public)
132    }
133}
134
135impl From<&KernelAction> for ActionKind {
136    #[inline]
137    fn from(action: &KernelAction) -> Self {
138        match action {
139            KernelAction::BeginAllocating { .. } => Self::BeginAllocating,
140            KernelAction::Deposit { .. } => Self::Deposit,
141            KernelAction::AtomicWithdraw { .. } => Self::AtomicWithdraw,
142            KernelAction::RequestWithdraw { .. } => Self::RequestWithdraw,
143            KernelAction::ExecuteWithdraw { .. } => Self::ExecuteWithdraw,
144            KernelAction::BeginRefreshing { .. } => Self::BeginRefreshing,
145            KernelAction::FinishAllocating { .. } => Self::FinishAllocating,
146            KernelAction::SyncExternalAssets { .. } => Self::SyncExternalAssets,
147            KernelAction::RebalanceWithdraw { .. } => Self::RebalanceWithdraw,
148            KernelAction::FinishRefreshing { .. } => Self::FinishRefreshing,
149            KernelAction::AbortRefreshing { .. } => Self::AbortRefreshing,
150            KernelAction::SettlePayout { .. } => Self::SettlePayout,
151            KernelAction::AbortAllocating { .. } => Self::AbortAllocating,
152            KernelAction::AbortWithdrawing { .. } => Self::AbortWithdrawing,
153            KernelAction::RefreshFees { .. } => Self::RefreshFees,
154            KernelAction::Pause { .. } => Self::Pause,
155            KernelAction::EmergencyReset => Self::EmergencyReset,
156        }
157    }
158}
159
160impl From<KernelAction> for ActionKind {
161    #[inline]
162    fn from(action: KernelAction) -> Self {
163        Self::from(&action)
164    }
165}
166
167#[templar_vault_macros::vault_derive]
168#[derive(Clone, Copy, PartialEq, Eq)]
169pub enum Caller {
170    Admin,
171    Curator,
172    Sentinel,
173    Allocator,
174    User,
175}
176
177#[templar_vault_macros::vault_derive]
178#[derive(Clone, PartialEq, Eq)]
179pub enum AuthError {
180    NotAuthorized { caller: Caller, action: ActionKind },
181    InvalidProof,
182    MissingRole,
183    VaultPaused,
184}
185
186/// Result type for auth operations.
187pub type AuthResult<T> = Result<T, AuthError>;
188
189/// Pluggable authorization adapter interface.
190///
191/// Curator vaults use RBAC checks while strategy vaults use Merkle proof
192/// verification against a globally updatable root.
193pub trait AuthAdapter {
194    /// Authorize an action for a caller.
195    fn authorize(
196        &self,
197        action: ActionKind,
198        caller: Address,
199        proof: Option<&[u8]>,
200    ) -> AuthResult<()>;
201
202    /// Check if the vault is currently paused.
203    fn is_paused(&self) -> bool;
204}