Conformance & Security
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, a runtime trap, or an envelope whose proof does not verify — a byte-bearing method returns a normal result whose decoy flag is true and whose ciphertext is a deterministic pseudo-random stream seeded by the requested key. The decoy has a plausible, key-derived length and streams through the identical chunk machinery, so a passive observer (and the operator) cannot distinguish a hit from a miss by status, shape, or size. A client treats decoy: true as not-found, never as an error.
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 miss with an indistinguishable
decoystream, 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 dig RPC: Network Content Interface specification, a companion to the DigStore whitepaper and the dighub API Interface.