wraith.toml and scrub.toml are created automatically by wraith init. drift.toml is optional; add it only when wraith check reports drifts you want to suppress or reclassify.
Runtime simulation (fault injection, latency, rate limiting, tracing) is configured via CLI flags on wraith serve, not through wraith.toml. See Simulation for the full reference.
Response mode: strict or synth (permissive is reserved, not yet implemented)
deterministic_seed
u64
42
Seed for deterministic random generation
debug
bool
false
Enable debug response headers
strip_headers
bool
true
Strip non-allowlisted response headers (vendor cf-*, x-cache, x-served-by, x-powered-by, nel, report-to, etc.). Set to false to replay every recorded header verbatim.
rewrite_self_urls
bool
true
Rewrite absolute URLs whose host matches service.base_url (response bodies and Location:) to point back at the twin so clients don’t leak off following next-page or related-resource URLs.
Resolution policy for created / created_at / updated_at timestamp holes. real (the default) reads SystemTime::now() per request so sequential creates produce strictly-increasing timestamps — matches every real API. deterministic advances a seed-derived monotonic counter from base_epoch for byte-identical golden replay. fixed freezes the clock at base_epoch.
Field
Type
Default
Description
mode
string
"real"
real, deterministic, or fixed
base_epoch
u64
1640995200
Unix seconds. Starting value for deterministic; frozen value for fixed. Ignored when mode = real.
Replay cache for Idempotency-Key-style POST headers. Disabled by default so non-Stripe twins don’t inadvertently get the behavior surprise — opt in per twin.
Field
Type
Default
Description
enabled
bool
false
Master toggle
header
string
"Idempotency-Key"
Header carrying the idempotency key
ttl_seconds
u64
86400
Cache entry TTL. Stale entries are lazily evicted on lookup.
Length policy for variable-length arrays. median (default; back-compatible) collapses bimodal corpora — use p75, p90, or max for catalog / search APIs.
drop_empty_array_responses
bool
false
When true, responses whose every array is empty are excluded from anti-unification per status group (only when at least one non-empty response exists for that group — never prunes to zero).
max_array_representatives
integer or "all"
8
Distinct elements retained per variable-length array. Integer N keeps a deterministic sample of up to N elements in first-seen order. "all" retains every distinct element.
# Recommended config for bimodal / search APIs
[generate.anti_unification]
array_length = "p90"
drop_empty_array_responses = true
max_array_representatives = "all"# or a bound like 200
Recovers request → response correlation when a route’s response depends on a request field (a parent id, a useCase scope, a search filter). Without this, synth collapses every value to one global representative.
Field
Type
Default
Description
mode
string
"off"
off (inert; pre-v0.8.0 behavior), manual, or auto. auto additionally detects keys for unruled routes when one strongly predicts the response.
A twin becomes an overlay when wraith.toml carries a [base] section. Without it, the twin is a “root” twin and overlay code paths are inert. See Overlays for the full reference.
Field
Type
Required
Description
artifact
string
yes
Artifact id of the provider twin
digest
string
yes
Content digest of the provider’s model (sha256:<64 hex>) — pins the overlay to a specific base version
User-defined scrub rules are applied in order after built-in rules.
Field
Type
Required
Description
scope
ScrubScope
yes
header, cookie, jsonpath, regex, query_param
match
string
yes
Pattern to match (name, JSONPath, or regex)
action
ScrubAction
yes
tokenize, mask, redact, or pseudonymize
replacement
string
no
Required when action is mask
apply_to
ApplyTarget[]
no
header_values, body, query
pseudonymize produces a deterministic user_<base62> HMAC envelope. Idempotent — re-running scrub on already-pseudonymized values is a no-op. Useful for username-shaped values in URL path segments or response bodies where you want a stable but obfuscated identifier.
Default PII detection runs on every recorded body and outbound response (wraith doctor audits recordings; wraith serve rescrubs outbound bodies). Covers email, phone, SSN, credit card (with Luhn check), name fields (via key-name + cardinality + value-shape heuristics), and git-author blobs (Bob <[email protected]>).
Field
Type
Default
Description
detect
bool
true
Master toggle. When false, wraith doctor skips the PII audit pass entirely (other doctor checks still run).
allowlist
string[]
[]
JSONPath-style glob patterns that bypass PII detection. * matches one path segment; leading $ is anchor-stripped; matching is suffix-based.
default_action
string
"tokenize"
Action emitted when writing scrubbed PII. tokenize, redact, or reject. Note: parsed and stored for round-trip; not yet enforced at scrub-write time.
fields.always
string[]
[]
JSON paths unconditionally treated as PII regardless of cardinality detection. Used when auto-detection misclassifies a real PII field as enum (e.g. a small fixture where every entity has "Alice").
The detection chain is fields.always (forced) → allowlist (suppressed) → cardinality-detected enum_paths (skipped) → default name-key allowlist → heuristic classification. allowlist is the highest-precedence suppression layer.
Optional. Lives next to scrub.toml at twins/<name>/drift.toml. Controls how wraith check treats drifts that it classifies in the conformance report.
Every divergence emitted by wraith check carries a stable drift_id (a fingerprint derived from route + path + category + expected/actual values) and a drift_type (e.g. additive_optional_field, field_removed, status_code_shift). drift.toml lets you suppress or reclassify drifts by glob-matching any of those fields.
Absent file is a silent no-op. Parse or validation errors are logged as warnings and the check continues.
[[diff.suppress]] (in wraith.toml) removes divergences before they are classified as drifts. Use it for divergences that are inherent to your twin (placeholder timestamps, generated IDs) and shouldn’t be reported at all.
[[suppress]] (in drift.toml) keeps divergences in the report but suppresses them at the drift layer. Use it when a drift has been reviewed and accepted, but you still want the raw divergence visible in the JSON output.