liminal_server/server/connection/supervisor/supervisor_authority.rs
1use super::{Arc, ConnectionControl, ConnectionSupervisor, ServerError};
2
3impl ConnectionSupervisor {
4 /// Installs the services registry (SRV-028), once: lifecycle requests
5 /// are served from it and its processes' credentials admitted.
6 ///
7 /// # Errors
8 /// [`ServerError::ConfigValidation`] when one is already installed.
9 pub fn install_lifecycle(
10 &self,
11 lifecycle: Arc<crate::services::lifecycle::Lifecycle>,
12 ) -> Result<(), ServerError> {
13 self.inner
14 .runtime
15 .lifecycle
16 .set(lifecycle)
17 .map_err(|_| ServerError::ConfigValidation {
18 message: "a services registry was already installed".to_owned(),
19 })
20 }
21
22 /// Installs the grant-revocation policy (ACCESS-005), once, before the
23 /// first connection. From then on every `Connect` must present a pass
24 /// whose grant-decision binding the authority admits and must negotiate
25 /// the reason-bearing close; a bearer or open-access `Connect` is refused
26 /// `revocation_binding_missing`.
27 ///
28 /// # Errors
29 /// [`ServerError::ConfigValidation`] when an authority is already
30 /// installed.
31 pub fn install_revocation(
32 &self,
33 authority: Arc<crate::auth_revocation::RevocationAuthority>,
34 ) -> Result<(), ServerError> {
35 self.inner
36 .runtime
37 .install_revocation(authority)
38 .map_err(|_| ServerError::ConfigValidation {
39 message: "a grant-revocation authority was already installed".to_owned(),
40 })
41 }
42
43 /// Applies one event of the Lys grant-change stream the caller owns and
44 /// reads (ACCESS-005 R2, R4), then tells each affected connection once.
45 /// The denied state is in force before any connection is told; when a
46 /// connection's control cannot be published the refusal is counted by
47 /// name and the connection's own ready wake delivers the sweep. Nothing
48 /// is retried on a timer.
49 ///
50 /// # Errors
51 /// [`ServerError::ConfigValidation`] when no authority is installed.
52 pub fn apply_grant_event(
53 &self,
54 event: &crate::auth_revocation::GrantFeedEvent,
55 ) -> Result<crate::auth_revocation::ApplyOutcome, ServerError> {
56 let Some(authority) = self.inner.runtime.revocation() else {
57 return Err(ServerError::ConfigValidation {
58 message: "no grant-revocation authority is installed".to_owned(),
59 });
60 };
61 let outcome = authority.apply(event);
62 let mut told = std::collections::BTreeSet::new();
63 for effect in &outcome.effects {
64 let pid = effect.pid();
65 if !told.insert(pid) {
66 continue;
67 }
68 if !self
69 .inner
70 .enqueue_control(pid, ConnectionControl::Revocation)
71 {
72 authority.record_close_publication_refused(pid);
73 let woken = self
74 .inner
75 .runtime
76 .ready_waker(pid)
77 .as_ref()
78 .is_some_and(super::wake::ReadyWaker::fire);
79 tracing::warn!(
80 connection_pid = pid,
81 woken,
82 "revocation control refused; the connection's ready wake carries the sweep"
83 );
84 }
85 }
86 Ok(outcome)
87 }
88}