@agent-inspect/redact 6.17.5 → 6.17.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -37,6 +37,10 @@ console.log(result.value, result.findings);
37
37
 
38
38
  - Pure local transformation; no network
39
39
  - Profiles: `local` · `share` · `strict`
40
+ - Redaction is best-effort, not a safety certification — run `verify-safe` before sharing
41
+ - High-confidence credentials (including bounded `token=` / `api_key=` / `internal_token=` forms) are covered by built-in profiles
42
+ - Context-sensitive findings may still require review; CLI custom policies are not yet supported (use programmatic `detectors`)
43
+ - `strict` adds more key rules; it does not guarantee different bytes from `share` on every input
40
44
 
41
45
  ## API
42
46
 
package/dist/index.cjs CHANGED
@@ -58,6 +58,17 @@ function isCredentialSensitiveKey(key, sensitiveKeys) {
58
58
  return false;
59
59
  }
60
60
 
61
+ // packages/redact/src/key-value-secret.ts
62
+ var KEY_VALUE_SECRET_PATTERN_SOURCE = String.raw`\b(?:api[_-]?key|internal[_-]?token|access[_-]?token|auth[_-]?token|password|secret|token)=([^\s"'\\]{8,})`;
63
+ var KEY_VALUE_SECRET_PATTERN = new RegExp(
64
+ KEY_VALUE_SECRET_PATTERN_SOURCE,
65
+ "i"
66
+ );
67
+ function valueContainsKeyValueSecret(value) {
68
+ KEY_VALUE_SECRET_PATTERN.lastIndex = 0;
69
+ return KEY_VALUE_SECRET_PATTERN.test(value);
70
+ }
71
+
61
72
  // packages/redact/src/index.ts
62
73
  var DEFAULT_REDACT_KEYS = [
63
74
  "authorization",
@@ -264,6 +275,15 @@ var credentialDetectors = [
264
275
  pattern: /-----BEGIN [A-Z ]*PRIVATE KEY-----[\s\S]*-----END [A-Z ]*PRIVATE KEY-----/,
265
276
  severity: "error"
266
277
  }),
278
+ {
279
+ id: "value.keyValueSecret",
280
+ severity: "error",
281
+ matchKind: "value",
282
+ detect(input) {
283
+ if (typeof input.value !== "string") return [];
284
+ return valueContainsKeyValueSecret(input.value) ? [{ action: "replace", severity: "error", matchKind: "value" }] : [];
285
+ }
286
+ },
267
287
  {
268
288
  id: "value.creditCard",
269
289
  severity: "error",
@@ -511,11 +531,14 @@ function redact(value, options) {
511
531
  }
512
532
 
513
533
  exports.DEFAULT_REDACT_KEYS = DEFAULT_REDACT_KEYS;
534
+ exports.KEY_VALUE_SECRET_PATTERN = KEY_VALUE_SECRET_PATTERN;
535
+ exports.KEY_VALUE_SECRET_PATTERN_SOURCE = KEY_VALUE_SECRET_PATTERN_SOURCE;
514
536
  exports.Redactor = Redactor;
515
537
  exports.SHARE_PROFILE_EXTRA_KEYS = SHARE_PROFILE_EXTRA_KEYS;
516
538
  exports.STRICT_PROFILE_EXTRA_KEYS = STRICT_PROFILE_EXTRA_KEYS;
517
539
  exports.createRedactionProfile = createRedactionProfile;
518
540
  exports.createRedactor = createRedactor;
519
541
  exports.redact = redact;
542
+ exports.valueContainsKeyValueSecret = valueContainsKeyValueSecret;
520
543
  //# sourceMappingURL=index.cjs.map
521
544
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/sensitive-key.ts","../src/index.ts"],"names":["crypto"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Mirrors `packages/core/src/safety/sensitive-key.ts` for dependency-light\n * @agent-inspect/redact consumers. Keep both copies in sync (6.14.2 parity).\n */\n\n/** True when the original key already uses an explicit separator. */\nfunction keyHasExplicitSeparator(value: string): boolean {\n return /[_\\-.]/.test(value);\n}\n\n/**\n * Canonicalize field names so camelCase / kebab / dot / snake forms share a\n * snake_case shape the compound matcher can recognize (`userPassword` →\n * `user_password`).\n */\nexport function normalizeSensitiveKey(value: string): string {\n return value\n .replace(/([a-z0-9])([A-Z])/g, \"$1_$2\")\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"_\")\n .replace(/^_+|_+$/g, \"\");\n}\n\nexport const NON_CREDENTIAL_TOKEN_CONFIG_KEYS: ReadonlySet<string> = new Set(\n [\n \"tokens\",\n \"max_tokens\",\n \"min_tokens\",\n \"ls_max_tokens\",\n \"token_count\",\n \"token_limit\",\n \"token_budget\",\n \"input_tokens\",\n \"output_tokens\",\n \"total_tokens\",\n \"cached_tokens\",\n \"prompt_tokens\",\n \"completion_tokens\",\n ].map(normalizeSensitiveKey),\n);\n\nfunction isTokenCredentialKey(normalized: string): boolean {\n if (NON_CREDENTIAL_TOKEN_CONFIG_KEYS.has(normalized)) return false;\n if (normalized === \"token\") return true;\n if (normalized.endsWith(\"tokens\")) return false;\n return normalized.endsWith(\"token\");\n}\n\n/**\n * True when the field name looks credential-sensitive under the shared policy.\n *\n * Suffix compounds (`user_password`, `userPassword`) always match. Prefix\n * compounds (`email_note`) match only when the original key already contained\n * an explicit separator, so camelCase topic fields like `emailNote` stay for\n * value detectors instead of key redaction.\n */\nexport function isCredentialSensitiveKey(\n key: string | undefined,\n sensitiveKeys: readonly string[],\n): boolean {\n if (!key) return false;\n const normalized = normalizeSensitiveKey(key);\n if (!normalized) return false;\n if (NON_CREDENTIAL_TOKEN_CONFIG_KEYS.has(normalized)) return false;\n\n const allowPrefixCompound = keyHasExplicitSeparator(key);\n\n for (const sensitive of sensitiveKeys) {\n const s = normalizeSensitiveKey(sensitive);\n if (!s) continue;\n if (s === \"token\") {\n if (isTokenCredentialKey(normalized)) return true;\n continue;\n }\n if (normalized === s) return true;\n if (normalized.endsWith(`_${s}`)) return true;\n if (allowPrefixCompound && normalized.startsWith(`${s}_`)) return true;\n }\n return false;\n}\n","import crypto from \"node:crypto\";\nimport { isCredentialSensitiveKey } from \"./sensitive-key.js\";\n\nexport type RedactionProfile = \"local\" | \"share\" | \"strict\";\n\nexport type RedactionAction = \"replace\" | \"hash\" | \"prefix\" | \"truncate\" | \"keep\";\n\nexport type RedactionSeverity = \"info\" | \"warning\" | \"error\";\n\nexport type RedactionMatchKind = \"key\" | \"value\" | \"custom\";\n\nexport type RedactionRule =\n | string\n | { key: string; strategy: \"full\" }\n | { key: string; strategy: \"prefix\"; keep?: number }\n | { key: string; strategy: \"hash\" };\n\nexport interface RedactionFinding {\n path: string;\n detector: string;\n action: RedactionAction;\n severity: RedactionSeverity;\n matchKind: RedactionMatchKind;\n preview?: string;\n}\n\nexport interface RedactionDetection {\n action?: RedactionAction;\n replacement?: unknown;\n severity?: RedactionSeverity;\n matchKind?: RedactionMatchKind;\n preview?: string;\n}\n\nexport interface RedactionDetectorInput {\n path: string;\n key?: string;\n value: unknown;\n}\n\nexport interface RedactionDetector {\n id: string;\n severity?: RedactionSeverity;\n matchKind?: RedactionMatchKind;\n detect(input: RedactionDetectorInput): RedactionDetection[];\n}\n\nexport interface RedactionResult<T = unknown> {\n value: T;\n findings: RedactionFinding[];\n redacted: boolean;\n profile: RedactionProfile;\n}\n\nexport interface ResolvedRedactionProfile {\n profile: RedactionProfile;\n extraKeys: readonly string[];\n maxMetadataValueLengthCap?: number;\n maxPreviewLengthCap?: number;\n}\n\nexport interface RedactOptions {\n profile?: RedactionProfile;\n detectors?: RedactionDetector[];\n rules?: RedactionRule[];\n replacement?: string;\n maxDepth?: number;\n maxStringLength?: number;\n collectFindings?: boolean;\n}\n\nexport interface RedactorOptions extends RedactOptions {\n extraKeys?: readonly string[];\n}\n\nexport const DEFAULT_REDACT_KEYS = [\n \"authorization\",\n \"cookie\",\n \"token\",\n \"apiKey\",\n \"password\",\n \"secret\",\n \"email\",\n] as const;\n\nexport const SHARE_PROFILE_EXTRA_KEYS = [\n \"userEmail\",\n \"customerEmail\",\n \"phone\",\n \"phoneNumber\",\n \"address\",\n \"ip\",\n \"ipAddress\",\n \"sessionId\",\n \"requestId\",\n \"correlationId\",\n \"decisionId\",\n \"groupId\",\n \"customerId\",\n \"userId\",\n \"accountId\",\n \"tenantId\",\n \"orgId\",\n \"organizationId\",\n \"traceId\",\n \"spanId\",\n \"parentSpanId\",\n \"currentTask\",\n \"task\",\n \"userInput\",\n \"requestText\",\n \"conversationText\",\n] as const;\n\nexport const STRICT_PROFILE_EXTRA_KEYS = [\n \"prompt\",\n \"completion\",\n \"input\",\n \"output\",\n \"inputPreview\",\n \"outputPreview\",\n \"message\",\n \"messages\",\n \"transcript\",\n \"context\",\n \"document\",\n \"documents\",\n \"chunk\",\n \"chunks\",\n \"retrieval\",\n \"query\",\n] as const;\n\ntype CompiledRule =\n | { key: string; strategy: \"full\" }\n | { key: string; strategy: \"prefix\"; keep: number }\n | { key: string; strategy: \"hash\" };\n\ninterface RedactionState {\n findings: RedactionFinding[];\n seen: WeakMap<object, unknown>;\n}\n\ninterface PatternDetectorOptions {\n id: string;\n pattern: RegExp;\n severity?: RedactionSeverity;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n\nfunction toKey(key: string): string {\n return key.toLowerCase();\n}\n\nfunction findCompiledKeyRule(\n key: string,\n rules: readonly CompiledRule[],\n): CompiledRule | undefined {\n const exact = toKey(key);\n const direct = rules.find((candidate) => candidate.key === exact);\n if (direct) return direct;\n return rules.find((candidate) => isCredentialSensitiveKey(key, [candidate.key]));\n}\n\nfunction stableHash(value: string): string {\n const hash = crypto.createHash(\"sha256\").update(value, \"utf8\").digest(\"hex\");\n return hash.slice(0, 8);\n}\n\nfunction stringifyScalar(value: unknown): string | undefined {\n if (typeof value === \"string\") return value;\n if (typeof value === \"number\" || typeof value === \"boolean\" || typeof value === \"bigint\") {\n return String(value);\n }\n return undefined;\n}\n\nfunction patternDetector(options: PatternDetectorOptions): RedactionDetector {\n return {\n id: options.id,\n severity: options.severity ?? \"warning\",\n matchKind: \"value\",\n detect(input) {\n if (typeof input.value !== \"string\") return [];\n options.pattern.lastIndex = 0;\n return options.pattern.test(input.value)\n ? [{ action: \"replace\", severity: options.severity ?? \"warning\", matchKind: \"value\" }]\n : [];\n },\n };\n}\n\nfunction digitsOnly(value: string): string {\n return value.replace(/\\D/g, \"\");\n}\n\nfunction passesLuhn(value: string): boolean {\n const digits = digitsOnly(value);\n if (digits.length < 13 || digits.length > 19) return false;\n\n let sum = 0;\n let double = false;\n for (let i = digits.length - 1; i >= 0; i -= 1) {\n let digit = Number(digits[i]);\n if (double) {\n digit *= 2;\n if (digit > 9) digit -= 9;\n }\n sum += digit;\n double = !double;\n }\n return sum % 10 === 0;\n}\n\nconst UUID_RE =\n /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;\n\n/** 13-digit Unix epoch milliseconds in a plausible modern range. */\nconst EPOCH_MS_RE = /^1[0-9]{12}$/;\n\nconst EMAIL_RE = /\\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,}\\b/gi;\n\nfunction pathSuggestsNonCard(path: string): boolean {\n const normalized = path.toLowerCase().replace(/[^a-z0-9._]/g, \"\");\n return (\n /(^|\\.)(tokenusage|usage)(\\.|$)/.test(normalized) ||\n /(startedat|endedat|durationms|timestamp|createdat|updatedat)(\\.|$)/.test(normalized) ||\n /(^|\\.)(runid|traceid|spanid|eventid|sessionid|userid|parentid|requestid|correlationid)(\\.|$)/.test(\n normalized,\n ) ||\n /(^|\\.)ts(\\.|$)/.test(normalized)\n );\n}\n\nfunction isUuidLike(value: string): boolean {\n return UUID_RE.test(value.trim());\n}\n\nfunction isPlausibleCardCandidate(candidate: string, fullValue: string): boolean {\n const digits = digitsOnly(candidate);\n if (digits.length < 13 || digits.length > 19) return false;\n if (!passesLuhn(candidate)) return false;\n\n const trimmed = fullValue.trim();\n if (isUuidLike(trimmed)) return false;\n\n // Naked epoch-ms timestamps are not PANs.\n if (EPOCH_MS_RE.test(digits) && digitsOnly(trimmed) === digits && /^\\d+$/.test(trimmed)) {\n return false;\n }\n\n // Reject candidates glued inside longer alphanumeric IDs without card separators.\n const start = fullValue.indexOf(candidate);\n if (start >= 0) {\n const before = fullValue[start - 1];\n const after = fullValue[start + candidate.length];\n if (before && /[A-Za-z0-9_]/.test(before)) return false;\n if (after && /[A-Za-z0-9_]/.test(after)) return false;\n }\n\n return true;\n}\n\nfunction looksLikePathOrPackageOrUrl(value: string): boolean {\n const trimmed = value.trim();\n if (/^(?:[a-z][a-z0-9+.-]*:)?\\/\\//i.test(trimmed)) return true;\n if (/^webpack:/i.test(trimmed)) return true;\n if (/^@[A-Za-z0-9_.-]+\\/[A-Za-z0-9_.@/-]+$/.test(trimmed)) return true;\n if (/^[A-Za-z]:[\\\\/]/.test(trimmed) || /^[/\\\\]/.test(trimmed)) return true;\n // Path-like single token (slashes, no whitespace).\n if (/[\\\\/]/.test(trimmed) && !/\\s/.test(trimmed)) return true;\n return false;\n}\n\nfunction emailMatchIsPathAdjacent(value: string, index: number, length: number): boolean {\n const before = value[index - 1];\n const after = value[index + length];\n return before === \"/\" || before === \"\\\\\" || after === \"/\" || after === \"\\\\\";\n}\n\nfunction valueContainsEmail(value: string): boolean {\n if (looksLikePathOrPackageOrUrl(value)) return false;\n EMAIL_RE.lastIndex = 0;\n for (const match of value.matchAll(EMAIL_RE)) {\n const text = match[0] ?? \"\";\n const index = match.index ?? 0;\n if (emailMatchIsPathAdjacent(value, index, text.length)) continue;\n return true;\n }\n return false;\n}\n\nconst credentialDetectors: readonly RedactionDetector[] = [\n patternDetector({\n id: \"value.authorizationHeader\",\n pattern: /^(?:basic|bearer|digest|apikey)\\s+[a-z0-9._~+/=-]+$/i,\n severity: \"error\",\n }),\n patternDetector({\n id: \"value.bearerToken\",\n pattern: /\\bbearer\\s+[a-z0-9._~+/=-]{12,}\\b/i,\n severity: \"error\",\n }),\n patternDetector({\n id: \"value.cookie\",\n pattern: /\\b[a-z0-9_.-]+=[^;\\s]+(?:;\\s*[a-z0-9_.-]+=[^;\\s]+)+/i,\n severity: \"error\",\n }),\n patternDetector({\n id: \"value.jwt\",\n pattern: /\\beyJ[a-zA-Z0-9_-]{8,}\\.[a-zA-Z0-9_-]{8,}\\.[a-zA-Z0-9_-]{8,}\\b/,\n severity: \"error\",\n }),\n patternDetector({\n id: \"value.providerApiKey\",\n pattern: /\\b(?:sk-(?:proj-)?[a-zA-Z0-9_-]{16,}|sk-ant-[a-zA-Z0-9_-]{16,}|AIza[0-9A-Za-z_-]{20,})\\b/,\n severity: \"error\",\n }),\n patternDetector({\n id: \"value.githubToken\",\n pattern: /\\b(?:ghp|gho|ghu|ghs|ghr)_[A-Za-z0-9_]{20,}\\b/,\n severity: \"error\",\n }),\n patternDetector({\n id: \"value.awsAccessKey\",\n pattern: /\\b(?:AKIA|ASIA)[A-Z0-9]{16}\\b/,\n severity: \"error\",\n }),\n patternDetector({\n id: \"value.privateKey\",\n pattern: /-----BEGIN [A-Z ]*PRIVATE KEY-----[\\s\\S]*-----END [A-Z ]*PRIVATE KEY-----/,\n severity: \"error\",\n }),\n {\n id: \"value.creditCard\",\n severity: \"error\",\n matchKind: \"value\",\n detect(input) {\n if (typeof input.value !== \"string\") return [];\n if (pathSuggestsNonCard(input.path)) return [];\n if (isUuidLike(input.value)) return [];\n const candidatePattern = /(?:\\d[ -]?){13,19}/g;\n for (const match of input.value.matchAll(candidatePattern)) {\n const candidate = match[0] ?? \"\";\n if (isPlausibleCardCandidate(candidate, input.value)) {\n return [{ action: \"replace\", severity: \"error\", matchKind: \"value\" }];\n }\n }\n return [];\n },\n },\n];\n\nconst identifierDetectors: readonly RedactionDetector[] = [\n {\n id: \"value.email\",\n severity: \"warning\",\n matchKind: \"value\",\n detect(input) {\n if (typeof input.value !== \"string\") return [];\n return valueContainsEmail(input.value)\n ? [{ action: \"replace\", severity: \"warning\", matchKind: \"value\" }]\n : [];\n },\n },\n patternDetector({\n id: \"value.phone\",\n pattern: /\\b(?:\\+\\d{1,3}[\\s.-]?)?(?:\\(?\\d{3}\\)?[\\s.-])\\d{3}[\\s.-]\\d{4}\\b/,\n }),\n patternDetector({\n id: \"value.ipv4\",\n pattern: /\\b(?:(?:25[0-5]|2[0-4]\\d|1?\\d?\\d)\\.){3}(?:25[0-5]|2[0-4]\\d|1?\\d?\\d)\\b/,\n }),\n patternDetector({\n id: \"value.ipv6\",\n pattern: /\\b(?:[0-9a-f]{1,4}:){2,7}[0-9a-f]{1,4}\\b/i,\n }),\n];\n\nfunction builtInDetectorsForProfile(profile: RedactionProfile): readonly RedactionDetector[] {\n if (profile === \"local\") return credentialDetectors;\n return [...credentialDetectors, ...identifierDetectors];\n}\n\nfunction compileRules(\n rules?: RedactionRule[],\n extraKeys?: readonly string[],\n): CompiledRule[] {\n const out = new Map<string, CompiledRule>();\n\n const set = (rule: CompiledRule) => {\n const key = toKey(rule.key);\n out.set(key, { ...rule, key } as CompiledRule);\n };\n\n for (const key of DEFAULT_REDACT_KEYS) {\n set({ key, strategy: \"full\" });\n }\n\n for (const key of extraKeys ?? []) {\n if (typeof key === \"string\" && key.length > 0) {\n set({ key, strategy: \"full\" });\n }\n }\n\n for (const rule of rules ?? []) {\n if (typeof rule === \"string\") {\n set({ key: rule, strategy: \"full\" });\n continue;\n }\n\n if (rule.strategy === \"full\") set({ key: rule.key, strategy: \"full\" });\n if (rule.strategy === \"hash\") set({ key: rule.key, strategy: \"hash\" });\n if (rule.strategy === \"prefix\") {\n set({\n key: rule.key,\n strategy: \"prefix\",\n keep: typeof rule.keep === \"number\" ? rule.keep : 8,\n });\n }\n }\n\n return [...out.values()];\n}\n\nfunction actionForRule(rule: CompiledRule): RedactionAction {\n if (rule.strategy === \"full\") return \"replace\";\n return rule.strategy;\n}\n\nfunction applyRule(\n rule: CompiledRule,\n value: unknown,\n replacement: string,\n): unknown {\n if (rule.strategy === \"full\") return replacement;\n\n const asString = stringifyScalar(value);\n if (rule.strategy === \"prefix\") {\n if (asString === undefined) return replacement;\n const keep = Math.max(0, Math.floor(rule.keep));\n return asString.length <= keep ? `${asString}…` : `${asString.slice(0, keep)}…`;\n }\n\n if (rule.strategy === \"hash\") {\n if (asString === undefined) return \"[HASH:unknown]\";\n return `[HASH:${stableHash(asString)}]`;\n }\n\n return value;\n}\n\nfunction childPath(path: string, key: string): string {\n if (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(key)) {\n return path ? `${path}.${key}` : key;\n }\n return `${path || \"$\"}[${JSON.stringify(key)}]`;\n}\n\nfunction indexPath(path: string, index: number): string {\n return `${path || \"$\"}[${index}]`;\n}\n\nfunction makeFinding(\n path: string,\n detector: string,\n action: RedactionAction,\n matchKind: RedactionMatchKind,\n severity: RedactionSeverity = \"warning\",\n preview?: string,\n): RedactionFinding {\n return preview === undefined\n ? { path, detector, action, severity, matchKind }\n : { path, detector, action, severity, matchKind, preview };\n}\n\nexport function createRedactionProfile(profile: RedactionProfile = \"local\"): ResolvedRedactionProfile {\n switch (profile) {\n case \"local\":\n return { profile: \"local\", extraKeys: [] };\n case \"share\":\n return {\n profile: \"share\",\n extraKeys: SHARE_PROFILE_EXTRA_KEYS,\n maxMetadataValueLengthCap: 500,\n maxPreviewLengthCap: 200,\n };\n case \"strict\":\n return {\n profile: \"strict\",\n extraKeys: [...SHARE_PROFILE_EXTRA_KEYS, ...STRICT_PROFILE_EXTRA_KEYS],\n maxMetadataValueLengthCap: 200,\n maxPreviewLengthCap: 80,\n };\n }\n}\n\nexport class Redactor {\n readonly #rules: CompiledRule[];\n readonly #detectors: readonly RedactionDetector[];\n readonly #profile: RedactionProfile;\n readonly #replacement: string;\n readonly #maxDepth: number;\n readonly #collectFindings: boolean;\n\n constructor(options?: RedactorOptions) {\n const resolved = createRedactionProfile(options?.profile ?? \"local\");\n this.#profile = resolved.profile;\n this.#rules = compileRules(options?.rules, [\n ...resolved.extraKeys,\n ...(options?.extraKeys ?? []),\n ]);\n this.#detectors = [\n ...builtInDetectorsForProfile(this.#profile),\n ...(options?.detectors ?? []),\n ];\n this.#replacement = options?.replacement ?? \"[REDACTED]\";\n this.#maxDepth = options?.maxDepth ?? 32;\n this.#collectFindings = options?.collectFindings ?? true;\n }\n\n redactValue(key: string, value: unknown): unknown {\n return this.#redactValue(value, key, key, 0, {\n findings: [],\n seen: new WeakMap<object, unknown>(),\n });\n }\n\n redactRecord(record: Record<string, unknown>): Record<string, unknown> {\n return this.redact(record).value as Record<string, unknown>;\n }\n\n redact<T = unknown>(value: T): RedactionResult<T> {\n const state: RedactionState = {\n findings: [],\n seen: new WeakMap<object, unknown>(),\n };\n const redacted = this.#redactValue(value, undefined, \"$\", 0, state);\n return {\n value: redacted as T,\n findings: state.findings,\n redacted: state.findings.some((finding) => finding.action !== \"keep\"),\n profile: this.#profile,\n };\n }\n\n #recordFinding(state: RedactionState, finding: RedactionFinding): void {\n if (this.#collectFindings) state.findings.push(finding);\n }\n\n #redactValue(\n value: unknown,\n key: string | undefined,\n path: string,\n depth: number,\n state: RedactionState,\n ): unknown {\n if (depth > this.#maxDepth) {\n this.#recordFinding(\n state,\n makeFinding(path, \"structure.maxDepth\", \"truncate\", \"value\", \"warning\"),\n );\n return \"[Truncated]\";\n }\n\n if (key !== undefined) {\n const rule = findCompiledKeyRule(key, this.#rules);\n if (rule) {\n this.#recordFinding(\n state,\n makeFinding(path, `key.${rule.key}`, actionForRule(rule), \"key\", \"warning\"),\n );\n return applyRule(rule, value, this.#replacement);\n }\n }\n\n for (const detector of this.#detectors) {\n const detections = detector.detect({ path, key, value });\n for (const detection of detections) {\n const action = detection.action ?? \"replace\";\n this.#recordFinding(\n state,\n makeFinding(\n path,\n detector.id,\n action,\n detection.matchKind ?? detector.matchKind ?? \"custom\",\n detection.severity ?? detector.severity ?? \"warning\",\n detection.preview,\n ),\n );\n if (action !== \"keep\") {\n return detection.replacement ?? this.#replacement;\n }\n }\n }\n\n if (Array.isArray(value)) {\n if (state.seen.has(value)) return state.seen.get(value);\n const out: unknown[] = [];\n state.seen.set(value, out);\n value.forEach((item, index) => {\n out[index] = this.#redactValue(item, undefined, indexPath(path, index), depth + 1, state);\n });\n return out;\n }\n\n if (isRecord(value)) {\n if (state.seen.has(value)) return state.seen.get(value);\n const out: Record<string, unknown> = {};\n state.seen.set(value, out);\n for (const [entryKey, entryValue] of Object.entries(value)) {\n out[entryKey] = this.#redactValue(\n entryValue,\n entryKey,\n childPath(path === \"$\" ? \"\" : path, entryKey),\n depth + 1,\n state,\n );\n }\n return out;\n }\n\n return value;\n }\n}\n\nexport function createRedactor(options?: RedactorOptions): Redactor {\n return new Redactor(options);\n}\n\nexport function redact<T = unknown>(value: T, options?: RedactOptions): RedactionResult<T> {\n return createRedactor(options).redact(value);\n}\n"]}
1
+ {"version":3,"sources":["../src/sensitive-key.ts","../src/key-value-secret.ts","../src/index.ts"],"names":["crypto"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Mirrors `packages/core/src/safety/sensitive-key.ts` for dependency-light\n * @agent-inspect/redact consumers. Keep both copies in sync (6.14.2 parity).\n */\n\n/** True when the original key already uses an explicit separator. */\nfunction keyHasExplicitSeparator(value: string): boolean {\n return /[_\\-.]/.test(value);\n}\n\n/**\n * Canonicalize field names so camelCase / kebab / dot / snake forms share a\n * snake_case shape the compound matcher can recognize (`userPassword` →\n * `user_password`).\n */\nexport function normalizeSensitiveKey(value: string): string {\n return value\n .replace(/([a-z0-9])([A-Z])/g, \"$1_$2\")\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"_\")\n .replace(/^_+|_+$/g, \"\");\n}\n\nexport const NON_CREDENTIAL_TOKEN_CONFIG_KEYS: ReadonlySet<string> = new Set(\n [\n \"tokens\",\n \"max_tokens\",\n \"min_tokens\",\n \"ls_max_tokens\",\n \"token_count\",\n \"token_limit\",\n \"token_budget\",\n \"input_tokens\",\n \"output_tokens\",\n \"total_tokens\",\n \"cached_tokens\",\n \"prompt_tokens\",\n \"completion_tokens\",\n ].map(normalizeSensitiveKey),\n);\n\nfunction isTokenCredentialKey(normalized: string): boolean {\n if (NON_CREDENTIAL_TOKEN_CONFIG_KEYS.has(normalized)) return false;\n if (normalized === \"token\") return true;\n if (normalized.endsWith(\"tokens\")) return false;\n return normalized.endsWith(\"token\");\n}\n\n/**\n * True when the field name looks credential-sensitive under the shared policy.\n *\n * Suffix compounds (`user_password`, `userPassword`) always match. Prefix\n * compounds (`email_note`) match only when the original key already contained\n * an explicit separator, so camelCase topic fields like `emailNote` stay for\n * value detectors instead of key redaction.\n */\nexport function isCredentialSensitiveKey(\n key: string | undefined,\n sensitiveKeys: readonly string[],\n): boolean {\n if (!key) return false;\n const normalized = normalizeSensitiveKey(key);\n if (!normalized) return false;\n if (NON_CREDENTIAL_TOKEN_CONFIG_KEYS.has(normalized)) return false;\n\n const allowPrefixCompound = keyHasExplicitSeparator(key);\n\n for (const sensitive of sensitiveKeys) {\n const s = normalizeSensitiveKey(sensitive);\n if (!s) continue;\n if (s === \"token\") {\n if (isTokenCredentialKey(normalized)) return true;\n continue;\n }\n if (normalized === s) return true;\n if (normalized.endsWith(`_${s}`)) return true;\n if (allowPrefixCompound && normalized.startsWith(`${s}_`)) return true;\n }\n return false;\n}\n","/**\n * High-confidence key/value credential forms shared with core\n * `safety.secretPattern` / `key-value-secret` (keep sources in sync).\n *\n * Matches house-format credentials such as:\n * internal_token=<credential>\n * token=<credential>\n * api_key=<credential>\n *\n * Intentionally does **not** match metric/config lookalikes such as\n * maxTokens=, tokenCount=, secret=false, or short placeholders.\n */\nexport const KEY_VALUE_SECRET_PATTERN_SOURCE =\n String.raw`\\b(?:api[_-]?key|internal[_-]?token|access[_-]?token|auth[_-]?token|password|secret|token)=([^\\s\"'\\\\]{8,})`;\n\nexport const KEY_VALUE_SECRET_PATTERN = new RegExp(\n KEY_VALUE_SECRET_PATTERN_SOURCE,\n \"i\",\n);\n\nexport function valueContainsKeyValueSecret(value: string): boolean {\n KEY_VALUE_SECRET_PATTERN.lastIndex = 0;\n return KEY_VALUE_SECRET_PATTERN.test(value);\n}\n","import crypto from \"node:crypto\";\nimport { isCredentialSensitiveKey } from \"./sensitive-key.js\";\nimport { valueContainsKeyValueSecret } from \"./key-value-secret.js\";\n\nexport type RedactionProfile = \"local\" | \"share\" | \"strict\";\n\nexport type RedactionAction = \"replace\" | \"hash\" | \"prefix\" | \"truncate\" | \"keep\";\n\nexport type RedactionSeverity = \"info\" | \"warning\" | \"error\";\n\nexport type RedactionMatchKind = \"key\" | \"value\" | \"custom\";\n\nexport type RedactionRule =\n | string\n | { key: string; strategy: \"full\" }\n | { key: string; strategy: \"prefix\"; keep?: number }\n | { key: string; strategy: \"hash\" };\n\nexport interface RedactionFinding {\n path: string;\n detector: string;\n action: RedactionAction;\n severity: RedactionSeverity;\n matchKind: RedactionMatchKind;\n preview?: string;\n}\n\nexport interface RedactionDetection {\n action?: RedactionAction;\n replacement?: unknown;\n severity?: RedactionSeverity;\n matchKind?: RedactionMatchKind;\n preview?: string;\n}\n\nexport interface RedactionDetectorInput {\n path: string;\n key?: string;\n value: unknown;\n}\n\nexport interface RedactionDetector {\n id: string;\n severity?: RedactionSeverity;\n matchKind?: RedactionMatchKind;\n detect(input: RedactionDetectorInput): RedactionDetection[];\n}\n\nexport interface RedactionResult<T = unknown> {\n value: T;\n findings: RedactionFinding[];\n redacted: boolean;\n profile: RedactionProfile;\n}\n\nexport interface ResolvedRedactionProfile {\n profile: RedactionProfile;\n extraKeys: readonly string[];\n maxMetadataValueLengthCap?: number;\n maxPreviewLengthCap?: number;\n}\n\nexport interface RedactOptions {\n profile?: RedactionProfile;\n detectors?: RedactionDetector[];\n rules?: RedactionRule[];\n replacement?: string;\n maxDepth?: number;\n maxStringLength?: number;\n collectFindings?: boolean;\n}\n\nexport interface RedactorOptions extends RedactOptions {\n extraKeys?: readonly string[];\n}\n\nexport const DEFAULT_REDACT_KEYS = [\n \"authorization\",\n \"cookie\",\n \"token\",\n \"apiKey\",\n \"password\",\n \"secret\",\n \"email\",\n] as const;\n\nexport const SHARE_PROFILE_EXTRA_KEYS = [\n \"userEmail\",\n \"customerEmail\",\n \"phone\",\n \"phoneNumber\",\n \"address\",\n \"ip\",\n \"ipAddress\",\n \"sessionId\",\n \"requestId\",\n \"correlationId\",\n \"decisionId\",\n \"groupId\",\n \"customerId\",\n \"userId\",\n \"accountId\",\n \"tenantId\",\n \"orgId\",\n \"organizationId\",\n \"traceId\",\n \"spanId\",\n \"parentSpanId\",\n \"currentTask\",\n \"task\",\n \"userInput\",\n \"requestText\",\n \"conversationText\",\n] as const;\n\nexport const STRICT_PROFILE_EXTRA_KEYS = [\n \"prompt\",\n \"completion\",\n \"input\",\n \"output\",\n \"inputPreview\",\n \"outputPreview\",\n \"message\",\n \"messages\",\n \"transcript\",\n \"context\",\n \"document\",\n \"documents\",\n \"chunk\",\n \"chunks\",\n \"retrieval\",\n \"query\",\n] as const;\n\ntype CompiledRule =\n | { key: string; strategy: \"full\" }\n | { key: string; strategy: \"prefix\"; keep: number }\n | { key: string; strategy: \"hash\" };\n\ninterface RedactionState {\n findings: RedactionFinding[];\n seen: WeakMap<object, unknown>;\n}\n\ninterface PatternDetectorOptions {\n id: string;\n pattern: RegExp;\n severity?: RedactionSeverity;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n\nfunction toKey(key: string): string {\n return key.toLowerCase();\n}\n\nfunction findCompiledKeyRule(\n key: string,\n rules: readonly CompiledRule[],\n): CompiledRule | undefined {\n const exact = toKey(key);\n const direct = rules.find((candidate) => candidate.key === exact);\n if (direct) return direct;\n return rules.find((candidate) => isCredentialSensitiveKey(key, [candidate.key]));\n}\n\nfunction stableHash(value: string): string {\n const hash = crypto.createHash(\"sha256\").update(value, \"utf8\").digest(\"hex\");\n return hash.slice(0, 8);\n}\n\nfunction stringifyScalar(value: unknown): string | undefined {\n if (typeof value === \"string\") return value;\n if (typeof value === \"number\" || typeof value === \"boolean\" || typeof value === \"bigint\") {\n return String(value);\n }\n return undefined;\n}\n\nfunction patternDetector(options: PatternDetectorOptions): RedactionDetector {\n return {\n id: options.id,\n severity: options.severity ?? \"warning\",\n matchKind: \"value\",\n detect(input) {\n if (typeof input.value !== \"string\") return [];\n options.pattern.lastIndex = 0;\n return options.pattern.test(input.value)\n ? [{ action: \"replace\", severity: options.severity ?? \"warning\", matchKind: \"value\" }]\n : [];\n },\n };\n}\n\nfunction digitsOnly(value: string): string {\n return value.replace(/\\D/g, \"\");\n}\n\nfunction passesLuhn(value: string): boolean {\n const digits = digitsOnly(value);\n if (digits.length < 13 || digits.length > 19) return false;\n\n let sum = 0;\n let double = false;\n for (let i = digits.length - 1; i >= 0; i -= 1) {\n let digit = Number(digits[i]);\n if (double) {\n digit *= 2;\n if (digit > 9) digit -= 9;\n }\n sum += digit;\n double = !double;\n }\n return sum % 10 === 0;\n}\n\nconst UUID_RE =\n /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;\n\n/** 13-digit Unix epoch milliseconds in a plausible modern range. */\nconst EPOCH_MS_RE = /^1[0-9]{12}$/;\n\nconst EMAIL_RE = /\\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,}\\b/gi;\n\nfunction pathSuggestsNonCard(path: string): boolean {\n const normalized = path.toLowerCase().replace(/[^a-z0-9._]/g, \"\");\n return (\n /(^|\\.)(tokenusage|usage)(\\.|$)/.test(normalized) ||\n /(startedat|endedat|durationms|timestamp|createdat|updatedat)(\\.|$)/.test(normalized) ||\n /(^|\\.)(runid|traceid|spanid|eventid|sessionid|userid|parentid|requestid|correlationid)(\\.|$)/.test(\n normalized,\n ) ||\n /(^|\\.)ts(\\.|$)/.test(normalized)\n );\n}\n\nfunction isUuidLike(value: string): boolean {\n return UUID_RE.test(value.trim());\n}\n\nfunction isPlausibleCardCandidate(candidate: string, fullValue: string): boolean {\n const digits = digitsOnly(candidate);\n if (digits.length < 13 || digits.length > 19) return false;\n if (!passesLuhn(candidate)) return false;\n\n const trimmed = fullValue.trim();\n if (isUuidLike(trimmed)) return false;\n\n // Naked epoch-ms timestamps are not PANs.\n if (EPOCH_MS_RE.test(digits) && digitsOnly(trimmed) === digits && /^\\d+$/.test(trimmed)) {\n return false;\n }\n\n // Reject candidates glued inside longer alphanumeric IDs without card separators.\n const start = fullValue.indexOf(candidate);\n if (start >= 0) {\n const before = fullValue[start - 1];\n const after = fullValue[start + candidate.length];\n if (before && /[A-Za-z0-9_]/.test(before)) return false;\n if (after && /[A-Za-z0-9_]/.test(after)) return false;\n }\n\n return true;\n}\n\nfunction looksLikePathOrPackageOrUrl(value: string): boolean {\n const trimmed = value.trim();\n if (/^(?:[a-z][a-z0-9+.-]*:)?\\/\\//i.test(trimmed)) return true;\n if (/^webpack:/i.test(trimmed)) return true;\n if (/^@[A-Za-z0-9_.-]+\\/[A-Za-z0-9_.@/-]+$/.test(trimmed)) return true;\n if (/^[A-Za-z]:[\\\\/]/.test(trimmed) || /^[/\\\\]/.test(trimmed)) return true;\n // Path-like single token (slashes, no whitespace).\n if (/[\\\\/]/.test(trimmed) && !/\\s/.test(trimmed)) return true;\n return false;\n}\n\nfunction emailMatchIsPathAdjacent(value: string, index: number, length: number): boolean {\n const before = value[index - 1];\n const after = value[index + length];\n return before === \"/\" || before === \"\\\\\" || after === \"/\" || after === \"\\\\\";\n}\n\nfunction valueContainsEmail(value: string): boolean {\n if (looksLikePathOrPackageOrUrl(value)) return false;\n EMAIL_RE.lastIndex = 0;\n for (const match of value.matchAll(EMAIL_RE)) {\n const text = match[0] ?? \"\";\n const index = match.index ?? 0;\n if (emailMatchIsPathAdjacent(value, index, text.length)) continue;\n return true;\n }\n return false;\n}\n\nconst credentialDetectors: readonly RedactionDetector[] = [\n patternDetector({\n id: \"value.authorizationHeader\",\n pattern: /^(?:basic|bearer|digest|apikey)\\s+[a-z0-9._~+/=-]+$/i,\n severity: \"error\",\n }),\n patternDetector({\n id: \"value.bearerToken\",\n pattern: /\\bbearer\\s+[a-z0-9._~+/=-]{12,}\\b/i,\n severity: \"error\",\n }),\n patternDetector({\n id: \"value.cookie\",\n pattern: /\\b[a-z0-9_.-]+=[^;\\s]+(?:;\\s*[a-z0-9_.-]+=[^;\\s]+)+/i,\n severity: \"error\",\n }),\n patternDetector({\n id: \"value.jwt\",\n pattern: /\\beyJ[a-zA-Z0-9_-]{8,}\\.[a-zA-Z0-9_-]{8,}\\.[a-zA-Z0-9_-]{8,}\\b/,\n severity: \"error\",\n }),\n patternDetector({\n id: \"value.providerApiKey\",\n pattern: /\\b(?:sk-(?:proj-)?[a-zA-Z0-9_-]{16,}|sk-ant-[a-zA-Z0-9_-]{16,}|AIza[0-9A-Za-z_-]{20,})\\b/,\n severity: \"error\",\n }),\n patternDetector({\n id: \"value.githubToken\",\n pattern: /\\b(?:ghp|gho|ghu|ghs|ghr)_[A-Za-z0-9_]{20,}\\b/,\n severity: \"error\",\n }),\n patternDetector({\n id: \"value.awsAccessKey\",\n pattern: /\\b(?:AKIA|ASIA)[A-Z0-9]{16}\\b/,\n severity: \"error\",\n }),\n patternDetector({\n id: \"value.privateKey\",\n pattern: /-----BEGIN [A-Z ]*PRIVATE KEY-----[\\s\\S]*-----END [A-Z ]*PRIVATE KEY-----/,\n severity: \"error\",\n }),\n {\n id: \"value.keyValueSecret\",\n severity: \"error\",\n matchKind: \"value\",\n detect(input) {\n if (typeof input.value !== \"string\") return [];\n return valueContainsKeyValueSecret(input.value)\n ? [{ action: \"replace\", severity: \"error\", matchKind: \"value\" }]\n : [];\n },\n },\n {\n id: \"value.creditCard\",\n severity: \"error\",\n matchKind: \"value\",\n detect(input) {\n if (typeof input.value !== \"string\") return [];\n if (pathSuggestsNonCard(input.path)) return [];\n if (isUuidLike(input.value)) return [];\n const candidatePattern = /(?:\\d[ -]?){13,19}/g;\n for (const match of input.value.matchAll(candidatePattern)) {\n const candidate = match[0] ?? \"\";\n if (isPlausibleCardCandidate(candidate, input.value)) {\n return [{ action: \"replace\", severity: \"error\", matchKind: \"value\" }];\n }\n }\n return [];\n },\n },\n];\n\nconst identifierDetectors: readonly RedactionDetector[] = [\n {\n id: \"value.email\",\n severity: \"warning\",\n matchKind: \"value\",\n detect(input) {\n if (typeof input.value !== \"string\") return [];\n return valueContainsEmail(input.value)\n ? [{ action: \"replace\", severity: \"warning\", matchKind: \"value\" }]\n : [];\n },\n },\n patternDetector({\n id: \"value.phone\",\n pattern: /\\b(?:\\+\\d{1,3}[\\s.-]?)?(?:\\(?\\d{3}\\)?[\\s.-])\\d{3}[\\s.-]\\d{4}\\b/,\n }),\n patternDetector({\n id: \"value.ipv4\",\n pattern: /\\b(?:(?:25[0-5]|2[0-4]\\d|1?\\d?\\d)\\.){3}(?:25[0-5]|2[0-4]\\d|1?\\d?\\d)\\b/,\n }),\n patternDetector({\n id: \"value.ipv6\",\n pattern: /\\b(?:[0-9a-f]{1,4}:){2,7}[0-9a-f]{1,4}\\b/i,\n }),\n];\n\nfunction builtInDetectorsForProfile(profile: RedactionProfile): readonly RedactionDetector[] {\n if (profile === \"local\") return credentialDetectors;\n return [...credentialDetectors, ...identifierDetectors];\n}\n\nfunction compileRules(\n rules?: RedactionRule[],\n extraKeys?: readonly string[],\n): CompiledRule[] {\n const out = new Map<string, CompiledRule>();\n\n const set = (rule: CompiledRule) => {\n const key = toKey(rule.key);\n out.set(key, { ...rule, key } as CompiledRule);\n };\n\n for (const key of DEFAULT_REDACT_KEYS) {\n set({ key, strategy: \"full\" });\n }\n\n for (const key of extraKeys ?? []) {\n if (typeof key === \"string\" && key.length > 0) {\n set({ key, strategy: \"full\" });\n }\n }\n\n for (const rule of rules ?? []) {\n if (typeof rule === \"string\") {\n set({ key: rule, strategy: \"full\" });\n continue;\n }\n\n if (rule.strategy === \"full\") set({ key: rule.key, strategy: \"full\" });\n if (rule.strategy === \"hash\") set({ key: rule.key, strategy: \"hash\" });\n if (rule.strategy === \"prefix\") {\n set({\n key: rule.key,\n strategy: \"prefix\",\n keep: typeof rule.keep === \"number\" ? rule.keep : 8,\n });\n }\n }\n\n return [...out.values()];\n}\n\nfunction actionForRule(rule: CompiledRule): RedactionAction {\n if (rule.strategy === \"full\") return \"replace\";\n return rule.strategy;\n}\n\nfunction applyRule(\n rule: CompiledRule,\n value: unknown,\n replacement: string,\n): unknown {\n if (rule.strategy === \"full\") return replacement;\n\n const asString = stringifyScalar(value);\n if (rule.strategy === \"prefix\") {\n if (asString === undefined) return replacement;\n const keep = Math.max(0, Math.floor(rule.keep));\n return asString.length <= keep ? `${asString}…` : `${asString.slice(0, keep)}…`;\n }\n\n if (rule.strategy === \"hash\") {\n if (asString === undefined) return \"[HASH:unknown]\";\n return `[HASH:${stableHash(asString)}]`;\n }\n\n return value;\n}\n\nfunction childPath(path: string, key: string): string {\n if (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(key)) {\n return path ? `${path}.${key}` : key;\n }\n return `${path || \"$\"}[${JSON.stringify(key)}]`;\n}\n\nfunction indexPath(path: string, index: number): string {\n return `${path || \"$\"}[${index}]`;\n}\n\nfunction makeFinding(\n path: string,\n detector: string,\n action: RedactionAction,\n matchKind: RedactionMatchKind,\n severity: RedactionSeverity = \"warning\",\n preview?: string,\n): RedactionFinding {\n return preview === undefined\n ? { path, detector, action, severity, matchKind }\n : { path, detector, action, severity, matchKind, preview };\n}\n\nexport function createRedactionProfile(profile: RedactionProfile = \"local\"): ResolvedRedactionProfile {\n switch (profile) {\n case \"local\":\n return { profile: \"local\", extraKeys: [] };\n case \"share\":\n return {\n profile: \"share\",\n extraKeys: SHARE_PROFILE_EXTRA_KEYS,\n maxMetadataValueLengthCap: 500,\n maxPreviewLengthCap: 200,\n };\n case \"strict\":\n return {\n profile: \"strict\",\n extraKeys: [...SHARE_PROFILE_EXTRA_KEYS, ...STRICT_PROFILE_EXTRA_KEYS],\n maxMetadataValueLengthCap: 200,\n maxPreviewLengthCap: 80,\n };\n }\n}\n\nexport class Redactor {\n readonly #rules: CompiledRule[];\n readonly #detectors: readonly RedactionDetector[];\n readonly #profile: RedactionProfile;\n readonly #replacement: string;\n readonly #maxDepth: number;\n readonly #collectFindings: boolean;\n\n constructor(options?: RedactorOptions) {\n const resolved = createRedactionProfile(options?.profile ?? \"local\");\n this.#profile = resolved.profile;\n this.#rules = compileRules(options?.rules, [\n ...resolved.extraKeys,\n ...(options?.extraKeys ?? []),\n ]);\n this.#detectors = [\n ...builtInDetectorsForProfile(this.#profile),\n ...(options?.detectors ?? []),\n ];\n this.#replacement = options?.replacement ?? \"[REDACTED]\";\n this.#maxDepth = options?.maxDepth ?? 32;\n this.#collectFindings = options?.collectFindings ?? true;\n }\n\n redactValue(key: string, value: unknown): unknown {\n return this.#redactValue(value, key, key, 0, {\n findings: [],\n seen: new WeakMap<object, unknown>(),\n });\n }\n\n redactRecord(record: Record<string, unknown>): Record<string, unknown> {\n return this.redact(record).value as Record<string, unknown>;\n }\n\n redact<T = unknown>(value: T): RedactionResult<T> {\n const state: RedactionState = {\n findings: [],\n seen: new WeakMap<object, unknown>(),\n };\n const redacted = this.#redactValue(value, undefined, \"$\", 0, state);\n return {\n value: redacted as T,\n findings: state.findings,\n redacted: state.findings.some((finding) => finding.action !== \"keep\"),\n profile: this.#profile,\n };\n }\n\n #recordFinding(state: RedactionState, finding: RedactionFinding): void {\n if (this.#collectFindings) state.findings.push(finding);\n }\n\n #redactValue(\n value: unknown,\n key: string | undefined,\n path: string,\n depth: number,\n state: RedactionState,\n ): unknown {\n if (depth > this.#maxDepth) {\n this.#recordFinding(\n state,\n makeFinding(path, \"structure.maxDepth\", \"truncate\", \"value\", \"warning\"),\n );\n return \"[Truncated]\";\n }\n\n if (key !== undefined) {\n const rule = findCompiledKeyRule(key, this.#rules);\n if (rule) {\n this.#recordFinding(\n state,\n makeFinding(path, `key.${rule.key}`, actionForRule(rule), \"key\", \"warning\"),\n );\n return applyRule(rule, value, this.#replacement);\n }\n }\n\n for (const detector of this.#detectors) {\n const detections = detector.detect({ path, key, value });\n for (const detection of detections) {\n const action = detection.action ?? \"replace\";\n this.#recordFinding(\n state,\n makeFinding(\n path,\n detector.id,\n action,\n detection.matchKind ?? detector.matchKind ?? \"custom\",\n detection.severity ?? detector.severity ?? \"warning\",\n detection.preview,\n ),\n );\n if (action !== \"keep\") {\n return detection.replacement ?? this.#replacement;\n }\n }\n }\n\n if (Array.isArray(value)) {\n if (state.seen.has(value)) return state.seen.get(value);\n const out: unknown[] = [];\n state.seen.set(value, out);\n value.forEach((item, index) => {\n out[index] = this.#redactValue(item, undefined, indexPath(path, index), depth + 1, state);\n });\n return out;\n }\n\n if (isRecord(value)) {\n if (state.seen.has(value)) return state.seen.get(value);\n const out: Record<string, unknown> = {};\n state.seen.set(value, out);\n for (const [entryKey, entryValue] of Object.entries(value)) {\n out[entryKey] = this.#redactValue(\n entryValue,\n entryKey,\n childPath(path === \"$\" ? \"\" : path, entryKey),\n depth + 1,\n state,\n );\n }\n return out;\n }\n\n return value;\n }\n}\n\nexport function createRedactor(options?: RedactorOptions): Redactor {\n return new Redactor(options);\n}\n\nexport function redact<T = unknown>(value: T, options?: RedactOptions): RedactionResult<T> {\n return createRedactor(options).redact(value);\n}\n\nexport {\n KEY_VALUE_SECRET_PATTERN,\n KEY_VALUE_SECRET_PATTERN_SOURCE,\n valueContainsKeyValueSecret,\n} from \"./key-value-secret.js\";\n\n"]}
package/dist/index.d.cts CHANGED
@@ -1,3 +1,19 @@
1
+ /**
2
+ * High-confidence key/value credential forms shared with core
3
+ * `safety.secretPattern` / `key-value-secret` (keep sources in sync).
4
+ *
5
+ * Matches house-format credentials such as:
6
+ * internal_token=<credential>
7
+ * token=<credential>
8
+ * api_key=<credential>
9
+ *
10
+ * Intentionally does **not** match metric/config lookalikes such as
11
+ * maxTokens=, tokenCount=, secret=false, or short placeholders.
12
+ */
13
+ declare const KEY_VALUE_SECRET_PATTERN_SOURCE: string;
14
+ declare const KEY_VALUE_SECRET_PATTERN: RegExp;
15
+ declare function valueContainsKeyValueSecret(value: string): boolean;
16
+
1
17
  type RedactionProfile = "local" | "share" | "strict";
2
18
  type RedactionAction = "replace" | "hash" | "prefix" | "truncate" | "keep";
3
19
  type RedactionSeverity = "info" | "warning" | "error";
@@ -77,4 +93,4 @@ declare class Redactor {
77
93
  declare function createRedactor(options?: RedactorOptions): Redactor;
78
94
  declare function redact<T = unknown>(value: T, options?: RedactOptions): RedactionResult<T>;
79
95
 
80
- export { DEFAULT_REDACT_KEYS, type RedactOptions, type RedactionAction, type RedactionDetection, type RedactionDetector, type RedactionDetectorInput, type RedactionFinding, type RedactionMatchKind, type RedactionProfile, type RedactionResult, type RedactionRule, type RedactionSeverity, Redactor, type RedactorOptions, type ResolvedRedactionProfile, SHARE_PROFILE_EXTRA_KEYS, STRICT_PROFILE_EXTRA_KEYS, createRedactionProfile, createRedactor, redact };
96
+ export { DEFAULT_REDACT_KEYS, KEY_VALUE_SECRET_PATTERN, KEY_VALUE_SECRET_PATTERN_SOURCE, type RedactOptions, type RedactionAction, type RedactionDetection, type RedactionDetector, type RedactionDetectorInput, type RedactionFinding, type RedactionMatchKind, type RedactionProfile, type RedactionResult, type RedactionRule, type RedactionSeverity, Redactor, type RedactorOptions, type ResolvedRedactionProfile, SHARE_PROFILE_EXTRA_KEYS, STRICT_PROFILE_EXTRA_KEYS, createRedactionProfile, createRedactor, redact, valueContainsKeyValueSecret };
package/dist/index.d.ts CHANGED
@@ -1,3 +1,19 @@
1
+ /**
2
+ * High-confidence key/value credential forms shared with core
3
+ * `safety.secretPattern` / `key-value-secret` (keep sources in sync).
4
+ *
5
+ * Matches house-format credentials such as:
6
+ * internal_token=<credential>
7
+ * token=<credential>
8
+ * api_key=<credential>
9
+ *
10
+ * Intentionally does **not** match metric/config lookalikes such as
11
+ * maxTokens=, tokenCount=, secret=false, or short placeholders.
12
+ */
13
+ declare const KEY_VALUE_SECRET_PATTERN_SOURCE: string;
14
+ declare const KEY_VALUE_SECRET_PATTERN: RegExp;
15
+ declare function valueContainsKeyValueSecret(value: string): boolean;
16
+
1
17
  type RedactionProfile = "local" | "share" | "strict";
2
18
  type RedactionAction = "replace" | "hash" | "prefix" | "truncate" | "keep";
3
19
  type RedactionSeverity = "info" | "warning" | "error";
@@ -77,4 +93,4 @@ declare class Redactor {
77
93
  declare function createRedactor(options?: RedactorOptions): Redactor;
78
94
  declare function redact<T = unknown>(value: T, options?: RedactOptions): RedactionResult<T>;
79
95
 
80
- export { DEFAULT_REDACT_KEYS, type RedactOptions, type RedactionAction, type RedactionDetection, type RedactionDetector, type RedactionDetectorInput, type RedactionFinding, type RedactionMatchKind, type RedactionProfile, type RedactionResult, type RedactionRule, type RedactionSeverity, Redactor, type RedactorOptions, type ResolvedRedactionProfile, SHARE_PROFILE_EXTRA_KEYS, STRICT_PROFILE_EXTRA_KEYS, createRedactionProfile, createRedactor, redact };
96
+ export { DEFAULT_REDACT_KEYS, KEY_VALUE_SECRET_PATTERN, KEY_VALUE_SECRET_PATTERN_SOURCE, type RedactOptions, type RedactionAction, type RedactionDetection, type RedactionDetector, type RedactionDetectorInput, type RedactionFinding, type RedactionMatchKind, type RedactionProfile, type RedactionResult, type RedactionRule, type RedactionSeverity, Redactor, type RedactorOptions, type ResolvedRedactionProfile, SHARE_PROFILE_EXTRA_KEYS, STRICT_PROFILE_EXTRA_KEYS, createRedactionProfile, createRedactor, redact, valueContainsKeyValueSecret };
package/dist/index.mjs CHANGED
@@ -52,6 +52,17 @@ function isCredentialSensitiveKey(key, sensitiveKeys) {
52
52
  return false;
53
53
  }
54
54
 
55
+ // packages/redact/src/key-value-secret.ts
56
+ var KEY_VALUE_SECRET_PATTERN_SOURCE = String.raw`\b(?:api[_-]?key|internal[_-]?token|access[_-]?token|auth[_-]?token|password|secret|token)=([^\s"'\\]{8,})`;
57
+ var KEY_VALUE_SECRET_PATTERN = new RegExp(
58
+ KEY_VALUE_SECRET_PATTERN_SOURCE,
59
+ "i"
60
+ );
61
+ function valueContainsKeyValueSecret(value) {
62
+ KEY_VALUE_SECRET_PATTERN.lastIndex = 0;
63
+ return KEY_VALUE_SECRET_PATTERN.test(value);
64
+ }
65
+
55
66
  // packages/redact/src/index.ts
56
67
  var DEFAULT_REDACT_KEYS = [
57
68
  "authorization",
@@ -258,6 +269,15 @@ var credentialDetectors = [
258
269
  pattern: /-----BEGIN [A-Z ]*PRIVATE KEY-----[\s\S]*-----END [A-Z ]*PRIVATE KEY-----/,
259
270
  severity: "error"
260
271
  }),
272
+ {
273
+ id: "value.keyValueSecret",
274
+ severity: "error",
275
+ matchKind: "value",
276
+ detect(input) {
277
+ if (typeof input.value !== "string") return [];
278
+ return valueContainsKeyValueSecret(input.value) ? [{ action: "replace", severity: "error", matchKind: "value" }] : [];
279
+ }
280
+ },
261
281
  {
262
282
  id: "value.creditCard",
263
283
  severity: "error",
@@ -504,6 +524,6 @@ function redact(value, options) {
504
524
  return createRedactor(options).redact(value);
505
525
  }
506
526
 
507
- export { DEFAULT_REDACT_KEYS, Redactor, SHARE_PROFILE_EXTRA_KEYS, STRICT_PROFILE_EXTRA_KEYS, createRedactionProfile, createRedactor, redact };
527
+ export { DEFAULT_REDACT_KEYS, KEY_VALUE_SECRET_PATTERN, KEY_VALUE_SECRET_PATTERN_SOURCE, Redactor, SHARE_PROFILE_EXTRA_KEYS, STRICT_PROFILE_EXTRA_KEYS, createRedactionProfile, createRedactor, redact, valueContainsKeyValueSecret };
508
528
  //# sourceMappingURL=index.mjs.map
509
529
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/sensitive-key.ts","../src/index.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * Mirrors `packages/core/src/safety/sensitive-key.ts` for dependency-light\n * @agent-inspect/redact consumers. Keep both copies in sync (6.14.2 parity).\n */\n\n/** True when the original key already uses an explicit separator. */\nfunction keyHasExplicitSeparator(value: string): boolean {\n return /[_\\-.]/.test(value);\n}\n\n/**\n * Canonicalize field names so camelCase / kebab / dot / snake forms share a\n * snake_case shape the compound matcher can recognize (`userPassword` →\n * `user_password`).\n */\nexport function normalizeSensitiveKey(value: string): string {\n return value\n .replace(/([a-z0-9])([A-Z])/g, \"$1_$2\")\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"_\")\n .replace(/^_+|_+$/g, \"\");\n}\n\nexport const NON_CREDENTIAL_TOKEN_CONFIG_KEYS: ReadonlySet<string> = new Set(\n [\n \"tokens\",\n \"max_tokens\",\n \"min_tokens\",\n \"ls_max_tokens\",\n \"token_count\",\n \"token_limit\",\n \"token_budget\",\n \"input_tokens\",\n \"output_tokens\",\n \"total_tokens\",\n \"cached_tokens\",\n \"prompt_tokens\",\n \"completion_tokens\",\n ].map(normalizeSensitiveKey),\n);\n\nfunction isTokenCredentialKey(normalized: string): boolean {\n if (NON_CREDENTIAL_TOKEN_CONFIG_KEYS.has(normalized)) return false;\n if (normalized === \"token\") return true;\n if (normalized.endsWith(\"tokens\")) return false;\n return normalized.endsWith(\"token\");\n}\n\n/**\n * True when the field name looks credential-sensitive under the shared policy.\n *\n * Suffix compounds (`user_password`, `userPassword`) always match. Prefix\n * compounds (`email_note`) match only when the original key already contained\n * an explicit separator, so camelCase topic fields like `emailNote` stay for\n * value detectors instead of key redaction.\n */\nexport function isCredentialSensitiveKey(\n key: string | undefined,\n sensitiveKeys: readonly string[],\n): boolean {\n if (!key) return false;\n const normalized = normalizeSensitiveKey(key);\n if (!normalized) return false;\n if (NON_CREDENTIAL_TOKEN_CONFIG_KEYS.has(normalized)) return false;\n\n const allowPrefixCompound = keyHasExplicitSeparator(key);\n\n for (const sensitive of sensitiveKeys) {\n const s = normalizeSensitiveKey(sensitive);\n if (!s) continue;\n if (s === \"token\") {\n if (isTokenCredentialKey(normalized)) return true;\n continue;\n }\n if (normalized === s) return true;\n if (normalized.endsWith(`_${s}`)) return true;\n if (allowPrefixCompound && normalized.startsWith(`${s}_`)) return true;\n }\n return false;\n}\n","import crypto from \"node:crypto\";\nimport { isCredentialSensitiveKey } from \"./sensitive-key.js\";\n\nexport type RedactionProfile = \"local\" | \"share\" | \"strict\";\n\nexport type RedactionAction = \"replace\" | \"hash\" | \"prefix\" | \"truncate\" | \"keep\";\n\nexport type RedactionSeverity = \"info\" | \"warning\" | \"error\";\n\nexport type RedactionMatchKind = \"key\" | \"value\" | \"custom\";\n\nexport type RedactionRule =\n | string\n | { key: string; strategy: \"full\" }\n | { key: string; strategy: \"prefix\"; keep?: number }\n | { key: string; strategy: \"hash\" };\n\nexport interface RedactionFinding {\n path: string;\n detector: string;\n action: RedactionAction;\n severity: RedactionSeverity;\n matchKind: RedactionMatchKind;\n preview?: string;\n}\n\nexport interface RedactionDetection {\n action?: RedactionAction;\n replacement?: unknown;\n severity?: RedactionSeverity;\n matchKind?: RedactionMatchKind;\n preview?: string;\n}\n\nexport interface RedactionDetectorInput {\n path: string;\n key?: string;\n value: unknown;\n}\n\nexport interface RedactionDetector {\n id: string;\n severity?: RedactionSeverity;\n matchKind?: RedactionMatchKind;\n detect(input: RedactionDetectorInput): RedactionDetection[];\n}\n\nexport interface RedactionResult<T = unknown> {\n value: T;\n findings: RedactionFinding[];\n redacted: boolean;\n profile: RedactionProfile;\n}\n\nexport interface ResolvedRedactionProfile {\n profile: RedactionProfile;\n extraKeys: readonly string[];\n maxMetadataValueLengthCap?: number;\n maxPreviewLengthCap?: number;\n}\n\nexport interface RedactOptions {\n profile?: RedactionProfile;\n detectors?: RedactionDetector[];\n rules?: RedactionRule[];\n replacement?: string;\n maxDepth?: number;\n maxStringLength?: number;\n collectFindings?: boolean;\n}\n\nexport interface RedactorOptions extends RedactOptions {\n extraKeys?: readonly string[];\n}\n\nexport const DEFAULT_REDACT_KEYS = [\n \"authorization\",\n \"cookie\",\n \"token\",\n \"apiKey\",\n \"password\",\n \"secret\",\n \"email\",\n] as const;\n\nexport const SHARE_PROFILE_EXTRA_KEYS = [\n \"userEmail\",\n \"customerEmail\",\n \"phone\",\n \"phoneNumber\",\n \"address\",\n \"ip\",\n \"ipAddress\",\n \"sessionId\",\n \"requestId\",\n \"correlationId\",\n \"decisionId\",\n \"groupId\",\n \"customerId\",\n \"userId\",\n \"accountId\",\n \"tenantId\",\n \"orgId\",\n \"organizationId\",\n \"traceId\",\n \"spanId\",\n \"parentSpanId\",\n \"currentTask\",\n \"task\",\n \"userInput\",\n \"requestText\",\n \"conversationText\",\n] as const;\n\nexport const STRICT_PROFILE_EXTRA_KEYS = [\n \"prompt\",\n \"completion\",\n \"input\",\n \"output\",\n \"inputPreview\",\n \"outputPreview\",\n \"message\",\n \"messages\",\n \"transcript\",\n \"context\",\n \"document\",\n \"documents\",\n \"chunk\",\n \"chunks\",\n \"retrieval\",\n \"query\",\n] as const;\n\ntype CompiledRule =\n | { key: string; strategy: \"full\" }\n | { key: string; strategy: \"prefix\"; keep: number }\n | { key: string; strategy: \"hash\" };\n\ninterface RedactionState {\n findings: RedactionFinding[];\n seen: WeakMap<object, unknown>;\n}\n\ninterface PatternDetectorOptions {\n id: string;\n pattern: RegExp;\n severity?: RedactionSeverity;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n\nfunction toKey(key: string): string {\n return key.toLowerCase();\n}\n\nfunction findCompiledKeyRule(\n key: string,\n rules: readonly CompiledRule[],\n): CompiledRule | undefined {\n const exact = toKey(key);\n const direct = rules.find((candidate) => candidate.key === exact);\n if (direct) return direct;\n return rules.find((candidate) => isCredentialSensitiveKey(key, [candidate.key]));\n}\n\nfunction stableHash(value: string): string {\n const hash = crypto.createHash(\"sha256\").update(value, \"utf8\").digest(\"hex\");\n return hash.slice(0, 8);\n}\n\nfunction stringifyScalar(value: unknown): string | undefined {\n if (typeof value === \"string\") return value;\n if (typeof value === \"number\" || typeof value === \"boolean\" || typeof value === \"bigint\") {\n return String(value);\n }\n return undefined;\n}\n\nfunction patternDetector(options: PatternDetectorOptions): RedactionDetector {\n return {\n id: options.id,\n severity: options.severity ?? \"warning\",\n matchKind: \"value\",\n detect(input) {\n if (typeof input.value !== \"string\") return [];\n options.pattern.lastIndex = 0;\n return options.pattern.test(input.value)\n ? [{ action: \"replace\", severity: options.severity ?? \"warning\", matchKind: \"value\" }]\n : [];\n },\n };\n}\n\nfunction digitsOnly(value: string): string {\n return value.replace(/\\D/g, \"\");\n}\n\nfunction passesLuhn(value: string): boolean {\n const digits = digitsOnly(value);\n if (digits.length < 13 || digits.length > 19) return false;\n\n let sum = 0;\n let double = false;\n for (let i = digits.length - 1; i >= 0; i -= 1) {\n let digit = Number(digits[i]);\n if (double) {\n digit *= 2;\n if (digit > 9) digit -= 9;\n }\n sum += digit;\n double = !double;\n }\n return sum % 10 === 0;\n}\n\nconst UUID_RE =\n /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;\n\n/** 13-digit Unix epoch milliseconds in a plausible modern range. */\nconst EPOCH_MS_RE = /^1[0-9]{12}$/;\n\nconst EMAIL_RE = /\\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,}\\b/gi;\n\nfunction pathSuggestsNonCard(path: string): boolean {\n const normalized = path.toLowerCase().replace(/[^a-z0-9._]/g, \"\");\n return (\n /(^|\\.)(tokenusage|usage)(\\.|$)/.test(normalized) ||\n /(startedat|endedat|durationms|timestamp|createdat|updatedat)(\\.|$)/.test(normalized) ||\n /(^|\\.)(runid|traceid|spanid|eventid|sessionid|userid|parentid|requestid|correlationid)(\\.|$)/.test(\n normalized,\n ) ||\n /(^|\\.)ts(\\.|$)/.test(normalized)\n );\n}\n\nfunction isUuidLike(value: string): boolean {\n return UUID_RE.test(value.trim());\n}\n\nfunction isPlausibleCardCandidate(candidate: string, fullValue: string): boolean {\n const digits = digitsOnly(candidate);\n if (digits.length < 13 || digits.length > 19) return false;\n if (!passesLuhn(candidate)) return false;\n\n const trimmed = fullValue.trim();\n if (isUuidLike(trimmed)) return false;\n\n // Naked epoch-ms timestamps are not PANs.\n if (EPOCH_MS_RE.test(digits) && digitsOnly(trimmed) === digits && /^\\d+$/.test(trimmed)) {\n return false;\n }\n\n // Reject candidates glued inside longer alphanumeric IDs without card separators.\n const start = fullValue.indexOf(candidate);\n if (start >= 0) {\n const before = fullValue[start - 1];\n const after = fullValue[start + candidate.length];\n if (before && /[A-Za-z0-9_]/.test(before)) return false;\n if (after && /[A-Za-z0-9_]/.test(after)) return false;\n }\n\n return true;\n}\n\nfunction looksLikePathOrPackageOrUrl(value: string): boolean {\n const trimmed = value.trim();\n if (/^(?:[a-z][a-z0-9+.-]*:)?\\/\\//i.test(trimmed)) return true;\n if (/^webpack:/i.test(trimmed)) return true;\n if (/^@[A-Za-z0-9_.-]+\\/[A-Za-z0-9_.@/-]+$/.test(trimmed)) return true;\n if (/^[A-Za-z]:[\\\\/]/.test(trimmed) || /^[/\\\\]/.test(trimmed)) return true;\n // Path-like single token (slashes, no whitespace).\n if (/[\\\\/]/.test(trimmed) && !/\\s/.test(trimmed)) return true;\n return false;\n}\n\nfunction emailMatchIsPathAdjacent(value: string, index: number, length: number): boolean {\n const before = value[index - 1];\n const after = value[index + length];\n return before === \"/\" || before === \"\\\\\" || after === \"/\" || after === \"\\\\\";\n}\n\nfunction valueContainsEmail(value: string): boolean {\n if (looksLikePathOrPackageOrUrl(value)) return false;\n EMAIL_RE.lastIndex = 0;\n for (const match of value.matchAll(EMAIL_RE)) {\n const text = match[0] ?? \"\";\n const index = match.index ?? 0;\n if (emailMatchIsPathAdjacent(value, index, text.length)) continue;\n return true;\n }\n return false;\n}\n\nconst credentialDetectors: readonly RedactionDetector[] = [\n patternDetector({\n id: \"value.authorizationHeader\",\n pattern: /^(?:basic|bearer|digest|apikey)\\s+[a-z0-9._~+/=-]+$/i,\n severity: \"error\",\n }),\n patternDetector({\n id: \"value.bearerToken\",\n pattern: /\\bbearer\\s+[a-z0-9._~+/=-]{12,}\\b/i,\n severity: \"error\",\n }),\n patternDetector({\n id: \"value.cookie\",\n pattern: /\\b[a-z0-9_.-]+=[^;\\s]+(?:;\\s*[a-z0-9_.-]+=[^;\\s]+)+/i,\n severity: \"error\",\n }),\n patternDetector({\n id: \"value.jwt\",\n pattern: /\\beyJ[a-zA-Z0-9_-]{8,}\\.[a-zA-Z0-9_-]{8,}\\.[a-zA-Z0-9_-]{8,}\\b/,\n severity: \"error\",\n }),\n patternDetector({\n id: \"value.providerApiKey\",\n pattern: /\\b(?:sk-(?:proj-)?[a-zA-Z0-9_-]{16,}|sk-ant-[a-zA-Z0-9_-]{16,}|AIza[0-9A-Za-z_-]{20,})\\b/,\n severity: \"error\",\n }),\n patternDetector({\n id: \"value.githubToken\",\n pattern: /\\b(?:ghp|gho|ghu|ghs|ghr)_[A-Za-z0-9_]{20,}\\b/,\n severity: \"error\",\n }),\n patternDetector({\n id: \"value.awsAccessKey\",\n pattern: /\\b(?:AKIA|ASIA)[A-Z0-9]{16}\\b/,\n severity: \"error\",\n }),\n patternDetector({\n id: \"value.privateKey\",\n pattern: /-----BEGIN [A-Z ]*PRIVATE KEY-----[\\s\\S]*-----END [A-Z ]*PRIVATE KEY-----/,\n severity: \"error\",\n }),\n {\n id: \"value.creditCard\",\n severity: \"error\",\n matchKind: \"value\",\n detect(input) {\n if (typeof input.value !== \"string\") return [];\n if (pathSuggestsNonCard(input.path)) return [];\n if (isUuidLike(input.value)) return [];\n const candidatePattern = /(?:\\d[ -]?){13,19}/g;\n for (const match of input.value.matchAll(candidatePattern)) {\n const candidate = match[0] ?? \"\";\n if (isPlausibleCardCandidate(candidate, input.value)) {\n return [{ action: \"replace\", severity: \"error\", matchKind: \"value\" }];\n }\n }\n return [];\n },\n },\n];\n\nconst identifierDetectors: readonly RedactionDetector[] = [\n {\n id: \"value.email\",\n severity: \"warning\",\n matchKind: \"value\",\n detect(input) {\n if (typeof input.value !== \"string\") return [];\n return valueContainsEmail(input.value)\n ? [{ action: \"replace\", severity: \"warning\", matchKind: \"value\" }]\n : [];\n },\n },\n patternDetector({\n id: \"value.phone\",\n pattern: /\\b(?:\\+\\d{1,3}[\\s.-]?)?(?:\\(?\\d{3}\\)?[\\s.-])\\d{3}[\\s.-]\\d{4}\\b/,\n }),\n patternDetector({\n id: \"value.ipv4\",\n pattern: /\\b(?:(?:25[0-5]|2[0-4]\\d|1?\\d?\\d)\\.){3}(?:25[0-5]|2[0-4]\\d|1?\\d?\\d)\\b/,\n }),\n patternDetector({\n id: \"value.ipv6\",\n pattern: /\\b(?:[0-9a-f]{1,4}:){2,7}[0-9a-f]{1,4}\\b/i,\n }),\n];\n\nfunction builtInDetectorsForProfile(profile: RedactionProfile): readonly RedactionDetector[] {\n if (profile === \"local\") return credentialDetectors;\n return [...credentialDetectors, ...identifierDetectors];\n}\n\nfunction compileRules(\n rules?: RedactionRule[],\n extraKeys?: readonly string[],\n): CompiledRule[] {\n const out = new Map<string, CompiledRule>();\n\n const set = (rule: CompiledRule) => {\n const key = toKey(rule.key);\n out.set(key, { ...rule, key } as CompiledRule);\n };\n\n for (const key of DEFAULT_REDACT_KEYS) {\n set({ key, strategy: \"full\" });\n }\n\n for (const key of extraKeys ?? []) {\n if (typeof key === \"string\" && key.length > 0) {\n set({ key, strategy: \"full\" });\n }\n }\n\n for (const rule of rules ?? []) {\n if (typeof rule === \"string\") {\n set({ key: rule, strategy: \"full\" });\n continue;\n }\n\n if (rule.strategy === \"full\") set({ key: rule.key, strategy: \"full\" });\n if (rule.strategy === \"hash\") set({ key: rule.key, strategy: \"hash\" });\n if (rule.strategy === \"prefix\") {\n set({\n key: rule.key,\n strategy: \"prefix\",\n keep: typeof rule.keep === \"number\" ? rule.keep : 8,\n });\n }\n }\n\n return [...out.values()];\n}\n\nfunction actionForRule(rule: CompiledRule): RedactionAction {\n if (rule.strategy === \"full\") return \"replace\";\n return rule.strategy;\n}\n\nfunction applyRule(\n rule: CompiledRule,\n value: unknown,\n replacement: string,\n): unknown {\n if (rule.strategy === \"full\") return replacement;\n\n const asString = stringifyScalar(value);\n if (rule.strategy === \"prefix\") {\n if (asString === undefined) return replacement;\n const keep = Math.max(0, Math.floor(rule.keep));\n return asString.length <= keep ? `${asString}…` : `${asString.slice(0, keep)}…`;\n }\n\n if (rule.strategy === \"hash\") {\n if (asString === undefined) return \"[HASH:unknown]\";\n return `[HASH:${stableHash(asString)}]`;\n }\n\n return value;\n}\n\nfunction childPath(path: string, key: string): string {\n if (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(key)) {\n return path ? `${path}.${key}` : key;\n }\n return `${path || \"$\"}[${JSON.stringify(key)}]`;\n}\n\nfunction indexPath(path: string, index: number): string {\n return `${path || \"$\"}[${index}]`;\n}\n\nfunction makeFinding(\n path: string,\n detector: string,\n action: RedactionAction,\n matchKind: RedactionMatchKind,\n severity: RedactionSeverity = \"warning\",\n preview?: string,\n): RedactionFinding {\n return preview === undefined\n ? { path, detector, action, severity, matchKind }\n : { path, detector, action, severity, matchKind, preview };\n}\n\nexport function createRedactionProfile(profile: RedactionProfile = \"local\"): ResolvedRedactionProfile {\n switch (profile) {\n case \"local\":\n return { profile: \"local\", extraKeys: [] };\n case \"share\":\n return {\n profile: \"share\",\n extraKeys: SHARE_PROFILE_EXTRA_KEYS,\n maxMetadataValueLengthCap: 500,\n maxPreviewLengthCap: 200,\n };\n case \"strict\":\n return {\n profile: \"strict\",\n extraKeys: [...SHARE_PROFILE_EXTRA_KEYS, ...STRICT_PROFILE_EXTRA_KEYS],\n maxMetadataValueLengthCap: 200,\n maxPreviewLengthCap: 80,\n };\n }\n}\n\nexport class Redactor {\n readonly #rules: CompiledRule[];\n readonly #detectors: readonly RedactionDetector[];\n readonly #profile: RedactionProfile;\n readonly #replacement: string;\n readonly #maxDepth: number;\n readonly #collectFindings: boolean;\n\n constructor(options?: RedactorOptions) {\n const resolved = createRedactionProfile(options?.profile ?? \"local\");\n this.#profile = resolved.profile;\n this.#rules = compileRules(options?.rules, [\n ...resolved.extraKeys,\n ...(options?.extraKeys ?? []),\n ]);\n this.#detectors = [\n ...builtInDetectorsForProfile(this.#profile),\n ...(options?.detectors ?? []),\n ];\n this.#replacement = options?.replacement ?? \"[REDACTED]\";\n this.#maxDepth = options?.maxDepth ?? 32;\n this.#collectFindings = options?.collectFindings ?? true;\n }\n\n redactValue(key: string, value: unknown): unknown {\n return this.#redactValue(value, key, key, 0, {\n findings: [],\n seen: new WeakMap<object, unknown>(),\n });\n }\n\n redactRecord(record: Record<string, unknown>): Record<string, unknown> {\n return this.redact(record).value as Record<string, unknown>;\n }\n\n redact<T = unknown>(value: T): RedactionResult<T> {\n const state: RedactionState = {\n findings: [],\n seen: new WeakMap<object, unknown>(),\n };\n const redacted = this.#redactValue(value, undefined, \"$\", 0, state);\n return {\n value: redacted as T,\n findings: state.findings,\n redacted: state.findings.some((finding) => finding.action !== \"keep\"),\n profile: this.#profile,\n };\n }\n\n #recordFinding(state: RedactionState, finding: RedactionFinding): void {\n if (this.#collectFindings) state.findings.push(finding);\n }\n\n #redactValue(\n value: unknown,\n key: string | undefined,\n path: string,\n depth: number,\n state: RedactionState,\n ): unknown {\n if (depth > this.#maxDepth) {\n this.#recordFinding(\n state,\n makeFinding(path, \"structure.maxDepth\", \"truncate\", \"value\", \"warning\"),\n );\n return \"[Truncated]\";\n }\n\n if (key !== undefined) {\n const rule = findCompiledKeyRule(key, this.#rules);\n if (rule) {\n this.#recordFinding(\n state,\n makeFinding(path, `key.${rule.key}`, actionForRule(rule), \"key\", \"warning\"),\n );\n return applyRule(rule, value, this.#replacement);\n }\n }\n\n for (const detector of this.#detectors) {\n const detections = detector.detect({ path, key, value });\n for (const detection of detections) {\n const action = detection.action ?? \"replace\";\n this.#recordFinding(\n state,\n makeFinding(\n path,\n detector.id,\n action,\n detection.matchKind ?? detector.matchKind ?? \"custom\",\n detection.severity ?? detector.severity ?? \"warning\",\n detection.preview,\n ),\n );\n if (action !== \"keep\") {\n return detection.replacement ?? this.#replacement;\n }\n }\n }\n\n if (Array.isArray(value)) {\n if (state.seen.has(value)) return state.seen.get(value);\n const out: unknown[] = [];\n state.seen.set(value, out);\n value.forEach((item, index) => {\n out[index] = this.#redactValue(item, undefined, indexPath(path, index), depth + 1, state);\n });\n return out;\n }\n\n if (isRecord(value)) {\n if (state.seen.has(value)) return state.seen.get(value);\n const out: Record<string, unknown> = {};\n state.seen.set(value, out);\n for (const [entryKey, entryValue] of Object.entries(value)) {\n out[entryKey] = this.#redactValue(\n entryValue,\n entryKey,\n childPath(path === \"$\" ? \"\" : path, entryKey),\n depth + 1,\n state,\n );\n }\n return out;\n }\n\n return value;\n }\n}\n\nexport function createRedactor(options?: RedactorOptions): Redactor {\n return new Redactor(options);\n}\n\nexport function redact<T = unknown>(value: T, options?: RedactOptions): RedactionResult<T> {\n return createRedactor(options).redact(value);\n}\n"]}
1
+ {"version":3,"sources":["../src/sensitive-key.ts","../src/key-value-secret.ts","../src/index.ts"],"names":[],"mappings":";;;;;AAMA,SAAS,wBAAwB,KAAA,EAAwB;AACvD,EAAA,OAAO,QAAA,CAAS,KAAK,KAAK,CAAA;AAC5B;AAOO,SAAS,sBAAsB,KAAA,EAAuB;AAC3D,EAAA,OAAO,KAAA,CACJ,OAAA,CAAQ,oBAAA,EAAsB,OAAO,CAAA,CACrC,WAAA,EAAY,CACZ,OAAA,CAAQ,aAAA,EAAe,GAAG,CAAA,CAC1B,OAAA,CAAQ,YAAY,EAAE,CAAA;AAC3B;AAEO,IAAM,mCAAwD,IAAI,GAAA;AAAA,EACvE;AAAA,IACE,QAAA;AAAA,IACA,YAAA;AAAA,IACA,YAAA;AAAA,IACA,eAAA;AAAA,IACA,aAAA;AAAA,IACA,aAAA;AAAA,IACA,cAAA;AAAA,IACA,cAAA;AAAA,IACA,eAAA;AAAA,IACA,cAAA;AAAA,IACA,eAAA;AAAA,IACA,eAAA;AAAA,IACA;AAAA,GACF,CAAE,IAAI,qBAAqB;AAC7B,CAAA;AAEA,SAAS,qBAAqB,UAAA,EAA6B;AACzD,EAAA,IAAI,gCAAA,CAAiC,GAAA,CAAI,UAAU,CAAA,EAAG,OAAO,KAAA;AAC7D,EAAA,IAAI,UAAA,KAAe,SAAS,OAAO,IAAA;AACnC,EAAA,IAAI,UAAA,CAAW,QAAA,CAAS,QAAQ,CAAA,EAAG,OAAO,KAAA;AAC1C,EAAA,OAAO,UAAA,CAAW,SAAS,OAAO,CAAA;AACpC;AAUO,SAAS,wBAAA,CACd,KACA,aAAA,EACS;AACT,EAAA,IAAI,CAAC,KAAK,OAAO,KAAA;AACjB,EAAA,MAAM,UAAA,GAAa,sBAAsB,GAAG,CAAA;AAC5C,EAAA,IAAI,CAAC,YAAY,OAAO,KAAA;AACxB,EAAA,IAAI,gCAAA,CAAiC,GAAA,CAAI,UAAU,CAAA,EAAG,OAAO,KAAA;AAE7D,EAAA,MAAM,mBAAA,GAAsB,wBAAwB,GAAG,CAAA;AAEvD,EAAA,KAAA,MAAW,aAAa,aAAA,EAAe;AACrC,IAAA,MAAM,CAAA,GAAI,sBAAsB,SAAS,CAAA;AACzC,IAAA,IAAI,CAAC,CAAA,EAAG;AACR,IAAA,IAAI,MAAM,OAAA,EAAS;AACjB,MAAA,IAAI,oBAAA,CAAqB,UAAU,CAAA,EAAG,OAAO,IAAA;AAC7C,MAAA;AAAA,IACF;AACA,IAAA,IAAI,UAAA,KAAe,GAAG,OAAO,IAAA;AAC7B,IAAA,IAAI,WAAW,QAAA,CAAS,CAAA,CAAA,EAAI,CAAC,CAAA,CAAE,GAAG,OAAO,IAAA;AACzC,IAAA,IAAI,uBAAuB,UAAA,CAAW,UAAA,CAAW,GAAG,CAAC,CAAA,CAAA,CAAG,GAAG,OAAO,IAAA;AAAA,EACpE;AACA,EAAA,OAAO,KAAA;AACT;;;ACnEO,IAAM,kCACX,MAAA,CAAO,GAAA,CAAA,0GAAA;AAEF,IAAM,2BAA2B,IAAI,MAAA;AAAA,EAC1C,+BAAA;AAAA,EACA;AACF;AAEO,SAAS,4BAA4B,KAAA,EAAwB;AAClE,EAAA,wBAAA,CAAyB,SAAA,GAAY,CAAA;AACrC,EAAA,OAAO,wBAAA,CAAyB,KAAK,KAAK,CAAA;AAC5C;;;ACqDO,IAAM,mBAAA,GAAsB;AAAA,EACjC,eAAA;AAAA,EACA,QAAA;AAAA,EACA,OAAA;AAAA,EACA,QAAA;AAAA,EACA,UAAA;AAAA,EACA,QAAA;AAAA,EACA;AACF;AAEO,IAAM,wBAAA,GAA2B;AAAA,EACtC,WAAA;AAAA,EACA,eAAA;AAAA,EACA,OAAA;AAAA,EACA,aAAA;AAAA,EACA,SAAA;AAAA,EACA,IAAA;AAAA,EACA,WAAA;AAAA,EACA,WAAA;AAAA,EACA,WAAA;AAAA,EACA,eAAA;AAAA,EACA,YAAA;AAAA,EACA,SAAA;AAAA,EACA,YAAA;AAAA,EACA,QAAA;AAAA,EACA,WAAA;AAAA,EACA,UAAA;AAAA,EACA,OAAA;AAAA,EACA,gBAAA;AAAA,EACA,SAAA;AAAA,EACA,QAAA;AAAA,EACA,cAAA;AAAA,EACA,aAAA;AAAA,EACA,MAAA;AAAA,EACA,WAAA;AAAA,EACA,aAAA;AAAA,EACA;AACF;AAEO,IAAM,yBAAA,GAA4B;AAAA,EACvC,QAAA;AAAA,EACA,YAAA;AAAA,EACA,OAAA;AAAA,EACA,QAAA;AAAA,EACA,cAAA;AAAA,EACA,eAAA;AAAA,EACA,SAAA;AAAA,EACA,UAAA;AAAA,EACA,YAAA;AAAA,EACA,SAAA;AAAA,EACA,UAAA;AAAA,EACA,WAAA;AAAA,EACA,OAAA;AAAA,EACA,QAAA;AAAA,EACA,WAAA;AAAA,EACA;AACF;AAkBA,SAAS,SAAS,KAAA,EAAkD;AAClE,EAAA,OAAO,OAAO,UAAU,QAAA,IAAY,KAAA,KAAU,QAAQ,CAAC,KAAA,CAAM,QAAQ,KAAK,CAAA;AAC5E;AAGA,SAAS,MAAM,GAAA,EAAqB;AAClC,EAAA,OAAO,IAAI,WAAA,EAAY;AACzB;AAEA,SAAS,mBAAA,CACP,KACA,KAAA,EAC0B;AAC1B,EAAA,MAAM,KAAA,GAAQ,MAAM,GAAG,CAAA;AACvB,EAAA,MAAM,SAAS,KAAA,CAAM,IAAA,CAAK,CAAC,SAAA,KAAc,SAAA,CAAU,QAAQ,KAAK,CAAA;AAChE,EAAA,IAAI,QAAQ,OAAO,MAAA;AACnB,EAAA,OAAO,KAAA,CAAM,IAAA,CAAK,CAAC,SAAA,KAAc,wBAAA,CAAyB,KAAK,CAAC,SAAA,CAAU,GAAG,CAAC,CAAC,CAAA;AACjF;AAEA,SAAS,WAAW,KAAA,EAAuB;AACzC,EAAA,MAAM,IAAA,GAAO,MAAA,CAAO,UAAA,CAAW,QAAQ,CAAA,CAAE,OAAO,KAAA,EAAO,MAAM,CAAA,CAAE,MAAA,CAAO,KAAK,CAAA;AAC3E,EAAA,OAAO,IAAA,CAAK,KAAA,CAAM,CAAA,EAAG,CAAC,CAAA;AACxB;AAEA,SAAS,gBAAgB,KAAA,EAAoC;AAC3D,EAAA,IAAI,OAAO,KAAA,KAAU,QAAA,EAAU,OAAO,KAAA;AACtC,EAAA,IAAI,OAAO,UAAU,QAAA,IAAY,OAAO,UAAU,SAAA,IAAa,OAAO,UAAU,QAAA,EAAU;AACxF,IAAA,OAAO,OAAO,KAAK,CAAA;AAAA,EACrB;AACA,EAAA,OAAO,MAAA;AACT;AAEA,SAAS,gBAAgB,OAAA,EAAoD;AAC3E,EAAA,OAAO;AAAA,IACL,IAAI,OAAA,CAAQ,EAAA;AAAA,IACZ,QAAA,EAAU,QAAQ,QAAA,IAAY,SAAA;AAAA,IAC9B,SAAA,EAAW,OAAA;AAAA,IACX,OAAO,KAAA,EAAO;AACZ,MAAA,IAAI,OAAO,KAAA,CAAM,KAAA,KAAU,QAAA,SAAiB,EAAC;AAC7C,MAAA,OAAA,CAAQ,QAAQ,SAAA,GAAY,CAAA;AAC5B,MAAA,OAAO,QAAQ,OAAA,CAAQ,IAAA,CAAK,MAAM,KAAK,CAAA,GACnC,CAAC,EAAE,MAAA,EAAQ,SAAA,EAAW,QAAA,EAAU,QAAQ,QAAA,IAAY,SAAA,EAAW,WAAW,OAAA,EAAS,IACnF,EAAC;AAAA,IACP;AAAA,GACF;AACF;AAEA,SAAS,WAAW,KAAA,EAAuB;AACzC,EAAA,OAAO,KAAA,CAAM,OAAA,CAAQ,KAAA,EAAO,EAAE,CAAA;AAChC;AAEA,SAAS,WAAW,KAAA,EAAwB;AAC1C,EAAA,MAAM,MAAA,GAAS,WAAW,KAAK,CAAA;AAC/B,EAAA,IAAI,OAAO,MAAA,GAAS,EAAA,IAAM,MAAA,CAAO,MAAA,GAAS,IAAI,OAAO,KAAA;AAErD,EAAA,IAAI,GAAA,GAAM,CAAA;AACV,EAAA,IAAI,MAAA,GAAS,KAAA;AACb,EAAA,KAAA,IAAS,IAAI,MAAA,CAAO,MAAA,GAAS,GAAG,CAAA,IAAK,CAAA,EAAG,KAAK,CAAA,EAAG;AAC9C,IAAA,IAAI,KAAA,GAAQ,MAAA,CAAO,MAAA,CAAO,CAAC,CAAC,CAAA;AAC5B,IAAA,IAAI,MAAA,EAAQ;AACV,MAAA,KAAA,IAAS,CAAA;AACT,MAAA,IAAI,KAAA,GAAQ,GAAG,KAAA,IAAS,CAAA;AAAA,IAC1B;AACA,IAAA,GAAA,IAAO,KAAA;AACP,IAAA,MAAA,GAAS,CAAC,MAAA;AAAA,EACZ;AACA,EAAA,OAAO,MAAM,EAAA,KAAO,CAAA;AACtB;AAEA,IAAM,OAAA,GACJ,4EAAA;AAGF,IAAM,WAAA,GAAc,cAAA;AAEpB,IAAM,QAAA,GAAW,6CAAA;AAEjB,SAAS,oBAAoB,IAAA,EAAuB;AAClD,EAAA,MAAM,aAAa,IAAA,CAAK,WAAA,EAAY,CAAE,OAAA,CAAQ,gBAAgB,EAAE,CAAA;AAChE,EAAA,OACE,gCAAA,CAAiC,KAAK,UAAU,CAAA,IAChD,qEAAqE,IAAA,CAAK,UAAU,KACpF,8FAAA,CAA+F,IAAA;AAAA,IAC7F;AAAA,GACF,IACA,gBAAA,CAAiB,IAAA,CAAK,UAAU,CAAA;AAEpC;AAEA,SAAS,WAAW,KAAA,EAAwB;AAC1C,EAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,KAAA,CAAM,IAAA,EAAM,CAAA;AAClC;AAEA,SAAS,wBAAA,CAAyB,WAAmB,SAAA,EAA4B;AAC/E,EAAA,MAAM,MAAA,GAAS,WAAW,SAAS,CAAA;AACnC,EAAA,IAAI,OAAO,MAAA,GAAS,EAAA,IAAM,MAAA,CAAO,MAAA,GAAS,IAAI,OAAO,KAAA;AACrD,EAAA,IAAI,CAAC,UAAA,CAAW,SAAS,CAAA,EAAG,OAAO,KAAA;AAEnC,EAAA,MAAM,OAAA,GAAU,UAAU,IAAA,EAAK;AAC/B,EAAA,IAAI,UAAA,CAAW,OAAO,CAAA,EAAG,OAAO,KAAA;AAGhC,EAAA,IAAI,WAAA,CAAY,IAAA,CAAK,MAAM,CAAA,IAAK,UAAA,CAAW,OAAO,CAAA,KAAM,MAAA,IAAU,OAAA,CAAQ,IAAA,CAAK,OAAO,CAAA,EAAG;AACvF,IAAA,OAAO,KAAA;AAAA,EACT;AAGA,EAAA,MAAM,KAAA,GAAQ,SAAA,CAAU,OAAA,CAAQ,SAAS,CAAA;AACzC,EAAA,IAAI,SAAS,CAAA,EAAG;AACd,IAAA,MAAM,MAAA,GAAS,SAAA,CAAU,KAAA,GAAQ,CAAC,CAAA;AAClC,IAAA,MAAM,KAAA,GAAQ,SAAA,CAAU,KAAA,GAAQ,SAAA,CAAU,MAAM,CAAA;AAChD,IAAA,IAAI,MAAA,IAAU,cAAA,CAAe,IAAA,CAAK,MAAM,GAAG,OAAO,KAAA;AAClD,IAAA,IAAI,KAAA,IAAS,cAAA,CAAe,IAAA,CAAK,KAAK,GAAG,OAAO,KAAA;AAAA,EAClD;AAEA,EAAA,OAAO,IAAA;AACT;AAEA,SAAS,4BAA4B,KAAA,EAAwB;AAC3D,EAAA,MAAM,OAAA,GAAU,MAAM,IAAA,EAAK;AAC3B,EAAA,IAAI,+BAAA,CAAgC,IAAA,CAAK,OAAO,CAAA,EAAG,OAAO,IAAA;AAC1D,EAAA,IAAI,YAAA,CAAa,IAAA,CAAK,OAAO,CAAA,EAAG,OAAO,IAAA;AACvC,EAAA,IAAI,uCAAA,CAAwC,IAAA,CAAK,OAAO,CAAA,EAAG,OAAO,IAAA;AAClE,EAAA,IAAI,iBAAA,CAAkB,KAAK,OAAO,CAAA,IAAK,SAAS,IAAA,CAAK,OAAO,GAAG,OAAO,IAAA;AAEtE,EAAA,IAAI,OAAA,CAAQ,KAAK,OAAO,CAAA,IAAK,CAAC,IAAA,CAAK,IAAA,CAAK,OAAO,CAAA,EAAG,OAAO,IAAA;AACzD,EAAA,OAAO,KAAA;AACT;AAEA,SAAS,wBAAA,CAAyB,KAAA,EAAe,KAAA,EAAe,MAAA,EAAyB;AACvF,EAAA,MAAM,MAAA,GAAS,KAAA,CAAM,KAAA,GAAQ,CAAC,CAAA;AAC9B,EAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,KAAA,GAAQ,MAAM,CAAA;AAClC,EAAA,OAAO,WAAW,GAAA,IAAO,MAAA,KAAW,IAAA,IAAQ,KAAA,KAAU,OAAO,KAAA,KAAU,IAAA;AACzE;AAEA,SAAS,mBAAmB,KAAA,EAAwB;AAClD,EAAA,IAAI,2BAAA,CAA4B,KAAK,CAAA,EAAG,OAAO,KAAA;AAC/C,EAAA,QAAA,CAAS,SAAA,GAAY,CAAA;AACrB,EAAA,KAAA,MAAW,KAAA,IAAS,KAAA,CAAM,QAAA,CAAS,QAAQ,CAAA,EAAG;AAC5C,IAAA,MAAM,IAAA,GAAO,KAAA,CAAM,CAAC,CAAA,IAAK,EAAA;AACzB,IAAA,MAAM,KAAA,GAAQ,MAAM,KAAA,IAAS,CAAA;AAC7B,IAAA,IAAI,wBAAA,CAAyB,KAAA,EAAO,KAAA,EAAO,IAAA,CAAK,MAAM,CAAA,EAAG;AACzD,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,OAAO,KAAA;AACT;AAEA,IAAM,mBAAA,GAAoD;AAAA,EACxD,eAAA,CAAgB;AAAA,IACd,EAAA,EAAI,2BAAA;AAAA,IACJ,OAAA,EAAS,sDAAA;AAAA,IACT,QAAA,EAAU;AAAA,GACX,CAAA;AAAA,EACD,eAAA,CAAgB;AAAA,IACd,EAAA,EAAI,mBAAA;AAAA,IACJ,OAAA,EAAS,oCAAA;AAAA,IACT,QAAA,EAAU;AAAA,GACX,CAAA;AAAA,EACD,eAAA,CAAgB;AAAA,IACd,EAAA,EAAI,cAAA;AAAA,IACJ,OAAA,EAAS,sDAAA;AAAA,IACT,QAAA,EAAU;AAAA,GACX,CAAA;AAAA,EACD,eAAA,CAAgB;AAAA,IACd,EAAA,EAAI,WAAA;AAAA,IACJ,OAAA,EAAS,gEAAA;AAAA,IACT,QAAA,EAAU;AAAA,GACX,CAAA;AAAA,EACD,eAAA,CAAgB;AAAA,IACd,EAAA,EAAI,sBAAA;AAAA,IACJ,OAAA,EAAS,0FAAA;AAAA,IACT,QAAA,EAAU;AAAA,GACX,CAAA;AAAA,EACD,eAAA,CAAgB;AAAA,IACd,EAAA,EAAI,mBAAA;AAAA,IACJ,OAAA,EAAS,+CAAA;AAAA,IACT,QAAA,EAAU;AAAA,GACX,CAAA;AAAA,EACD,eAAA,CAAgB;AAAA,IACd,EAAA,EAAI,oBAAA;AAAA,IACJ,OAAA,EAAS,+BAAA;AAAA,IACT,QAAA,EAAU;AAAA,GACX,CAAA;AAAA,EACD,eAAA,CAAgB;AAAA,IACd,EAAA,EAAI,kBAAA;AAAA,IACJ,OAAA,EAAS,2EAAA;AAAA,IACT,QAAA,EAAU;AAAA,GACX,CAAA;AAAA,EACD;AAAA,IACE,EAAA,EAAI,sBAAA;AAAA,IACJ,QAAA,EAAU,OAAA;AAAA,IACV,SAAA,EAAW,OAAA;AAAA,IACX,OAAO,KAAA,EAAO;AACZ,MAAA,IAAI,OAAO,KAAA,CAAM,KAAA,KAAU,QAAA,SAAiB,EAAC;AAC7C,MAAA,OAAO,2BAAA,CAA4B,KAAA,CAAM,KAAK,CAAA,GAC1C,CAAC,EAAE,MAAA,EAAQ,SAAA,EAAW,QAAA,EAAU,OAAA,EAAS,SAAA,EAAW,OAAA,EAAS,IAC7D,EAAC;AAAA,IACP;AAAA,GACF;AAAA,EACA;AAAA,IACE,EAAA,EAAI,kBAAA;AAAA,IACJ,QAAA,EAAU,OAAA;AAAA,IACV,SAAA,EAAW,OAAA;AAAA,IACX,OAAO,KAAA,EAAO;AACZ,MAAA,IAAI,OAAO,KAAA,CAAM,KAAA,KAAU,QAAA,SAAiB,EAAC;AAC7C,MAAA,IAAI,mBAAA,CAAoB,KAAA,CAAM,IAAI,CAAA,SAAU,EAAC;AAC7C,MAAA,IAAI,UAAA,CAAW,KAAA,CAAM,KAAK,CAAA,SAAU,EAAC;AACrC,MAAA,MAAM,gBAAA,GAAmB,qBAAA;AACzB,MAAA,KAAA,MAAW,KAAA,IAAS,KAAA,CAAM,KAAA,CAAM,QAAA,CAAS,gBAAgB,CAAA,EAAG;AAC1D,QAAA,MAAM,SAAA,GAAY,KAAA,CAAM,CAAC,CAAA,IAAK,EAAA;AAC9B,QAAA,IAAI,wBAAA,CAAyB,SAAA,EAAW,KAAA,CAAM,KAAK,CAAA,EAAG;AACpD,UAAA,OAAO,CAAC,EAAE,MAAA,EAAQ,SAAA,EAAW,UAAU,OAAA,EAAS,SAAA,EAAW,SAAS,CAAA;AAAA,QACtE;AAAA,MACF;AACA,MAAA,OAAO,EAAC;AAAA,IACV;AAAA;AAEJ,CAAA;AAEA,IAAM,mBAAA,GAAoD;AAAA,EACxD;AAAA,IACE,EAAA,EAAI,aAAA;AAAA,IACJ,QAAA,EAAU,SAAA;AAAA,IACV,SAAA,EAAW,OAAA;AAAA,IACX,OAAO,KAAA,EAAO;AACZ,MAAA,IAAI,OAAO,KAAA,CAAM,KAAA,KAAU,QAAA,SAAiB,EAAC;AAC7C,MAAA,OAAO,kBAAA,CAAmB,KAAA,CAAM,KAAK,CAAA,GACjC,CAAC,EAAE,MAAA,EAAQ,SAAA,EAAW,QAAA,EAAU,SAAA,EAAW,SAAA,EAAW,OAAA,EAAS,IAC/D,EAAC;AAAA,IACP;AAAA,GACF;AAAA,EACA,eAAA,CAAgB;AAAA,IACd,EAAA,EAAI,aAAA;AAAA,IACJ,OAAA,EAAS;AAAA,GACV,CAAA;AAAA,EACD,eAAA,CAAgB;AAAA,IACd,EAAA,EAAI,YAAA;AAAA,IACJ,OAAA,EAAS;AAAA,GACV,CAAA;AAAA,EACD,eAAA,CAAgB;AAAA,IACd,EAAA,EAAI,YAAA;AAAA,IACJ,OAAA,EAAS;AAAA,GACV;AACH,CAAA;AAEA,SAAS,2BAA2B,OAAA,EAAyD;AAC3F,EAAA,IAAI,OAAA,KAAY,SAAS,OAAO,mBAAA;AAChC,EAAA,OAAO,CAAC,GAAG,mBAAA,EAAqB,GAAG,mBAAmB,CAAA;AACxD;AAEA,SAAS,YAAA,CACP,OACA,SAAA,EACgB;AAChB,EAAA,MAAM,GAAA,uBAAU,GAAA,EAA0B;AAE1C,EAAA,MAAM,GAAA,GAAM,CAAC,IAAA,KAAuB;AAClC,IAAA,MAAM,GAAA,GAAM,KAAA,CAAM,IAAA,CAAK,GAAG,CAAA;AAC1B,IAAA,GAAA,CAAI,IAAI,GAAA,EAAK,EAAE,GAAG,IAAA,EAAM,KAAqB,CAAA;AAAA,EAC/C,CAAA;AAEA,EAAA,KAAA,MAAW,OAAO,mBAAA,EAAqB;AACrC,IAAA,GAAA,CAAI,EAAE,GAAA,EAAK,QAAA,EAAU,MAAA,EAAQ,CAAA;AAAA,EAC/B;AAEA,EAAA,KAAA,MAAW,GAAA,IAAO,SAAA,IAAa,EAAC,EAAG;AACjC,IAAA,IAAI,OAAO,GAAA,KAAQ,QAAA,IAAY,GAAA,CAAI,SAAS,CAAA,EAAG;AAC7C,MAAA,GAAA,CAAI,EAAE,GAAA,EAAK,QAAA,EAAU,MAAA,EAAQ,CAAA;AAAA,IAC/B;AAAA,EACF;AAEA,EAAA,KAAA,MAAW,IAAA,IAAQ,KAAA,IAAS,EAAC,EAAG;AAC9B,IAAA,IAAI,OAAO,SAAS,QAAA,EAAU;AAC5B,MAAA,GAAA,CAAI,EAAE,GAAA,EAAK,IAAA,EAAM,QAAA,EAAU,QAAQ,CAAA;AACnC,MAAA;AAAA,IACF;AAEA,IAAA,IAAI,IAAA,CAAK,QAAA,KAAa,MAAA,EAAQ,GAAA,CAAI,EAAE,KAAK,IAAA,CAAK,GAAA,EAAK,QAAA,EAAU,MAAA,EAAQ,CAAA;AACrE,IAAA,IAAI,IAAA,CAAK,QAAA,KAAa,MAAA,EAAQ,GAAA,CAAI,EAAE,KAAK,IAAA,CAAK,GAAA,EAAK,QAAA,EAAU,MAAA,EAAQ,CAAA;AACrE,IAAA,IAAI,IAAA,CAAK,aAAa,QAAA,EAAU;AAC9B,MAAA,GAAA,CAAI;AAAA,QACF,KAAK,IAAA,CAAK,GAAA;AAAA,QACV,QAAA,EAAU,QAAA;AAAA,QACV,MAAM,OAAO,IAAA,CAAK,IAAA,KAAS,QAAA,GAAW,KAAK,IAAA,GAAO;AAAA,OACnD,CAAA;AAAA,IACH;AAAA,EACF;AAEA,EAAA,OAAO,CAAC,GAAG,GAAA,CAAI,MAAA,EAAQ,CAAA;AACzB;AAEA,SAAS,cAAc,IAAA,EAAqC;AAC1D,EAAA,IAAI,IAAA,CAAK,QAAA,KAAa,MAAA,EAAQ,OAAO,SAAA;AACrC,EAAA,OAAO,IAAA,CAAK,QAAA;AACd;AAEA,SAAS,SAAA,CACP,IAAA,EACA,KAAA,EACA,WAAA,EACS;AACT,EAAA,IAAI,IAAA,CAAK,QAAA,KAAa,MAAA,EAAQ,OAAO,WAAA;AAErC,EAAA,MAAM,QAAA,GAAW,gBAAgB,KAAK,CAAA;AACtC,EAAA,IAAI,IAAA,CAAK,aAAa,QAAA,EAAU;AAC9B,IAAA,IAAI,QAAA,KAAa,QAAW,OAAO,WAAA;AACnC,IAAA,MAAM,IAAA,GAAO,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,KAAA,CAAM,IAAA,CAAK,IAAI,CAAC,CAAA;AAC9C,IAAA,OAAO,QAAA,CAAS,MAAA,IAAU,IAAA,GAAO,CAAA,EAAG,QAAQ,CAAA,MAAA,CAAA,GAAM,CAAA,EAAG,QAAA,CAAS,KAAA,CAAM,CAAA,EAAG,IAAI,CAAC,CAAA,MAAA,CAAA;AAAA,EAC9E;AAEA,EAAA,IAAI,IAAA,CAAK,aAAa,MAAA,EAAQ;AAC5B,IAAA,IAAI,QAAA,KAAa,QAAW,OAAO,gBAAA;AACnC,IAAA,OAAO,CAAA,MAAA,EAAS,UAAA,CAAW,QAAQ,CAAC,CAAA,CAAA,CAAA;AAAA,EACtC;AAEA,EAAA,OAAO,KAAA;AACT;AAEA,SAAS,SAAA,CAAU,MAAc,GAAA,EAAqB;AACpD,EAAA,IAAI,4BAAA,CAA6B,IAAA,CAAK,GAAG,CAAA,EAAG;AAC1C,IAAA,OAAO,IAAA,GAAO,CAAA,EAAG,IAAI,CAAA,CAAA,EAAI,GAAG,CAAA,CAAA,GAAK,GAAA;AAAA,EACnC;AACA,EAAA,OAAO,GAAG,IAAA,IAAQ,GAAG,IAAI,IAAA,CAAK,SAAA,CAAU,GAAG,CAAC,CAAA,CAAA,CAAA;AAC9C;AAEA,SAAS,SAAA,CAAU,MAAc,KAAA,EAAuB;AACtD,EAAA,OAAO,CAAA,EAAG,IAAA,IAAQ,GAAG,CAAA,CAAA,EAAI,KAAK,CAAA,CAAA,CAAA;AAChC;AAEA,SAAS,YACP,IAAA,EACA,QAAA,EACA,QACA,SAAA,EACA,QAAA,GAA8B,WAC9B,OAAA,EACkB;AAClB,EAAA,OAAO,OAAA,KAAY,MAAA,GACf,EAAE,IAAA,EAAM,UAAU,MAAA,EAAQ,QAAA,EAAU,SAAA,EAAU,GAC9C,EAAE,IAAA,EAAM,QAAA,EAAU,MAAA,EAAQ,QAAA,EAAU,WAAW,OAAA,EAAQ;AAC7D;AAEO,SAAS,sBAAA,CAAuB,UAA4B,OAAA,EAAmC;AACpG,EAAA,QAAQ,OAAA;AAAS,IACf,KAAK,OAAA;AACH,MAAA,OAAO,EAAE,OAAA,EAAS,OAAA,EAAS,SAAA,EAAW,EAAC,EAAE;AAAA,IAC3C,KAAK,OAAA;AACH,MAAA,OAAO;AAAA,QACL,OAAA,EAAS,OAAA;AAAA,QACT,SAAA,EAAW,wBAAA;AAAA,QACX,yBAAA,EAA2B,GAAA;AAAA,QAC3B,mBAAA,EAAqB;AAAA,OACvB;AAAA,IACF,KAAK,QAAA;AACH,MAAA,OAAO;AAAA,QACL,OAAA,EAAS,QAAA;AAAA,QACT,SAAA,EAAW,CAAC,GAAG,wBAAA,EAA0B,GAAG,yBAAyB,CAAA;AAAA,QACrE,yBAAA,EAA2B,GAAA;AAAA,QAC3B,mBAAA,EAAqB;AAAA,OACvB;AAAA;AAEN;AAEO,IAAM,WAAN,MAAe;AAAA,EACX,MAAA;AAAA,EACA,UAAA;AAAA,EACA,QAAA;AAAA,EACA,YAAA;AAAA,EACA,SAAA;AAAA,EACA,gBAAA;AAAA,EAET,YAAY,OAAA,EAA2B;AACrC,IAAA,MAAM,QAAA,GAAW,sBAAA,CAAuB,OAAA,EAAS,OAAA,IAAW,OAAO,CAAA;AACnE,IAAA,IAAA,CAAK,WAAW,QAAA,CAAS,OAAA;AACzB,IAAA,IAAA,CAAK,MAAA,GAAS,YAAA,CAAa,OAAA,EAAS,KAAA,EAAO;AAAA,MACzC,GAAG,QAAA,CAAS,SAAA;AAAA,MACZ,GAAI,OAAA,EAAS,SAAA,IAAa;AAAC,KAC5B,CAAA;AACD,IAAA,IAAA,CAAK,UAAA,GAAa;AAAA,MAChB,GAAG,0BAAA,CAA2B,IAAA,CAAK,QAAQ,CAAA;AAAA,MAC3C,GAAI,OAAA,EAAS,SAAA,IAAa;AAAC,KAC7B;AACA,IAAA,IAAA,CAAK,YAAA,GAAe,SAAS,WAAA,IAAe,YAAA;AAC5C,IAAA,IAAA,CAAK,SAAA,GAAY,SAAS,QAAA,IAAY,EAAA;AACtC,IAAA,IAAA,CAAK,gBAAA,GAAmB,SAAS,eAAA,IAAmB,IAAA;AAAA,EACtD;AAAA,EAEA,WAAA,CAAY,KAAa,KAAA,EAAyB;AAChD,IAAA,OAAO,IAAA,CAAK,YAAA,CAAa,KAAA,EAAO,GAAA,EAAK,KAAK,CAAA,EAAG;AAAA,MAC3C,UAAU,EAAC;AAAA,MACX,IAAA,sBAAU,OAAA;AAAyB,KACpC,CAAA;AAAA,EACH;AAAA,EAEA,aAAa,MAAA,EAA0D;AACrE,IAAA,OAAO,IAAA,CAAK,MAAA,CAAO,MAAM,CAAA,CAAE,KAAA;AAAA,EAC7B;AAAA,EAEA,OAAoB,KAAA,EAA8B;AAChD,IAAA,MAAM,KAAA,GAAwB;AAAA,MAC5B,UAAU,EAAC;AAAA,MACX,IAAA,sBAAU,OAAA;AAAyB,KACrC;AACA,IAAA,MAAM,WAAW,IAAA,CAAK,YAAA,CAAa,OAAO,MAAA,EAAW,GAAA,EAAK,GAAG,KAAK,CAAA;AAClE,IAAA,OAAO;AAAA,MACL,KAAA,EAAO,QAAA;AAAA,MACP,UAAU,KAAA,CAAM,QAAA;AAAA,MAChB,QAAA,EAAU,MAAM,QAAA,CAAS,IAAA,CAAK,CAAC,OAAA,KAAY,OAAA,CAAQ,WAAW,MAAM,CAAA;AAAA,MACpE,SAAS,IAAA,CAAK;AAAA,KAChB;AAAA,EACF;AAAA,EAEA,cAAA,CAAe,OAAuB,OAAA,EAAiC;AACrE,IAAA,IAAI,IAAA,CAAK,gBAAA,EAAkB,KAAA,CAAM,QAAA,CAAS,KAAK,OAAO,CAAA;AAAA,EACxD;AAAA,EAEA,YAAA,CACE,KAAA,EACA,GAAA,EACA,IAAA,EACA,OACA,KAAA,EACS;AACT,IAAA,IAAI,KAAA,GAAQ,KAAK,SAAA,EAAW;AAC1B,MAAA,IAAA,CAAK,cAAA;AAAA,QACH,KAAA;AAAA,QACA,WAAA,CAAY,IAAA,EAAM,oBAAA,EAAsB,UAAA,EAAY,SAAS,SAAS;AAAA,OACxE;AACA,MAAA,OAAO,aAAA;AAAA,IACT;AAEA,IAAA,IAAI,QAAQ,MAAA,EAAW;AACrB,MAAA,MAAM,IAAA,GAAO,mBAAA,CAAoB,GAAA,EAAK,IAAA,CAAK,MAAM,CAAA;AACjD,MAAA,IAAI,IAAA,EAAM;AACR,QAAA,IAAA,CAAK,cAAA;AAAA,UACH,KAAA;AAAA,UACA,WAAA,CAAY,IAAA,EAAM,CAAA,IAAA,EAAO,IAAA,CAAK,GAAG,IAAI,aAAA,CAAc,IAAI,CAAA,EAAG,KAAA,EAAO,SAAS;AAAA,SAC5E;AACA,QAAA,OAAO,SAAA,CAAU,IAAA,EAAM,KAAA,EAAO,IAAA,CAAK,YAAY,CAAA;AAAA,MACjD;AAAA,IACF;AAEA,IAAA,KAAA,MAAW,QAAA,IAAY,KAAK,UAAA,EAAY;AACtC,MAAA,MAAM,aAAa,QAAA,CAAS,MAAA,CAAO,EAAE,IAAA,EAAM,GAAA,EAAK,OAAO,CAAA;AACvD,MAAA,KAAA,MAAW,aAAa,UAAA,EAAY;AAClC,QAAA,MAAM,MAAA,GAAS,UAAU,MAAA,IAAU,SAAA;AACnC,QAAA,IAAA,CAAK,cAAA;AAAA,UACH,KAAA;AAAA,UACA,WAAA;AAAA,YACE,IAAA;AAAA,YACA,QAAA,CAAS,EAAA;AAAA,YACT,MAAA;AAAA,YACA,SAAA,CAAU,SAAA,IAAa,QAAA,CAAS,SAAA,IAAa,QAAA;AAAA,YAC7C,SAAA,CAAU,QAAA,IAAY,QAAA,CAAS,QAAA,IAAY,SAAA;AAAA,YAC3C,SAAA,CAAU;AAAA;AACZ,SACF;AACA,QAAA,IAAI,WAAW,MAAA,EAAQ;AACrB,UAAA,OAAO,SAAA,CAAU,eAAe,IAAA,CAAK,YAAA;AAAA,QACvC;AAAA,MACF;AAAA,IACF;AAEA,IAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,EAAG;AACxB,MAAA,IAAI,KAAA,CAAM,KAAK,GAAA,CAAI,KAAK,GAAG,OAAO,KAAA,CAAM,IAAA,CAAK,GAAA,CAAI,KAAK,CAAA;AACtD,MAAA,MAAM,MAAiB,EAAC;AACxB,MAAA,KAAA,CAAM,IAAA,CAAK,GAAA,CAAI,KAAA,EAAO,GAAG,CAAA;AACzB,MAAA,KAAA,CAAM,OAAA,CAAQ,CAAC,IAAA,EAAM,KAAA,KAAU;AAC7B,QAAA,GAAA,CAAI,KAAK,CAAA,GAAI,IAAA,CAAK,YAAA,CAAa,IAAA,EAAM,MAAA,EAAW,SAAA,CAAU,IAAA,EAAM,KAAK,CAAA,EAAG,KAAA,GAAQ,CAAA,EAAG,KAAK,CAAA;AAAA,MAC1F,CAAC,CAAA;AACD,MAAA,OAAO,GAAA;AAAA,IACT;AAEA,IAAA,IAAI,QAAA,CAAS,KAAK,CAAA,EAAG;AACnB,MAAA,IAAI,KAAA,CAAM,KAAK,GAAA,CAAI,KAAK,GAAG,OAAO,KAAA,CAAM,IAAA,CAAK,GAAA,CAAI,KAAK,CAAA;AACtD,MAAA,MAAM,MAA+B,EAAC;AACtC,MAAA,KAAA,CAAM,IAAA,CAAK,GAAA,CAAI,KAAA,EAAO,GAAG,CAAA;AACzB,MAAA,KAAA,MAAW,CAAC,QAAA,EAAU,UAAU,KAAK,MAAA,CAAO,OAAA,CAAQ,KAAK,CAAA,EAAG;AAC1D,QAAA,GAAA,CAAI,QAAQ,IAAI,IAAA,CAAK,YAAA;AAAA,UACnB,UAAA;AAAA,UACA,QAAA;AAAA,UACA,SAAA,CAAU,IAAA,KAAS,GAAA,GAAM,EAAA,GAAK,MAAM,QAAQ,CAAA;AAAA,UAC5C,KAAA,GAAQ,CAAA;AAAA,UACR;AAAA,SACF;AAAA,MACF;AACA,MAAA,OAAO,GAAA;AAAA,IACT;AAEA,IAAA,OAAO,KAAA;AAAA,EACT;AACF;AAEO,SAAS,eAAe,OAAA,EAAqC;AAClE,EAAA,OAAO,IAAI,SAAS,OAAO,CAAA;AAC7B;AAEO,SAAS,MAAA,CAAoB,OAAU,OAAA,EAA6C;AACzF,EAAA,OAAO,cAAA,CAAe,OAAO,CAAA,CAAE,MAAA,CAAO,KAAK,CAAA;AAC7C","file":"index.mjs","sourcesContent":["/**\n * Mirrors `packages/core/src/safety/sensitive-key.ts` for dependency-light\n * @agent-inspect/redact consumers. Keep both copies in sync (6.14.2 parity).\n */\n\n/** True when the original key already uses an explicit separator. */\nfunction keyHasExplicitSeparator(value: string): boolean {\n return /[_\\-.]/.test(value);\n}\n\n/**\n * Canonicalize field names so camelCase / kebab / dot / snake forms share a\n * snake_case shape the compound matcher can recognize (`userPassword` →\n * `user_password`).\n */\nexport function normalizeSensitiveKey(value: string): string {\n return value\n .replace(/([a-z0-9])([A-Z])/g, \"$1_$2\")\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"_\")\n .replace(/^_+|_+$/g, \"\");\n}\n\nexport const NON_CREDENTIAL_TOKEN_CONFIG_KEYS: ReadonlySet<string> = new Set(\n [\n \"tokens\",\n \"max_tokens\",\n \"min_tokens\",\n \"ls_max_tokens\",\n \"token_count\",\n \"token_limit\",\n \"token_budget\",\n \"input_tokens\",\n \"output_tokens\",\n \"total_tokens\",\n \"cached_tokens\",\n \"prompt_tokens\",\n \"completion_tokens\",\n ].map(normalizeSensitiveKey),\n);\n\nfunction isTokenCredentialKey(normalized: string): boolean {\n if (NON_CREDENTIAL_TOKEN_CONFIG_KEYS.has(normalized)) return false;\n if (normalized === \"token\") return true;\n if (normalized.endsWith(\"tokens\")) return false;\n return normalized.endsWith(\"token\");\n}\n\n/**\n * True when the field name looks credential-sensitive under the shared policy.\n *\n * Suffix compounds (`user_password`, `userPassword`) always match. Prefix\n * compounds (`email_note`) match only when the original key already contained\n * an explicit separator, so camelCase topic fields like `emailNote` stay for\n * value detectors instead of key redaction.\n */\nexport function isCredentialSensitiveKey(\n key: string | undefined,\n sensitiveKeys: readonly string[],\n): boolean {\n if (!key) return false;\n const normalized = normalizeSensitiveKey(key);\n if (!normalized) return false;\n if (NON_CREDENTIAL_TOKEN_CONFIG_KEYS.has(normalized)) return false;\n\n const allowPrefixCompound = keyHasExplicitSeparator(key);\n\n for (const sensitive of sensitiveKeys) {\n const s = normalizeSensitiveKey(sensitive);\n if (!s) continue;\n if (s === \"token\") {\n if (isTokenCredentialKey(normalized)) return true;\n continue;\n }\n if (normalized === s) return true;\n if (normalized.endsWith(`_${s}`)) return true;\n if (allowPrefixCompound && normalized.startsWith(`${s}_`)) return true;\n }\n return false;\n}\n","/**\n * High-confidence key/value credential forms shared with core\n * `safety.secretPattern` / `key-value-secret` (keep sources in sync).\n *\n * Matches house-format credentials such as:\n * internal_token=<credential>\n * token=<credential>\n * api_key=<credential>\n *\n * Intentionally does **not** match metric/config lookalikes such as\n * maxTokens=, tokenCount=, secret=false, or short placeholders.\n */\nexport const KEY_VALUE_SECRET_PATTERN_SOURCE =\n String.raw`\\b(?:api[_-]?key|internal[_-]?token|access[_-]?token|auth[_-]?token|password|secret|token)=([^\\s\"'\\\\]{8,})`;\n\nexport const KEY_VALUE_SECRET_PATTERN = new RegExp(\n KEY_VALUE_SECRET_PATTERN_SOURCE,\n \"i\",\n);\n\nexport function valueContainsKeyValueSecret(value: string): boolean {\n KEY_VALUE_SECRET_PATTERN.lastIndex = 0;\n return KEY_VALUE_SECRET_PATTERN.test(value);\n}\n","import crypto from \"node:crypto\";\nimport { isCredentialSensitiveKey } from \"./sensitive-key.js\";\nimport { valueContainsKeyValueSecret } from \"./key-value-secret.js\";\n\nexport type RedactionProfile = \"local\" | \"share\" | \"strict\";\n\nexport type RedactionAction = \"replace\" | \"hash\" | \"prefix\" | \"truncate\" | \"keep\";\n\nexport type RedactionSeverity = \"info\" | \"warning\" | \"error\";\n\nexport type RedactionMatchKind = \"key\" | \"value\" | \"custom\";\n\nexport type RedactionRule =\n | string\n | { key: string; strategy: \"full\" }\n | { key: string; strategy: \"prefix\"; keep?: number }\n | { key: string; strategy: \"hash\" };\n\nexport interface RedactionFinding {\n path: string;\n detector: string;\n action: RedactionAction;\n severity: RedactionSeverity;\n matchKind: RedactionMatchKind;\n preview?: string;\n}\n\nexport interface RedactionDetection {\n action?: RedactionAction;\n replacement?: unknown;\n severity?: RedactionSeverity;\n matchKind?: RedactionMatchKind;\n preview?: string;\n}\n\nexport interface RedactionDetectorInput {\n path: string;\n key?: string;\n value: unknown;\n}\n\nexport interface RedactionDetector {\n id: string;\n severity?: RedactionSeverity;\n matchKind?: RedactionMatchKind;\n detect(input: RedactionDetectorInput): RedactionDetection[];\n}\n\nexport interface RedactionResult<T = unknown> {\n value: T;\n findings: RedactionFinding[];\n redacted: boolean;\n profile: RedactionProfile;\n}\n\nexport interface ResolvedRedactionProfile {\n profile: RedactionProfile;\n extraKeys: readonly string[];\n maxMetadataValueLengthCap?: number;\n maxPreviewLengthCap?: number;\n}\n\nexport interface RedactOptions {\n profile?: RedactionProfile;\n detectors?: RedactionDetector[];\n rules?: RedactionRule[];\n replacement?: string;\n maxDepth?: number;\n maxStringLength?: number;\n collectFindings?: boolean;\n}\n\nexport interface RedactorOptions extends RedactOptions {\n extraKeys?: readonly string[];\n}\n\nexport const DEFAULT_REDACT_KEYS = [\n \"authorization\",\n \"cookie\",\n \"token\",\n \"apiKey\",\n \"password\",\n \"secret\",\n \"email\",\n] as const;\n\nexport const SHARE_PROFILE_EXTRA_KEYS = [\n \"userEmail\",\n \"customerEmail\",\n \"phone\",\n \"phoneNumber\",\n \"address\",\n \"ip\",\n \"ipAddress\",\n \"sessionId\",\n \"requestId\",\n \"correlationId\",\n \"decisionId\",\n \"groupId\",\n \"customerId\",\n \"userId\",\n \"accountId\",\n \"tenantId\",\n \"orgId\",\n \"organizationId\",\n \"traceId\",\n \"spanId\",\n \"parentSpanId\",\n \"currentTask\",\n \"task\",\n \"userInput\",\n \"requestText\",\n \"conversationText\",\n] as const;\n\nexport const STRICT_PROFILE_EXTRA_KEYS = [\n \"prompt\",\n \"completion\",\n \"input\",\n \"output\",\n \"inputPreview\",\n \"outputPreview\",\n \"message\",\n \"messages\",\n \"transcript\",\n \"context\",\n \"document\",\n \"documents\",\n \"chunk\",\n \"chunks\",\n \"retrieval\",\n \"query\",\n] as const;\n\ntype CompiledRule =\n | { key: string; strategy: \"full\" }\n | { key: string; strategy: \"prefix\"; keep: number }\n | { key: string; strategy: \"hash\" };\n\ninterface RedactionState {\n findings: RedactionFinding[];\n seen: WeakMap<object, unknown>;\n}\n\ninterface PatternDetectorOptions {\n id: string;\n pattern: RegExp;\n severity?: RedactionSeverity;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n\nfunction toKey(key: string): string {\n return key.toLowerCase();\n}\n\nfunction findCompiledKeyRule(\n key: string,\n rules: readonly CompiledRule[],\n): CompiledRule | undefined {\n const exact = toKey(key);\n const direct = rules.find((candidate) => candidate.key === exact);\n if (direct) return direct;\n return rules.find((candidate) => isCredentialSensitiveKey(key, [candidate.key]));\n}\n\nfunction stableHash(value: string): string {\n const hash = crypto.createHash(\"sha256\").update(value, \"utf8\").digest(\"hex\");\n return hash.slice(0, 8);\n}\n\nfunction stringifyScalar(value: unknown): string | undefined {\n if (typeof value === \"string\") return value;\n if (typeof value === \"number\" || typeof value === \"boolean\" || typeof value === \"bigint\") {\n return String(value);\n }\n return undefined;\n}\n\nfunction patternDetector(options: PatternDetectorOptions): RedactionDetector {\n return {\n id: options.id,\n severity: options.severity ?? \"warning\",\n matchKind: \"value\",\n detect(input) {\n if (typeof input.value !== \"string\") return [];\n options.pattern.lastIndex = 0;\n return options.pattern.test(input.value)\n ? [{ action: \"replace\", severity: options.severity ?? \"warning\", matchKind: \"value\" }]\n : [];\n },\n };\n}\n\nfunction digitsOnly(value: string): string {\n return value.replace(/\\D/g, \"\");\n}\n\nfunction passesLuhn(value: string): boolean {\n const digits = digitsOnly(value);\n if (digits.length < 13 || digits.length > 19) return false;\n\n let sum = 0;\n let double = false;\n for (let i = digits.length - 1; i >= 0; i -= 1) {\n let digit = Number(digits[i]);\n if (double) {\n digit *= 2;\n if (digit > 9) digit -= 9;\n }\n sum += digit;\n double = !double;\n }\n return sum % 10 === 0;\n}\n\nconst UUID_RE =\n /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;\n\n/** 13-digit Unix epoch milliseconds in a plausible modern range. */\nconst EPOCH_MS_RE = /^1[0-9]{12}$/;\n\nconst EMAIL_RE = /\\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,}\\b/gi;\n\nfunction pathSuggestsNonCard(path: string): boolean {\n const normalized = path.toLowerCase().replace(/[^a-z0-9._]/g, \"\");\n return (\n /(^|\\.)(tokenusage|usage)(\\.|$)/.test(normalized) ||\n /(startedat|endedat|durationms|timestamp|createdat|updatedat)(\\.|$)/.test(normalized) ||\n /(^|\\.)(runid|traceid|spanid|eventid|sessionid|userid|parentid|requestid|correlationid)(\\.|$)/.test(\n normalized,\n ) ||\n /(^|\\.)ts(\\.|$)/.test(normalized)\n );\n}\n\nfunction isUuidLike(value: string): boolean {\n return UUID_RE.test(value.trim());\n}\n\nfunction isPlausibleCardCandidate(candidate: string, fullValue: string): boolean {\n const digits = digitsOnly(candidate);\n if (digits.length < 13 || digits.length > 19) return false;\n if (!passesLuhn(candidate)) return false;\n\n const trimmed = fullValue.trim();\n if (isUuidLike(trimmed)) return false;\n\n // Naked epoch-ms timestamps are not PANs.\n if (EPOCH_MS_RE.test(digits) && digitsOnly(trimmed) === digits && /^\\d+$/.test(trimmed)) {\n return false;\n }\n\n // Reject candidates glued inside longer alphanumeric IDs without card separators.\n const start = fullValue.indexOf(candidate);\n if (start >= 0) {\n const before = fullValue[start - 1];\n const after = fullValue[start + candidate.length];\n if (before && /[A-Za-z0-9_]/.test(before)) return false;\n if (after && /[A-Za-z0-9_]/.test(after)) return false;\n }\n\n return true;\n}\n\nfunction looksLikePathOrPackageOrUrl(value: string): boolean {\n const trimmed = value.trim();\n if (/^(?:[a-z][a-z0-9+.-]*:)?\\/\\//i.test(trimmed)) return true;\n if (/^webpack:/i.test(trimmed)) return true;\n if (/^@[A-Za-z0-9_.-]+\\/[A-Za-z0-9_.@/-]+$/.test(trimmed)) return true;\n if (/^[A-Za-z]:[\\\\/]/.test(trimmed) || /^[/\\\\]/.test(trimmed)) return true;\n // Path-like single token (slashes, no whitespace).\n if (/[\\\\/]/.test(trimmed) && !/\\s/.test(trimmed)) return true;\n return false;\n}\n\nfunction emailMatchIsPathAdjacent(value: string, index: number, length: number): boolean {\n const before = value[index - 1];\n const after = value[index + length];\n return before === \"/\" || before === \"\\\\\" || after === \"/\" || after === \"\\\\\";\n}\n\nfunction valueContainsEmail(value: string): boolean {\n if (looksLikePathOrPackageOrUrl(value)) return false;\n EMAIL_RE.lastIndex = 0;\n for (const match of value.matchAll(EMAIL_RE)) {\n const text = match[0] ?? \"\";\n const index = match.index ?? 0;\n if (emailMatchIsPathAdjacent(value, index, text.length)) continue;\n return true;\n }\n return false;\n}\n\nconst credentialDetectors: readonly RedactionDetector[] = [\n patternDetector({\n id: \"value.authorizationHeader\",\n pattern: /^(?:basic|bearer|digest|apikey)\\s+[a-z0-9._~+/=-]+$/i,\n severity: \"error\",\n }),\n patternDetector({\n id: \"value.bearerToken\",\n pattern: /\\bbearer\\s+[a-z0-9._~+/=-]{12,}\\b/i,\n severity: \"error\",\n }),\n patternDetector({\n id: \"value.cookie\",\n pattern: /\\b[a-z0-9_.-]+=[^;\\s]+(?:;\\s*[a-z0-9_.-]+=[^;\\s]+)+/i,\n severity: \"error\",\n }),\n patternDetector({\n id: \"value.jwt\",\n pattern: /\\beyJ[a-zA-Z0-9_-]{8,}\\.[a-zA-Z0-9_-]{8,}\\.[a-zA-Z0-9_-]{8,}\\b/,\n severity: \"error\",\n }),\n patternDetector({\n id: \"value.providerApiKey\",\n pattern: /\\b(?:sk-(?:proj-)?[a-zA-Z0-9_-]{16,}|sk-ant-[a-zA-Z0-9_-]{16,}|AIza[0-9A-Za-z_-]{20,})\\b/,\n severity: \"error\",\n }),\n patternDetector({\n id: \"value.githubToken\",\n pattern: /\\b(?:ghp|gho|ghu|ghs|ghr)_[A-Za-z0-9_]{20,}\\b/,\n severity: \"error\",\n }),\n patternDetector({\n id: \"value.awsAccessKey\",\n pattern: /\\b(?:AKIA|ASIA)[A-Z0-9]{16}\\b/,\n severity: \"error\",\n }),\n patternDetector({\n id: \"value.privateKey\",\n pattern: /-----BEGIN [A-Z ]*PRIVATE KEY-----[\\s\\S]*-----END [A-Z ]*PRIVATE KEY-----/,\n severity: \"error\",\n }),\n {\n id: \"value.keyValueSecret\",\n severity: \"error\",\n matchKind: \"value\",\n detect(input) {\n if (typeof input.value !== \"string\") return [];\n return valueContainsKeyValueSecret(input.value)\n ? [{ action: \"replace\", severity: \"error\", matchKind: \"value\" }]\n : [];\n },\n },\n {\n id: \"value.creditCard\",\n severity: \"error\",\n matchKind: \"value\",\n detect(input) {\n if (typeof input.value !== \"string\") return [];\n if (pathSuggestsNonCard(input.path)) return [];\n if (isUuidLike(input.value)) return [];\n const candidatePattern = /(?:\\d[ -]?){13,19}/g;\n for (const match of input.value.matchAll(candidatePattern)) {\n const candidate = match[0] ?? \"\";\n if (isPlausibleCardCandidate(candidate, input.value)) {\n return [{ action: \"replace\", severity: \"error\", matchKind: \"value\" }];\n }\n }\n return [];\n },\n },\n];\n\nconst identifierDetectors: readonly RedactionDetector[] = [\n {\n id: \"value.email\",\n severity: \"warning\",\n matchKind: \"value\",\n detect(input) {\n if (typeof input.value !== \"string\") return [];\n return valueContainsEmail(input.value)\n ? [{ action: \"replace\", severity: \"warning\", matchKind: \"value\" }]\n : [];\n },\n },\n patternDetector({\n id: \"value.phone\",\n pattern: /\\b(?:\\+\\d{1,3}[\\s.-]?)?(?:\\(?\\d{3}\\)?[\\s.-])\\d{3}[\\s.-]\\d{4}\\b/,\n }),\n patternDetector({\n id: \"value.ipv4\",\n pattern: /\\b(?:(?:25[0-5]|2[0-4]\\d|1?\\d?\\d)\\.){3}(?:25[0-5]|2[0-4]\\d|1?\\d?\\d)\\b/,\n }),\n patternDetector({\n id: \"value.ipv6\",\n pattern: /\\b(?:[0-9a-f]{1,4}:){2,7}[0-9a-f]{1,4}\\b/i,\n }),\n];\n\nfunction builtInDetectorsForProfile(profile: RedactionProfile): readonly RedactionDetector[] {\n if (profile === \"local\") return credentialDetectors;\n return [...credentialDetectors, ...identifierDetectors];\n}\n\nfunction compileRules(\n rules?: RedactionRule[],\n extraKeys?: readonly string[],\n): CompiledRule[] {\n const out = new Map<string, CompiledRule>();\n\n const set = (rule: CompiledRule) => {\n const key = toKey(rule.key);\n out.set(key, { ...rule, key } as CompiledRule);\n };\n\n for (const key of DEFAULT_REDACT_KEYS) {\n set({ key, strategy: \"full\" });\n }\n\n for (const key of extraKeys ?? []) {\n if (typeof key === \"string\" && key.length > 0) {\n set({ key, strategy: \"full\" });\n }\n }\n\n for (const rule of rules ?? []) {\n if (typeof rule === \"string\") {\n set({ key: rule, strategy: \"full\" });\n continue;\n }\n\n if (rule.strategy === \"full\") set({ key: rule.key, strategy: \"full\" });\n if (rule.strategy === \"hash\") set({ key: rule.key, strategy: \"hash\" });\n if (rule.strategy === \"prefix\") {\n set({\n key: rule.key,\n strategy: \"prefix\",\n keep: typeof rule.keep === \"number\" ? rule.keep : 8,\n });\n }\n }\n\n return [...out.values()];\n}\n\nfunction actionForRule(rule: CompiledRule): RedactionAction {\n if (rule.strategy === \"full\") return \"replace\";\n return rule.strategy;\n}\n\nfunction applyRule(\n rule: CompiledRule,\n value: unknown,\n replacement: string,\n): unknown {\n if (rule.strategy === \"full\") return replacement;\n\n const asString = stringifyScalar(value);\n if (rule.strategy === \"prefix\") {\n if (asString === undefined) return replacement;\n const keep = Math.max(0, Math.floor(rule.keep));\n return asString.length <= keep ? `${asString}…` : `${asString.slice(0, keep)}…`;\n }\n\n if (rule.strategy === \"hash\") {\n if (asString === undefined) return \"[HASH:unknown]\";\n return `[HASH:${stableHash(asString)}]`;\n }\n\n return value;\n}\n\nfunction childPath(path: string, key: string): string {\n if (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(key)) {\n return path ? `${path}.${key}` : key;\n }\n return `${path || \"$\"}[${JSON.stringify(key)}]`;\n}\n\nfunction indexPath(path: string, index: number): string {\n return `${path || \"$\"}[${index}]`;\n}\n\nfunction makeFinding(\n path: string,\n detector: string,\n action: RedactionAction,\n matchKind: RedactionMatchKind,\n severity: RedactionSeverity = \"warning\",\n preview?: string,\n): RedactionFinding {\n return preview === undefined\n ? { path, detector, action, severity, matchKind }\n : { path, detector, action, severity, matchKind, preview };\n}\n\nexport function createRedactionProfile(profile: RedactionProfile = \"local\"): ResolvedRedactionProfile {\n switch (profile) {\n case \"local\":\n return { profile: \"local\", extraKeys: [] };\n case \"share\":\n return {\n profile: \"share\",\n extraKeys: SHARE_PROFILE_EXTRA_KEYS,\n maxMetadataValueLengthCap: 500,\n maxPreviewLengthCap: 200,\n };\n case \"strict\":\n return {\n profile: \"strict\",\n extraKeys: [...SHARE_PROFILE_EXTRA_KEYS, ...STRICT_PROFILE_EXTRA_KEYS],\n maxMetadataValueLengthCap: 200,\n maxPreviewLengthCap: 80,\n };\n }\n}\n\nexport class Redactor {\n readonly #rules: CompiledRule[];\n readonly #detectors: readonly RedactionDetector[];\n readonly #profile: RedactionProfile;\n readonly #replacement: string;\n readonly #maxDepth: number;\n readonly #collectFindings: boolean;\n\n constructor(options?: RedactorOptions) {\n const resolved = createRedactionProfile(options?.profile ?? \"local\");\n this.#profile = resolved.profile;\n this.#rules = compileRules(options?.rules, [\n ...resolved.extraKeys,\n ...(options?.extraKeys ?? []),\n ]);\n this.#detectors = [\n ...builtInDetectorsForProfile(this.#profile),\n ...(options?.detectors ?? []),\n ];\n this.#replacement = options?.replacement ?? \"[REDACTED]\";\n this.#maxDepth = options?.maxDepth ?? 32;\n this.#collectFindings = options?.collectFindings ?? true;\n }\n\n redactValue(key: string, value: unknown): unknown {\n return this.#redactValue(value, key, key, 0, {\n findings: [],\n seen: new WeakMap<object, unknown>(),\n });\n }\n\n redactRecord(record: Record<string, unknown>): Record<string, unknown> {\n return this.redact(record).value as Record<string, unknown>;\n }\n\n redact<T = unknown>(value: T): RedactionResult<T> {\n const state: RedactionState = {\n findings: [],\n seen: new WeakMap<object, unknown>(),\n };\n const redacted = this.#redactValue(value, undefined, \"$\", 0, state);\n return {\n value: redacted as T,\n findings: state.findings,\n redacted: state.findings.some((finding) => finding.action !== \"keep\"),\n profile: this.#profile,\n };\n }\n\n #recordFinding(state: RedactionState, finding: RedactionFinding): void {\n if (this.#collectFindings) state.findings.push(finding);\n }\n\n #redactValue(\n value: unknown,\n key: string | undefined,\n path: string,\n depth: number,\n state: RedactionState,\n ): unknown {\n if (depth > this.#maxDepth) {\n this.#recordFinding(\n state,\n makeFinding(path, \"structure.maxDepth\", \"truncate\", \"value\", \"warning\"),\n );\n return \"[Truncated]\";\n }\n\n if (key !== undefined) {\n const rule = findCompiledKeyRule(key, this.#rules);\n if (rule) {\n this.#recordFinding(\n state,\n makeFinding(path, `key.${rule.key}`, actionForRule(rule), \"key\", \"warning\"),\n );\n return applyRule(rule, value, this.#replacement);\n }\n }\n\n for (const detector of this.#detectors) {\n const detections = detector.detect({ path, key, value });\n for (const detection of detections) {\n const action = detection.action ?? \"replace\";\n this.#recordFinding(\n state,\n makeFinding(\n path,\n detector.id,\n action,\n detection.matchKind ?? detector.matchKind ?? \"custom\",\n detection.severity ?? detector.severity ?? \"warning\",\n detection.preview,\n ),\n );\n if (action !== \"keep\") {\n return detection.replacement ?? this.#replacement;\n }\n }\n }\n\n if (Array.isArray(value)) {\n if (state.seen.has(value)) return state.seen.get(value);\n const out: unknown[] = [];\n state.seen.set(value, out);\n value.forEach((item, index) => {\n out[index] = this.#redactValue(item, undefined, indexPath(path, index), depth + 1, state);\n });\n return out;\n }\n\n if (isRecord(value)) {\n if (state.seen.has(value)) return state.seen.get(value);\n const out: Record<string, unknown> = {};\n state.seen.set(value, out);\n for (const [entryKey, entryValue] of Object.entries(value)) {\n out[entryKey] = this.#redactValue(\n entryValue,\n entryKey,\n childPath(path === \"$\" ? \"\" : path, entryKey),\n depth + 1,\n state,\n );\n }\n return out;\n }\n\n return value;\n }\n}\n\nexport function createRedactor(options?: RedactorOptions): Redactor {\n return new Redactor(options);\n}\n\nexport function redact<T = unknown>(value: T, options?: RedactOptions): RedactionResult<T> {\n return createRedactor(options).redact(value);\n}\n\nexport {\n KEY_VALUE_SECRET_PATTERN,\n KEY_VALUE_SECRET_PATTERN_SOURCE,\n valueContainsKeyValueSecret,\n} from \"./key-value-secret.js\";\n\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-inspect/redact",
3
- "version": "6.17.5",
3
+ "version": "6.17.7",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "description": "Reusable deterministic redaction utilities for local AgentInspect workflows",