Superbee wire protocol
September 15, 2026 ยท View on GitHub
This file is the repository authority for the currently implemented Superbee storage seam over
HTTP. It documents the protocol implemented by @superbee/server and consumed by
RemoteBackend; code and tests are behavior evidence, not separate protocol specifications.
The current route prefix is /v0. Blob routes are an additive v0.1 capability under that prefix.
The protocol is pre-1.0 and may change, but a change is not implemented until this contract and its
behavioral proofs change together.
Security boundary
The reference serve() implementation has no authentication or authorization. It ignores the
Authorization header and binds to 127.0.0.1 by default. Loopback prevents access from another
machine; it does not protect against another process or user on the same machine. Passing a
non-loopback host exposes the same unauthenticated server and is not a production deployment.
A production host uses @superbee/server/router, whose context resolver authenticates and
authorizes the one canonical resolved bundle route, then returns a bundle-bound backend and trusted
attribution. That router ignores client-supplied X-Actor and X-Agent; the Node package-root
reference adapter retains both as advisory, client-controlled strings for compatibility.
RemoteBackend can send Authorization: Bearer <token> on every request, but that capability does
not make the reference server enforce it. A gated deployment owns the meaning of that token.
Conventions
- Paths are
/v0/bundles/{bundle}/.... The reference router closes over one backend: it accepts any syntactically valid{bundle}segment but does not use it to select among bundles. - The Worker-safe
@superbee/server/routersubpath instead requires exactlybnd_plus 32 lowercase hexadecimal characters. Its public resolver rejects labels, aliases, uppercase ids, percent escapes, encoded slash or backslash, and empty or repeated bundle segments before the trusted context resolver can run.GET /v0/capabilitiesis deployment-scoped and bypasses that resolver and storage. resolveWireRequest(Request)governs the normalizedpathnameexposed by the Fetch/WHATWG URL API. An adapter that can inspect an HTTP request-target before URL normalization may enforce stricter raw-target rules separately. The Fetch router does not reconstruct raw bytes that the platform no longer exposes. Encoded separators and malformed bundle tokens that survive normalization are rejected. Normalized-away dot forms are outside this router's observable boundary and can become a canonical route (for example,/bundles/./bnd_.../docs); rejecting their raw spelling requires an upstream adapter with request-target access.- Document IDs and blob keys may contain
/; clients encode each segment independently. Every route validates decoded IDs/keys before backend access. Document IDs cannot address reservedindex.mdorlog.md, and cannot contain a control character (any code unit below U+0020, or U+007F): every document route, read-many entries included, answers400 USAGEto such an id before any backend access, even where the core id rule would admit it locally. Blob keys cannot end in.mdand reject absolute, traversal, and dot-prefixed segments. - JSON responses use
content-type: application/json; charset=utf-8. Blob reads use the blob's content type and raw bytes. SuccessfulHEADresponses and allHEADfailures are bodyless. - Except for
HEAD, errors have shape{ "error": { "code": "...", "message": "...", "details": ... } }. Current router-owned classes are400 USAGE,404 NOT_FOUND,412 VERSION_CONFLICT, and500 RUNTIME. Unsupported methods currently return400 USAGE, not405.401 AUTH_REQUIREDand403 FORBIDDENare host-owned: a gated host answers them before the router runs, and the reference router never emits them. On an identified write that ordering matters: an authorization refusal arrives before the key is claimed, so nothing is recorded under it. - Version-carrying responses send a bare content-addressed token in
X-Version(primary) and the same token as a quotedETag(secondary). A conforming client must refuse a successful versioned read that has neither header; it must not silently downgrade a later CAS write. If-None-Match: *means expect-absent create.If-Matchaccepts the bare token and quoted or weak ETag forms. Omitting both requests an unconditional write. An empty expected version is invalid client input, not an unconditional-write spelling.X-Actoris advisory write attribution.X-Agentis reserved for a trusted authentication gate; see the no-auth caveat above. Deletes create no revision and send neither attribution header fromRemoteBackend.- Document and blob deletes are idempotent: both return
200 { "deleted": true|false }; absence isdeleted:false, not404. A supplied staleIf-Matchstill returns412. A document delete that carriedIf-Matchanswers with the version headers naming that token; an unconditional delete sends none. Idempotency-Keyidentifies a documentPUTorDELETEso it is applied at most once and its outcome can be looked up afterwards; see "Identified writes and outcome lookup" below. On any other endpoint the header is400 USAGE, never ignored.
Implemented endpoints
{id...} and {key...} mean one or more independently encoded path segments; {key} on the
operation route is exactly one.
| Method | Path | Success contract |
|---|---|---|
| GET | /v0/capabilities | 200 capability booleans: history, enforced_cas, projections, backlinks, blobs, operations, heads, snapshot. |
| GET | /v0/bundles/{bundle}/docs | 200 { count, docs, next_cursor }; filters/pagination below. |
| POST | /v0/bundles/{bundle}/docs:read-many | JSON { ids: string[] }; 200 { results }, or all-or-nothing 404 with details.missing. |
| GET | /v0/bundles/{bundle}/heads | 200 { count, digest, heads } with the digest as ETag, or bodyless 304 when If-None-Match names it; see "Heads and snapshot". |
| GET | /v0/bundles/{bundle}/snapshot | 200 NDJSON stream of every document between a header and an end line, digest as ETag; see "Heads and snapshot". |
| GET | /v0/bundles/{bundle}/docs/{id...} | 200 { id, frontmatter, body } plus version headers. |
| PUT | /v0/bundles/{bundle}/docs/{id...} | JSON { frontmatter, body? }; 201 for expect-absent create, otherwise 200, with { version } plus version headers. |
| HEAD | /v0/bundles/{bundle}/docs/{id...} | Bodyless 200 plus version headers, 404 absent, or 400 invalid. |
| DELETE | /v0/bundles/{bundle}/docs/{id...} | 200 { deleted }; optional If-Match, echoed as version headers when supplied. |
| GET | /v0/bundles/{bundle}/docs/{id...}/versions | 200 { versions }, each carrying version, actor, timestamp, and optional agent. |
| GET | /v0/bundles/{bundle}/reserved/{name} | {name} is index.md or log.md; optional dir; 200 { content } plus version headers, or 404. |
| PUT | /v0/bundles/{bundle}/reserved/{name} | {name} is index.md or log.md; optional dir; JSON { content }; 201 expect-absent or 200, with { version } plus headers. |
| GET | /v0/bundles/{bundle}/blobs | 200 { count, keys, next_cursor }; prefix/pagination below. |
| GET | /v0/bundles/{bundle}/blobs/{key...} | Raw bytes with stored Content-Type and version headers, or JSON 404. |
| PUT | /v0/bundles/{bundle}/blobs/{key...} | Raw request bytes; optional Content-Type; 201 expect-absent or 200, with { version } plus headers. |
| HEAD | /v0/bundles/{bundle}/blobs/{key...} | Bodyless 200 with content type/version, 404 absent, or 400 invalid. |
| DELETE | /v0/bundles/{bundle}/blobs/{key...} | 200 { deleted }; optional If-Match. |
| GET | /v0/bundles/{bundle}/operations/{key} | 200 recorded outcome of the identified write under {key}, or 404 NOT_FOUND when nothing is recorded; requires write access. |
There are deliberately no collection-delete routes and no reserved-file delete route.
List projection and pagination
Document list query parameters are prefix, type, repeated tag, fields, limit, and
cursor. Filters are ANDed. The default page size is 50; a missing, non-positive, or unparsable
limit also selects 50. count is the total filtered count before cursor pagination. The default row
is { id, version, type, title, timestamp }; fields=frontmatter returns
{ id, version, frontmatter }. The fields name is therefore a projection selector on the wire,
not the CLI/core QueryFilter.fields equality filter.
Blob list accepts prefix, limit, and cursor with the same page-size and envelope semantics.
Both cursors are the last returned ID/key. If that cursor vanished, the next page resumes using the
same localeCompare ordering as the backend scan.
Documents, canonical bytes, and blobs
The document route transports a parsed document as JSON, not the original Markdown byte stream.
RemoteBackend.read() reconstructs the requested ID with the returned frontmatter/body and retains
the server's content-addressed version token. A CLI doc read --out over --remote therefore emits
Superbee's canonical OKF serialization. It is byte-identical to a local export for an engine-written
canonical document, but external formatting, YAML key order, quoting, or whitespace may not survive
a remote round trip even when document meaning does. The version header identifies server state; it
must not be inferred by hashing the client's reconstructed export.
RemoteBackend.write() captures document metadata through one client-side JSON encoder before
sending the PUT. Plain records (including null-prototype records), dense arrays, null, strings,
booleans, and finite numbers other than negative zero are supported. Valid ordinary Dates retain
the existing ISO-string conversion. Shared references are expanded as JSON values; object identity
and YAML aliases are not transported. Local YAML storage is not restricted by this client policy.
Values that would be dropped or changed silently are refused with an InvalidInputError subtype
and a field path: undefined, functions, symbols, BigInt, nonfinite numbers, negative zero, cycles,
sparse arrays or extra enumerable array properties, enumerable symbol keys, custom instances,
binary values, invalid or extended Dates, accessors, and custom serialization hooks. The encoder
does not invoke user getters or toJSON hooks. Ordinary noncallable toJSON fields are data.
Nesting beyond 512 containers is explicitly refused. No document PUT is sent on refusal.
The identified-operation transport maps this local refusal to refused / USAGE, not an unknown
delivery requiring retries. Capability discovery may already have issued a GET; the local refusal
does not imply an outcome was recorded by the server.
The server uses the same captured metadata rule for document GET, batch reads, full list
projections, and snapshot document frames. Incompatible stored metadata fails an ordinary
response with 500 RUNTIME and a field path, not a client-input error or changed data. Compact
lists check only their emitted metadata fields; an incompatible hidden extension does not
prevent listing. Absent optional fields stay absent. A snapshot encountering incompatible
metadata errors its stream without an end frame, including after earlier valid batches. Clients
must reject completion; browser bootstrap retains its incomplete marker and does not reconcile
deletions from that failed snapshot. Local YAML reads and writes remain unrestricted.
This does not fix first-write Date version differences or server write-key ordering.
Blobs are the raw-byte channel. Blob PUT and GET carry exact bytes as the HTTP body, with content
type in Content-Type and identity in the version headers. Blob keys ending in .md are rejected so
the blob channel cannot become an accidental bypass around document parsing and ID safety.
Heads and snapshot
A working copy that re-walks a whole bundle on every sync (one hundred list pages plus reads at
5,000 documents) and bootstraps with hundreds of round trips has no way to ask what changed. Heads
and snapshot are the bounded reconciliation mechanism the browser working copy uses: one round
trip says whether and what changed, and one response carries the whole bundle. Both routes are
read-only, additive, and reported by GET /v0/capabilities as heads and snapshot.
Heads
GET /v0/bundles/{bundle}/heads answers 200 { count, digest, heads } where heads is every
document as { id, version }, sorted by id in UTF-16 code unit order, and count equals the
number of rows. Code unit order is independent of any locale and is not the localeCompare
collation the list route uses; a host must not substitute the list order. There is no pagination
and no filter: the whole listing is the point of the route. Reserved files are not heads.
The digest is sha256:<hex> over the UTF-8 bytes of the sorted rows concatenated as
id, \n, version, \n for each row, in order, with no other separator; an empty bundle
digests the empty byte string. The recipe is injective only when no id contains a line feed
(U+000A), which the concept id rule alone does not guarantee, so the wire enforces it: every
document route refuses an id containing a control character (Conventions), and a host whose
bundle already holds such an id, written outside the wire, fails heads with 500 RUNTIME and
fails the snapshot before its header line rather than minting a digest that another listing could
share. Any host computes the same token from the same heads (headsDigest in @superbee/core/storage
is the reference recipe). The digest changes whenever any document is created, updated or
deleted.
The response carries the digest as a quoted ETag. A request whose If-None-Match names that
digest, bare, quoted or weak, alone or in a comma-separated list, answers a bodyless 304 with the
same ETag: nothing changed since the client obtained that digest. On a 200 the client diffs
heads against its own copy: an id missing from heads is a deletion, a differing version is a
change, an unknown id is a creation. RemoteBackend.heads({ ifNoneMatch }) maps 304 to null
and refuses a 200 whose digest is missing or malformed, whose count disagrees with its rows, or
whose rows do not digest by the recipe to the digest it served (a listing that is whole by its
own count but is not the state its digest names is never diffed as deletions); a 304 to a
request that sent no If-None-Match is likewise refused as malformed.
Snapshot
GET /v0/bundles/{bundle}/snapshot answers 200 with
content-type: application/x-ndjson; charset=utf-8: one JSON object per line, each line
terminated by \n. The grammar is:
- exactly one header,
{ "kind": "snapshot", "count": N, "digest": "sha256:..." }; - exactly N document lines,
{ "kind": "doc", "id", "version", "frontmatter", "body" }, in id order; - exactly one terminator,
{ "kind": "end", "count": N }.
A client that does not see the end line, or sees one whose count differs from the header's
announcement or from the document lines it received, must treat the snapshot as truncated and
discard or re-request it; RemoteBackend.snapshot() reports that as RemoteError code
SNAPSHOT_TRUNCATED, including a transport failure mid-body. A client that saw the whole body
must also recompute the digest over the { id, version } of the document lines it received and
compare it to the header's before recording that digest as matched; RemoteBackend.snapshot()
rejects the iteration with code SNAPSHOT_DIGEST_MISMATCH when they differ. That is not
truncation: the body was whole, the authority contradicted its own header, and re-requesting is
not known to repair it. The header's digest equals what heads would return for the same
state, so a bootstrap that consumes a snapshot can start its later heads checks from it; the
response also carries it as ETag. Reserved files are not part of a snapshot: a client fetches
index.md through the reserved route as today.
The body streams. The reference router produces the heads listing first (so a malformed document
fails the request before any byte of the response exists, exactly as it fails a list), then reads
bodies in batches of 50 and encodes each batch as it is produced; the node:http bootstrap pipes
the body to the socket. A document deleted between the listing and its batch errors the stream,
which the client observes as truncation. A document changed in that window errors the stream the
same way: the router compares each read version to the listed head and never emits a line the
header digest does not describe, so the client sees truncation and re-requests.
A host may implement heads and snapshot over a change log or over a scan; the reference scans:
list for the ids, then reads in batches of 50 keeping only each document's version, so the
listing touches every document once but holds no bodies. The snapshot then reads the bodies again
in batches of 50 as it streams. Either way the client pays one round trip.
Identified writes and outcome lookup
A write over a network has three answers, not two: applied, refused, or lost before the client
learned which. A document PUT or DELETE that carries an Idempotency-Key header is an
identified write: the authority applies it at most once under that key and keeps the answer, so a
client whose response was lost can look the answer up instead of guessing.
- The key is 1 to 128 printable ASCII characters with no space; anything else is
400 USAGE. Identity is scoped per bundle and per key. - The header is accepted on document
PUTandDELETEonly. Reserved-file and blob writes do not accept it in this slice, and a key on any other endpoint is400 USAGE, so a client never believes an unsupported write was identified. - The key is claimed before the write is applied. A duplicate submission, including one that
arrives while the first application is still in progress, receives the recorded response
replayed: the same status, the same
X-VersionandETag, the same body. Payload differences under the same key, method and id are not inspected. - A recorded outcome is bound to the method and decoded document id it was recorded for. The same
key resubmitted with a different method or id is
400 USAGEwithdetails: { recorded: { method, id } }, never a replay. - Content rejections are recorded outcomes: a duplicate of a
412 VERSION_CONFLICTreplays the412, and a duplicate of a400 USAGEreplays the400. A host-owned401 AUTH_REQUIREDor403 FORBIDDENis answered before the key is claimed, so nothing is recorded under it. If the application throws before any response exists (a runtime failure, not a 4xx or 5xx response), the claim is released with nothing recorded and a later submission applies fresh. - An identified
DELETEmust carry a well-formedIf-Matchtoken, a content-addressed version (sha256:followed by 64 lowercase hex characters, bare or in ETag form); without one, or with an empty or malformed one, the request is400 USAGEbefore the key is claimed and nothing is recorded. The delete's response echoes theIf-Matchtoken as its version headers, which is the version its recorded outcome is committed at. That holds fordeleted: falseas well: an absent target is the idempotent success the wire promises, and the token the client supplied remains the revision its outcome names. GET /v0/bundles/{bundle}/operations/{key}returns the recorded outcome as exactly one of{ "kind": "committed", "version" },{ "kind": "conflict", "actual" }, or{ "kind": "refused", "code", "message" }(theOutcomeunion of@superbee/core/uncertain-writewithoutunknown). It requires write access: the caller must hold the right to make the write in order to learn its outcome.404 NOT_FOUNDmeans the authority holds nothing under that key; an invalid key is400 USAGE.- Retention. The reference store keeps an outcome for a window, 24 hours by default and
configurable with an injectable clock. A host states its window. A
404after expiry is indistinguishable from never recorded. A resubmission after expiry is safe only because the write carries its compare-and-swap premise: a committed write resubmitted after expiry answers412whoseactualequals the client's own committed version. The client's uncertain-write primitive (performUncertainWritein@superbee/core/uncertain-write) returns that outcome as{ "kind": "committed", "version": actual }, so the intent is acknowledged at its own version and its shared base moves, exactly as a200would have settled it; a412naming any other version, or a deleted target, stays a conflict. That property is what makes expiry safe, and it is why an identified write is always a guarded write. GET /v0/capabilitiesreportsoperations: trueexactly when the host records outcomes. A host without a store answers any request carryingIdempotency-Key, and the lookup route, with400 USAGE"request identity is not supported by this host".
Outcome-store adapter completion
The server's OperationClaim.record and release callbacks may be synchronous or asynchronous.
TypeScript consumers of this interface must await callback results, including when accessing
recordedAt from the reference memory store's returned record.
The router awaits recording before returning the identified result (including a content refusal),
and awaits release before returning an application failure. A rejected recording produces a runtime
failure, not the successful mutation response, and the router does not automatically release that
possibly applied operation. The store owns reconciliation and settlement of waiting duplicates.
Callback failures remain 500 RUNTIME even if an adapter throws a document-typed error.
Awaiting these callbacks is not a durable exactly-once protocol by itself. A persistent host must couple mutation evidence to its storage commit and reconcile that evidence before permitting a failed or interrupted claim to apply again. The reference memory store has no restart durability.
Client behavior
RemoteBackend maps the HTTP surface back to the StorageBackend seam:
404document reads become anENOENT-shaped error; absent blob reads returnnull.412reconstructsVersionConflictfromdetails.expectedanddetails.actual.- Other non-2xx responses become
RemoteErrorwith the wire code and HTTP status. A missing or malformed envelope uses a status-derived fallback. - Network failures and only
500,502,503, and504are retried by default, with bounded exponential backoff and jitter. A real 4xx, including401and412, is never retried. A guarded write whose response was lost may surface a conservative conflict after retry.RemoteBackendalso permits unconditional writes; because a retry after an ambiguous transport failure can repeat one, callers that require lost-update safety must supplyIf-Match/expect-absent semantics. - Full-frontmatter list pagination supplies the optional
queryHeadspush-down. Core re-applies query semantics, so a foreign backend may over-return but cannot redefine matches. RemoteBackend.heads()andRemoteBackend.snapshot()are the client half of "Heads and snapshot" above. A snapshot resolves once its header line is parsed and then streams its documents as an async iterable; iterating to completion is the completeness signal, a body that ends or fails first rejects the iteration withSNAPSHOT_TRUNCATED, and a whole body whose rows do not digest to its header rejects it withSNAPSHOT_DIGEST_MISMATCH. Transient retry covers obtaining the response only; re-requesting a truncated snapshot is the consumer's decision.- The grammar those two methods admit is owned by
parseHeadsAnswer(payload)andreadSnapshotStream(body, { status })in@superbee/core/remote, which also exports theSNAPSHOT_TRUNCATEDandSNAPSHOT_DIGEST_MISMATCHcodes; the methods are thin callers over them. A host that serves the same heads listing or NDJSON snapshot through routes of its own validates the answers with these reference validators rather than a second parser, since the admission they decide is what a working copy deletes locally. WriteOptions.requestIdandDeleteOptions.requestIdtravel asIdempotency-Key; a malformed one is anInvalidInputErrorbefore any request is sent. Transient retries of an identified write are true replays.RemoteBackend.lookupOperation(requestId)reads the outcome route and maps404tonull.createRemoteOperationTransportin@superbee/core/remote-operationsis the uncertain-write transport over those two calls: adocument.writeintent becomes an identified guardedPUT, and a lost answer is resolved by lookup before any resubmission.
Behavior evidence
The router's sole raw URL/method boundary dispatches through its exported WIRE_ENDPOINTS registry,
whose rows own endpoint id, method, path template, resource kind, and access class. The public
resolver returns either a deployment-scoped capability route or a bundle-scoped route carrying the
canonical bundle id, endpoint id, access class, and decoded resource. The Worker router passes that
same object to its context resolver once and dispatches through the returned bound backend.
The contract test pins that boundary, requires the exact endpoint table above to match the runtime
registry, and validates every source/test anchor in this proof table. The referenced behavioral
suites exercise the semantics through the router, RemoteBackend, and a real socket.
| ID | Contract area | Implementation evidence | Behavioral proof |
|---|---|---|---|
| WIRE-PROOF-01 | Capabilities and single-backend routing. | packages/server/src/router.ts::id: "capabilities" | packages/core/test/wire-protocol.test.ts::GET /v0/capabilities reports |
| WIRE-PROOF-02 | Document collection, projections, filters, cursors, and read-many. | packages/server/src/router.ts::id: "docs-read-many" | packages/core/test/wire-protocol.test.ts::GET /docs list endpoint carries count |
| WIRE-PROOF-03 | Document member read/write/head/delete and version headers. | packages/server/src/router.ts::id: "doc-delete" | packages/core/test/wire-protocol.test.ts::raw DELETE /docs/{id} response shape |
| WIRE-PROOF-04 | History and attribution payload. | packages/server/src/router.ts::case "doc-versions" | packages/core/test/wire-protocol.test.ts::GET /docs/{id}/versions returns |
| WIRE-PROOF-05 | Reserved file get/put only. | packages/server/src/router.ts::reserved file name must be index.md or log.md | packages/core/test/wire-protocol.test.ts::reserved files have no delete route |
| WIRE-PROOF-06 | Blob collection and raw byte member routes. | packages/server/src/router.ts::case "blob-read" | packages/core/test/wire-protocol.test.ts::REAL socket GET returns EXACT bytes |
| WIRE-PROOF-07 | Reference server is loopback by default and unauthenticated. | packages/server/src/serve.ts::NO AUTH in v0 | packages/core/test/wire-protocol.test.ts::serve() boots a real node:http listener |
| WIRE-PROOF-08 | Remote canonical export differs from an original-byte guarantee. | packages/cli/src/commands/doc/common.ts::canonical OKF re-serialization | packages/cli/test/remote.test.ts::canonical re-serialization is byte-identical |
| WIRE-PROOF-09 | Missing version transport fails closed. | packages/core/src/remote-backend.ts::VERSION_MISSING | packages/cli/test/remote-auth.test.ts::response stripped of BOTH version headers |
| WIRE-PROOF-10 | Identified writes apply once, replay their record, and are looked up by key. | packages/server/src/router.ts::id: "operation-lookup"; packages/server/src/operation-outcomes.ts::class MemoryOperationOutcomeStore | packages/core/test/wire-protocol.test.ts::identified PUT is applied once; packages/browser-local/test/sync.test.ts::lost acknowledgement: the fixture applies then drops the response |
| WIRE-PROOF-11 | Heads digest, 304 on If-None-Match, and deletions visible as missing ids. | packages/server/src/router.ts::id: "docs-heads"; packages/core/src/heads-digest.ts::export function headsDigest | packages/core/test/wire-protocol.test.ts::GET /heads lists every id and version under the documented digest; packages/core/test/wire-protocol.test.ts::RemoteBackend.heads maps 304 to null |
| WIRE-PROOF-12 | Snapshot streams terminated NDJSON; a cut body or count mismatch is truncation. | packages/server/src/router.ts::id: "docs-snapshot"; packages/server/src/serve.ts::pipeline(Readable.fromWeb | packages/core/test/wire-protocol.test.ts::GET /snapshot streams header, docs in id order, and end; packages/core/test/wire-protocol.test.ts::a snapshot cut after 40 lines; packages/core/test/wire-protocol.test.ts::serve() streams a 500-document snapshot |
Known deviations and open questions
These are current limitations, not promises that a client may paper over:
- The Node package-root reference adapter remains single-backend and does not select among bundles. Explicit bundle selection belongs to the Worker-safe subpath's host context resolver.
- A document whose final path segment is literally
versionsis ambiguous with the history subresource. - There is no original-document-byte endpoint. Canonical JSON reconstruction is the only remote
document export; blobs are raw but cannot use
.mdkeys. - A malformed document still fails a list. The wire has no
skippedrow/envelope to express the CLI's local quarantine-style partial result. - Wire
fieldsselects a projection and cannot express core's arbitrary field-equality filter. requestFromIncomingMessagesupports a maximum body size, but referenceserve()currently supplies no cap.- Authentication, authorization, and trusted principal/agent attribution belong to a gated host; the reference server implements none of them.
backlinksis reported false and has no wire endpoint; clients derive graph results from reads.- Transient retry applies at the transport boundary, including unconditional writes. The storage seam permits those writes, so a caller that needs lost-update protection must provide a CAS premise. Only an identified write turns a retry into a replay; an unidentified guarded write retried after a lost response may still surface a conservative conflict.
- Request identity covers document
PUTandDELETEonly. Reserved-file and blob writes carry no identity yet, and the reference outcome store is in-memory: a restarted reference server holds no records, which a client observes as404on lookup.