Skip to main content

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}