Skip to content

Statepatch synchronizes Statewire Documents across network boundaries.

Documents start with mount, followed by add, replace, or remove operations.

Mounting documents

mount

Starts syncing a document by sending its initial value.

{
  "op": "mount",
  "protocol": "harness-sdk",
  "doc": 1,
  "key": ["t1", "main", "42"],
  "value": {"text": "Hello"}
}
  • doc gives the document a numeric ID for subsequent operations. Omitted means 0; producers always omit doc: 0.
  • protocol names a selected application protocol.
  • main: true identifies that protocol’s main document. At most one is mounted per table.
  • Optional key is the document’s read address within its protocol. A main document may also have a key.
  • value contains the document's initial data.

unmount

Stops syncing the document identified by doc over this transport.

{"op": "unmount", "doc": 1}

Document lookup

  • Document IDs belong to an attach.
  • Protocols scope document keys. Message IDs unique within a thread use [threadId, ns, messageId].
  • [".", ns, messageId] addresses a message before a thread ID exists. The client’s protocol key prefix resolves . when canonical identity becomes available.
  • Relative keys remain usable for local reads while unresolved. Shared storage uses resolved keys and an optional client-configured namespace.
  • Protocol negotiation defines mounts, main documents, key resolution, and storage identity.

Mutating documents

Paths

Inside a document, a path lists the object keys and list indices leading to a value.

  • ["messages", 0, "text"] points to the first message's text field.
  • [] points to the whole document.
  • Object keys are strings; list indices are nonnegative whole numbers.
  • Objects and lists along the path must already exist.

add (list)

Inserts a list item and shifts later items to the right.

Previous state
{ "items": ["a","c"] }
Operation
{ "op": "add", "path": ["items",1], "value": "b" }
Final state
{ "items": ["a","b","c"] }

The final path index is the insertion position, from 0 to the list length: 0 inserts at the start; the length inserts at the end.

add (string)

Inserts text into a string.

Previous state
{ "text": "Hello" }
Operation
{ "op": "add", "path": ["text",5], "value": " world" }
Final state
{ "text": "Hello world" }
  • The final path index is the insertion position, counted in Unicode code points from 0 to the string length.
  • The inserted value must be a string.

replace

Sets the value at a path.

Previous state
{ "count": 0 }
Operation
{ "op": "replace", "path": ["count"], "value": 1 }
Final state
{ "count": 1 }
  • Object keys can be new. List items must already exist.
  • Use [] to replace the whole document.

remove

Deletes an existing object key or list item, shifting later list items to the left.

Previous state
{ "items": ["a","b","c"] }
Operation
{ "op": "remove", "path": ["items",1] }
Final state
{ "items": ["a","c"] }

Operation format

A statepatch is an ordered array of statepatch operations. Each operation has an op and selects a document by its numeric doc ID, which defaults to 0.

opdoc*pathkeyvaluemeta*
mount✓—✓✓✓
unmount✓————
add (list)✓✓—✓✓
add (string)✓✓—✓✓
replace✓✓—✓✓
remove✓✓———

* Optional. All other checked fields are required.

Operations apply in order; each sees the previous operation's changes. Operations that break the path or operation rules are protocol errors.

Client handling

  • Clients skip unknown operations and warn once per operation name.

Statepatch is inspired by JSON Patch, Immer patches, and SuperJSON.

Python validation

from statepatch import WireEncodingError exports a ValueError subclass for invalid wire values. Observable mutations raise it for encoding violations. Statewire preserves these library diagnostics while redacting unexpected handler exceptions.