fix(studio): keep AI provider and model details private

This commit is contained in:
Clintchiz committed 2026-10-19 23:20:50 +05:30
1 parent 5aec369054
commit 6d0c47fba7
5 files changed
+65 -51

No files matched your search

+40 -18
View File
@@ -86,8 +86,9 @@ test("AI proposals use engine validation, preserve draft source, locks and revis
const response = await handler(await request());
const batch = await response!.json();
expect(batch.alternatives).toHaveLength(3);
expect(batch.provenance.provider).toBe("APIMart");
expect(batch.provenance.model).toBe("gpt-5-mini");
expect(batch.provenance.provider).toBe("AI");
expect(batch.provenance.model).toBeUndefined();
expect(JSON.stringify(batch)).not.toMatch(/APIMart|gpt-5-mini|custom-model/i);
expect(JSON.stringify(system)).toBe(original);
const locked = await handler(
await request(await input(["/tokens/shape.control"])),
@@ -114,7 +115,7 @@ test("metadata and errors never contain the key or raw upstream response", async
new Request("https://components.example/design-studio/api/generation"),
);
const text = await meta!.text();
expect(text).toContain("gpt-5-mini");
expect(text).not.toMatch(/apimart|gpt-5-mini/i);
expect(JSON.parse(text).timeoutMs).toBe(AI_TIMEOUT_MS);
expect(AI_TIMEOUT_MS).toBe(60_000);
expect(text).not.toContain("test-secret");
@@ -122,6 +123,7 @@ test("metadata and errors never contain the key or raw upstream response", async
const body = await failure!.text();
expect(body).not.toContain("test-secret");
expect(body).not.toContain("upstream credentials");
expect(body).not.toMatch(/APIMart|APIMART_API_KEY|gpt-5-mini/i);
expect(body).toContain("WRN-STUDIO-PROVIDER");
});
@@ -139,7 +141,7 @@ test("a completion beyond the old 20-second deadline produces three validated al
expect(response!.status).toBe(200);
const batch = await response!.json();
expect(batch.alternatives).toHaveLength(3);
expect(batch.provenance.provider).toBe("APIMart");
expect(batch.provenance.provider).toBe("AI");
expect(JSON.stringify(system)).toBe(original);
}, 30_000);
@@ -186,9 +188,9 @@ test("same-origin checks, body bounds and local fallback remain enforced", async
'<head><script type="module"></script></head><div id="diagnostics"></div>',
false,
),
).toContain("APIMART_API_KEY");
).not.toMatch(/APIMART|gpt-/i);
expect(addStudioGuide('<div id="diagnostics"></div>', true)).toContain(
"APIMart AI is enabled",
"AI design assistance is available",
);
});
@@ -225,9 +227,9 @@ test("temporary APIMart failures retry once and return three validated designs",
test("authentication and quota failures provide actionable redacted diagnostics without retrying", async () => {
for (const [status, code, hint] of [
[401, "invalid_api_key", "server API key"],
[402, "insufficient_quota", "credit or quota"],
[404, "model_not_found", "configured model"],
[401, "invalid_api_key", "server configuration issue"],
[402, "insufficient_quota", "service usage limit"],
[404, "model_not_found", "server configuration issue"],
] as const) {
let calls = 0;
const handler = studioAI(
@@ -296,7 +298,7 @@ test("network and repeated rate failures remain bounded and describe the actual
const body = await (await handler(await request()))!.text();
expect(calls).toBe(2);
expect(body).toContain(
network ? "could not reach APIMart" : "rate limiting",
network ? "could not reach the AI service" : "rate limiting",
);
expect(body).not.toContain("test-secret");
}
@@ -421,14 +423,34 @@ test("the configured model is used consistently for metadata and upstream reques
const metadata = await (await handler(
new Request("https://components.example/design-studio/api/generation"),
))!.json();
expect(metadata.model).toBe("custom-model");
expect(metadata.model).toBeUndefined();
const batch = await (await handler(await request()))!.json();
expect(selected).toBe("custom-model");
expect(batch.provenance.model).toBe("custom-model");
expect(
addStudioGuide('<div id="diagnostics"></div>', true, "custom-model"),
).toContain("custom-model");
expect(
addStudioGuide('<div id="diagnostics"></div>', true, "<script>"),
).not.toContain("with <script>");
expect(batch.provenance.model).toBeUndefined();
expect(JSON.stringify(batch)).not.toMatch(/APIMart|gpt-5-mini|custom-model/i);
expect(addStudioGuide('<div id="diagnostics"></div>', true)).not.toMatch(
/APIMart|custom-model|gpt-/i,
);
});
test("all public AI failure categories hide provider and model configuration", async () => {
for (const status of [400, 401, 402, 403, 404, 429, 500]) {
const handler = studioAI(
"test-secret",
mockFetch(
async () =>
new Response(
JSON.stringify({
error: { message: "APIMart custom-secret-model" },
}),
{ status },
),
),
"custom-secret-model",
);
const response = await handler(await request());
expect(await response!.text()).not.toMatch(
/APIMart|custom-secret-model|test-secret/i,
);
}
});