Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.voight.xyz/llms.txt

Use this file to discover all available pages before exploring further.

When you pick Standard privacy mode, every string field in every event is run through scrubPii() before the SDK ships it. This page documents exactly which patterns match and how each is replaced.

How it works

The function runs a list of regular expressions in deliberate order (most-specific first, multi-line patterns first). Once a pattern matches, the matched substring is replaced with a tagged token like [REDACTED-API-KEY]. The result is idempotent — re-running scrubPii() on already-scrubbed text leaves it stable. The pattern set is:
NameReplacement token
PEM private key block[REDACTED-PRIVATE-KEY]
JWT[REDACTED-JWT]
Anthropic key (sk-ant-...)[REDACTED-API-KEY]
OpenAI key (sk-... / sk-proj-...)[REDACTED-API-KEY]
Stripe live keys (sk_live_... / pk_live_...)[REDACTED-API-KEY]
GitHub fine-grained PAT (github_pat_...)[REDACTED-API-KEY]
GitHub classic PAT (ghp_...)[REDACTED-API-KEY]
AWS access key (AKIA...)[REDACTED-API-KEY]
Slack token (xoxb- / xoxp- / xoxa-)[REDACTED-API-KEY]
Voight key (vk_...)[REDACTED-API-KEY]
Email (name@host.tld)[REDACTED-EMAIL]
Phone in E.164 format (+1234567890)[REDACTED-PHONE]
Credit card (13–19 digits + Luhn checksum)[REDACTED-CARD]
The actual regular expressions (with character classes and quantifiers) live in the SDK source — view them at voight-sdk/src/privacy.ts.

Examples

import { scrubPii } from '@voightxyz/sdk'

scrubPii(`curl -H "Authorization: Bearer sk-ant-api03-AbCd...X" https://api.example.com`)
// → curl -H "Authorization: Bearer [REDACTED-API-KEY]" https://api.example.com

scrubPii(`paid with 4242424242424242 — confirmation @ alice@example.com`)
// → paid with [REDACTED-CARD] — confirmation @ [REDACTED-EMAIL]

scrubPii(`auth=eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NSJ9.signature`)
// → auth=[REDACTED-JWT]

scrubPii(`call +14155552671 to confirm`)
// → call [REDACTED-PHONE] to confirm

scrubPii(`-----BEGIN RSA PRIVATE KEY-----\nMIIEowIBAAKCAQ...\n-----END RSA PRIVATE KEY-----`)
// → [REDACTED-PRIVATE-KEY]

What it deliberately doesn’t match

To avoid false positives that would harm dev workflows:
Looks likeBut not redactedReason
email_templatenot an emailno @ in middle
support@appnot an emailno TLD
sk_test_xxx (Stripe test keys)not redactednot actual money
AKIAfoo (lowercase tail)not an AWS keyreal keys are uppercase
16-digit order numbersnot a cardfails Luhn checksum
10-digit numbers without +not a phoneE.164 requires + prefix
The full test suite (tests/unit/privacy.test.ts — 30+ tests) verifies positive matches + adversarial negatives.

Idempotency

scrubPii() is idempotent. Re-running it on already-scrubbed text is safe:
const once = scrubPii(`alice@example.com KEY=AKIAIOSFODNN7EXAMPLE`)
const twice = scrubPii(once)
// once === twice  →  true
This matters because the SDK runs it once per event, but if a downstream layer ever runs it again, nothing breaks.

Performance

Designed to handle a 2KB event payload in under 10ms on a modern laptop. The pattern set is small (~13 regexes), there’s no network or filesystem I/O, and the regexes are anchored with word boundaries to avoid catastrophic backtracking.

Adding new patterns

The pattern set is intentionally conservative — we’d rather miss an edge case than create false positives that confuse developers. Industry libraries like gitleaks, detect-secrets, or trufflehog ship 400+ patterns; we don’t. If you have a credential format that should be covered (especially crypto wallet private keys / mnemonic phrases / API tokens for AI providers we haven’t added yet), open an issue at voightxyz/voight-sdk.

What gets sent under Minimal mode

If Standard’s scrubbing isn’t strict enough for your use case, Minimal mode drops the content fields entirelyreasoning, errorMessage, input, metadata.detail, metadata.response_preview, metadata.responseText, metadata.cwd, metadata.git all disappear. What’s left is tool names, timings, token counts, and identifiers — useful for dashboards, useless to anyone trying to reconstruct your work. See the privacy overview field-by-field table for details.

Next

Data handling

Where data lives once it leaves your machine, retention, deletion flow.