liminal-server 0.27.4

Standalone server for the liminal messaging bus
Documentation
//! ACCESS-013 R2: a seat on an open exchange, as the agent path reads it.
//!
//! An exchange with no `[auth]` proves nothing about a connection; it records
//! the name the connection declared (`open:<name>`, or `open:anonymous`). The
//! agent path decides identity through a [`LysSession`], so a declared name
//! is carried as one: holder kind `open`, holder the bare name, every hot act
//! admitted because the exchange gates nothing, and every act that asks Lys
//! (a link, a live decision, a prepared hold) refused as unavailable by name.

use crate::auth_lys::session::LysSession;
use crate::auth_lys::{
    AccessAction, AccessDecisionError, AccessResource, DeliberateDecision, GrantReceipt, HotAction,
    RefusalCause, SubjectBinding,
};
use crate::link::LinkAction;

/// The holder kind an open seat carries.
pub const OPEN_KIND: &str = "open";

/// The receipt every hot act on an open exchange carries.
pub const OPEN_GRANT: &str = "open";

/// What an open seat declared, carried into the agent path.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct OpenSession {
    name: String,
}

impl OpenSession {
    /// The seat that declared `name` (`anonymous` when it declared none).
    #[must_use]
    pub const fn new(name: String) -> Self {
        Self { name }
    }

    fn unavailable(resource: &AccessResource, action: AccessAction) -> AccessDecisionError {
        super::binding::refusal(resource, action, "", RefusalCause::DeliberateUnavailable)
    }
}

impl LysSession for OpenSession {
    fn holder(&self) -> &str {
        &self.name
    }

    fn holder_kind(&self) -> Option<&str> {
        Some(OPEN_KIND)
    }

    fn decide(
        &self,
        _subject: &SubjectBinding,
        _action: HotAction,
        _now: u64,
    ) -> Result<GrantReceipt, AccessDecisionError> {
        Ok(GrantReceipt {
            grant: OPEN_GRANT.to_owned(),
        })
    }

    fn decide_link(
        &self,
        subject: &SubjectBinding,
        action: LinkAction,
        _now: u64,
    ) -> Result<GrantReceipt, AccessDecisionError> {
        Err(Self::unavailable(
            subject.resource(),
            action.access_action(),
        ))
    }

    fn open_link(
        &self,
        link: &AccessResource,
        end: LinkAction,
        _now: u64,
    ) -> Result<DeliberateDecision, AccessDecisionError> {
        Err(Self::unavailable(link, end.access_action()))
    }

    fn decide_live(
        &self,
        resource: &AccessResource,
        action: AccessAction,
        _now: u64,
    ) -> Result<DeliberateDecision, AccessDecisionError> {
        Err(Self::unavailable(resource, action))
    }
}