calternal_collab::session
Public Note links cannot submit room updates (DESIGN §54, #981).
Live Note rooms materialize edits as Markdown. Rooms flush after 750 ms of
quiet, at the latest MAX_FLUSH_WAIT, or when the last client leaves.
With history enabled, authored updates become durable before file saves;
startup resumes their Yrs lineage and recognizes either hash of an unfinished
save intent. External file edits become forward changes. Without history,
startup validates the cached room against Markdown (DESIGN §§31, 61, #975).
Room epochs (see crate::stored): every connection first receives the
room’s epoch as a custom y-protocols message (MESSAGE_ROOM_EPOCH). A
client that names another epoch (?epoch=) is closed before any sync, and
a client without one is closed when its SyncStep1 shows a document from
another lineage. A clean unload and Hub::shutdown store the room’s Yrs
state, so the next load continues the same epoch.
Daily notes use the same stable Note identity as every other Markdown file.
Their [tz=<zone>] Log metadata is restored by the Notes writer after the
shared bridge escapes it, while room flushes and Journal writes keep the
same checked-replace lock (DESIGN §§9, 31; #606).
History (#975, DESIGN §61): integration installs one shared HistoryStore. Notes, guest sessions and agent turns all capture updates before broadcast. The same document-neutral writer is available to Canvas rooms. Client IDs bind to a connection, independent of client-supplied awareness names.
Hostile clients (adversarial round 2): a room accepts only updates after
which the document still converts to Markdown. Any other update is rolled
back and its sender is disconnected, so no client can make every later
flush fail. Awareness clocks near u32::MAX are refused because the
disconnect cleanup increments them.
Canvas rooms accept element events, not client structs. The same author-bound
validator serves HTTP and WebSocket edits; clean rooms never write (§60, #976).
Source: crates/calternal-collab/src/session.rs
Structs
Section titled “Structs”AgentTurn
Section titled “AgentTurn”pub struct AgentTurnOne named agent turn. Call apply once with the turn’s completed Markdown
and finish to clear presence and persist. Each apply is one Yrs transaction.
Implements: Drop
AgentTurn::apply
Section titled “AgentTurn::apply”pub async fn apply(&self, markdown: &str) -> Result<(), String>Parse the completed agent text and merge it against the turn base (#907). After parsing succeeds, this turn permits only one apply attempt, even if shutdown or the merge fails. A successful merge marks the room dirty, broadcasts its update, and schedules persistence (DESIGN §27). Apply one verified agent turn. History admission precedes mutation and the server-issued turn ID is captured before broadcast (#975).
AgentTurn::finish
Section titled “AgentTurn::finish”pub async fn finish(mut self) -> Result<(), String>Clear agent presence, flush the room, and unload it when idle (#907). A notification failure is logged after persistence and does not undo the completed turn (DESIGN §27).
Source: crates/calternal-collab/src/session.rs:2272
pub struct HubSingle collaboration writer for live Notes, with an optional shared history adapter installed by the Phase 2 integration (#975, DESIGN §60–61).
Implements: Clone, crate::history::HistoryMutations
Hub::new
Section titled “Hub::new”pub fn new( root: Root, db: Db, origin: String, user_data_directory: PathBuf, ) -> Result<Self, notify::Error>Start the shared room map and invalidation watchers. Watcher clones use the same history slot, installed before rooms open (#975, DESIGN §61).
Hub::with_history
Section titled “Hub::with_history”pub async fn with_history( self, store: Arc<dyn HistoryStore>, limits: WriteLimits, ) -> crate::history::Result<Self>Install the shared store and durable budget. The integration job supplies slice A; this slice does not create a second history store (#975).
Hub::router
Section titled “Hub::router”pub fn router(self) -> RouterNo doc comment.
Hub::live_clients
Section titled “Hub::live_clients”pub async fn live_clients(&self, user: &str, id: &str) -> Option<usize>Connected client count of a loaded room, or None when no room is
loaded for this Note. Used by tests and diagnostics.
Hub::with_shared_notes
Section titled “Hub::with_shared_notes”pub fn with_shared_notes(mut self, access: Arc<dyn SharedNoteAccess>) -> SelfInstall the Files Share authority after its security-state model lands.
Hub::with_trusted_proxies
Section titled “Hub::with_trusted_proxies”pub fn with_trusted_proxies(mut self, trusted_proxies: Vec<ipnet::IpNet>) -> SelfUse the instance’s trusted-proxy rule for per-IP connection limits (§54, #981).
Hub::shutdown
Section titled “Hub::shutdown”pub async fn shutdown(&self)Save every loaded room and store its state, for a graceful stop (SIGTERM). Tabs that stay open then resync with the same epoch after the restart. Call it after the listener has stopped.
Hub::notify_external_change
Section titled “Hub::notify_external_change”pub async fn notify_external_change(&self, owner: &str, path: &str)Apply a Notes invalidation immediately after another server write.
Hub::notify_external_change_as
Section titled “Hub::notify_external_change_as”pub async fn notify_external_change_as(&self, owner: &str, path: &str, author: Author)Server-side parity routes preserve their verified author when they reconcile a file write. This adds no public write endpoint (#975).
Hub::begin_agent
Section titled “Hub::begin_agent”pub async fn begin_agent( &self, user: &str, id: &str, name: &str, color: &str, ) -> Result<AgentTurn, String>Start an agent turn with visible awareness. Only one agent may edit a given live Note at a time; the AI plugin queues turns above this API.
Source: crates/calternal-collab/src/session.rs:879
SharedNotePermission
Section titled “SharedNotePermission”pub enum SharedNotePermissionNo doc comment.
Variants
DeniedViewerEditor
Implements: Clone, Copy, Debug, Eq, PartialEq
Source: crates/calternal-collab/src/session.rs:831
Traits
Section titled “Traits”SharedNoteAccess
Section titled “SharedNoteAccess”pub trait SharedNoteAccess: Send + SyncThe Files plugin must verify an editor Share against immutable item identity. Without that security-state adapter, cross-home access fails closed.
SharedNoteAccess::access
Section titled “SharedNoteAccess::access”fn access<'a>( &'a self, recipient: &'a str, owner: &'a str, note_id: &'a str, ) -> Pin<Box<dyn Future<Output = SharedNotePermission> + Send + 'a>>;No doc comment.
SharedNoteAccess::canvas_access
Section titled “SharedNoteAccess::canvas_access”fn canvas_access<'a>( &'a self, _author: &'a str, _owner: &'a str, _path: &'a str, ) -> Pin<Box<dyn Future<Output = SharedNotePermission> + Send + 'a>>Authorize a linked Note/Task by its current path and Files item identity. Canvas owner authority must never stand in for the editing User (#977).
SharedNoteAccess::note_saved
Section titled “SharedNoteAccess::note_saved”fn note_saved<'a>( &'a self, _owner: &'a str, _path: &'a str, _before: FileFingerprint, ) -> Pin<Box<dyn Future<Output = Result<(), String>> + Send + 'a>>Refresh Files’ fingerprint after this room’s authorized atomic write. A failure leaves the Share unavailable until the refresh succeeds.
Source: crates/calternal-collab/src/session.rs:753
Functions
Section titled “Functions”openapi
Section titled “openapi”pub fn openapi() -> utoipa::openapi::OpenApiOpenAPI fragment for both live Note WebSocket handshakes.
Source: crates/calternal-collab/src/session.rs:2989
Constants
Section titled “Constants”MAX_FLUSH_WAIT
Section titled “MAX_FLUSH_WAIT”pub const MAX_FLUSH_WAIT: DurationLongest time an edit waits for its save while clients keep typing.
Source: crates/calternal-collab/src/session.rs:507
MAX_MESSAGE_BYTES
Section titled “MAX_MESSAGE_BYTES”pub const MAX_MESSAGE_BYTES: usizeLargest y-sync message a client may send. The Notes REST body limit is 10 MiB; the margin covers Yjs encoding overhead of a full-document sync.
Source: crates/calternal-collab/src/session.rs:515
MESSAGE_ROOM_EPOCH
Section titled “MESSAGE_ROOM_EPOCH”pub const MESSAGE_ROOM_EPOCH: u8Custom y-protocols message type of the room epoch frame. Payload: the
epoch as a UTF-8 byte string (y-protocols writeVarUint8Array). Types 0 to
3 are taken by y-protocols; clients ignore unknown types.
Source: crates/calternal-collab/src/session.rs:519
SHUTDOWN_FLUSH_WAIT
Section titled “SHUTDOWN_FLUSH_WAIT”pub const SHUTDOWN_FLUSH_WAIT: DurationTime Hub::shutdown may spend saving rooms before the process exits.