docs(core): clarify redaction scope + add nested request-body test

Address round-1 review feedback on fetchTracking redaction:
- Cross-reference REDACTED_VALUE / REDACTED_HEADER_VALUE so a reader
  understands why two identical "[REDACTED]" constants coexist.
- Document that redactBody deliberately scopes to form-encoded + JSON
  (multipart/binary bodies pass through; OAuth never uses multipart).
- Add a tracker-path test asserting a nested sensitive key in a JSON
  request body is redacted in the recorded copy while the live outbound
  body stays byte-identical.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S3fTN8H3R8YV4yUGvZjYnX
This commit is contained in:
cliffhall 2026-07-01 22:34:40 -04:00
commit 775b98a019

View file

@ -477,6 +477,35 @@ describe("createFetchTracker", () => {
expect(bodies[0]!.body).toBe('{"tools":[]}');
});
it("redacts a nested sensitive key in a JSON request body through the tracker", async () => {
let outboundInit: RequestInit | undefined;
const baseFetch = vi.fn(
async (_input: RequestInfo | URL, init?: RequestInit) => {
outboundInit = init;
return new Response("ok");
},
);
const tracked: FetchRequestEntryBase[] = [];
const fetcher = createFetchTracker(baseFetch as typeof fetch, {
trackRequest: (entry) => tracked.push(entry),
});
const liveBody = JSON.stringify({
params: { arguments: { access_token: "sekret", page: 2 } },
});
await fetcher("https://example.com/mcp", {
method: "POST",
headers: { "content-type": "application/json" },
body: liveBody,
});
// Recorded copy has the nested secret masked; non-sensitive siblings kept.
expect(JSON.parse(tracked[0]!.requestBody!)).toEqual({
params: { arguments: { access_token: REDACTED_VALUE, page: 2 } },
});
expect(JSON.stringify(tracked[0])).not.toContain("sekret");
// The live outbound request body is byte-identical (unredacted).
expect(outboundInit?.body).toBe(liveBody);
});
it("does not throw on a malformed body — logs it as-is", async () => {
const baseFetch = vi.fn(async () => new Response("ok"));
const tracked: FetchRequestEntryBase[] = [];