retestkit 1.4.1 → 1.5.0
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 +59 -40
- package/dist/config.js +8 -8
- package/dist/config.js.map +1 -1
- package/dist/logger.js +1 -1
- package/dist/logger.js.map +1 -1
- package/dist/prompts/index.d.ts +1 -1
- package/dist/prompts/index.d.ts.map +1 -1
- package/dist/prompts/index.js +21 -21
- package/dist/prompts/index.js.map +1 -1
- package/dist/prompts/templates/mcp/retest-crawl.md +7 -0
- package/{src/prompts/templates/mcp/webtest-discover-flows.md → dist/prompts/templates/mcp/retest-discover-flows.md} +1 -1
- package/{src/prompts/templates/mcp/webtest-discover.md → dist/prompts/templates/mcp/retest-discover.md} +2 -2
- package/dist/prompts/templates/mcp/retest-full-workflow.md +12 -0
- package/{src/prompts/templates/mcp/webtest-generate-tests.md → dist/prompts/templates/mcp/retest-generate-tests.md} +1 -1
- package/{src/prompts/templates/mcp/webtest-run-test.md → dist/prompts/templates/mcp/retest-run-test.md} +1 -1
- package/{src/prompts/templates/mcp/webtest-start.md → dist/prompts/templates/mcp/retest-start.md} +1 -1
- package/{src → dist}/prompts/templates/sampling/system-prefix.md +1 -1
- package/dist/resources/index.js +7 -7
- package/dist/resources/index.js.map +1 -1
- package/dist/schemas/config.js +2 -2
- package/dist/schemas/config.js.map +1 -1
- package/dist/security/index.js +1 -1
- package/dist/security/index.js.map +1 -1
- package/dist/server.js +3 -3
- package/dist/server.js.map +1 -1
- package/dist/test-utils/mock-context.js +22 -22
- package/dist/test-utils/mock-context.js.map +1 -1
- package/dist/tools/index.d.ts +1 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +5 -5
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/retest/crawl.d.ts.map +1 -0
- package/dist/tools/{webtest → retest}/crawl.js +7 -7
- package/dist/tools/retest/crawl.js.map +1 -0
- package/dist/tools/retest/discover-features.d.ts.map +1 -0
- package/dist/tools/{webtest → retest}/discover-features.js +6 -6
- package/dist/tools/retest/discover-features.js.map +1 -0
- package/dist/tools/retest/discover-flows.d.ts.map +1 -0
- package/dist/tools/{webtest → retest}/discover-flows.js +6 -6
- package/dist/tools/retest/discover-flows.js.map +1 -0
- package/dist/tools/retest/generate-tests.d.ts.map +1 -0
- package/dist/tools/{webtest → retest}/generate-tests.js +5 -5
- package/dist/tools/retest/generate-tests.js.map +1 -0
- package/dist/tools/retest/index.d.ts.map +1 -0
- package/dist/tools/retest/index.js.map +1 -0
- package/dist/tools/retest/run-test-case.d.ts.map +1 -0
- package/dist/tools/{webtest → retest}/run-test-case.js +3 -3
- package/dist/tools/retest/run-test-case.js.map +1 -0
- package/dist/tools/retest/schemas.d.ts.map +1 -0
- package/dist/tools/retest/schemas.js.map +1 -0
- package/dist/tools/retest/start-analysis.d.ts.map +1 -0
- package/dist/tools/{webtest → retest}/start-analysis.js +5 -5
- package/dist/tools/retest/start-analysis.js.map +1 -0
- package/dist/workspace/index.js +8 -8
- package/dist/workspace/index.js.map +1 -1
- package/dist/workspace/types.d.ts +2 -2
- package/dist/workspace/types.d.ts.map +1 -1
- package/package.json +6 -2
- package/.claude/commands/openspec/apply.md +0 -23
- package/.claude/commands/openspec/archive.md +0 -27
- package/.claude/commands/openspec/proposal.md +0 -28
- package/.gemini/commands/openspec/apply.toml +0 -21
- package/.gemini/commands/openspec/archive.toml +0 -25
- package/.gemini/commands/openspec/proposal.toml +0 -26
- package/.github/prompts/openspec-apply.prompt.md +0 -22
- package/.github/prompts/openspec-archive.prompt.md +0 -26
- package/.github/prompts/openspec-proposal.prompt.md +0 -27
- package/.github/workflows/release.yml +0 -33
- package/.kilocode/workflows/openspec-apply.md +0 -17
- package/.kilocode/workflows/openspec-archive.md +0 -21
- package/.kilocode/workflows/openspec-proposal.md +0 -22
- package/.mcp.json +0 -23
- package/.opencode/command/openspec-apply.md +0 -25
- package/.opencode/command/openspec-archive.md +0 -28
- package/.opencode/command/openspec-proposal.md +0 -30
- package/.roo/commands/openspec-apply.md +0 -20
- package/.roo/commands/openspec-archive.md +0 -24
- package/.roo/commands/openspec-proposal.md +0 -25
- package/.vscode/mcp.json +0 -23
- package/AGENTS.md +0 -18
- package/CLAUDE.md +0 -18
- package/dist/tools/webtest/crawl.d.ts.map +0 -1
- package/dist/tools/webtest/crawl.js.map +0 -1
- package/dist/tools/webtest/discover-features.d.ts.map +0 -1
- package/dist/tools/webtest/discover-features.js.map +0 -1
- package/dist/tools/webtest/discover-flows.d.ts.map +0 -1
- package/dist/tools/webtest/discover-flows.js.map +0 -1
- package/dist/tools/webtest/generate-tests.d.ts.map +0 -1
- package/dist/tools/webtest/generate-tests.js.map +0 -1
- package/dist/tools/webtest/index.d.ts.map +0 -1
- package/dist/tools/webtest/index.js.map +0 -1
- package/dist/tools/webtest/run-test-case.d.ts.map +0 -1
- package/dist/tools/webtest/run-test-case.js.map +0 -1
- package/dist/tools/webtest/schemas.d.ts.map +0 -1
- package/dist/tools/webtest/schemas.js.map +0 -1
- package/dist/tools/webtest/start-analysis.d.ts.map +0 -1
- package/dist/tools/webtest/start-analysis.js.map +0 -1
- package/openspec/AGENTS.md +0 -456
- package/openspec/changes/archive/2025-12-18-add-hybrid-artifact-paths/proposal.md +0 -33
- package/openspec/changes/archive/2025-12-18-add-hybrid-artifact-paths/specs/webtest-resources/spec.md +0 -27
- package/openspec/changes/archive/2025-12-18-add-hybrid-artifact-paths/specs/webtest-tools/spec.md +0 -304
- package/openspec/changes/archive/2025-12-18-add-hybrid-artifact-paths/tasks.md +0 -43
- package/openspec/changes/archive/2025-12-18-add-mcp-server-foundation/design.md +0 -209
- package/openspec/changes/archive/2025-12-18-add-mcp-server-foundation/proposal.md +0 -41
- package/openspec/changes/archive/2025-12-18-add-mcp-server-foundation/specs/mcp-server-core/spec.md +0 -183
- package/openspec/changes/archive/2025-12-18-add-mcp-server-foundation/tasks.md +0 -112
- package/openspec/changes/archive/2025-12-18-add-webtest-orchestrator/design.md +0 -333
- package/openspec/changes/archive/2025-12-18-add-webtest-orchestrator/proposal.md +0 -66
- package/openspec/changes/archive/2025-12-18-add-webtest-orchestrator/specs/mcp-server-core/spec.md +0 -129
- package/openspec/changes/archive/2025-12-18-add-webtest-orchestrator/specs/webtest-lifecycle/spec.md +0 -138
- package/openspec/changes/archive/2025-12-18-add-webtest-orchestrator/specs/webtest-logging/spec.md +0 -211
- package/openspec/changes/archive/2025-12-18-add-webtest-orchestrator/specs/webtest-prompts/spec.md +0 -157
- package/openspec/changes/archive/2025-12-18-add-webtest-orchestrator/specs/webtest-resources/spec.md +0 -213
- package/openspec/changes/archive/2025-12-18-add-webtest-orchestrator/specs/webtest-sampling/spec.md +0 -257
- package/openspec/changes/archive/2025-12-18-add-webtest-orchestrator/specs/webtest-tools/spec.md +0 -501
- package/openspec/changes/archive/2025-12-18-add-webtest-orchestrator/tasks.md +0 -264
- package/openspec/changes/archive/2025-12-18-allow-analysis-of-incomplete-crawls/proposal.md +0 -24
- package/openspec/changes/archive/2025-12-18-allow-analysis-of-incomplete-crawls/specs/webtest-tools/spec.md +0 -80
- package/openspec/changes/archive/2025-12-18-allow-analysis-of-incomplete-crawls/tasks.md +0 -8
- package/openspec/changes/archive/2025-12-18-fix-crawl-loop-stability/design.md +0 -90
- package/openspec/changes/archive/2025-12-18-fix-crawl-loop-stability/proposal.md +0 -28
- package/openspec/changes/archive/2025-12-18-fix-crawl-loop-stability/specs/webtest-sampling/spec.md +0 -90
- package/openspec/changes/archive/2025-12-18-fix-crawl-loop-stability/tasks.md +0 -33
- package/openspec/changes/archive/2025-12-18-use-markdown-artifacts/design.md +0 -558
- package/openspec/changes/archive/2025-12-18-use-markdown-artifacts/proposal.md +0 -119
- package/openspec/changes/archive/2025-12-18-use-markdown-artifacts/specs/webtest-resources/spec.md +0 -109
- package/openspec/changes/archive/2025-12-18-use-markdown-artifacts/specs/webtest-tools/spec.md +0 -121
- package/openspec/changes/archive/2025-12-18-use-markdown-artifacts/tasks.md +0 -133
- package/openspec/changes/extract-prompts-to-markdown/design.md +0 -86
- package/openspec/changes/extract-prompts-to-markdown/proposal.md +0 -50
- package/openspec/changes/extract-prompts-to-markdown/specs/webtest-prompts/spec.md +0 -74
- package/openspec/changes/extract-prompts-to-markdown/tasks.md +0 -40
- package/openspec/changes/refactor-webtest-naming/design.md +0 -95
- package/openspec/changes/refactor-webtest-naming/proposal.md +0 -66
- package/openspec/changes/refactor-webtest-naming/specs/webtest-prompts/spec.md +0 -79
- package/openspec/changes/refactor-webtest-naming/specs/webtest-resources/spec.md +0 -80
- package/openspec/changes/refactor-webtest-naming/specs/webtest-sampling/spec.md +0 -122
- package/openspec/changes/refactor-webtest-naming/specs/webtest-tools/spec.md +0 -113
- package/openspec/changes/refactor-webtest-naming/tasks.md +0 -119
- package/openspec/changes/rename-package-to-retest/proposal.md +0 -52
- package/openspec/changes/rename-package-to-retest/specs/mcp-server-core/spec.md +0 -53
- package/openspec/changes/rename-package-to-retest/specs/retest-lifecycle/spec.md +0 -68
- package/openspec/changes/rename-package-to-retest/specs/retest-logging/spec.md +0 -35
- package/openspec/changes/rename-package-to-retest/specs/retest-prompts/spec.md +0 -159
- package/openspec/changes/rename-package-to-retest/specs/retest-resources/spec.md +0 -251
- package/openspec/changes/rename-package-to-retest/specs/retest-sampling/spec.md +0 -99
- package/openspec/changes/rename-package-to-retest/specs/retest-tools/spec.md +0 -295
- package/openspec/changes/rename-package-to-retest/tasks.md +0 -71
- package/openspec/project.md +0 -31
- package/openspec/specs/mcp-server-core/spec.md +0 -178
- package/openspec/specs/webtest-lifecycle/spec.md +0 -136
- package/openspec/specs/webtest-logging/spec.md +0 -209
- package/openspec/specs/webtest-prompts/spec.md +0 -155
- package/openspec/specs/webtest-resources/spec.md +0 -248
- package/openspec/specs/webtest-sampling/spec.md +0 -344
- package/openspec/specs/webtest-tools/spec.md +0 -282
- package/release.config.js +0 -9
- package/src/config.test.ts +0 -96
- package/src/config.ts +0 -32
- package/src/elicitation/index.test.ts +0 -399
- package/src/elicitation/index.ts +0 -171
- package/src/elicitation/types.ts +0 -68
- package/src/index.ts +0 -83
- package/src/lifecycle/index.test.ts +0 -260
- package/src/lifecycle/index.ts +0 -101
- package/src/logger.redaction.test.ts +0 -322
- package/src/logger.test.ts +0 -123
- package/src/logger.ts +0 -229
- package/src/playwright-client/index.ts +0 -392
- package/src/playwright-client/types.ts +0 -99
- package/src/progress/index.test.ts +0 -327
- package/src/progress/index.ts +0 -170
- package/src/progress/types.ts +0 -25
- package/src/prompts/index.test.ts +0 -451
- package/src/prompts/index.ts +0 -246
- package/src/prompts/loader.test.ts +0 -100
- package/src/prompts/loader.ts +0 -59
- package/src/prompts/templates/mcp/webtest-crawl.md +0 -7
- package/src/prompts/templates/mcp/webtest-full-workflow.md +0 -12
- package/src/resources/index.ts +0 -250
- package/src/resources/subscriptions.ts +0 -37
- package/src/sampling/index.test.ts +0 -414
- package/src/sampling/index.ts +0 -286
- package/src/sampling/prompts.ts +0 -194
- package/src/sampling/types.ts +0 -60
- package/src/schemas/config.ts +0 -39
- package/src/security/index.test.ts +0 -441
- package/src/security/index.ts +0 -361
- package/src/security/security-scenarios.test.ts +0 -468
- package/src/server.ts +0 -211
- package/src/test-utils/index.ts +0 -6
- package/src/test-utils/mock-context.ts +0 -426
- package/src/test-utils/mock-playwright-client.ts +0 -422
- package/src/tools/index.ts +0 -11
- package/src/tools/webtest/crawl.test.ts +0 -834
- package/src/tools/webtest/crawl.ts +0 -901
- package/src/tools/webtest/discover-features.ts +0 -412
- package/src/tools/webtest/discover-flows.ts +0 -408
- package/src/tools/webtest/generate-tests.test.ts +0 -532
- package/src/tools/webtest/generate-tests.ts +0 -425
- package/src/tools/webtest/index.ts +0 -7
- package/src/tools/webtest/integration.test.ts +0 -536
- package/src/tools/webtest/run-test-case.test.ts +0 -659
- package/src/tools/webtest/run-test-case.ts +0 -508
- package/src/tools/webtest/schemas.ts +0 -201
- package/src/tools/webtest/start-analysis.test.ts +0 -151
- package/src/tools/webtest/start-analysis.ts +0 -158
- package/src/transports/http.ts +0 -19
- package/src/transports/index.ts +0 -30
- package/src/transports/stdio.ts +0 -7
- package/src/types/capabilities.test.ts +0 -193
- package/src/types/capabilities.ts +0 -50
- package/src/types/context.ts +0 -21
- package/src/types/tool.ts +0 -11
- package/src/workspace/index.ts +0 -945
- package/src/workspace/markdown.ts +0 -272
- package/src/workspace/types.ts +0 -186
- package/tests/integration/server.test.ts +0 -89
- package/tests/integration/tools.test.ts +0 -99
- package/tsconfig.json +0 -20
- package/vitest.config.ts +0 -9
- package/vitest.integration.config.ts +0 -10
- /package/{src → dist}/prompts/templates/sampling/crawl-action.md +0 -0
- /package/{src → dist}/prompts/templates/sampling/feature-discovery.md +0 -0
- /package/{src → dist}/prompts/templates/sampling/flow-discovery.md +0 -0
- /package/{src → dist}/prompts/templates/sampling/page-content-wrapper.md +0 -0
- /package/{src → dist}/prompts/templates/sampling/test-evaluation.md +0 -0
- /package/{src → dist}/prompts/templates/sampling/test-generation.md +0 -0
- /package/dist/tools/{webtest → retest}/crawl.d.ts +0 -0
- /package/dist/tools/{webtest → retest}/discover-features.d.ts +0 -0
- /package/dist/tools/{webtest → retest}/discover-flows.d.ts +0 -0
- /package/dist/tools/{webtest → retest}/generate-tests.d.ts +0 -0
- /package/dist/tools/{webtest → retest}/index.d.ts +0 -0
- /package/dist/tools/{webtest → retest}/index.js +0 -0
- /package/dist/tools/{webtest → retest}/run-test-case.d.ts +0 -0
- /package/dist/tools/{webtest → retest}/schemas.d.ts +0 -0
- /package/dist/tools/{webtest → retest}/schemas.js +0 -0
- /package/dist/tools/{webtest → retest}/start-analysis.d.ts +0 -0
|
@@ -1,322 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Sensitive Data Redaction Tests (Phase 11.4)
|
|
3
|
-
*
|
|
4
|
-
* Tests for:
|
|
5
|
-
* - URL params with sensitive keys redacted
|
|
6
|
-
* - Cookie values redacted in logs
|
|
7
|
-
* - Password input values redacted
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
|
11
|
-
import { createLogger } from "./logger.js";
|
|
12
|
-
|
|
13
|
-
describe("Sensitive Data Redaction", () => {
|
|
14
|
-
let stderrWrite: ReturnType<typeof vi.spyOn>;
|
|
15
|
-
let output: string[];
|
|
16
|
-
|
|
17
|
-
beforeEach(() => {
|
|
18
|
-
output = [];
|
|
19
|
-
stderrWrite = vi
|
|
20
|
-
.spyOn(process.stderr, "write")
|
|
21
|
-
.mockImplementation((chunk: string | Uint8Array) => {
|
|
22
|
-
output.push(chunk.toString());
|
|
23
|
-
return true;
|
|
24
|
-
});
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
afterEach(() => {
|
|
28
|
-
stderrWrite.mockRestore();
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
describe("URL Parameter Redaction (11.4.1)", () => {
|
|
32
|
-
it("redacts password in URL params object", () => {
|
|
33
|
-
const logger = createLogger("info");
|
|
34
|
-
logger.info("User request", {
|
|
35
|
-
urlParams: { username: "alice", password: "secret123" },
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
const entry = JSON.parse(output[0]);
|
|
39
|
-
expect(entry.data.urlParams.username).toBe("alice");
|
|
40
|
-
expect(entry.data.urlParams.password).toBe("[REDACTED]");
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
it("redacts token in URL params object", () => {
|
|
44
|
-
const logger = createLogger("info");
|
|
45
|
-
logger.info("API request", {
|
|
46
|
-
params: { action: "login", token: "abc123xyz" },
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
const entry = JSON.parse(output[0]);
|
|
50
|
-
expect(entry.data.params.action).toBe("login");
|
|
51
|
-
expect(entry.data.params.token).toBe("[REDACTED]");
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
it("redacts apiKey in URL params object", () => {
|
|
55
|
-
const logger = createLogger("info");
|
|
56
|
-
logger.info("API request", {
|
|
57
|
-
queryParams: { endpoint: "/users", apiKey: "sk-123456" },
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
const entry = JSON.parse(output[0]);
|
|
61
|
-
expect(entry.data.queryParams.endpoint).toBe("/users");
|
|
62
|
-
expect(entry.data.queryParams.apiKey).toBe("[REDACTED]");
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
it("redacts auth params in deeply nested objects", () => {
|
|
66
|
-
const logger = createLogger("info");
|
|
67
|
-
logger.info("Request details", {
|
|
68
|
-
request: {
|
|
69
|
-
path: "/api/users",
|
|
70
|
-
query: {
|
|
71
|
-
safe: "value",
|
|
72
|
-
token: "sensitive-token",
|
|
73
|
-
},
|
|
74
|
-
},
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
const entry = JSON.parse(output[0]);
|
|
78
|
-
expect(entry.data.request.path).toBe("/api/users");
|
|
79
|
-
expect(entry.data.request.query.safe).toBe("value");
|
|
80
|
-
expect(entry.data.request.query.token).toBe("[REDACTED]");
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
it("redacts secret key variations", () => {
|
|
84
|
-
const logger = createLogger("info");
|
|
85
|
-
logger.info("Config", {
|
|
86
|
-
secret: "mySecret",
|
|
87
|
-
secretKey: "mySecretKey",
|
|
88
|
-
privateKey: "myPrivateKey",
|
|
89
|
-
accessToken: "myAccessToken",
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
const entry = JSON.parse(output[0]);
|
|
93
|
-
expect(entry.data.secret).toBe("[REDACTED]");
|
|
94
|
-
expect(entry.data.secretKey).toBe("[REDACTED]");
|
|
95
|
-
// Note: these depend on exact implementation - testing what's in the actual patterns
|
|
96
|
-
});
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
describe("Cookie Value Redaction (11.4.2)", () => {
|
|
100
|
-
it("redacts cookie field in data object", () => {
|
|
101
|
-
const logger = createLogger("info");
|
|
102
|
-
logger.info("Browser cookies", {
|
|
103
|
-
cookie: "session=abc123; auth=xyz789",
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
const entry = JSON.parse(output[0]);
|
|
107
|
-
expect(entry.data.cookie).toBe("[REDACTED]");
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
it("redacts cookies field in data object", () => {
|
|
111
|
-
const logger = createLogger("info");
|
|
112
|
-
logger.info("Request headers", {
|
|
113
|
-
headers: {
|
|
114
|
-
"content-type": "application/json",
|
|
115
|
-
cookies: "session=abc123",
|
|
116
|
-
},
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
const entry = JSON.parse(output[0]);
|
|
120
|
-
expect(entry.data.headers["content-type"]).toBe("application/json");
|
|
121
|
-
// Check if cookies is redacted (depends on implementation)
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
it("redacts session ID in nested object", () => {
|
|
125
|
-
const logger = createLogger("info");
|
|
126
|
-
logger.info("Session data", {
|
|
127
|
-
user: {
|
|
128
|
-
id: 123,
|
|
129
|
-
sessionId: "sess_abc123xyz",
|
|
130
|
-
},
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
const entry = JSON.parse(output[0]);
|
|
134
|
-
expect(entry.data.user.id).toBe(123);
|
|
135
|
-
// sessionId may or may not be redacted depending on patterns
|
|
136
|
-
});
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
describe("Password Input Value Redaction (11.4.3)", () => {
|
|
140
|
-
it("redacts password field at top level", () => {
|
|
141
|
-
const logger = createLogger("info");
|
|
142
|
-
logger.info("Login attempt", {
|
|
143
|
-
username: "alice",
|
|
144
|
-
password: "SuperSecret123!",
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
const entry = JSON.parse(output[0]);
|
|
148
|
-
expect(entry.data.username).toBe("alice");
|
|
149
|
-
expect(entry.data.password).toBe("[REDACTED]");
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
it("redacts password in form data", () => {
|
|
153
|
-
const logger = createLogger("info");
|
|
154
|
-
logger.info("Form submission", {
|
|
155
|
-
formData: {
|
|
156
|
-
email: "test@example.com",
|
|
157
|
-
password: "MyPassword123",
|
|
158
|
-
rememberMe: true,
|
|
159
|
-
},
|
|
160
|
-
});
|
|
161
|
-
|
|
162
|
-
const entry = JSON.parse(output[0]);
|
|
163
|
-
expect(entry.data.formData.email).toBe("test@example.com");
|
|
164
|
-
expect(entry.data.formData.password).toBe("[REDACTED]");
|
|
165
|
-
expect(entry.data.formData.rememberMe).toBe(true);
|
|
166
|
-
});
|
|
167
|
-
|
|
168
|
-
it("redacts password confirmation field", () => {
|
|
169
|
-
const logger = createLogger("info");
|
|
170
|
-
logger.info("Registration", {
|
|
171
|
-
email: "user@example.com",
|
|
172
|
-
password: "NewPass123",
|
|
173
|
-
passwordConfirm: "NewPass123",
|
|
174
|
-
});
|
|
175
|
-
|
|
176
|
-
const entry = JSON.parse(output[0]);
|
|
177
|
-
expect(entry.data.email).toBe("user@example.com");
|
|
178
|
-
expect(entry.data.password).toBe("[REDACTED]");
|
|
179
|
-
// passwordConfirm might also be redacted
|
|
180
|
-
});
|
|
181
|
-
|
|
182
|
-
it("redacts authorization header", () => {
|
|
183
|
-
const logger = createLogger("info");
|
|
184
|
-
logger.info("API call", {
|
|
185
|
-
headers: {
|
|
186
|
-
authorization: "Bearer eyJhbGciOiJIUzI1NiIs...",
|
|
187
|
-
"content-type": "application/json",
|
|
188
|
-
},
|
|
189
|
-
});
|
|
190
|
-
|
|
191
|
-
const entry = JSON.parse(output[0]);
|
|
192
|
-
expect(entry.data.headers.authorization).toBe("[REDACTED]");
|
|
193
|
-
expect(entry.data.headers["content-type"]).toBe("application/json");
|
|
194
|
-
});
|
|
195
|
-
|
|
196
|
-
it("redacts credential in any position", () => {
|
|
197
|
-
const logger = createLogger("info");
|
|
198
|
-
logger.info("Auth flow", {
|
|
199
|
-
step1: { user: "admin", password: "secret" },
|
|
200
|
-
step2: { verified: true },
|
|
201
|
-
});
|
|
202
|
-
|
|
203
|
-
const entry = JSON.parse(output[0]);
|
|
204
|
-
expect(entry.data.step1.user).toBe("admin");
|
|
205
|
-
expect(entry.data.step1.password).toBe("[REDACTED]");
|
|
206
|
-
expect(entry.data.step2.verified).toBe(true);
|
|
207
|
-
});
|
|
208
|
-
});
|
|
209
|
-
|
|
210
|
-
describe("Non-Sensitive Data Preservation", () => {
|
|
211
|
-
it("preserves non-sensitive URL params", () => {
|
|
212
|
-
const logger = createLogger("info");
|
|
213
|
-
logger.info("Page request", {
|
|
214
|
-
url: "https://example.com/page",
|
|
215
|
-
params: {
|
|
216
|
-
page: 1,
|
|
217
|
-
sort: "name",
|
|
218
|
-
filter: "active",
|
|
219
|
-
},
|
|
220
|
-
});
|
|
221
|
-
|
|
222
|
-
const entry = JSON.parse(output[0]);
|
|
223
|
-
expect(entry.data.url).toBe("https://example.com/page");
|
|
224
|
-
expect(entry.data.params.page).toBe(1);
|
|
225
|
-
expect(entry.data.params.sort).toBe("name");
|
|
226
|
-
expect(entry.data.params.filter).toBe("active");
|
|
227
|
-
});
|
|
228
|
-
|
|
229
|
-
it("preserves user data except password", () => {
|
|
230
|
-
const logger = createLogger("info");
|
|
231
|
-
logger.info("User profile", {
|
|
232
|
-
user: {
|
|
233
|
-
name: "John Doe",
|
|
234
|
-
email: "john@example.com",
|
|
235
|
-
role: "admin",
|
|
236
|
-
createdAt: "2024-01-01",
|
|
237
|
-
},
|
|
238
|
-
});
|
|
239
|
-
|
|
240
|
-
const entry = JSON.parse(output[0]);
|
|
241
|
-
expect(entry.data.user.name).toBe("John Doe");
|
|
242
|
-
expect(entry.data.user.email).toBe("john@example.com");
|
|
243
|
-
expect(entry.data.user.role).toBe("admin");
|
|
244
|
-
});
|
|
245
|
-
|
|
246
|
-
it("preserves arrays of non-sensitive data", () => {
|
|
247
|
-
const logger = createLogger("info");
|
|
248
|
-
logger.info("Items list", {
|
|
249
|
-
items: [
|
|
250
|
-
{ id: 1, name: "Item 1" },
|
|
251
|
-
{ id: 2, name: "Item 2" },
|
|
252
|
-
],
|
|
253
|
-
});
|
|
254
|
-
|
|
255
|
-
const entry = JSON.parse(output[0]);
|
|
256
|
-
expect(entry.data.items).toHaveLength(2);
|
|
257
|
-
expect(entry.data.items[0].name).toBe("Item 1");
|
|
258
|
-
});
|
|
259
|
-
|
|
260
|
-
it("preserves numeric and boolean values", () => {
|
|
261
|
-
const logger = createLogger("info");
|
|
262
|
-
logger.info("Metrics", {
|
|
263
|
-
count: 42,
|
|
264
|
-
enabled: true,
|
|
265
|
-
ratio: 0.75,
|
|
266
|
-
});
|
|
267
|
-
|
|
268
|
-
const entry = JSON.parse(output[0]);
|
|
269
|
-
expect(entry.data.count).toBe(42);
|
|
270
|
-
expect(entry.data.enabled).toBe(true);
|
|
271
|
-
expect(entry.data.ratio).toBe(0.75);
|
|
272
|
-
});
|
|
273
|
-
});
|
|
274
|
-
|
|
275
|
-
describe("Edge Cases", () => {
|
|
276
|
-
it("handles null values gracefully", () => {
|
|
277
|
-
const logger = createLogger("info");
|
|
278
|
-
logger.info("Null test", {
|
|
279
|
-
value: null,
|
|
280
|
-
password: null,
|
|
281
|
-
});
|
|
282
|
-
|
|
283
|
-
const entry = JSON.parse(output[0]);
|
|
284
|
-
expect(entry.data.value).toBeNull();
|
|
285
|
-
// null password might still be redacted or kept as null
|
|
286
|
-
});
|
|
287
|
-
|
|
288
|
-
it("handles undefined values gracefully", () => {
|
|
289
|
-
const logger = createLogger("info");
|
|
290
|
-
logger.info("Undefined test", {
|
|
291
|
-
value: undefined,
|
|
292
|
-
});
|
|
293
|
-
|
|
294
|
-
const entry = JSON.parse(output[0]);
|
|
295
|
-
// undefined may be omitted or serialized as null
|
|
296
|
-
});
|
|
297
|
-
|
|
298
|
-
it("handles empty strings", () => {
|
|
299
|
-
const logger = createLogger("info");
|
|
300
|
-
logger.info("Empty test", {
|
|
301
|
-
password: "",
|
|
302
|
-
name: "",
|
|
303
|
-
});
|
|
304
|
-
|
|
305
|
-
const entry = JSON.parse(output[0]);
|
|
306
|
-
expect(entry.data.password).toBe("[REDACTED]");
|
|
307
|
-
expect(entry.data.name).toBe("");
|
|
308
|
-
});
|
|
309
|
-
|
|
310
|
-
it("handles special characters in values", () => {
|
|
311
|
-
const logger = createLogger("info");
|
|
312
|
-
logger.info("Special chars", {
|
|
313
|
-
query: 'SELECT * FROM users WHERE name = "test"',
|
|
314
|
-
json: '{"key": "value"}',
|
|
315
|
-
});
|
|
316
|
-
|
|
317
|
-
const entry = JSON.parse(output[0]);
|
|
318
|
-
expect(entry.data.query).toContain("SELECT");
|
|
319
|
-
expect(entry.data.json).toContain("key");
|
|
320
|
-
});
|
|
321
|
-
});
|
|
322
|
-
});
|
package/src/logger.test.ts
DELETED
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
|
2
|
-
import { createLogger } from "./logger.js";
|
|
3
|
-
|
|
4
|
-
describe("logger", () => {
|
|
5
|
-
let stderrWrite: ReturnType<typeof vi.spyOn>;
|
|
6
|
-
let output: string[];
|
|
7
|
-
|
|
8
|
-
beforeEach(() => {
|
|
9
|
-
output = [];
|
|
10
|
-
stderrWrite = vi
|
|
11
|
-
.spyOn(process.stderr, "write")
|
|
12
|
-
.mockImplementation((chunk: string | Uint8Array) => {
|
|
13
|
-
output.push(chunk.toString());
|
|
14
|
-
return true;
|
|
15
|
-
});
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
afterEach(() => {
|
|
19
|
-
stderrWrite.mockRestore();
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
describe("log levels", () => {
|
|
23
|
-
it("logs info messages at info level", () => {
|
|
24
|
-
const logger = createLogger("info");
|
|
25
|
-
logger.info("test message");
|
|
26
|
-
expect(output.length).toBe(1);
|
|
27
|
-
const entry = JSON.parse(output[0]);
|
|
28
|
-
expect(entry.level).toBe("info");
|
|
29
|
-
expect(entry.message).toBe("test message");
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
it("does not log debug messages at info level", () => {
|
|
33
|
-
const logger = createLogger("info");
|
|
34
|
-
logger.debug("debug message");
|
|
35
|
-
expect(output.length).toBe(0);
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
it("logs debug messages at debug level", () => {
|
|
39
|
-
const logger = createLogger("debug");
|
|
40
|
-
logger.debug("debug message");
|
|
41
|
-
expect(output.length).toBe(1);
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
it("logs error messages at all levels", () => {
|
|
45
|
-
const logger = createLogger("error");
|
|
46
|
-
logger.error("error message");
|
|
47
|
-
expect(output.length).toBe(1);
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
it("does not log warn at error level", () => {
|
|
51
|
-
const logger = createLogger("error");
|
|
52
|
-
logger.warn("warn message");
|
|
53
|
-
expect(output.length).toBe(0);
|
|
54
|
-
});
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
describe("structured output", () => {
|
|
58
|
-
it("outputs valid JSON", () => {
|
|
59
|
-
const logger = createLogger("info");
|
|
60
|
-
logger.info("test");
|
|
61
|
-
expect(() => JSON.parse(output[0])).not.toThrow();
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
it("includes timestamp", () => {
|
|
65
|
-
const logger = createLogger("info");
|
|
66
|
-
logger.info("test");
|
|
67
|
-
const entry = JSON.parse(output[0]);
|
|
68
|
-
expect(entry.timestamp).toBeDefined();
|
|
69
|
-
expect(new Date(entry.timestamp).getTime()).not.toBeNaN();
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
it("includes data when provided", () => {
|
|
73
|
-
const logger = createLogger("info");
|
|
74
|
-
logger.info("test", { key: "value" });
|
|
75
|
-
const entry = JSON.parse(output[0]);
|
|
76
|
-
expect(entry.data).toEqual({ key: "value" });
|
|
77
|
-
});
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
describe("secret redaction", () => {
|
|
81
|
-
it("redacts password field", () => {
|
|
82
|
-
const logger = createLogger("info");
|
|
83
|
-
logger.info("test", { password: "secret123" });
|
|
84
|
-
const entry = JSON.parse(output[0]);
|
|
85
|
-
expect(entry.data.password).toBe("[REDACTED]");
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
it("redacts token field", () => {
|
|
89
|
-
const logger = createLogger("info");
|
|
90
|
-
logger.info("test", { token: "abc123" });
|
|
91
|
-
const entry = JSON.parse(output[0]);
|
|
92
|
-
expect(entry.data.token).toBe("[REDACTED]");
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
it("redacts apiKey field", () => {
|
|
96
|
-
const logger = createLogger("info");
|
|
97
|
-
logger.info("test", { apiKey: "key123" });
|
|
98
|
-
const entry = JSON.parse(output[0]);
|
|
99
|
-
expect(entry.data.apiKey).toBe("[REDACTED]");
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
it("redacts authorization field", () => {
|
|
103
|
-
const logger = createLogger("info");
|
|
104
|
-
logger.info("test", { authorization: "Bearer token" });
|
|
105
|
-
const entry = JSON.parse(output[0]);
|
|
106
|
-
expect(entry.data.authorization).toBe("[REDACTED]");
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
it("redacts nested sensitive fields", () => {
|
|
110
|
-
const logger = createLogger("info");
|
|
111
|
-
logger.info("test", { user: { password: "secret" } });
|
|
112
|
-
const entry = JSON.parse(output[0]);
|
|
113
|
-
expect(entry.data.user.password).toBe("[REDACTED]");
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
it("does not redact non-sensitive fields", () => {
|
|
117
|
-
const logger = createLogger("info");
|
|
118
|
-
logger.info("test", { username: "alice" });
|
|
119
|
-
const entry = JSON.parse(output[0]);
|
|
120
|
-
expect(entry.data.username).toBe("alice");
|
|
121
|
-
});
|
|
122
|
-
});
|
|
123
|
-
});
|
package/src/logger.ts
DELETED
|
@@ -1,229 +0,0 @@
|
|
|
1
|
-
import type { LogLevel } from "./schemas/config.js";
|
|
2
|
-
|
|
3
|
-
const LOG_LEVELS: Record<LogLevel, number> = {
|
|
4
|
-
debug: 0,
|
|
5
|
-
info: 1,
|
|
6
|
-
warn: 2,
|
|
7
|
-
error: 3,
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
const MCP_LOG_LEVELS: Record<LogLevel, string> = {
|
|
11
|
-
debug: "debug",
|
|
12
|
-
info: "info",
|
|
13
|
-
warn: "warning",
|
|
14
|
-
error: "error",
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
const REDACT_KEYS = [
|
|
18
|
-
"password",
|
|
19
|
-
"token",
|
|
20
|
-
"secret",
|
|
21
|
-
"apikey",
|
|
22
|
-
"authorization",
|
|
23
|
-
"api_key",
|
|
24
|
-
"access_token",
|
|
25
|
-
"refresh_token",
|
|
26
|
-
"cookie",
|
|
27
|
-
"session",
|
|
28
|
-
"credential",
|
|
29
|
-
];
|
|
30
|
-
|
|
31
|
-
const SENSITIVE_URL_PARAMS = [
|
|
32
|
-
"password",
|
|
33
|
-
"token",
|
|
34
|
-
"secret",
|
|
35
|
-
"key",
|
|
36
|
-
"auth",
|
|
37
|
-
"session",
|
|
38
|
-
"code",
|
|
39
|
-
"state",
|
|
40
|
-
];
|
|
41
|
-
|
|
42
|
-
const MAX_HTML_LOG_LENGTH = 500;
|
|
43
|
-
|
|
44
|
-
function shouldRedact(key: string): boolean {
|
|
45
|
-
const lowerKey = key.toLowerCase();
|
|
46
|
-
return REDACT_KEYS.some((redactKey) => lowerKey.includes(redactKey));
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
function redactUrlParams(url: string): string {
|
|
50
|
-
try {
|
|
51
|
-
const parsed = new URL(url);
|
|
52
|
-
for (const param of SENSITIVE_URL_PARAMS) {
|
|
53
|
-
if (parsed.searchParams.has(param)) {
|
|
54
|
-
parsed.searchParams.set(param, "[REDACTED]");
|
|
55
|
-
}
|
|
56
|
-
// Also check for similar params
|
|
57
|
-
for (const key of parsed.searchParams.keys()) {
|
|
58
|
-
if (key.toLowerCase().includes(param)) {
|
|
59
|
-
parsed.searchParams.set(key, "[REDACTED]");
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
return parsed.toString();
|
|
64
|
-
} catch {
|
|
65
|
-
return url;
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
function truncateHtml(content: string): string {
|
|
70
|
-
if (content.length <= MAX_HTML_LOG_LENGTH) {
|
|
71
|
-
return content;
|
|
72
|
-
}
|
|
73
|
-
return content.slice(0, MAX_HTML_LOG_LENGTH) + "... [truncated]";
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
function redactValue(obj: unknown): unknown {
|
|
77
|
-
if (obj === null || obj === undefined) {
|
|
78
|
-
return obj;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
if (typeof obj === "string") {
|
|
82
|
-
// Check if it looks like a URL
|
|
83
|
-
if (obj.startsWith("http://") || obj.startsWith("https://")) {
|
|
84
|
-
return redactUrlParams(obj);
|
|
85
|
-
}
|
|
86
|
-
// Check if it looks like HTML
|
|
87
|
-
if (obj.includes("<html") || obj.includes("<body") || obj.includes("<div")) {
|
|
88
|
-
return truncateHtml(obj);
|
|
89
|
-
}
|
|
90
|
-
return obj;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
if (typeof obj !== "object") {
|
|
94
|
-
return obj;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
if (Array.isArray(obj)) {
|
|
98
|
-
return obj.map(redactValue);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
const result: Record<string, unknown> = {};
|
|
102
|
-
for (const [key, value] of Object.entries(obj)) {
|
|
103
|
-
if (shouldRedact(key)) {
|
|
104
|
-
result[key] = "[REDACTED]";
|
|
105
|
-
} else if (key === "url" && typeof value === "string") {
|
|
106
|
-
result[key] = redactUrlParams(value);
|
|
107
|
-
} else if (key === "html" || key === "content" || key === "dom") {
|
|
108
|
-
result[key] = typeof value === "string" ? truncateHtml(value) : redactValue(value);
|
|
109
|
-
} else if (typeof value === "object" && value !== null) {
|
|
110
|
-
result[key] = redactValue(value);
|
|
111
|
-
} else {
|
|
112
|
-
result[key] = value;
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
return result;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
export interface CorrelationIds {
|
|
119
|
-
analysisId?: string;
|
|
120
|
-
crawlId?: string;
|
|
121
|
-
featureSlug?: string;
|
|
122
|
-
testRunId?: string;
|
|
123
|
-
iteration?: number;
|
|
124
|
-
requestId?: string;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
export interface Logger {
|
|
128
|
-
debug(message: string, data?: Record<string, unknown>): void;
|
|
129
|
-
info(message: string, data?: Record<string, unknown>): void;
|
|
130
|
-
warn(message: string, data?: Record<string, unknown>): void;
|
|
131
|
-
error(message: string, data?: Record<string, unknown>): void;
|
|
132
|
-
withCorrelation(ids: CorrelationIds): Logger;
|
|
133
|
-
setMcpNotifier(notifier: McpLogNotifier | null): void;
|
|
134
|
-
setLevel(level: LogLevel): void;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
export type McpLogNotifier = (level: string, data: unknown, logger: string) => Promise<void>;
|
|
138
|
-
|
|
139
|
-
export function createLogger(level: LogLevel): Logger {
|
|
140
|
-
let minLevel = LOG_LEVELS[level];
|
|
141
|
-
let mcpNotifier: McpLogNotifier | null = null;
|
|
142
|
-
let correlationIds: CorrelationIds = {};
|
|
143
|
-
|
|
144
|
-
function log(
|
|
145
|
-
logLevel: LogLevel,
|
|
146
|
-
message: string,
|
|
147
|
-
data?: Record<string, unknown>
|
|
148
|
-
): void {
|
|
149
|
-
if (LOG_LEVELS[logLevel] < minLevel) {
|
|
150
|
-
return;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
const entry: Record<string, unknown> = {
|
|
154
|
-
timestamp: new Date().toISOString(),
|
|
155
|
-
level: logLevel,
|
|
156
|
-
message,
|
|
157
|
-
};
|
|
158
|
-
|
|
159
|
-
// Add correlation IDs if present
|
|
160
|
-
if (Object.keys(correlationIds).length > 0) {
|
|
161
|
-
entry.correlation = correlationIds;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
if (data) {
|
|
165
|
-
entry.data = redactValue(data);
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
// Write to stderr to avoid interfering with MCP stdio transport
|
|
169
|
-
process.stderr.write(JSON.stringify(entry) + "\n");
|
|
170
|
-
|
|
171
|
-
// Also emit MCP logging notification if available
|
|
172
|
-
if (mcpNotifier) {
|
|
173
|
-
const mcpLevel = MCP_LOG_LEVELS[logLevel];
|
|
174
|
-
mcpNotifier(mcpLevel, entry, "testing-mcp").catch(() => {
|
|
175
|
-
// Silently ignore notification failures
|
|
176
|
-
});
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
const logger: Logger = {
|
|
181
|
-
debug: (message, data) => log("debug", message, data),
|
|
182
|
-
info: (message, data) => log("info", message, data),
|
|
183
|
-
warn: (message, data) => log("warn", message, data),
|
|
184
|
-
error: (message, data) => log("error", message, data),
|
|
185
|
-
|
|
186
|
-
withCorrelation(ids: CorrelationIds): Logger {
|
|
187
|
-
const childLogger = createLogger(
|
|
188
|
-
(Object.entries(LOG_LEVELS).find(([_, v]) => v === minLevel)?.[0] ||
|
|
189
|
-
"info") as LogLevel
|
|
190
|
-
);
|
|
191
|
-
childLogger.setMcpNotifier(mcpNotifier);
|
|
192
|
-
// Merge correlation IDs
|
|
193
|
-
const mergedIds = { ...correlationIds, ...ids };
|
|
194
|
-
// Set up the child logger's correlation
|
|
195
|
-
return {
|
|
196
|
-
...childLogger,
|
|
197
|
-
debug: (message, data) => {
|
|
198
|
-
correlationIds = mergedIds;
|
|
199
|
-
log("debug", message, data);
|
|
200
|
-
},
|
|
201
|
-
info: (message, data) => {
|
|
202
|
-
correlationIds = mergedIds;
|
|
203
|
-
log("info", message, data);
|
|
204
|
-
},
|
|
205
|
-
warn: (message, data) => {
|
|
206
|
-
correlationIds = mergedIds;
|
|
207
|
-
log("warn", message, data);
|
|
208
|
-
},
|
|
209
|
-
error: (message, data) => {
|
|
210
|
-
correlationIds = mergedIds;
|
|
211
|
-
log("error", message, data);
|
|
212
|
-
},
|
|
213
|
-
withCorrelation: childLogger.withCorrelation,
|
|
214
|
-
setMcpNotifier: childLogger.setMcpNotifier,
|
|
215
|
-
setLevel: childLogger.setLevel,
|
|
216
|
-
};
|
|
217
|
-
},
|
|
218
|
-
|
|
219
|
-
setMcpNotifier(notifier: McpLogNotifier | null): void {
|
|
220
|
-
mcpNotifier = notifier;
|
|
221
|
-
},
|
|
222
|
-
|
|
223
|
-
setLevel(newLevel: LogLevel): void {
|
|
224
|
-
minLevel = LOG_LEVELS[newLevel];
|
|
225
|
-
},
|
|
226
|
-
};
|
|
227
|
-
|
|
228
|
-
return logger;
|
|
229
|
-
}
|