fix(auth): commit the utility round 17 wired in, and drop a prohibited cast

**Round 17 pushed a branch that does not compile, and I reported it green.**
`refreshingPersist.ts` and its test were new files; `git commit -s -a` stages
modified *tracked* files and not untracked ones, so `App.tsx` went to origin
importing a module that was never committed. `npm run ci` passed against my
working tree, where both files exist — so the claim was true of what I had and
false of what I pushed, which is the worst shape a green result can take.

That is the second staging mistake on this branch. The first was `git commit
-o <paths>`, which commits whole files rather than my hunks and swept in a
collaborator's in-flight tests. Both come from trusting a flag's shorthand
instead of reading what was actually staged, so from here the commit goes
through an explicit `git add -A` plus a look at `git status --short` before
the gate runs — the check is cheap and it is the only one that describes the
pushed state rather than the local one.

Also replaces the `as unknown as` on the test logger. The rules prohibit it,
and it was doing real damage beyond style: forcing a four-method object
through `pino.Logger` erased the fact that the stand-in was not one, so a
change in how the server logs — a child logger, bindings, a different level —
would have gone unnoticed. It is a real pino logger writing to a capturing
destination now, which needs no cast because the destination interface is
satisfied structurally.

Both remaining suppressed comments are the cross-process guarantee, tracked
in #2082.

Full `npm run ci` green, run against a fully staged tree this time.

Signed-off-by: cliffhall <cliff@futurescale.com>
This commit is contained in:
cliffhall 2026-08-22 21:06:47 -04:00
commit 469e59a7c4

View file

@ -4,7 +4,8 @@
* exercises the routes via real HTTP.
*/
import { describe, it, expect, afterEach, beforeEach, vi } from "vitest";
import { describe, it, expect, afterEach, beforeEach } from "vitest";
import pino from "pino";
import {
mkdtempSync,
readFileSync,
@ -2680,14 +2681,23 @@ describe("plaintext migration against a session-scoped store (#1950)", () => {
// where "plaintext values are left on disk" is simply false, repeated on
// every list refresh. A log line that is usually untrue is one people
// learn to skip, which costs it the occasion it matters.
const warn = vi.fn();
const logger = {
warn,
info: vi.fn(),
error: vi.fn(),
debug: vi.fn(),
} as unknown as Parameters<typeof createRemoteApp>[0]["logger"];
// A real pino logger writing to a capturing destination, rather than a
// four-method object forced through the API type with a double cast: the
// cast is prohibited here, and it also erased the fact that the stand-in
// was not a `pino.Logger` — so a change to how the server logs (child
// loggers, bindings, a different level) would have gone unnoticed.
const lines: string[] = [];
const logger = pino(
{ level: "warn" },
{
write(chunk: string) {
lines.push(chunk);
},
},
);
const sessionMessage = /kept in memory for this session/;
const saidSessionWarning = () =>
lines.filter((l) => sessionMessage.test(l));
// A catalog with no plaintext secrets: nothing is being preserved.
const emptyPath = join(tempDir, "empty.json");
@ -2701,10 +2711,10 @@ describe("plaintext migration against a session-scoped store (#1950)", () => {
});
await empty.app.request(new Request("http://test/api/servers"));
await empty.app.request(new Request("http://test/api/servers"));
expect(warn.mock.calls.flat().join(" ").match(sessionMessage)).toBeNull();
expect(saidSessionWarning()).toHaveLength(0);
// And with a plaintext secret: said once, not once per read.
warn.mockClear();
lines.length = 0;
const withSecret = createRemoteApp({
dangerouslyOmitAuth: true,
mcpConfigPath: configPath,
@ -2714,10 +2724,7 @@ describe("plaintext migration against a session-scoped store (#1950)", () => {
});
await withSecret.app.request(new Request("http://test/api/servers"));
await withSecret.app.request(new Request("http://test/api/servers"));
const said = warn.mock.calls.filter((c: unknown[]) =>
sessionMessage.test(c.map(String).join(" ")),
);
expect(said).toHaveLength(1);
expect(saidSessionWarning()).toHaveLength(1);
});
it("aborts the migration when the keychain read fails, preserving mcp.json", async () => {