Files
openclaw/src/logging/log-tail.test.ts
Agustin Rivera 851294126b Redact Gmail watcher startup args from log tail (#62661)
* fix(logging): redact gmail watcher startup args

* fix(logging): normalize redaction formatting

* fix(logging): harden gmail watcher log redaction

* fix(logging): honor configured log tail redaction

* fix(logging): skip redact pattern resolution when off

* fix(logging): reuse compiled redact regexes

* chore: untrack USER.md (covered by .gitignore)

* chore: untrack USER.md (covered by .gitignore)

* fix(logging): avoid double-resolution in log-tail redaction

* fix(logging): redact across line boundaries for multiline patterns

* fix(logging): guard redactSensitiveLines against empty input

* chore(changelog): add Gmail watcher log redaction entry

---------

Co-authored-by: Devin Robison <drobison@nvidia.com>
2026-04-10 14:07:28 -06:00

57 lines
2.1 KiB
TypeScript

import fs from "node:fs/promises";
import os from "node:os";
import path from "node:path";
import { afterEach, describe, expect, it, vi } from "vitest";
import { resetLogger, setLoggerOverride } from "../logging.js";
const resolvedRedaction = { mode: "tools" as const, patterns: [/custom-secret-[a-z]+/g] };
const { redactSensitiveLinesMock, resolveRedactOptionsMock } = vi.hoisted(() => ({
redactSensitiveLinesMock: vi.fn((lines: string[], options?: unknown) =>
options === resolvedRedaction
? lines.map((line) => line.replace("custom-secret-abcdefghijklmnopqrstuvwxyz", "custom…wxyz"))
: lines,
),
resolveRedactOptionsMock: vi.fn(() => resolvedRedaction),
}));
vi.mock("./redact.js", async () => {
const actual = await vi.importActual<typeof import("./redact.js")>("./redact.js");
return {
...actual,
redactSensitiveLines: (lines: string[], options?: unknown) =>
redactSensitiveLinesMock(lines, options),
resolveRedactOptions: () => resolveRedactOptionsMock(),
};
});
describe("readConfiguredLogTail", () => {
afterEach(() => {
resolveRedactOptionsMock.mockClear();
redactSensitiveLinesMock.mockClear();
resetLogger();
setLoggerOverride(null);
});
it("applies redaction once per request across all returned lines", async () => {
const { readConfiguredLogTail } = await import("./log-tail.js");
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-log-tail-"));
const file = path.join(tempDir, "openclaw-2026-01-22.log");
await fs.writeFile(file, "custom-secret-abcdefghijklmnopqrstuvwxyz\nsecond line\n");
setLoggerOverride({ file });
const result = await readConfiguredLogTail();
expect(resolveRedactOptionsMock).toHaveBeenCalledTimes(1);
expect(redactSensitiveLinesMock).toHaveBeenCalledTimes(1);
expect(redactSensitiveLinesMock).toHaveBeenCalledWith(
["custom-secret-abcdefghijklmnopqrstuvwxyz", "second line"],
resolvedRedaction,
);
expect(result.lines).toEqual(["custom…wxyz", "second line"]);
await fs.rm(tempDir, { recursive: true, force: true });
});
});