What leaves your infrastructure
Trusset never sees the underlying KYC data. Names, birth dates, nationalities and document numbers stay on your machine, and no endpoint accepts them. What does travel is the evidence that a predicate held:Enforcement depends on the instance
Two settings decide how strict a submission is judged, and they are not the same field. APRODUCTION instance requires proofs and rejects stub manifests, whatever the instance itself is set to. A DEVELOPMENT instance does neither by default, which is what makes a structural dry run possible without generating STARKs.
An instance can also opt in on top of that. Read both from Get Operator Key: proofVerificationEnabled is what you asked for, proofVerificationEnforced is what a submission is actually judged against. Gate on the enforced flag.
Run the proof tool
init asks four questions about your institution, generates both keys, pins the batch date, and prints your operator public key. Load the keys, drop records in input/, and run it:
kycHash.hex, the kycHash field of manifest.json, and the kycHash column of the batch CSV.
init pins the batch date into config.json. Leave it pinned. Every per-subject key and commitment derives from that number, so a bundle proved against a moving clock cannot be reproduced tomorrow, which is exactly what an auditor asks for.From bundle to verified customer
1
Register your operator key, once
Every manifest signature is checked against this key. Take the value Rotating it later does not re-verify anything already filed. Claims added under the old key stay on chain, and their manifests no longer verify against the new one. Keep the old key with the bundles it signed.
npm run show prints.2
Verify on-chain with the root hash
Load the bundle’s
manifest.json and call verifyFromManifest. The wallet address, root hash, country, investor type, and expiry days are read straight from the manifest; pass overrides for anything you want to change.result.kycHash equals manifest.kycHash once the root hash is on-chain. result.operation is verify for a new identity and update for an existing one.If you only stored the root hash (for example from the batch CSV), call verify directly with kycHash:3
Add proof-backed claims
With the root on chain, the bundle can back claims. Send the signature and the STARKs alongside the manifest.
claims.added counts what landed, and claims.claims holds one entry per claim as { claimType, dataHash, status, txHash }. One transaction is sent per claim. Use selected: ['KYC'] to add a subset.4
Check the result
status.onChain.isVerified is now true and status.onChain.kycHash matches the manifest.Which claims a proof can back
TheKYC claim always derives from the root hash. Field-level claims derive from the manifest’s proof leaves:
A canonical field proved with a different circuit is skipped rather than filed elsewhere. A
country leaf proved with preimage_knowledge backs nothing, because filing it under another slot would let it read as an unrelated attestation.
AML, TAX_RESIDENCY, SANCTIONS_CHECK, and PEP_CHECK are not proof-backed. Add them with addClaim. Those four are also the only slots a leaf with no canonical meaning may be filed under.
Re-proving a subject
Re-running the tool always produces a new root, because the batch date is bound into every leaf hash. The bundle is legitimate and supersedes the registered one, but its root no longer matches what the registry holds.addClaimsFromProof refuses that with HASH_MISMATCH. Rotating the registered root to the new bundle is a separate, opt-in operation: see Attest Proofs, which takes the rotation transaction alongside the claims.
Onboard in batch
The tool’s batch CSV maps row-for-row ontobatchVerify entries - up to 500 subjects in one on-chain transaction:
Troubleshooting
A verdict is stored against the bundle, so re-submitting the same bundle answers from the recorded report rather than re-running the STARK verification.
verification.cached tells you which happened. A transient VERIFY_BUSY or VERIFY_TIMEOUT is never cached.