Skip to main content

liminal_server/agents/
open_session.rs

1//! ACCESS-013 R2: a seat on an open exchange, as the agent path reads it.
2//!
3//! An exchange with no `[auth]` proves nothing about a connection; it records
4//! the name the connection declared (`open:<name>`, or `open:anonymous`). The
5//! agent path decides identity through a [`LysSession`], so a declared name
6//! is carried as one: holder kind `open`, holder the bare name, every hot act
7//! admitted because the exchange gates nothing, and every act that asks Lys
8//! (a link, a live decision, a prepared hold) refused as unavailable by name.
9
10use crate::auth_lys::session::LysSession;
11use crate::auth_lys::{
12    AccessAction, AccessDecisionError, AccessResource, DeliberateDecision, GrantReceipt, HotAction,
13    RefusalCause, SubjectBinding,
14};
15use crate::link::LinkAction;
16
17/// The holder kind an open seat carries.
18pub const OPEN_KIND: &str = "open";
19
20/// The receipt every hot act on an open exchange carries.
21pub const OPEN_GRANT: &str = "open";
22
23/// What an open seat declared, carried into the agent path.
24#[derive(Debug, Clone, PartialEq, Eq)]
25pub struct OpenSession {
26    name: String,
27}
28
29impl OpenSession {
30    /// The seat that declared `name` (`anonymous` when it declared none).
31    #[must_use]
32    pub const fn new(name: String) -> Self {
33        Self { name }
34    }
35
36    fn unavailable(resource: &AccessResource, action: AccessAction) -> AccessDecisionError {
37        super::binding::refusal(resource, action, "", RefusalCause::DeliberateUnavailable)
38    }
39}
40
41impl LysSession for OpenSession {
42    fn holder(&self) -> &str {
43        &self.name
44    }
45
46    fn holder_kind(&self) -> Option<&str> {
47        Some(OPEN_KIND)
48    }
49
50    fn decide(
51        &self,
52        _subject: &SubjectBinding,
53        _action: HotAction,
54        _now: u64,
55    ) -> Result<GrantReceipt, AccessDecisionError> {
56        Ok(GrantReceipt {
57            grant: OPEN_GRANT.to_owned(),
58        })
59    }
60
61    fn decide_link(
62        &self,
63        subject: &SubjectBinding,
64        action: LinkAction,
65        _now: u64,
66    ) -> Result<GrantReceipt, AccessDecisionError> {
67        Err(Self::unavailable(
68            subject.resource(),
69            action.access_action(),
70        ))
71    }
72
73    fn open_link(
74        &self,
75        link: &AccessResource,
76        end: LinkAction,
77        _now: u64,
78    ) -> Result<DeliberateDecision, AccessDecisionError> {
79        Err(Self::unavailable(link, end.access_action()))
80    }
81
82    fn decide_live(
83        &self,
84        resource: &AccessResource,
85        action: AccessAction,
86        _now: u64,
87    ) -> Result<DeliberateDecision, AccessDecisionError> {
88        Err(Self::unavailable(resource, action))
89    }
90}