Document structure: how to get it
Architecture and boundaries of responsibility, the path of one user action, the semantic model, and the current Rust Session API for reading it.
Architecture and boundaries of responsibility
Section titled “Architecture and boundaries of responsibility”The data path is the same — in the desktop app, in the system web view, and when running headless:
| Layer | What it does | What it doesn’t do |
|---|---|---|
| Your application | Window, brand, sign-in, storage, workflows and their lifecycle | Doesn’t own the document’s model or its layout |
| The editor surface (Web Surface) | Canvas, ribbon, input, showing menus, delivering events | Doesn’t edit DOCX directly |
| Application adapter | Starting the process, parsing the greeting line with the address, exchange over JSON or WebSocket, window events | Doesn’t parse the document’s markup |
| Document session | Commands, selection, history, model and layout projections, saving | Doesn’t give arbitrary access to the page’s markup |
| The Rust core | The OOXML package, the document’s meaning, layout, writing back to the file | Doesn’t depend on the shell’s styling |
| The DOCX file | What gets saved and reopened | Is never replaced by an HTML snapshot |
The path of one user action
Section titled “The path of one user action”-
Pointer event. The surface receives the coordinates of a click, right-click, or double-click.
-
Hit-testing. The coordinate is mapped to a page, line, and caret position, and then to a document object.
-
Gathering context. The object itself, the selection, its parents in the document structure, the revision number, and the list of allowed commands are collected.
-
Interface decision. SumDoc and your side assemble the context menu — the document doesn’t change at this point.
-
Typed command. The chosen item turns into a command with the expected revision given.
-
Changing the document. The core checks the revision and permissions, changes the model, and returns confirmation with the new revision.
-
Redraw and save. The projections update; saving writes a DOCX that reopens with the same model.
How to get the document structure
Section titled “How to get the document structure”The term “document structure” is ambiguous. SumDoc splits it into five views, so you request only what you actually need.
| View | Command | Purpose | Sample data |
|---|---|---|---|
| Semantic model | model, model-docx |
Paragraphs, formatting runs, tables, references to styles and numbering, support markers | body.blocks[], paragraph_index, text, runs[] |
| Layout | compose, paginate |
Sections, pages, lines, breaks, geometry | page_index, line boundaries, page order |
| Scene | print, print-window, print-delta |
Pages ready to render, and drawing primitives | page scenes and their fingerprints |
| Review and styles | review, style |
Comments, tracked changes, style resolution | the review and style projections |
| Edit state | status, set-selection |
Revision, whether there are unsaved changes, undo and redo, selection, and view state | accepted_revision, selection_revision |
Example: the semantic model
Section titled “Example: the semantic model”# $CLI — path to the processor, see "Installation and verification""$CLI" model-docx /data/contract.docx --format json{ "model_version": "fastdoc-d1-document-model-v1", "block_count": 1, "paragraph_count": 1, "body": {"blocks": [{ "kind": "paragraph", "block_index": 0, "text": "SumDoc basic paragraph.", "style_ref": null, "numbering_ref": null, "runs": [{ "run_index": 0, "text": "SumDoc basic paragraph.", "direct_format": {"bold": null, "italic": null} }] }]}}How to start a session today and read the document
Section titled “How to start a session today and read the document”JSONL session: exchange over standard input and output
Section titled “JSONL session: exchange over standard input and output”The process prints the first readiness line with the fastdoc.session-serve.v1 schema. After that, every input line is a JSON request, and every output line is its response, tied together by identifier.
{"id":"open-1","cmd":"open", "path":"/data/contract.docx","document_id":"contract-42"}{"id":"model-1","cmd":"model"}{"id":"pages-1","cmd":"paginate"}{"id":"review-1","cmd":"review"}{"id":"state-1","cmd":"status"}{ "id": "model-1", "ok": true, "cmd": "model", "elapsed_ms": 2, "result": { "model_version": "...", "body": { "blocks": [] } }}WebSocket on a local address
Section titled “WebSocket on a local address”"$CLI" serve --ws 0# stdout: {"schema":"fastdoc.session-ws-bootstrap.v1",# "host":"127.0.0.1","port":49172,"token":"..."}-
Binding is 127.0.0.1 only. Port 0 is chosen automatically.
-
The token is a 256-bit secret from the system’s source of randomness. Don’t write it to logs or pass it to analytics.
-
The commands are the same. JSON-line exchange and WebSocket exchange go through the same session and the same request schema.
- Resolving an object from a coordinate — Hit-testing.
- What else the processor does — the capability map.