fix: gate direct session creation by workspace policy

This commit is contained in:
2026-08-04 06:13:22 +02:00
parent 7a780d8904
commit b686ffe271
5 changed files with 144 additions and 4 deletions
@@ -34,6 +34,9 @@ test("submitting includes browser-local migrated preferences and calls onCreated
http.get("http://localhost:8787/settings", () => HttpResponse.json({
workspace: "default", provider: "zai", model: "glm-5.2", thinking: "low",
})),
http.get("http://localhost:8787/workspaces", () => HttpResponse.json([{
id: "default", name: "default", file: "default.yaml", displayName: "Default",
}])),
http.post("http://localhost:8787/sessions", async ({ request }) => {
body = await request.json();
return HttpResponse.json({ id: "s1" });
@@ -51,6 +54,56 @@ test("submitting includes browser-local migrated preferences and calls onCreated
await waitFor(() => expect(onCreated).toHaveBeenCalledWith("s1"));
});
test("first-run direct dialog creation waits for registry policy without a mounted footer", async () => {
let body: unknown;
let releasePolicy!: () => void;
let summaryRequestStarted = false;
let policyRequestStarted = false;
const policyMayFinish = new Promise<void>((resolve) => { releasePolicy = resolve; });
const revision = {
id: "psd-clinical", commit: "a".repeat(40), blob: "b".repeat(40), snapshotPath: "/snapshot", state: "operational" as const,
};
localStorage.setItem("thothii.workspace-registry.v1.preferences", JSON.stringify({
workspaceId: "psd-clinical", provider: "deepseek", model: "deepseek-v4-pro", thinking: "medium",
}));
server.use(
http.get("http://localhost:8787/workspaces", () => {
summaryRequestStarted = true;
return HttpResponse.json([{
id: "psd-clinical", name: "psd-clinical", file: "psd-clinical.yaml", displayName: "PSD Clinical",
revision,
}]);
}),
http.get("http://localhost:8787/workspaces/psd-clinical", async () => {
policyRequestStarted = true;
await policyMayFinish;
return HttpResponse.json({
workspace: { llm_policy: { default: "zai/glm-5.2", allowed: ["zai/glm-5.2"] } }, revision,
});
}),
http.post("http://localhost:8787/sessions", async ({ request }) => {
body = await request.json();
return HttpResponse.json({ id: "s1" });
}),
);
const { onCreated } = renderDialog();
await userEvent.click(screen.getByRole("button", { name: /new/i }));
await userEvent.type(await screen.findByLabelText(/question/i), "q");
await userEvent.click(screen.getByRole("button", { name: /^create$/i }));
await waitFor(() => expect(summaryRequestStarted).toBe(true));
await waitFor(() => expect(policyRequestStarted).toBe(true));
expect(body).toBeUndefined();
expect(screen.getByRole("button", { name: /creating/i })).toBeDisabled();
releasePolicy();
await waitFor(() => expect(body).toEqual({
question: "q", workspaceId: "psd-clinical", provider: "zai", model: "glm-5.2", thinking: "medium",
}));
await waitFor(() => expect(onCreated).toHaveBeenCalledWith("s1"));
});
test("empty question shows a validation error and does not submit", async () => {
renderDialog();
await userEvent.click(screen.getByRole("button", { name: /new/i }));