All files / src redact.ts

100% Statements 12/12
100% Branches 4/4
100% Functions 2/2
100% Lines 12/12

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32    5x     5x             85x 85x 170x   85x     5x       23x 23x 46x 4x     23x    
import type { LilbeeSettings, SharedConfig } from "./types";
 
export const REDACTED = "[redacted]";
 
/** Key-value pairs whose key smells like a credential, in TOML/JSON/header shapes. */
const SECRET_LINE_PATTERNS: RegExp[] = [
    /\b((?:\w+[_-])?(?:token|api[_-]?key|apikey|secret)\s*[:=]\s*["']?)(?:bearer\s+)?[^"'\s]+/gi,
    /\b(authorization\s*[:=]\s*["']?)(?:bearer\s+)?[^"'\s]+/gi,
];
 
/** Blanks credential values in log/config text while keeping line shape. */
export function redactSecrets(text: string): string {
    let out = text;
    for (const pattern of SECRET_LINE_PATTERNS) {
        out = out.replace(pattern, `$1${REDACTED}`);
    }
    return out;
}
 
const SECRET_SETTING_KEYS = ["manualToken", "hfToken"] as const;
 
/** Returns a copy of the settings with credential fields blanked. */
export function redactSettings(settings: LilbeeSettings & Partial<SharedConfig>): Record<string, unknown> {
    const copy: Record<string, unknown> = { ...settings };
    for (const key of SECRET_SETTING_KEYS) {
        if (typeof copy[key] === "string" && copy[key].length > 0) {
            copy[key] = REDACTED;
        }
    }
    return copy;
}