sanitizer library

AllStak Flutter SDK sanitizer.

Recursively scrubs sensitive data across the event surface (user, extras, metadata, breadcrumbs.data, contexts, request, response).

Two layers, applied in one pass:

  1. KEY-NAME redaction (always): case-insensitive substring match on Map keys against the canonical denylist; the value becomes [REDACTED].
  2. VALUE-PATTERN redaction (this wave): scans free-text string values for high-risk PII patterns and replaces the matched span with [REDACTED]. Layered value-pattern data scrubbing: A) ALWAYS — credit-card numbers that pass the Luhn checksum, and US SSNs written with hyphens (NNN-NN-NNNN). These are never legitimately wanted in telemetry. B) UNLESS sendDefaultPii — email addresses and IPv4 literals.

Conforms to the canonical AllStak SDK denylist (docs/standards/sdk-platform-standards.md).

Semantics:

  • Case-insensitive substring match on Map keys (layer 1).
  • Value-pattern scrubbing on String values only (layer 2), gated per-key so identifiers that must survive verbatim (stack-frame paths, release/sdk fields, URLs/paths, the SDK's own sessionId, and the explicit user object set via setUser) are never corrupted.
  • Value replacement with the sentinel string [REDACTED] (key preserved).
  • Recursion into Map and Iterable; primitives pass through.
  • Cycle protection via identityHashCode set.
  • Pure: returns a sanitized copy; never mutates caller-owned structures.
  • Mobile-safe: synchronous, no I/O, no blocking calls.
  • Fail-open: an individual value scrubber that throws leaves that value untouched (still key-redacted) rather than dropping the event.

Classes

ScrubOptions
Options controlling which value-pattern scrubbers run.

Constants

kCorrelationAllowlist → const Set<String>
Exact (case-sensitive) AllStak wire field names that are non-secret correlation identifiers and must survive scrubbing. The release-health sessionId is the canonical example: the backend's error consumer keys off it to mark a session errored/crashed, so it MUST reach the wire raw.
kDefaultDenylist → const List<String>
kRedacted → const String
kValueScrubExemptKeys → const Set<String>
Map keys whose String value is an identifier/locator that must reach the wire VERBATIM — value-pattern scrubbing is skipped for these. They are NOT secret (key-name redaction still applies to anything on the denylist), but running PII regexes over them would corrupt legitimate data:
kValueScrubExemptSubtrees → const Set<String>
Top-level (exact, case-sensitive) keys whose ENTIRE subtree is exempt from value-pattern scrubbing. The explicit user object set via setUser (id/email/ip) is intentional identification and ships as-is — sendDefaultPii does NOT strip explicitly-set user data. Key-name redaction still applies inside the subtree (e.g. user.password).

Functions

sanitizerRedactionCount() int
Process-wide sanitizer redaction count. Counter only; no payload data.
scrub(Object? payload, {List<String>? extraDenylist, ScrubOptions options = const ScrubOptions()}) Object?
Returns a sanitized deep copy of payload. extraDenylist may add key terms; it must not narrow the canonical list. options gates the value scrubbers (ScrubOptions.sendDefaultPii). Fail-open at the value level.