Conformance & Security
The authoritative cross-implementation conformance discipline is Protocol · Conformance & parity; the blind serving model is Protocol · The blind host model. This page is the task-oriented node-operator contract.
The dig RPC is designed so that any node can join the network's read path by implementing one interface exactly. This page is the contract.
The blind serving model
A node stores, per hosted generation, the compiled .dig capsule — a self-defending WebAssembly module that is both the data and the code that gates access to it. To serve a resource, the node runs the capsule's own serve flow for the requested retrieval key inside a bounded host runtime. The capsule returns a ContentResponse envelope carrying the resource's ciphertext and a merkle inclusion proof rooted at the generation's content root. The node decodes the envelope framing host-side to split the two — which is not decryption, the ciphertext stays sealed — and returns ciphertext (base64) + proof (base64). The host runtime holds no URN and no key, so it never reads what it serves.
Decoys: no existence oracle
On any content miss — unknown store, unknown retrieval key, a root with no hosted capsule — the capsule returns a deterministic pseudo-random stream seeded by the requested key, byte-shaped identically to a hit. There is no decoy flag on the wire: the response is indistinguishable, so a passive observer (and the operator) cannot tell a hit from a miss by status, shape, or size. The client learns not-found only when the inclusion proof fails to verify or the GCM-SIV tag fails to decrypt. (A genuine infra failure — no host seed, module absent, a trap, an undecodable envelope — is the distinct error -32004, not a decoy.)
Root resolution
When root is an explicit 64-hex value, the node serves that exact generation. When root is "latest" or absent, the node resolves the store's newest confirmed generation from its capsule index and serves that; the resolved root is echoed back as root. Because a store's existence and its generation list are already public on-chain (and via dig.listCapsules), a "latest" request against a store with no confirmed generation returns an error, not a decoy — that is store-level discovery, not a private-resource oracle.
A trustless client pins an explicitly chain-verified root rather than relying on the node's "latest" resolution.
CORS and cross-origin use
The RPC is a public, credential-free service over public ciphertext, so it is fully cross-origin. A node must answer OPTIONS with 204 and set, on every response:
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST, OPTIONS
Access-Control-Allow-Headers: content-type
Access-Control-Max-Age: 86400
Cookies and credentials are never used or honored. This lets any web app, a sandboxed preview origin, or any third-party site call any node directly from the browser. A node must send a strict content-security and nosniff posture so its opaque JSON is never interpreted as an executable document.
Caching and immutability
RPC responses are not edge-cached: the body is a POST result and a single chunk request is cheap. Content is nonetheless effectively immutable when addressed by an explicit (store_id, root, retrieval_key, offset) tuple — the generation root pins the exact bytes — so a client may cache a verified, decrypted resource keyed by that tuple. A "latest" read is mutable by definition; clients that need stability pin the root echoed in the first chunk.
Rate limits and abuse
Rate limiting and request shaping are node-operator policy, not part of the wire contract. A node may reject or throttle abusive callers by IP or volume, and should do so without revealing content state (a throttle is an HTTP-level rejection, never a JSON-RPC error tied to a specific store or key). Because the interface is blind and read-only, the abuse surface is bandwidth, not data exposure.
Conformance checklist
A node is a conformant dig RPC endpoint if and only if it:
- accepts JSON-RPC 2.0 single and batch requests over HTTPS
POSTat a single origin, and answersOPTIONSper the CORS rules above; - implements
dig.getContent,dig.getProof,dig.getProofStatus,dig.getCapsule(and thedig.getModulealias),dig.getManifest,dig.getMetadata,dig.listCapsules,dig.health, anddig.methodswith the documented parameters and results; - returns the REAL merkle inclusion proof synchronously and serves only REAL execution-proof receipts (a forgeable mock is never published as a proof);
- streams byte methods with the chunk object, snapping to 64 KiB blocks and capping at the declared max chunk, with correct
total_length,complete, andnext_offset; - returns sealed ciphertext plus a root-anchored inclusion proof for real
dig.getContent/dig.getManifesthits, and never returns a URN, a key, or plaintext; - answers every content miss with an indistinguishable decoy stream (no
decoyflag on the wire), never a404or a distinguishing error, and never exposes an existence oracle for a private resource; - resolves
"latest"to the newest confirmed generation and echoes the resolvedroot; and - uses the JSON-RPC error codes only for malformed or unroutable calls.
The full normative text is the Protocol · The dig RPC section — the network content interface — alongside the DIGHUb API Interface.
Related
- Methods — the method set a conformant node must implement
- Streaming — the chunk object, alignment, and bounds
- Using the public network RPC — operating your own node
- Proofs & Security — the proofs nodes serve blindly
- Concepts & glossary — the dig RPC and capsule defined