config.json. After reading it you will know what every field does, which ones are hashed into the bundle, and which changes re-key every subject.
config.json lives in the repository root and is read from the current directory. npm run init writes a complete one; config.example.json is the same template with a placeholder issuer. The file is ignored by git.
Most of the file is folded into the bundle. The predicates, tiers, lists, manifest block and the three security settings that affect key derivation are hashed into configHash, which enters every per-subject key. Editing any of them changes every nonce, every commitment and every root a later run produces. Cosmetic fields (output.format, output.includeIndex, security.clearInputAfterProcessing) are excluded from the hash.
mapping
Names the input columns. Required.string[]
required
The hashed fields. Each becomes at least one leaf. Names must be unique and non-empty. The generated config lists
firstName, lastName, dateOfBirth, nationality, documentType, documentNumber, documentIssuingCountry.string
required
The column holding the subject’s address. Default
walletAddress.string
required
The column holding the country of residence. Required by the config validator, so
country is always a leaf and always carries the plaintext disclosure class. Default country.string
The column holding the MiFID II client category. When set,
investorType becomes a leaf with the plaintext disclosure class. When omitted there is no investorType leaf, and the passthrough block and index CSV carry the configured default. Default investorType.string
Passthrough column; default
softExpiryDays. Omit it to take the configured default for every row.string
Passthrough column; default
hardExpiryDays.string
The column holding the day the subject’s evidence was examined. Sets
validity.basisAsOf for every leaf of that row. Default evidenceDate.claims.defaults
Values applied to every predicate that does not set its own. Optional, but without it every predicate must carry a full descriptor and validity block.string | object
"self" means the bundle issuer warrants the claim. A party object (name, identifierScheme, identifier, jurisdiction) names another regulated firm under a reliance arrangement. Default "self".string
Used when a predicate’s descriptor has no
evidenceClass. One of the six classes listed under descriptor.object
Used when a predicate has no
validity block. Same shape as the per-predicate block.predicates
One entry per field, keyed by the field name. Every hashed field, pluscountry and investorType when mapped, needs a predicate. A field with no entry falls back to a built-in default, and a field with neither is a configuration error. An entry for a field that is neither in mapping.fields nor one of the two special fields is rejected as a typo.
Two of those defaults are worth overriding, and the generated config does.
minTier: RETAIL asserts nothing, because the circuit already refuses to prove NONE. preimage_knowledge proves only that the operator knows an opening of its own commitment. commitment_only gives the same binding at no proving cost, which is why the generated config uses it for the four identity fields. There is no document_types list in the repository, so the documentType default fails unless you record one.
circuit and params
string
required
One of
age_threshold, set_membership, tier_threshold, preimage_knowledge, commitment_only. The last is a leaf mode rather than a circuit. It produces the commitment and the leaf hash with no STARK, and the manifest records it as circuit: "preimage_knowledge" with disclosure: "commitment_only".object
Depends on the circuit. The resolved values are recorded in
manifest.leaves[].params and hashed into paramsHash, which the verifier recomputes.descriptor
Required for every predicate whenmanifest.version is 3.0.0. It is hashed into the leaf, so it is evidence, not a comment; editing it changes the root. See Concepts.
object
required
Three non-empty strings:
framework (for example MiFID_II, AMLD5, REG_D, NATIONAL), reference (the provision), and assertion (one line, in your own words). None is validated against a list; they are recorded as written.string
How the value was verified. One of
SELF_ATTESTED, DOCUMENTARY, THIRD_PARTY_RELIANCE, AUTHORITATIVE_SOURCE, CRYPTOGRAPHIC, PHYSICAL_PRESENCE. Falls back to claims.defaults.evidenceClass; required through one of the two.string | object
"self", or a party object. Falls back to claims.defaults.issuingParty, then to "self". A party object needs name, identifierScheme (one of LEI, BIC, FCA_FRN, BAFIN_ID, CRD_ID, INTERNAL), identifier, and a two-letter upper-case jurisdiction.string
Optional operator-side case or file reference. It travels in cleartext inside the signed manifest, so it must never contain subject data.
validity
Required for every predicate whenmanifest.version is 3.0.0, either here or through claims.defaults.validity. Exactly one of the three window forms must be given.
integer
A window of this many days starting on the batch date, inclusive of the first day:
until = from + days - 1. Must be a positive whole number.string
A fixed last day,
YYYY-MM-DD, on or after the batch date.boolean
true for a claim with no self-imposed end. Only a revocation record can end it.integer
How many days before the batch date the evidence was examined. Non-negative, default 0. Overridden per subject by the
evidenceDate column when present. The resulting basisAsOf must not be after the batch date.Several predicates on one field
A field may carry an array of predicate objects. Each becomes its own leaf, with its own nonce, commitment, proof and descriptor.
Two instances that resolve to the same parameters are rejected, since they would produce the same leaf name. Leaf names may contain only letters, digits,
_, ., @ and -. The proof file is proofs/<leafName>.bin, and a revocation names the leaf by this name.
tiers
The integer code behind each investor type name. Optional; missing keys take the defaults.tier_threshold circuit, which accepts witness tiers 1 to 3 only and proves tier - minTier is in {0, 1, 2}. Leave the numbers as they are; a remapped code outside 1 to 3 cannot be proved. NONE is rejected at proving time with E_TIER_NONE.
lists
One entry per allowlist id that aset_membership predicate references. Under manifest.version 3.0.0 the entry may be empty: the list resolves from the signed registry under security.registryDir, which is the only source that also keeps superseded versions.
string
A bare list-commitment JSON produced by
trusset-list-commit, relative to the repository root. Read only when no registry exists for the id. A version 3.0.0 run warns about it and then refuses to build the leaf, because the leaf could not record which list version it was proved against. It works under manifest.version 2.1.0 and 2.0.0.string
Optional pinned SHA-256 of that file. The run refuses to start when the file’s hash has drifted.
Allowlist source files
A list starts as a plain text file, by conventionconfig/list_commitments/<id>.source.txt: one entry per line, # starts a comment, blank lines are ignored. Whitespace-only lines and duplicate entries are rejected, the latter unless --allow-duplicates is passed. A list needs at least two entries. Every entry is NFC-normalised before it is hashed.
Record it in the registry:
init records version 1 for every *.source.txt it finds in that directory. Every later change to the set is a new version with a new effective date; a version whose values are unchanged is refused. The registry keeps two hashes per version: sourceSha256 over the file’s verbatim bytes, comments included, and contentHash over the values alone. Registries and archives has the records and the rotation rules.
The shipped country_allowlist.source.txt holds 17 ISO 3166-1 alpha-3 codes and is a sample.
output
Required.string
required
csv or json. The format of the batch index file.boolean
required
Whether the index file carries a running
index column. npm start -- --raw drops it for one run.boolean
false suppresses the index file in either format. Default true.string
Written by
init as output, and not read by this version: bundles are always written under output/ in the repository root.object
Values taken when a passthrough column is blank:
investorType (default RETAIL), softExpiryDays (365), hardExpiryDays (730). Expiry values are clamped to 0 to 36500.security
Required.boolean
required
true deletes every file under input/ after a real run. A dry run never deletes.string
How the batch as-of date is chosen.
fixed:<n> pins one epoch day for every run; init writes today’s. env:<VAR> reads it from that environment variable per run, which suits a scheduled pipeline. utc_today is the implicit default when the field is absent, and it is refused, because a bundle proved against the wall clock cannot be reproduced later. npm start -- --dev-unpinned-epoch overrides the refusal for development and stamps unpinnedEpoch: true into the manifest.boolean
true derives the per-subject key from the master key so reruns are byte-identical. false draws it from OS entropy and stores it only inside secrets.enc. Default true. npm start -- --no-deterministic overrides it for one run. Security model explains the trade.string
The environment variable holding the 32-byte hex master key. Default
TRUSSET_KYC_MASTER_KEY. Whatever name you choose, the CLI forwards the value to the prover under the canonical name.string
Root of the append-only registries. Default
config/registry.string
A version 1 field. Any value other than
rescue_prime prints one deprecation warning per run and is otherwise ignored.manifest
string
The wire version to emit.
3.0.0 is the default, and 2.1.0 and 2.0.0 are accepted. Pinning 2.1.0 produces the previous bundle shape with no issuer, descriptors or validity, which is the path for migrating downstream consumers first. See Migrating from v2.string
The environment variable holding the 32-byte hex ed25519 signing seed. Default
TRUSSET_KYC_SIGNING_KEY.object
The party legally responsible for every assertion in the bundle. Required for
3.0.0. Recorded in every manifest together with the public key derived from the signing key.Keys and environment
The prover needs two 32-byte hex values in the environment. The master key wraps per-subject keys and derives every nonce under deterministic mode. The signing key signs manifests and registries.init writes both to .trusset/keys.env; load them with set -a && . ./.trusset/keys.env && set +a in every shell. A dry run needs neither. The full list of variables the tool reads is on the CLI reference.
In the repository
- config.example.json
- cli/src/config.ts and cli/src/descriptors.ts, the validator
