Skip to content

Lease context is part of the 2026-09-30 Statewire wire contract. The attach results cursor and verdict gap-fill are part of 2026-11-01.

Statewire exchanges JSON messages: clients send frames; servers send packets. Statewire Transport carries these messages over a connection.

Value encoding

Values use Statewire Document encoding. Each meta array describes dates inside the field carrying the data:

  • State operations and context entries: value.
  • Command statements: params, starting with the argument index.
  • Command answers and fin: payload.

Frames (client → server)

A frame is a client message carrying lease context, command statements, or both.

FieldMeaningUsage
ctxArray of protocol-scoped context replacementsOptional
cmdArray of command statementsOptional
  • A frame contains at least one nonempty array. A supplied empty array, an empty frame, or any key other than ctx and cmd is a protocol violation. Transport headers on an initial attach and WebSocket heartbeats retain their transport rules.

Lease context: ctx

Each selected protocol has one client-owned context object on each attach, independently of its command lane's record.

{
  "ctx": [{
    "protocol": "acme-chat",
    "value": {"locale": "en", "updatedAt": "2026-09-29T12:00:00.000Z"},
    "meta": [{"path": ["updatedAt"], "type": "date"}]
  }],
  "cmd": [{"protocol": "acme-chat", "seq": 1, "method": "example", "params": []}]
}
FieldMeaningUsage
protocolSelected application protocol, including a selected subprotocolRequired string
valueFull context object in Statewire Document encodingRequired
metaDate metadata relative to this entry's valueOptional
  • Decode each value and optional meta with the Statewire Document codec. The decoded root is an object. Each protocol owns its context schema and validates its value.
  • Each protocol appears at most once in ctx. A malformed entry, duplicate target, unselected protocol, invalid metadata, invalid context value, or oversized entry is a protocol violation. Validate the whole frame and every context candidate before changing context or admitting commands.
  • Context starts as {}. Each entry replaces only its target protocol's object. Omitted protocols stay unchanged; value: {} clears that protocol's context fields.
  • Install the frame's context replacements together before comparing command watermarks or admitting commands. Each newly admitted command captures an immutable decoded context snapshot from its target protocol on its admitting attach. Repeated commands retain their original admission and outcome.
  • Hosts expose context to that protocol's command handlers and a context-change hook. Context changes can update the attach's document view even in a context-only frame. Application authorization uses the admitting attach's auth.
  • Context belongs to the attach, rather than the durable client record. Concurrent attaches sharing a client id have independent context. Already admitted work retains its captured context when the attach ends. Resumed execution uses its original captured context; if that snapshot cannot be recovered, fail the command rather than using another attach's context.
  • Within an attach, hosts install context in frame arrival order. The last received value wins. Context entries carry protocol, value, and optional meta; they have no sequence or revision field.
  • Clients retain each protocol's latest value and serialize its updates. On every new attach, including a fresh hello on a preserved socket, send the latest full values before submitting commands. Context restoration is independent of the connected flag.
  • Context replacements consume no command sequence numbers, admission watermarks, command verdicts, durable replay entries, or in-flight command capacity.
  • Command admission refusal leaves installed context intact. The refusal's syn applies only to commands. A context-only frame completes after its context is installed; a WebSocket context-only frame has no command answer.
  • Context entries carry full replacements. Each context update carries the full object.

Lanes

A statement is one command request. A lane is the ordered sequence of statements of one selected protocol. Every selected protocol owns one lane; the hello lists them in syn.protocols[] as {name, version, seq, record?}.

LanerecordNumberingAnswersPersistence
DurableAbsent1, 2, 3, …, continuing across attachesEvery attach of the client idClient record
Ephemeral"ephemeral"Restarts at 1 on every attach; the hello reports 0The admitting attach onlyNone
  • seq is minted in the statement's lane when the statement is queued.
  • Statements in one frame apply in array order across lanes. Across frames, arrival order. Replay after reconnect preserves order within a lane only.
  • Within a frame, each lane's statements carry consecutive positive integer sequence numbers. Invalid numbers or a break in a lane are protocol violations.
  • Unanswered ephemeral-lane statements are lost when their attach ends.

Command statements

A command statement calls an application command with positional arguments.

{"seq": 1, "protocol": "default", "method": "increment", "params": [1]}
FieldMeaningUsage
seqSequence number in the protocol's laneRequired
protocolSelected protocol name; subprotocols use their full <parent>/<child> nameRequired string
methodCommand nameRequired string
paramsPositional argumentsRequired array; use [] for zero arguments
metaDate metadata for paramsOptional
  • A missing protocol, method, or params, or a non-string protocol or method, is a malformed statement violation.
  • Invalid arguments or command metadata produce a rejected answer with code: "invalid-params". The command consumes its sequence number; other commands in the admitted frame can run.

Frame limits

LimitMaximumIf exceeded
Statements per frame, across lanes (MAX_COMMANDS_PER_FRAME)256Protocol violation; bundled clients split larger backlogs
Context entries per frameAt most one per selected protocolProtocol violation
Encoded context entry, including value and meta64 KiB of UTF-8Protocol violation
Encoded ephemeral document value (MAX_EPHEMERAL_DOCUMENT_BYTES)64 KiBrejected with code: "oversized-document"
Encoded frame8 MiB of UTF-8Transport size error

Packets

A packet is an object sent by the server.

FieldMeaningUsage
synConnection facts or admission watermarksInitial snapshot, refusal, watermark refresh, or identity confirmation
opsStatepatch array updating application stateInitial snapshot or state changes
cmdArray of command answersResults, progress, or admission acknowledgments
nextHold answers until the next ops arrayOptional true on a command-answer packet
idleWhether the instance has finished its workStandalone or alongside ops
finConnection endingFinal packet
  • Each attach receives its view of the selected protocols' documents. Command answers use that attach's selected contract.
  • Clients ignore results for commands they do not track. Cumulative dur acknowledgments still advance their lane's watermark.
  • A packet may combine state changes and answers. Apply ops first, then cmd entries in array order, and publish the changes together.
  • Clients ignore unknown packet keys.

Initial snapshot: syn + ops

A connection begins with a hello packet containing connection facts, the attach's document view, and answers to the attach request's ephemeral-lane statements.

{"syn": {"version": "2026-09-30", "protocols": [
   {"name": "harness-sdk", "version": "2026-09-13", "seq": 41},
   {"name": "harness-sdk/interest", "version": "2026-09-13", "record": "ephemeral", "seq": 0}],
   "idle": true, "id": "..."}, "ops": [ ...mount ops for the attach's view... ], "cmd": [ ...answers to ephemeral attach statements... ]}

A watermark is the highest sequence number accepted for processing in a lane. An admitted command may still be running.

syn fieldMeaningDefault
versionSelected Statewire dateRequired
protocolsSelected lanes, listed belowRequired
idleWhether the instance is idlefalse
idInstance identityAbsent
syn.protocols[] fieldMeaningDefault
nameSelected protocol nameRequired
versionSelected protocol versionRequired
seqLane watermark; 0 on an ephemeral laneRequired
record"ephemeral" marks a lane that ends with the attachAbsent
  • ops mounts the attach's whole document view and replaces the client's document table on reconnect. An empty view uses ops: [].
  • cmd carries the answers to the ephemeral-lane statements of the attach request.
  • Validate negotiation fields before applying the snapshot.
  • When every selected protocol is ephemeral, the client reports unanswered commands as lost when the connection ends and uses a fresh client id on the next connection.
  • A durable host may report a lower durable-lane seq before loading its retained admission record. Recovery uses refusal watermarks to resolve that case.
  • A server may end a connection immediately with fin as its first and only packet.

State changes: ops

ops applies a Statepatch to the client's document table. An accompanying applied answer marks the command's effects in that state.

{
  "ops": [{"op": "replace", "path": ["count"], "value": 1}],
  "cmd": [{"protocol": "default", "seq": 1, "type": "applied"}]
}

The client observes count: 1 before processing command default 1's applied answer.

Command answers: cmd

Each answer names the command's protocol and seq and reports admission, progress, or a result.

{"cmd": [{"protocol": "harness-sdk", "seq": 3, "type": "result", "payload": 1}]}
FieldMeaningUsage
protocolThe command's laneRequired
seqCommand sequence number in that laneRequired
typeProgress or terminal verdict, listed belowOmitted on an admission-only acknowledgment
payloadReturn value or application rejection dataOptional
metaDate metadata for payloadOptional
codeMachine-readable rejection codeOptional
messageError or rejection textOptional
durRetained admission through this sequence numberOptional true; durable lanes only

applied is an intermediate answer. The other types are terminal verdicts: they settle the command.

typeMeaning
appliedThe handler marked its effects as applied. Remove the optimistic update; the command may continue running.
resultThe command completed successfully. payload holds its return value, when present.
rejectedThe method or arguments were rejected, or the handler explicitly rejected the command.
failedThe handler threw. message is the command failed for unexpected exceptions; side effects may already exist. Explicit rejections and typed wire-encoding diagnostics retain their authored messages.
crashedThe host witnessed handler death, such as cancellation during shutdown or eviction.
expiredThe command was admitted, but its stored verdict is unavailable.
  • The handler chooses when to emit applied. Each admitted command has an optional applied transition and one terminal verdict. Repeated submissions can re-emit answers.
  • Built-in rejections use code: "unknown-command" or code: "invalid-params". The synced document pair uses no-document, oversized-document, and invalid-patch. Handler rejections carry message and optional payload, with code omitted.
  • Durable-lane answers fan out to every attach of the client id and persist in the client record. Ephemeral-lane answers return on the admitting attach only.
  • crashed requires the host to observe the failure. After server recovery, a repeated command whose verdict is unavailable receives expired.

Retained admission: dur

dur: true releases commands through seq in the named lane from the client's resend queue. Their results may still be pending.

{"cmd": [{"protocol": "harness-sdk", "seq": 7, "dur": true}]}
  • The acknowledgment is cumulative within its lane: this example covers harness-sdk commands 1 through 7.
  • A memory host acknowledges at admission, for the client record's lifetime. A durable host acknowledges when the admission's durable receipt completes.
  • dur may appear alone or on an answer, before or after applied or a terminal verdict.
  • Ephemeral lanes carry no dur.

Deferred answers: next

next: true holds a packet's answers until this connection receives its next ops array.

{"cmd": [{"protocol": "default", "seq": 1, "type": "applied"}], "next": true}
  • Apply the next ops, then the held answers, then any answers accompanying those ops.
  • With next omitted, process answers in their own packet. next is invalid beside ops or fin.
  • A fin or transport close releases held answers before handling the close. An applied answer still leaves the result pending.

Work status: idle

idle: true means the instance has finished its in-flight handlers, tracked tasks, and scheduled work.

{"idle": true}
  • The initial value is syn.idle, default false. Later packets omitting idle leave it unchanged.
  • New client input may start more work. A one-shot client may close when idle.
  • A host configured to finish on idle ends its connections with fin reason idle.

Connection ending: fin

fin ends the connection and tells the client how to proceed.

{"fin": {"reason": "gone", "message": "Instance deleted"}}
FieldMeaningUsage
reasonWhy the connection is ending, listed belowRequired
messageExplanatory textOptional
statusHTTP status, when applicableOptional
codeMachine-readable detail about the causeOptional
retryMinimum reconnect delay in milliseconds for retryable finishesOptional
payloadApplication dataOptional
metaDate metadata for payloadOptional
reasonMeaningClient actiononError
reconnectExpected disconnect; reconnect to continueReconnect with exponential backoff and jitterNo
errorUnexpected, potentially recoverable failureReconnect with exponential backoff and jitterYes
protocol-errorInvalid protocol data or an unsupported protocol versionStopYes
unauthorizedCredentials missing, invalid, or expiredRefresh credentials and reconnect once; stop after a second consecutive denialIf recovery fails
forbiddenAccess deniedStopYes
goneThe instance no longer existsStopNo
idleThe instance finished its workReattach when neededNo

code describes the specific cause. For reconnect:

codeMeaning
evictedThe instance left this host
overloadedThe host lacks capacity
lease-expiredThe attach reached its maximum authorization lifetime; reconnect and authorize again
client-fell-behindThe host's outgoing queue for the client filled; reconnect for a fresh snapshot
replacedA later attach of the same attacher retired this one
reauthorizeThe host ended this attach so it authorizes again, typically after a role change

For error:

codeMeaning
filter-failedThe host's read filter for this attach failed
compatibility-failedThe host could not project its state to this attach's selected versions
identity-unencodableThe host could not store the attach's authorization result as the client id's durable admission identity
{"fin": {"reason": "reconnect", "code": "overloaded", "retry": 5000}}
  • Recovery and onError behavior follow reason; clients ignore unknown code values.
  • gone, forbidden, protocol-error, and a second consecutive unauthorized fail unanswered commands. Other reasons keep durable-lane commands pending for reconnection; ephemeral-lane commands are lost.
  • Command failures are reported separately from connection finishes.
  • Every automatic reconnect after fin waits max(client backoff, min(fin.retry ?? 0, client backoff ceiling)) milliseconds from receipt of fin.
  • Unknown reasons follow the error path. A transport close without fin is a transport fault; reconnect.
  • Transport-specific failures and statuses are listed in Statewire Transport.

Admission

Admission accepts a frame's new statements for processing. All command lanes in a frame are admitted together; commands have individual outcomes afterward. Valid context replacements are installed before command admission and remain installed if new commands are refused.

Comparing with the watermark

In each lane, statements at or below its watermark are repeats. The first new statement must be watermark + 1.

Under 2026-09-30, for a harness-sdk watermark of 7:

Frame's harness-sdk sequence numbersOutcome
6, 7Repeat both; re-emit available answers
8Admit command 8
6, 7, 8, 9Repeat 6 and 7; admit 8 and 9
9Refuse the new statements: command 8 is missing
8, 10Protocol violation: the lane is not consecutive within the frame
  • Under 2026-11-01, the client gets its answers from the results cursor and sends a sequence number only while it is above the hello watermark. Another attach of the same client id can still land it first, such as a closed tab's frame arriving late. The host answers that repeat as under 2026-09-30. Hosts before statewire 0.27.5 and statewire Python 0.23.4 end the attach as a protocol violation instead.
  • Under 2026-09-30, a gap in a durable lane refuses all new statements in the frame with the per-lane watermarks. Answers to repeats may still be re-emitted. Under 2026-11-01, the gap refusal is unchanged.
  • Durable hosts load the retained durable-lane watermarks before comparing sequence numbers.

Attach statements

The attach request (POST /stream body or the WebSocket initial message) may carry a frame.

  • Context is validated under the selected contracts and installed before the snapshot and any initial command admission.
  • Ephemeral-lane statements are admitted before the snapshot is built: their documents ride the hello ops and their answers ride the hello cmd.
  • Durable-lane statements run after the hello.
  • The first ephemeral-lane statement of an attach carries seq: 1; any other first sequence number is a protocol violation.

Replacing an attach

Under 2026-11-02, every attach of one client connection carries the same Statewire-Attacher token, minted by the client (WebSocket: in the first frame's headers). Two tabs sharing a client id carry different tokens. A client id with one holder at a time (session storage that is not shared) may keep its token across connections: then a reloaded page's attach replaces the previous page's.

  • Before an attach's hello reads watermarks, the host retires the client id's earlier attaches with the same attacher. It does this after the principal checks, and a replaced attach does not count against the subscriber limit.
  • Admissions in progress under a retired attach finish first. No frame is admitted under it again: POST /frames answers 423, and its stream ends with fin reconnect / replaced.
  • So no frame sent on a replaced attach, including one whose hello never reached the client, lands after the new hello.
  • Under earlier versions the header is ignored.

Results cursor: res

Under 2026-11-01, the attach frame may carry res: per durable lane, the sequence number through which the client holds every answer.

{"res": [{"protocol": "harness-sdk", "seq": 41}]}
FieldMeaningRequirement
protocolSelected durable laneRequired, unique within res
seqCursor; the client holds answers through itRequired nonnegative integer

For each sequence number above the cursor and at or below the lane watermark, the hello cmd carries:

CommandAnswer
Settled, verdict retainedThe verdict
Running, after appliedapplied
Running, before appliedNothing; its answers ride the stream
Settled, verdict unavailableexpired
  • res is valid only on the attach request. On a POST /frames body, or under 2026-09-30, it is a protocol violation.
  • Ephemeral lanes are skipped.
  • Retained verdicts and applied answers above the cursor are always sent. expired covers at most 4096 sequence numbers past the cursor per lane.
  • A frame carrying only res is a valid attach frame.

Capacity

LimitMaximum
Admitted durable-lane commands per client that have not fully released, across lanes256
Admitted commands across the hostmaxInflightCommands / max_inflight_commands, default 1024

A frame exceeding either limit is refused with retry: 1000.

Refusals: syn

A refusal reports the exact admission watermarks and leaves the connection open. The frame's new statements remain unadmitted.

{"syn": {"protocols": [{"name": "harness-sdk", "seq": 41}], "retry": 1000}}
retryMeaningClient action
PresentTemporary pushbackWait this many milliseconds, then resend
AbsentSequence gapReconcile with the watermarks and resend from each lane's next sequence
  • protocols[] entries are {name, seq}: one per lane. Statements through those watermarks have been admitted; their answers arrive on the stream.
  • retry is a nonnegative integer in milliseconds. Hosts may use it for capacity pressure or other temporary conditions. Clients cap the wait at their backoff ceiling.
  • Under 2026-11-01, a refusal can reach the client after frames it sent since were admitted. For durable lanes the client resends nothing from a refusal: it waits out retry, if present, and the answers to its attempted ephemeral-lane statements, then reattaches, and the hello decides.
  • Refusal delivery over HTTP and WebSocket follows Statewire Transport.

Watermark refresh: syn

A mid-stream syn without retry reports lanes whose watermark moved.

{"syn": {"protocols": [{"name": "harness-sdk", "seq": 41}]}}
  • idle may ride a mid-stream syn.

Answers to repeated commands

Under 2026-09-30, within a retained client record, repeated sequence numbers in a lane refer to the same command execution.

Original commandAnswer to the repeat
Running, before appliedWait for its answers
Running, after appliedRe-emit applied
Settled, verdict retainedRe-emit the verdict
Admitted, verdict unavailableEmit expired
  • Verdicts are retained in memory for 30 seconds, up to 256 per client, with the newest kept. Durable hosts retain admission across restarts.
  • To execute a command again after rejected or failed, assign a new sequence number.

Reconnecting

Keep the client id and each durable lane's sequence clock across page loads, except when every selected protocol is ephemeral.

Under 2026-11-01:

  1. Reconnect with the latest retained context values and a results cursor per durable lane with unanswered commands: the sequence number below the oldest one.
  2. For each durable lane, compare unanswered commands with the hello watermark. Commands at or below it were admitted: their answers ride the hello. Commands the attach carried from watermark + 1 on run after the hello: they count as sent. Other commands above it never arrived: assign them new sequence numbers after those before sending them.
  3. A command above the watermark that the client saw admitted, or a first unanswered command above watermark + 1, proves the record that admitted it is gone: report the lane's commands as lost and restart its clock at the watermark.

Under 2026-09-30:

  1. Reconnect with the latest retained context values and receive a fresh snapshot. On a fresh hello replacing an attachment on an existing socket, restore context before sending commands.
  2. Resend pending durable-lane statements with their original sequence numbers, consecutively within each lane. Ephemeral lanes start again at 1.
  3. On a refusal with retry, wait before resending. On a gap refusal, compare each lane's first unposted command with its next expected sequence, using the higher of the refusal's seq for that lane and any dur acknowledged for it on this connection.
  4. If a command skips a prefix the client has already discarded, report held commands in that lane as lost and restart the lane's clock at the refusal's watermark.

For a refusal reporting {"name": "harness-sdk", "seq": 5}, with no higher dur acknowledged:

Client's pending harness-sdk commandsRecovery
6, 7, 8, 9Resend from 6
9, with 6–8 already discardedReport held commands as lost; the next command uses 6
  • A lower durable-lane watermark in the hello alone leaves pending commands under their original sequence numbers.

Reserved behavior

  • Method names beginning with statewire/ are reserved for protocol commands.
  • statewire/commands is mandatory within each protocol. Call it with the target protocol and params: []; its result is that selected contract's sorted command-name array, including itself.
  • The _ instance-id segment is reserved for attaching before an instance exists. Its identity confirmation is {"syn": {"id": "..."}}; placeholder attaches are currently stubbed in the hosts.

Client handling

  • Mid-stream syn.version, mid-stream syn.protocols[].version or syn.protocols[].record, and next beside ops are protocol errors.
  • Clients skip unknown metadata types from the server. Hosts reject unknown command metadata types as invalid-params; invalid context metadata is a frame violation.
  • Hosts may use custom admission pushback in addition to capacity limits.