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; answers whether it placed one. The seat owns its
17    /// own station, so one person's many seats never meet the per-owner bound.
18    ///
19    /// # Errors
20    /// Bounds, Lys placement or the store, by name.
21    pub fn place_own(&self, name: &str, at_ms: u64) -> Result<bool, AgentError> {
22        let mut index = self.lock()?;
23        if index.records.contains_key(name) {
24            return Ok(false);
25        }
26        let transition = AgentTransition {
27            holder: name.to_owned(),
28            at_ms,
29            change: AgentEvent::Create(AgentSpec {
30                harness: AgentHarness::Seat,
31                purpose: SELF_PLACED_PURPOSE.to_owned(),
32                service: None,
33            }),
34        };
35        validate_act(&self.bounds, name, &transition)?;
36        check_population(&index, &self.bounds, name)?;
37        let land = Land {
38            version: 1,
39            name: name.to_owned(),
40            owner: name.to_owned(),
41            transition,
42            receipt: None,
43        };
44        let bytes = serde_json::to_vec(&land).map_err(|_| AgentError::Invalid("event encoding"))?;
45        check_bytes(&self.bounds, bytes.len())?;
46        if self.placer.is_some() {
47            self.place(name, &format!("self:{name}"))?;
48        }
49        self.land(&mut index, land)?;
50        drop(index);
51        tracing::info!(agent = name, "AGENT_STATION_SELF_PLACED");
52        Ok(true)
53    }
54}