pub struct PermissionRegistry { /* private fields */ }Expand description
Registry for managing permission grants and requests.
This registry implements the new grant-based permission system with:
- Hierarchical permission levels (Admin > Execute > Write > Read > None)
- Path-based grants with optional recursion
- Domain and command pattern grants
- Batch permission request handling
§Lock Ordering
This struct contains multiple async mutexes. To prevent deadlocks, all methods follow these rules:
- Never hold multiple locks simultaneously - each method acquires locks in separate scopes, releasing one before acquiring the next
- Release locks before async operations - locks are released before sending to channels or awaiting other async calls
- Sequential ordering when multiple locks needed:
pending_requestsorpending_batchesfirst (for request lookup)session_grantssecond (for grant operations)
Example pattern used throughout:
// Good: sequential lock acquisition in separate scopes
let request = {
let mut pending = self.pending_requests.lock().await;
pending.remove(id)?
}; // lock released here
self.add_grant(session_id, grant).await; // acquires session_grantsImplementations§
Source§impl PermissionRegistry
impl PermissionRegistry
Sourcepub fn new(event_tx: Sender<ControllerEvent>) -> PermissionRegistry
pub fn new(event_tx: Sender<ControllerEvent>) -> PermissionRegistry
Creates a new PermissionRegistry.
§Arguments
event_tx- Channel to send events when permissions are requested.
Sourcepub async fn add_grant(&self, session_id: i64, grant: Grant)
pub async fn add_grant(&self, session_id: i64, grant: Grant)
Adds a grant for a session.
§Arguments
session_id- Session to add the grant to.grant- The grant to add.
Sourcepub async fn add_grants(&self, session_id: i64, new_grants: Vec<Grant>)
pub async fn add_grants(&self, session_id: i64, new_grants: Vec<Grant>)
Adds multiple grants for a session.
§Arguments
session_id- Session to add the grants to.new_grants- The grants to add.
Sourcepub async fn cleanup_expired(&self, session_id: i64)
pub async fn cleanup_expired(&self, session_id: i64)
Removes expired grants from a session.
Sourcepub async fn revoke_grants(
&self,
session_id: i64,
target: &GrantTarget,
) -> usize
pub async fn revoke_grants( &self, session_id: i64, target: &GrantTarget, ) -> usize
Sourcepub async fn get_grants(&self, session_id: i64) -> Vec<Grant>
pub async fn get_grants(&self, session_id: i64) -> Vec<Grant>
Sourcepub async fn clear_grants(&self, session_id: i64)
pub async fn clear_grants(&self, session_id: i64)
Sourcepub async fn check(&self, session_id: i64, request: &PermissionRequest) -> bool
pub async fn check(&self, session_id: i64, request: &PermissionRequest) -> bool
Checks if a permission request is satisfied by existing grants.
This checks if any grant in the session satisfies the request based on:
- Target coverage (grant target covers request target)
- Level hierarchy (grant level >= required level)
- Grant not expired
§Arguments
session_id- Session to check.request- The permission request to check.
§Returns
true if permission is granted, false otherwise.
Sourcepub async fn check_batch(
&self,
session_id: i64,
requests: &[PermissionRequest],
) -> HashSet<String>
pub async fn check_batch( &self, session_id: i64, requests: &[PermissionRequest], ) -> HashSet<String>
Sourcepub async fn find_satisfying_grant(
&self,
session_id: i64,
request: &PermissionRequest,
) -> Option<Grant>
pub async fn find_satisfying_grant( &self, session_id: i64, request: &PermissionRequest, ) -> Option<Grant>
Sourcepub async fn request_permission(
&self,
session_id: i64,
request: PermissionRequest,
turn_id: Option<TurnId>,
) -> Result<Receiver<PermissionPanelResponse>, PermissionError>
pub async fn request_permission( &self, session_id: i64, request: PermissionRequest, turn_id: Option<TurnId>, ) -> Result<Receiver<PermissionPanelResponse>, PermissionError>
Registers an individual permission request.
If the request is already satisfied by existing grants, returns an auto-approved response immediately. Otherwise, registers the request, emits an event, and returns a receiver to await the response.
§Arguments
session_id- Session requesting permission.request- The permission request.turn_id- Optional turn ID for UI context.
§Returns
A receiver that will receive a PermissionPanelResponse.
Sourcepub async fn respond_to_request(
&self,
request_id: &str,
response: PermissionPanelResponse,
) -> Result<(), PermissionError>
pub async fn respond_to_request( &self, request_id: &str, response: PermissionPanelResponse, ) -> Result<(), PermissionError>
Sourcepub async fn pending_for_session(
&self,
session_id: i64,
) -> Vec<PendingPermissionInfo>
pub async fn pending_for_session( &self, session_id: i64, ) -> Vec<PendingPermissionInfo>
Sourcepub async fn is_granted(
&self,
session_id: i64,
request: &PermissionRequest,
) -> bool
pub async fn is_granted( &self, session_id: i64, request: &PermissionRequest, ) -> bool
Check if permission is already granted for the session.
This is a convenience method that wraps check().
Uses the Grant::satisfies method from the permission system.
§Arguments
session_id- Session to check.request- The permission request to check.
§Returns
True if permission was previously granted for the session.
Sourcepub async fn register_batch(
&self,
session_id: i64,
requests: Vec<PermissionRequest>,
turn_id: Option<TurnId>,
) -> Result<Receiver<BatchPermissionResponse>, PermissionError>
pub async fn register_batch( &self, session_id: i64, requests: Vec<PermissionRequest>, turn_id: Option<TurnId>, ) -> Result<Receiver<BatchPermissionResponse>, PermissionError>
Registers a batch of permission requests.
Requests that are already satisfied by existing grants are auto-approved and not included in the batch sent to the UI.
§Arguments
session_id- Session requesting permissions.requests- The permission requests.turn_id- Optional turn ID for UI context.
§Returns
A receiver that will receive the batch response.
Sourcepub async fn respond_to_batch(
&self,
batch_id: &str,
response: BatchPermissionResponse,
) -> Result<(), PermissionError>
pub async fn respond_to_batch( &self, batch_id: &str, response: BatchPermissionResponse, ) -> Result<(), PermissionError>
Sourcepub async fn cancel_batch(&self, batch_id: &str) -> Result<(), PermissionError>
pub async fn cancel_batch(&self, batch_id: &str) -> Result<(), PermissionError>
Cancels a pending batch permission request.
This is called by the UI when the user closes the batch permission dialog without responding. Dropping the sender will cause the tools to receive errors.
§Arguments
batch_id- ID of the batch to cancel.
§Returns
Ok(()) if the batch was found and cancelled.
Sourcepub async fn cancel_session(&self, session_id: i64)
pub async fn cancel_session(&self, session_id: i64)
Cancels all pending requests for a session.
This drops the response channels, causing receivers to get errors.
§Arguments
session_id- Session to cancel.
Sourcepub async fn clear_session(&self, session_id: i64)
pub async fn clear_session(&self, session_id: i64)
Clears all state for a session (grants and pending requests).
§Arguments
session_id- Session to clear.
Sourcepub async fn has_pending(&self, session_id: i64) -> bool
pub async fn has_pending(&self, session_id: i64) -> bool
Sourcepub async fn pending_count(&self) -> usize
pub async fn pending_count(&self) -> usize
Gets count of pending requests across all sessions.
Sourcepub async fn pending_request_ids(&self, session_id: i64) -> Vec<String>
pub async fn pending_request_ids(&self, session_id: i64) -> Vec<String>
Gets pending request IDs for a session.
Sourcepub async fn pending_batch_ids(&self, session_id: i64) -> Vec<String>
pub async fn pending_batch_ids(&self, session_id: i64) -> Vec<String>
Gets pending batch IDs for a session.
Auto Trait Implementations§
impl !Freeze for PermissionRegistry
impl !RefUnwindSafe for PermissionRegistry
impl Send for PermissionRegistry
impl Sync for PermissionRegistry
impl Unpin for PermissionRegistry
impl !UnwindSafe for PermissionRegistry
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more