1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
//! ExecutionScope — multi-tenant isolation.
//!
//! Every operation carries a scope. No operation happens without one.
//! Based on Group 27 of the pre-plan.
use serde::{Deserialize, Serialize};
pub type TenantId = String;
pub type UserId = String;
pub type SessionId = String;
pub type ThreadId = String;
pub type TaskId = String;
/// Execution scope — flows through every storage operation.
///
/// Isolation rules:
/// - tenant_id: complete isolation. Tenant A never sees Tenant B.
/// - user_id: within tenant, users share collective but not private memory.
/// - session_id: within user, sessions share long-term memory but not in-progress state.
/// - thread_id: within session, threads are independent conversations.
/// - task_id: within thread, tasks track specific work items.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ExecutionScope {
pub tenant_id: TenantId,
pub user_id: UserId,
pub session_id: SessionId,
pub thread_id: ThreadId,
pub task_id: Option<TaskId>,
}
impl ExecutionScope {
pub fn new(
tenant_id: impl Into<String>,
user_id: impl Into<String>,
session_id: impl Into<String>,
thread_id: impl Into<String>,
) -> Self {
Self {
tenant_id: tenant_id.into(),
user_id: user_id.into(),
session_id: session_id.into(),
thread_id: thread_id.into(),
task_id: None,
}
}
#[must_use = "builder methods return the modified builder"]
pub fn with_task(mut self, task_id: impl Into<String>) -> Self {
self.task_id = Some(task_id.into());
self
}
/// SurrealDB namespace for this scope — tenant-level isolation.
///
/// Maps to `db.use_ns(scope.namespace())`. Each tenant gets a separate
/// SurrealDB namespace — complete isolation at the storage layer.
/// No query can cross namespace boundaries.
///
/// Used by `SurrealCheckpointer` at construction time and
/// by `SurrealMemoryStore` per-call via `scoped()`.
pub fn namespace(&self) -> &str {
&self.tenant_id
}
/// Database name within the namespace.
///
/// Maps to `db.use_db(scope.database())`. Fixed per deployment —
/// all agents share one database within a tenant namespace.
/// Table-level scoping (thread_id, user_id, session_id) provides
/// finer isolation within the database.
pub fn database(&self) -> &str {
"potential_expectations"
}
}