Skip to content
SumOfficeSumOfficeSumOffice

Rust Session Protocol — 41 commands

The full list of document session commands: the parameters, preconditions, and result of each command — 41 in total.

Parameters: document_id: string or null (optional); path: string (required)

Result: { opened, byte_count, digital_signature_present, session_id, document_id, revision, accepted_revision, dirty, history, open_stage_timings_ms }

{
"id": "req-1",
"cmd": "open",
"path": "/absolute/document.docx"
}

Parameters: —

Result: PaginationSnapshot

{
"id": "req-1",
"cmd": "paginate"
}

Parameters: —

Result: { pong: true }

{
"id": "req-1",
"cmd": "ping"
}

Parameters: tracked_change_markup_mode: string or null (optional)

Result: PrintParitySnapshot

{
"id": "req-1",
"cmd": "print"
}

Parameters: known_fingerprints: JSON array (optional); tracked_change_markup_mode: string or null (optional)

Result: snapshot details, changed_pages[], and unchanged_page_indexes[]

{
"id": "req-1",
"cmd": "print-delta"
}

Parameters: —

Result: { page_count, line_item_count, scene_fingerprints[] }

{
"id": "req-1",
"cmd": "print-summary"
}

Parameters: include_page_stack: boolean (optional); page_indexes: JSON array (optional, default empty); defer_raster_bytes: boolean (optional); soft_page_cursor: JSON (optional)

Result: the print window and the built pages; on request, page_stack and the window model

{
"id": "req-1",
"cmd": "print-window",
"page_indexes": [
0
]
}

Parameters: document_id: string or null (optional); transaction_order: integer (optional, default 0)

Result: history, the transition, redone=true, and a receipt

{
"id": "req-1",
"cmd": "redo"
}

Parameters: —

Result: SupportReport

{
"id": "req-1",
"cmd": "report"
}

Parameters: —

Result: ReviewSnapshot

{
"id": "req-1",
"cmd": "review"
}

Parameters: path: string or null (optional); rebase_package_baseline: boolean (optional)

Result: { saved, saved_document_itself?, byte_count, history_preserved, history }

{
"id": "req-1",
"cmd": "save"
}

Parameters: expected_revision: integer (required); request_id: string (required); session_id: string (required); target: JSON (required)

Result: fastdoc.persistent-save-checkpoint-receipt.v1

{
"id": "req-1",
"cmd": "save-checkpoint",
"expected_revision": 1,
"request_id": "request_id-1",
"session_id": "session_id-1",
"target": {
"path": "/absolute/document.docx",
"expected_hash": "sha256:..."
}
}

Parameters: request: JSON (required)

Result: SelectionUpdateReceipt

{
"id": "req-1",
"cmd": "set-selection",
"request": {
"...": "edit types — see “Typed editing types”"
}
}

Concurrent access. expected_revision and expected_selection_revision are required: a request sent from a stale state is rejected.

Parameters: —

Result: { id, ok:true, shutdown:true }

{
"id": "req-1",
"cmd": "shutdown"
}

Parameters: —

Result: SimpleFieldInventorySnapshot

{
"id": "req-1",
"cmd": "simple-field-inventory"
}

Parameters: base_undo_depth: integer (required); document_id: string (required); transition_kind: string or null (optional)

Result: history state

{
"id": "req-1",
"cmd": "squash-history",
"base_undo_depth": 1,
"document_id": "document_id-1"
}

Parameters: —

Result: session state: path, cache, history, revision, the unsaved flag, and the model hash

{
"id": "req-1",
"cmd": "status"
}

Parameters: —

Result: StyleSnapshot

{
"id": "req-1",
"cmd": "style"
}

Parameters: —

Result: TrackRevisionsStateSnapshot

{
"id": "req-1",
"cmd": "track-revisions-state"
}

Parameters: document_id: string or null (optional); transaction_order: integer (optional, default 0)

Result: history, the transition, undone=true, and a receipt

{
"id": "req-1",
"cmd": "undo"
}

The same session accepts these commands, but they didn’t make it into the original table. All of them require an open document.

cmd mut. params what it does result
propose no request: JSON (required) The same edit as apply-text-transaction, but on a throwaway copy of the session: the document doesn’t change { proposal_id, base_revision, after_revision, request_id, applied: false, change { range_before, deleted_text, inserted_text, before_text, after_text, before_hash, after_hash } }
commit-proposal yes proposal_id: string (required) Applies a proposal by its number; the revision is checked again { proposal_id, committed, repeated, base_revision, accepted_revision, change, applied }
snapshot-checkpoint no expected_revision: integer (required); request_id: string (required); session_id: string (required); target: string (required) Writes the current state to a new file target without clearing the unsaved flag details of the written file
vba-inspect no include_source: boolean (optional, default false) The macro project of the open document: modules, procedures, and with include_source the source text fastdoc.vba.project.v1
vba-plan no entrypoint: string (required); allow: boolean (optional); now_declared: boolean (optional); answer_declared: boolean (optional); granted_classes: JSON array (optional) The plan for running one entry point: what will stop it — before anything is started fastdoc.vba.plan.v1
vba-preview no entrypoint: string (required); allow: boolean (optional); now: string or null (optional); answer: string or null (optional); grants: JSON array (optional); cancel_file: string or null (optional) The macro runs against a snapshot of the session document; the diff goes out, the document doesn’t change fastdoc.vba.preview.v1
vba-trust no registry: string (required); action: string (optional, default ask); label: string or null (optional) The trust decision for the project: ask, trust, block, forget. Bound to the project hash and remembered in the registry file fastdoc.vba.trust.v1
vba-commit yes entrypoint: string (required); registry: string or null (optional); allow: boolean (optional); now: string or null (optional); answer: string or null (optional); grants: JSON array (optional); cancel_file: string or null (optional) The macro’s edits enter the open document by the same road as mutate. A refusal recorded in registry outranks allow fastdoc.vba.commit.v1
vba-document-event no event: string (required); registry: string or null (optional); allow: boolean (optional); now: string or null (optional); answer: string or null (optional); grants: JSON array (optional); cancel_file: string or null (optional) A document event from the shell — open, close, or new; reports what happened, doesn’t commit edits fastdoc.vba.document-event.v1
apply-concurrent-text-transaction yes request: JSON (required); site: string (required); local_site: string (required); order: JSON (optional); typing_attributes: JSON (optional); run_format: JSON (optional) A peer’s edit composed against an old revision: it is transferred onto the current state rather than rejected Edit confirmation (AcceptedEditTerminal) with a transfer block: the numbers seq, base, seen, own, site, local_site, through_earlier, through_later, insert_at, and the journal log
note-operation-order no request_id: string (required); seq: integer (required) The manager has named the number of its own, already applied edit in the shared order The fields known, outcome (known, unknown, or out_of_order), and the journal log
note-operation-baseline no seq: integer (required) Up to which number the file the document was opened from already contains other people’s work { baseline }
note-tracked-revision-range no participant: integer (required) The band of tracked-change numbers for a co-editing participant; 0 removes the band { participant, range { start, end } or null, next }

Parameters: request: JSON (required)

Result: a preview of the edit — proposal_id, the revisions before and after, change with the text before and after and hashes, applied: false

{
"id": "req-1",
"cmd": "propose",
"request": { "request_id": "edit-1", "expected_revision": 3, "…": "same as apply-text-transaction" }
}

Parameters: proposal_id: string (required)

Result: committed, repeated, base_revision, accepted_revision, change, applied. If the document has moved since propose, the refusal is proposal-stale and nothing is applied. A repeated call with the same number returns the same response with repeated: true, not a second effect.

{ "id": "req-2", "cmd": "commit-proposal", "proposal_id": "proposal-1" }

Parameters: expected_revision: integer (required); request_id: string (required); session_id: string (required); target: string (required)

Result: details of the written file. Unlike save-checkpoint, the person’s file, the “modified” flag, and the document address don’t change: target must be a new path, and the session must hold an unsaved edit.

{
"id": "req-3",
"cmd": "snapshot-checkpoint",
"session_id": "session_id-1",
"request_id": "request_id-1",
"expected_revision": 4,
"target": "/absolute/snapshot.docx"
}

Parameters: include_source: boolean (optional, default false)

Result: fastdoc.vba.project.v1 — macros_present, project_name, modules with procedures, offered_macros, user_forms. Read-only: the project is taken from the already open session package; the file isn’t read a second time.

{ "id": "req-4", "cmd": "vba-inspect", "include_source": true }

Parameters: entrypoint: string (required); allow: boolean (optional); now_declared: boolean (optional); answer_declared: boolean (optional); granted_classes: JSON array (optional)

Result: fastdoc.vba.plan.v1 — whether this run will go ahead and what exactly will stop it. Executes nothing and writes nothing; the plan describes a specific run, so it repeats the person’s decisions: whether the project identity is confirmed, whether the run moment and the answer to dialogs are given, and which classes of external objects are allowed.

{
"id": "req-5",
"cmd": "vba-plan",
"entrypoint": "Module1.FillContract",
"allow": true,
"now_declared": true,
"granted_classes": ["Scripting.FileSystemObject"]
}

Parameters: entrypoint: string (required); allow: boolean (optional); now: string or null (optional); answer: string or null (optional); grants: JSON array (optional); cancel_file: string or null (optional)

Result: fastdoc.vba.preview.v1 — entrypoint, result, denied_capability, stop, and the “before → after” diff. The macro does run — otherwise the preview would promise something other than what will happen — but the session document doesn’t change by a single byte: the run goes against a snapshot. The appearance of the cancel_file file stops the run at the nearest command boundary.

{
"id": "req-6",
"cmd": "vba-preview",
"entrypoint": "Module1.FillContract",
"allow": true,
"now": "2026-09-21T10:00:00",
"answer": "ok",
"grants": ["object:Scripting.FileSystemObject"]
}

Parameters: registry: string (required); action: string (optional, default ask); label: string or null (optional)

Result: fastdoc.vba.trust.v1 — what is recorded about the open document’s project. The decision is bound to the project bytes (the hash of the vbaProject.bin part), not to the file name: editing a macro revokes trust by itself. ask only shows the state; trust, block, and forget change it. Where to store the registry is up to your application.

{
"id": "req-7",
"cmd": "vba-trust",
"registry": "/absolute/macro-trust.json",
"action": "trust",
"label": "Contract template, fill-in macro"
}

Parameters: entrypoint: string (required); registry: string or null (optional); allow: boolean (optional); now: string or null (optional); answer: string or null (optional); grants: JSON array (optional); cancel_file: string or null (optional)

Result: fastdoc.vba.commit.v1 — entrypoint, result, and what entered the document. The edits take the same road as mutate: the document after the macro matches the document after the same edits made by hand. The policy decides whether to start: a refusal recorded in registry outranks allow. A canceled run isn’t committed at all.

{
"id": "req-8",
"cmd": "vba-commit",
"entrypoint": "Module1.FillContract",
"registry": "/absolute/macro-trust.json",
"now": "2026-09-21T10:00:00"
}

Parameters: event: string (required); registry: string or null (optional); allow: boolean (optional); now: string or null (optional); answer: string or null (optional); grants: JSON array (optional); cancel_file: string or null (optional)

Result: fastdoc.vba.document-event.v1 — what happened on the open, close, or new event. The event is raised by the shell, not by a flag: the “run or not” decision stays with the guard and the trust policy. Edits aren’t committed — that’s what vba-commit is for.

{ "id": "req-9", "cmd": "vba-document-event", "event": "open", "registry": "/absolute/macro-trust.json" }

Parameters: request: JSON (required); site: string (required); local_site: string (required); order: JSON (optional); typing_attributes: JSON (optional); run_format: JSON (optional)

Result: AcceptedEditTerminal with a transfer field — how the edit landed after the transfer. request is the same EditRequest as for apply-text-transaction, but expected_revision may be old: a peer’s edit is transferred onto the current state. order is { seq, base }: the edit’s number in the manager’s shared order and up to which number its author had absorbed everything; typing_attributes and run_format are what the author executed the edit with, so that here it lands with the same look.

{
"id": "req-10",
"cmd": "apply-concurrent-text-transaction",
"site": "boris",
"local_site": "anna",
"order": { "seq": 17, "base": 15 },
"request": { "request_id": "edit-17", "expected_revision": 15, "…": "same as apply-text-transaction" }
}

Parameters: request_id: string (required); seq: integer (required)

Result: known, outcome (known, unknown, or out_of_order), journal. Your own edit, already applied by apply-text-transaction, receives its number in the manager’s shared order.

{ "id": "req-11", "cmd": "note-operation-order", "request_id": "edit-16", "seq": 16 }

Parameters: seq: integer (required)

Result: baseline. Reports up to which number the file the document was opened from already contains other people’s work — for whoever arrives later.

{ "id": "req-12", "cmd": "note-operation-baseline", "seq": 15 }

Parameters: participant: integer (required)

Result: participant, range { start, end } or null, next. The core mints the numbers of its tracked changes within the participant’s band so that different people’s numbers in one document don’t collide; 0 removes the band.

{ "id": "req-13", "cmd": "note-tracked-revision-range", "participant": 2 }

The CanonicalDocument type is how the model command answers the question “what’s in the document right now”. It’s built from two layers, and that’s its main property.

Counters — how much of what is in the document: block_count, paragraph_count, run_count, section_count, table_count, table_row_count, table_cell_count, body_word_count, header_count, footer_count, footnote_count, endnote_count, field_count, comment_count, tracked_change_count, object_count, style_definition_count, numbering_definition_count, support_marker_count. You use them to check that the file opened as expected, without parsing the content.

Content — the objects themselves: body with text blocks, sections, headers, footers, footnotes, endnotes, fields, comments, tracked_changes, objects, style_definitions, numbering_definitions, support_markers. Plus document_design.

Four fields appear only when there’s something to show: document_protection, bibliography, footnote_properties, and endnote_properties.

model_version, stage_id, stage_name, and word_count_source stand apart: the model version, the parsing stage label, and where the word count was taken from. The document language is document_language: read from the first paragraph with text, then from the defaults layer, then from the most frequent paragraph language; the defaults layer itself (document_default_language) is stored in the model but doesn’t appear in the response.

AcceptedEditTerminal is the response to mutate and apply-text-transaction. It answers the question that comes up right after a successful edit: what to show the user without rereading the whole document.

Field What it is
receipt A receipt for the edit: before_revision and after_revision, the selection revision numbers before and after, selection_after itself, the history state, and the boundary of what changed. You use it to confirm that it was your change that got applied.
model_projection_patch What to redraw: story_id, node_id, the block number in the body, and paragraph_after itself — the paragraph after the edit. Plus before_hash and after_hash, which show which state the patch was built from.
model_delta What exactly changed in the text: the range before the edit, the deleted and inserted strings, the text before and after. Useful for a log and for replaying the edit on your side.
owner_state The session owner’s state at the moment of the response.
typing_attributes The character properties at the input point: what the next text you type will look like.
dirty Whether the document has unsaved changes.
projection_baseline Only for documents in restricted mode, and only in the response to the first edit after activation: a pair of hashes, owner_hash (what the shell held before activation) and model_hash (the model built from the same package). From it, the shell understands that two different hashes describe the same document. The field is absent from other responses.

The rule is simple: render from model_projection_patch — it gives you a ready-made paragraph and where to put it. model_delta is for when you need to record or replay the edit on your side, not display it.

PaginationSnapshot (the response to paginate) and ReviewSnapshot (the response to review) are built the same way as the model response: counters first, then content. If you’ve made sense of one, you’ll make sense of the others.

PaginationSnapshot — how the document breaks down into pages. Counters: section_count, explicit_break_count, rendered_break_observation_count, page_fragment_count, hard_split_count, table_placeholder_count, anchored_object_placeholder_count, support_marker_count. Content: sections, explicit_breaks, page_fragments, support_markers.

Separately, three spread flags — even_and_odd_headers_enabled, mirror_margins_enabled, gutter_at_top_enabled: different headers and footers for even and odd pages, mirrored margins, and a gutter at the top. Plus frontier_mode — how far layout has been computed.

ReviewSnapshot — comments and tracked changes. Counters: comment_count, tracked_change_count, resolved_comment_anchor_count, deferred_comment_anchor_count, support_marker_count. Content: comments, tracked_changes, support_markers. The snapshot_mode field says in what form the snapshot was taken.

Two anchor counters are worth telling apart: resolved_comment_anchor_count — comments whose anchor to the text was successfully restored; deferred_comment_anchor_count — those whose anchor is deferred. A nonzero second number means some comments currently have nothing to attach to for display.

Like model, both snapshots have model_version, stage_id, and stage_name — the model version and the parsing-stage marker.

Documentation assistant

Answers are assembled from the documentation and may be inaccurate — check the sources.