Skip to content

Commit 7190fc4

Browse files
brokemac79ooiuuii
andauthored
fix(doctor): diagnose blocked external channel plugins (#86629)
Diagnose configured channel plugins whose installed owners are blocked by trust or activation policy, while preserving multi-owner fallback and actionable channel safety warnings. Closes #83212. Co-authored-by: luyifan <[email protected]>
1 parent 9d9389b commit 7190fc4

6 files changed

Lines changed: 1547 additions & 131 deletions

File tree

src/commands/doctor-config-flow.test.ts

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ type TerminalNote = (message: string, title?: string) => void;
1414
const terminalNoteMock = vi.hoisted(() => vi.fn<TerminalNote>());
1515
const callGatewayMock = vi.hoisted(() => vi.fn());
1616
const runDoctorRepairSequenceMock = vi.hoisted(() => vi.fn());
17+
const collectDoctorPreviewNotesParamsMock = vi.hoisted(() => vi.fn());
1718
const collectImplicitFallbackClobberWarningsMock = vi.hoisted(() =>
1819
vi.fn<(cfg: unknown) => string[]>(() => []),
1920
);
@@ -1233,10 +1234,13 @@ vi.mock("./doctor/shared/preview-warnings.js", () => {
12331234
}
12341235

12351236
return {
1236-
collectDoctorPreviewNotes: vi.fn(async (params) => ({
1237-
infoNotes: [],
1238-
warningNotes: await collectWarnings(params),
1239-
})),
1237+
collectDoctorPreviewNotes: vi.fn(async (params) => {
1238+
collectDoctorPreviewNotesParamsMock(params);
1239+
return {
1240+
infoNotes: [],
1241+
warningNotes: await collectWarnings(params),
1242+
};
1243+
}),
12401244
collectDoctorPreviewWarnings: vi.fn(collectWarnings),
12411245
};
12421246
});
@@ -1505,6 +1509,7 @@ describe("doctor config flow", () => {
15051509
callGatewayMock.mockReset();
15061510
callGatewayMock.mockResolvedValue({});
15071511
runDoctorRepairSequenceMock.mockReset();
1512+
collectDoctorPreviewNotesParamsMock.mockClear();
15081513
collectImplicitFallbackClobberWarningsMock.mockClear();
15091514
collectImplicitFallbackClobberWarningsMock.mockReturnValue([]);
15101515
noteImplicitFallbackClobberWarningsMock.mockClear();
@@ -1524,6 +1529,35 @@ describe("doctor config flow", () => {
15241529
});
15251530
});
15261531

1532+
it("collects plugin blocker previews from the pre-auto-enable config", async () => {
1533+
await runDoctorConfigWithInput({
1534+
config: {
1535+
plugins: {
1536+
allow: ["existing-plugin"],
1537+
},
1538+
tools: {
1539+
alsoAllow: ["browser"],
1540+
},
1541+
},
1542+
run: loadAndMaybeMigrateDoctorConfig,
1543+
});
1544+
1545+
expect(collectDoctorPreviewNotesParamsMock).toHaveBeenCalledWith(
1546+
expect.objectContaining({
1547+
cfg: expect.objectContaining({
1548+
plugins: expect.objectContaining({
1549+
allow: ["existing-plugin", "browser"],
1550+
}),
1551+
}),
1552+
activationSourceConfig: expect.objectContaining({
1553+
plugins: expect.objectContaining({
1554+
allow: ["existing-plugin"],
1555+
}),
1556+
}),
1557+
}),
1558+
);
1559+
});
1560+
15271561
it("reloads gateway secrets and refreshes auth status after auth profile repairs", async () => {
15281562
runDoctorRepairSequenceMock.mockImplementation(async (params: { state: unknown }) => ({
15291563
state: params.state,
@@ -1721,7 +1755,9 @@ describe("doctor config flow", () => {
17211755

17221756
const warning = doctorWarnings.join("\n");
17231757
expect(warning).toContain("hooks.internal.entries.custom-hook:");
1724-
expect(warning).toContain("unsupported loader keys handler, extraDirs will not load hook modules");
1758+
expect(warning).toContain(
1759+
"unsupported loader keys handler, extraDirs will not load hook modules",
1760+
);
17251761
expect(warning).toContain("bootstrap-extra-files for session bootstrap content");
17261762
expect(warning).toContain("Doctor cannot rewrite this automatically");
17271763
expect(warning).not.toContain("hooks.internal.entries.valid-hook");

src/commands/doctor-config-flow.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,7 @@ export async function loadAndMaybeMigrateDoctorConfig(params: {
231231
}));
232232
}
233233

234+
const pluginActivationSourceConfig = candidate;
234235
const { applyPluginAutoEnable } = await import("../config/plugin-auto-enable.js");
235236
const autoEnable = applyPluginAutoEnable({ config: candidate, env: process.env });
236237
if (autoEnable.changes.length > 0) {
@@ -329,6 +330,7 @@ export async function loadAndMaybeMigrateDoctorConfig(params: {
329330
const { collectDoctorPreviewNotes } = await import("./doctor/shared/preview-warnings.js");
330331
const previewNotes = await collectDoctorPreviewNotes({
331332
cfg: candidate,
333+
activationSourceConfig: pluginActivationSourceConfig,
332334
doctorFixCommand,
333335
env: process.env,
334336
allowExec: params.options.allowExec === true,

0 commit comments

Comments
 (0)