Skip to main content

ijima_core/
namespace.rs

1// Copyright (C) 2026 Industrial Algebra
2// SPDX-License-Identifier: Apache-2.0
3
4//! Memory namespaces — the isolation boundary for multi-user access (D2).
5//!
6//! Every read and write through the [`crate::Store`] is scoped to a
7//! [`NamespaceId`]. A namespace is the unit of visibility: an operator's
8//! private memory, a shared project namespace, or the global commons
9//! (the legacy pi-mempalace "everyone sees everything" mode).
10
11/// Identifies a memory namespace.
12///
13/// Wire form is a stable opaque string (e.g. `ns_elliott_private`,
14/// `ns_ijima_shared`, `ns_global`). v0 stores this as a SurrealDB record
15/// field; a future promotion maps each namespace onto a native SurrealDB
16/// `NS`/`DB` scope for first-class isolation.
17#[derive(Debug, Clone, PartialEq, Eq, Hash)]
18#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
19#[cfg_attr(feature = "serde", serde(transparent))]
20pub struct NamespaceId(pub String);
21
22impl NamespaceId {
23    /// Construct a namespace id from any string-like value.
24    pub fn new(id: impl Into<String>) -> Self {
25        Self(id.into())
26    }
27
28    /// The stable wire string.
29    pub fn as_str(&self) -> &str {
30        &self.0
31    }
32}
33
34/// The visibility/isolation class of a namespace.
35#[derive(Debug, Clone, Copy, PartialEq, Eq)]
36#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
37pub enum NamespaceKind {
38    /// One operator's personal memory — visible only to that operator.
39    Private,
40    /// A project/team namespace — visible to a configured group.
41    Shared,
42    /// The global commons — visible to everyone (legacy pi-mempalace mode).
43    Global,
44}
45
46/// A namespace descriptor: its id, visibility class, and owning operator.
47#[derive(Debug, Clone, PartialEq, Eq)]
48#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
49pub struct Namespace {
50    /// Stable opaque identifier.
51    pub id: NamespaceId,
52    /// Visibility class.
53    pub kind: NamespaceKind,
54    /// Owning operator principal id (`"system"` for the global commons).
55    pub owner: String,
56}
57
58/// The global doctrine namespace — curated, Git-versioned memories
59/// ([`crate::MemorySource::Doctrine`]) mirrored from the seed pack.
60/// Readable by every principal via `?namespace=ns_doctrine`.
61pub const DOCTRINE_NAMESPACE: &str = "ns_doctrine";
62
63#[cfg(test)]
64mod tests {
65    use super::*;
66
67    #[test]
68    fn namespace_id_round_trips() {
69        let ns = NamespaceId::new("ns_elliott_private");
70        assert_eq!(ns.as_str(), "ns_elliott_private");
71        assert_eq!(ns, NamespaceId("ns_elliott_private".into()));
72    }
73
74    #[test]
75    fn global_namespace_owner_is_system() {
76        let global = Namespace {
77            id: NamespaceId::new("ns_global"),
78            kind: NamespaceKind::Global,
79            owner: "system".into(),
80        };
81        assert_eq!(global.kind, NamespaceKind::Global);
82        assert_eq!(global.owner, "system");
83    }
84}