fix(confidence-engine): bound focused investigation input
This commit is contained in:
@@ -393,6 +393,174 @@ describe("focused-deconstruct targetNodeId identity boundary", () => {
|
||||
}
|
||||
});
|
||||
|
||||
it("rejects oversized focused answer with 400 and does not reach reasoning seam", async () => {
|
||||
const generateReconstruction = vi.fn().mockResolvedValue({
|
||||
response: {},
|
||||
providerApiPath: "/api/chat",
|
||||
});
|
||||
|
||||
vi.doMock("@/lib/llm/provider", () => ({
|
||||
getProvider: () => ({ generateReconstruction }),
|
||||
getProviderModelName: () => "configured-model",
|
||||
}));
|
||||
|
||||
const largeAnswer = "x".repeat(10001);
|
||||
|
||||
const { POST } = await import("../app/api/focused-investigation/deconstruct/route.js");
|
||||
|
||||
const response = await POST(new Request("http://localhost/api/focused-investigation/deconstruct", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
targetNodeId: "node-id",
|
||||
targetLabel: "label",
|
||||
targetDescription: "description",
|
||||
centralStatement: "central statement",
|
||||
question: "question?",
|
||||
answer: largeAnswer,
|
||||
}),
|
||||
}));
|
||||
|
||||
expect(response.status).toBe(400);
|
||||
const json = await response.json();
|
||||
expect(json.error).toMatch(/answer.*exceeds maximum length/i);
|
||||
expect(generateReconstruction).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("accepts focused answer at exact server max (10000) and reaches reasoning seam", async () => {
|
||||
const generateReconstruction = vi.fn().mockResolvedValue({
|
||||
response: {
|
||||
targetNodeId: "node-id",
|
||||
observations: [],
|
||||
uncertainties: [],
|
||||
assumptions: [],
|
||||
relationships: [],
|
||||
possibleFollowUpQuestions: [],
|
||||
},
|
||||
providerApiPath: "/api/chat",
|
||||
});
|
||||
|
||||
vi.doMock("@/lib/llm/provider", () => ({
|
||||
getProvider: () => ({ generateReconstruction }),
|
||||
getProviderModelName: () => "configured-model",
|
||||
}));
|
||||
|
||||
const exactMaxAnswer = "x".repeat(10000);
|
||||
|
||||
const { POST } = await import("../app/api/focused-investigation/deconstruct/route.js");
|
||||
|
||||
const response = await POST(new Request("http://localhost/api/focused-investigation/deconstruct", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
targetNodeId: "node-id",
|
||||
targetLabel: "label",
|
||||
targetDescription: "description",
|
||||
centralStatement: "central statement",
|
||||
question: "question?",
|
||||
answer: exactMaxAnswer,
|
||||
}),
|
||||
}));
|
||||
|
||||
expect(response.status).toBe(200);
|
||||
const json = await response.json();
|
||||
expect(json.success).toBe(true);
|
||||
expect(generateReconstruction).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("rejects malformed required field (wrong type) with 400", async () => {
|
||||
const generateReconstruction = vi.fn().mockResolvedValue({
|
||||
response: {}, providerApiPath: "/api/chat",
|
||||
});
|
||||
|
||||
vi.doMock("@/lib/llm/provider", () => ({
|
||||
getProvider: () => ({ generateReconstruction }),
|
||||
getProviderModelName: () => "configured-model",
|
||||
}));
|
||||
|
||||
const { POST } = await import("../app/api/focused-investigation/deconstruct/route.js");
|
||||
|
||||
const response = await POST(new Request("http://localhost/api/focused-investigation/deconstruct", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
targetNodeId: ["not-a-string"],
|
||||
targetLabel: "label",
|
||||
targetDescription: "description",
|
||||
centralStatement: "central statement",
|
||||
question: "question?",
|
||||
answer: "answer.",
|
||||
}),
|
||||
}));
|
||||
|
||||
expect(response.status).toBe(400);
|
||||
const json = await response.json();
|
||||
expect(json.error).toMatch(/targetNodeId.*string/i);
|
||||
expect(generateReconstruction).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("rejects oversized targetDescription with 400", async () => {
|
||||
const generateReconstruction = vi.fn().mockResolvedValue({
|
||||
response: {}, providerApiPath: "/api/chat",
|
||||
});
|
||||
|
||||
vi.doMock("@/lib/llm/provider", () => ({
|
||||
getProvider: () => ({ generateReconstruction }),
|
||||
getProviderModelName: () => "configured-model",
|
||||
}));
|
||||
|
||||
const { POST } = await import("../app/api/focused-investigation/deconstruct/route.js");
|
||||
|
||||
const response = await POST(new Request("http://localhost/api/focused-investigation/deconstruct", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
targetNodeId: "node-id",
|
||||
targetLabel: "label",
|
||||
targetDescription: "x".repeat(2049),
|
||||
centralStatement: "central statement",
|
||||
question: "question?",
|
||||
answer: "answer.",
|
||||
}),
|
||||
}));
|
||||
|
||||
expect(response.status).toBe(400);
|
||||
const json = await response.json();
|
||||
expect(json.error).toMatch(/targetDescription.*exceeds maximum length/i);
|
||||
expect(generateReconstruction).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("rejects malformed centralStatement (number) with 400", async () => {
|
||||
const generateReconstruction = vi.fn().mockResolvedValue({
|
||||
response: {}, providerApiPath: "/api/chat",
|
||||
});
|
||||
|
||||
vi.doMock("@/lib/llm/provider", () => ({
|
||||
getProvider: () => ({ generateReconstruction }),
|
||||
getProviderModelName: () => "configured-model",
|
||||
}));
|
||||
|
||||
const { POST } = await import("../app/api/focused-investigation/deconstruct/route.js");
|
||||
|
||||
const response = await POST(new Request("http://localhost/api/focused-investigation/deconstruct", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
targetNodeId: "node-id",
|
||||
targetLabel: "label",
|
||||
targetDescription: "description",
|
||||
centralStatement: 12345,
|
||||
question: "question?",
|
||||
answer: "answer.",
|
||||
}),
|
||||
}));
|
||||
|
||||
expect(response.status).toBe(400);
|
||||
const json = await response.json();
|
||||
expect(json.error).toMatch(/centralStatement.*string/i);
|
||||
expect(generateReconstruction).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("returns a sanitized 503 when the provider is unavailable", async () => {
|
||||
const errorSpy = vi.spyOn(console, "error").mockImplementation(() => {});
|
||||
vi.doMock("@/lib/llm/provider", () => ({
|
||||
|
||||
Reference in New Issue
Block a user