Skip to main content

liminal_server/agents/
self_station.rs

1//! A seat's own station (ACCESS-013 R1): the holder already is the identity
2//! the record names, so placing it is not a deliberate act for anyone else
3//! to approve. It is placed in Lys exactly as an approved create is, and
4//! landed as an ordinary Create event with no draft receipt.
5
6use super::AgentRegistry;
7use super::storage::{Land, check_bytes, check_population, validate_act};
8use crate::agents::error::AgentError;
9use crate::agents::records::{AgentEvent, AgentHarness, AgentSpec, AgentTransition};
10
11/// The one sentence a self-placed record carries as its purpose.
12pub const SELF_PLACED_PURPOSE: &str = "Its own station, placed by the seat itself.";
13
14impl AgentRegistry {
15    /// Places the station `name` for the holder of the same name when the
16    /// registry holds none, owned by `owner`; answers whether it placed one.
17    /// A seat owns its own station (an open seat as `open:<name>`), so one
18    /// person's many seats never meet the per-owner bound.
19    ///
20    /// # Errors
21    /// Bounds, Lys placement or the store, by name.
22    pub fn place_own(&self, name: &str, owner: &str, at_ms: u64) -> Result<bool, AgentError> {
23        let mut index = self.lock()?;
24        if index.records.contains_key(name) {
25            return Ok(false);
26        }
27        let transition = AgentTransition {
28            holder: name.to_owned(),
29            at_ms,
30            change: AgentEvent::Create(AgentSpec {
31                harness: AgentHarness::Seat,
32                purpose: SELF_PLACED_PURPOSE.to_owned(),
33                service: None,
34            }),
35        };
36        validate_act(&self.bounds, name, &transition)?;
37        check_population(&index, &self.bounds, owner)?;
38        let land = Land {
39            version: 1,
40            name: name.to_owned(),
41            owner: owner.to_owned(),
42            transition,
43            receipt: None,
44        };
45        let bytes = serde_json::to_vec(&land).map_err(|_| AgentError::Invalid("event encoding"))?;
46        check_bytes(&self.bounds, bytes.len())?;
47        if self.placer.is_some() {
48            self.place(name, &format!("self:{name}"))?;
49        }
50        self.land(&mut index, land)?;
51        drop(index);
52        tracing::info!(agent = name, "AGENT_STATION_SELF_PLACED");
53        Ok(true)
54    }
55}