Corpus Commitment · corpus.commitment

Prove a document was in the training set, or prove it wasn't.

Somebody claims a model was trained on a specific set of documents, or that a specific document was not in it. Today you take their word for it. This receipt lets you check, and you keep the corpus the whole time.

30 of 30 local checks pass

This instrument ships with this release. The 30 checks above are the local smoke suite, run in process against a throwaway key with no network calls.

The fight this ends

A rights holder asks a simple question. Was my work used to train this model? The answers you can give today are a press statement, a policy page, or a lawsuit. None of them are checkable.

Handing over the corpus is not an answer either. It's commercially sensitive, it's often licensed, and it exposes every other work in the set to anyone who asks about one.

So you're stuck between a denial nobody can test and a disclosure you can't make. This receipt is the third option. You answer one question about one work, and the answer recomputes on the asker's machine.

Here is the shape

01

Commit before training

You build a sparse Merkle tree over salted per item content commitments and sign the root. The signed corpus_root carries the root, the schema_hash of the normalizer, the salt_commitment, and the item_count.

02

Commit the weights

When training finishes you sign a weights commitment. Its weights_binding names the weights_digest, the referenced_root, and the envelope digest of the corpus root receipt, so the model you shipped is tied to the corpus you committed.

03

Answer one query

A query arrives. You reply with a membership witness and the item salt opening, or with a non membership witness. The verifier recomputes the path to the committed root and reports a verdict of in_corpus or not_in_corpus.

What holds it together

The order matters more than the tree does. The root is signed before the weights commitment, so you can't assemble a flattering corpus after the fact and point the receipt at it. ROOT_BEFORE_TRAINING checks that ordering, and SINGLE_ROOT_PER_RUN refuses a second root for the same model run.

Change one document and the normalized hash changes, so the position moves and the path stops matching. Point the receipt at a different set of weights and WEIGHTS_BINDING refuses. Deny membership for a work that is in fact under the root and NONMEMBERSHIP_WITNESS_RECOMPUTE refuses, because an empty subtree constant can't fold to a root at an occupied position.

The answer is narrow on purpose. QUERY_NON_LEAKAGE caps the disclosure at the one item queried, so answering about one work tells the asker nothing about the rest of the corpus.

Verify one yourself

Verify is open. No key, no account, no rate on the answer you get back.

curl -sS -X POST https://thehiveryiq.com/v1/verify/corpus-commitment \
  -H 'content-type: application/json' \
  -d @answer.json

answer.json carries the signed answer plus the two linked receipts and the registries the verifier checks them against.

{
  "receipt": {
    "receipt_id": "...", "payload_sha256": "...", "sig_b64u": "...",
    "key_id": "did:hive:trainer-key", "algorithm": "Ed25519", "ts": 1908277800,
    "signed_body": {
      "receipt_type": "corpus.commitment",
      "answer_id": "rights-holder-query-0041",
      "corpus_root": { "model_run_id": "...", "root": "...", "salt_commitment": "..." },
      "weights_binding": { "weights_digest": "...", "referenced_root": "..." },
      "query": { "query_commitment": "...", "normalization": { "segment_digests": ["..."] } },
      "answer": { "answer_type": "membership", "item_key": "...", "item_salt_hex": "..." },
      "witness": { "depth": 256, "sibling_bitmap": "...", "siblings": ["..."] },
      "disclosure": { "disclosed_item_count": 1, "disclosed_item_keys": ["..."] },
      "verdict": "in_corpus"
    }
  },
  "corpus_root": { "signed_body": { "receipt_type": "corpus.root" } },
  "weights_commitment": { "signed_body": { "receipt_type": "corpus.weights" } },
  "evidence": {
    "root_registry": [ { "model_run_id": "...", "root": "...", "corpus_root_receipt_id": "..." } ],
    "normalization_registry": [ { "version": "ns1.4.0", "schema_hash": "..." } ]
  }
}

You get back valid, the ordered gates array, and on a refusal the failed_gate and reason that stopped it.

What gets checked

The verifier runs every gate in order and stops at the first failure, then tells you which one stopped it. A later gate never reads a field an earlier gate already showed to be untrustworthy.

Every gate the verifier runs, in order (21 gates)
Gate
SCHEMA
ISSUER_KEY_MATCH
ENVELOPE_SIGNATURE
CORPUS_ROOT_RECEIPT_LINK
CORPUS_ROOT_RECEIPT_INTEGRITY
WEIGHTS_BINDING
ROOT_BEFORE_TRAINING
SINGLE_ROOT_PER_RUN
SCHEMA_VERSION_PINNED
NORMALIZATION_CANONICAL
QUERY_COMMITMENT_RECOMPUTE
ANSWER_TYPE_BINDING
ANSWER_TYPE_PRECOMMITMENT_ORDER
SALT_OPENING_CONSISTENT
SPARSE_TREE_WELL_FORMED
WITNESS_AGAINST_CURRENT_ROOT
MEMBERSHIP_WITNESS_RECOMPUTE
NONMEMBERSHIP_WITNESS_RECOMPUTE
QUERY_NON_LEAKAGE
VERDICT_RECOMPUTE
BOUNDARY_CONSTANT

Field names come from the published schema: https://thehiveryiq.com/.well-known/schemas/corpus-commitment-v1.json. It ships with this release alongside the routes below, and the developer docs carry the schema catalog.

What this receipt does not say

This is the honesty boundary carried inside every corpus.commitment receipt, verbatim from the signed body.

This receipt attests only that one queried work, normalized under the pinned normalization schema version, is present at or absent from the position that work occupies in a sparse Merkle accumulator whose root the trainer signed before the weights commitment for the named model run, and that the disclosed witness recomputes to that root. A verdict of in_corpus means only that the item commitment for the queried work sits under the committed root. A verdict of not_in_corpus means only that the position for the queried work is empty under that same committed root. Neither verdict establishes that the committed corpus is the only data the model was trained on, that the trainer did not train on a second uncommitted corpus, that the item count is truthful about works never committed, that any work was used lawfully or unlawfully, that any licence, permission, exception, or exhaustion applies, or that the normalization schema captures every form in which a work may appear. It does not establish authorship, ownership, originality, or subsistence of any right in the queried work, and it says nothing about any work other than the one queried. This receipt decides no contractual, statutory, regulatory, evidentiary, or legal consequence, allocates no risk, fault, responsibility, liability, loss, or remedy, and authorizes no action, payment, sanction, denial, or remedy.

Hive never holds the underlying data

Hive never receives the corpus, the deleted object, the raw meter data, the analysis inputs, or the control inputs. Every value is a commitment the holder computed locally, and all this service can do is recompute the arithmetic between those commitments and refuse when it does not hold.

Endpoints

RouteWhat it does
POST /v1/mint/corpus-commitmentIssue an answer over commitments you computed locally. Needs Authorization: Bearer HIVE_TYPED_MINT_TOKEN and fails closed without it.
POST /v1/verify/corpus-commitmentRecompute the witness and the bindings. Open, no auth.

Where this sits

A corpus commitment answers one question about one work. Pair it with the other four instruments in this release when the dispute moves from what a model read to what a system did.

The other four instruments in this release: erasure receipt, meter witness, analysis replay, control replay. For the receipt that fixes a recording instead of a computation, see capture commitment. For the written papers, see papers.

Patent pending. Hive Civilization, The Hivery, Inc.