State Authority and Command Boundaries
Authoritative state, command publication, history, and write boundaries.
HEAD a63778e| Read this page when | A change affects state ownership, command publication, history, or document write boundaries. |
|---|---|
| First answer | Which state boundary or flow is authoritative for this decision? |
| Boundary | This page owns command publication and state authority; restore and projection details belong to the persistence page. |
| Follow-up | Read the linked source and verification evidence after selecting the contract. |
Authority model
| Scope | Authority | History | Sync |
|---|---|---|---|
document | Ordered CellPlane pages in one Yjs document | Page-local local origins | When collaborative |
workspace | Tool, local interaction, active viewport, and preferences | No | No |
session | Canvas identity, presentation mode, saved viewport, and optional external-source binding | No | No |
presence | Remote identity, cursor, transient selection | No | Ephemeral |
derived | Rendering, minimap, preview projections | No | No |
The local /workspace page projects native session descriptors and retained
legacy works; it is not another catalog. Blackboard retirement
owns conversion and source archives. New cloud backups store native .chardesk
snapshots. First backup binds opt-in revision-checked sync; independent recovery
copies remain independent. Divergent edits fork a conflict copy. Restoring a
backup binds the new local session at its downloaded revision. The account API
is separate from the encrypted collaboration relay. Workspace hides editor tools.
Workspace writes enter through CanvasCommands; EditorState contains data only and
Zustand is its read projection, not an alternate command surface. CanvasRuntime.store
exposes only getState, getInitialState, and subscribe; its mutable Store is test-internal.
Local grid navigation and selection clearing are
pure interaction transitions. Drawing previews update the transient scratch layer
through the same boundary. Scratch commits, existing-cell area fills, and static
range moves are addressed document writes owned by CanvasCommands, not alternate
Zustand actions. Selection delete, erase, fill, and style commands use the same
owner. Clipboard I/O reads a snapshot, validates its addressed selection after the
await boundary, then commits through an explicit mutation port.
interaction.staticGrid is the sole static-grid interaction authority. Its
navigate branch owns selection; its text-edit branch owns the input session.
Selection and cursor views are derived from that discriminated state, so they cannot
represent conflicting modes.
Text mutation enters through the Canvas text command executor. It derives CellPlane
writes and the next interaction.staticGrid from one initial snapshot; text actions
are not part of EditorState.
Session and Slide lifecycle mutations enter through their Canvas command executors.
One activation coordinator orders create, source-open, import, switch, active deletion,
and collaboration join. Asynchronous work runs outside the commit boundary, then validates
the latest activation intent and publishes a short synchronous commit; no draft spans an
await boundary. A stale import still registers its document and descriptor but does not
replace the user's newer active Canvas.
CanvasStateCommitCoordinator owns the synchronous command publication boundary.
Yjs content projection, local interaction, and history availability update one shared
draft; nested commands read that draft, and only the outer command publishes to
Zustand subscribers. Remote Yjs transactions outside a local command publish
immediately. This boundary provides one observable snapshot, not Yjs rollback.
A projection never writes back to its authority. Only local Yjs origins enter
undo history. Remote values pass Canvas decoders before projection; invalid records
stay out of editor state and surface as collaboration integrity issues.
Every write resolves a CanvasDocumentAddress (documentId, pageId) before opening
its transaction. Active-document convenience reads are projections only; commands do not
use Registry focus as an implicit write target.