fix(qa): apply pre-release multi-agent QA findings

Three small follow-ups surfaced by the v1.4.6 QA pass:

- Settings → KI: the "raw data" warning still used raw Tailwind orange
  tokens instead of the Dracula `dracula-orange` ones, breaking theme
  consistency and tipping below the WCAG-AA contrast floor on the
  card surface.
- Admin status grid: the Backups card cta read "View backups" but
  jumped to the system-status section (the dedicated backups view
  does not exist yet — that's a v1.5 feature). Re-labelling the cta
  to "Open system status" and the Integrations cta to "Open
  integrations" makes the destination honest. The href targets
  themselves are unchanged.
- `withIdempotency` body-content guard previously did `text.includes("sk-")`
  which silently broke caching for benign payloads containing common
  English compounds like "task-id", "risk-management", "disk-io".
  Tightened to a regex requiring the canonical secret prefix plus a
  realistic suffix length, so only actual API keys trip the guard.
  Three regression tests cover the false-positive cases.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Marc-André BombeckandClaude Opus 4.7 committed 2026-05-09 02:22:12 +02:00
1 parent dc4507a55f
commit 67575180b8
4 files changed
+28 -9

No files matched your search

+2 -2
View File
@@ -157,7 +157,7 @@ export function buildCards(data: StatusOverview): StatusCardProps[] {
{ label: "Push", value: data.integrations.webPush },
],
href: "/admin#section-admin-umami",
cta: "Configure",
cta: "Open integrations",
},
{
title: "Monitoring",
@@ -187,7 +187,7 @@ export function buildCards(data: StatusOverview): StatusCardProps[] {
{ label: "Retain", value: `${data.backups.retentionDays}d` },
],
href: "/admin#section-system-status",
cta: "View backups",
cta: "Open system status",
},
{
title: "Maintenance",
+1 -1
View File
@@ -362,7 +362,7 @@ function InsightsSettingsCard({
</div>
</div>
{settings?.privacyMode === "raw" && (
<div className="mt-2 rounded-lg bg-orange-500/10 p-2 text-xs text-orange-400">
<div className="bg-dracula-orange/15 text-dracula-orange mt-2 rounded-lg p-2 text-xs">
{t("settings.rawDataWarning")}
</div>
)}
+18
View File
@@ -300,6 +300,24 @@ describe("withIdempotency body-content exclusion (P12)", () => {
expect(prisma.idempotencyKey.create).not.toHaveBeenCalled();
});
it.each([
["task-id substring", '{"error":"task-id must not contain spaces"}'],
["risk-management word", '{"data":{"note":"risk-management"}}'],
["disk-io metric", '{"data":{"metric":"disk-io"}}'],
])(
"still caches a benign payload whose text contains %s (no false positive)",
async (_label, body) => {
const handler = vi.fn(
async () => new NextResponse(body, { status: 422 }),
);
const wrapped = withIdempotency<[NextRequest]>(handler, async () => "u-1");
await wrapped(
makeRequest("POST", { "idempotency-key": "key-12345678" }),
);
expect(prisma.idempotencyKey.create).toHaveBeenCalledTimes(1);
},
);
it("still caches a normal payload that does not carry a secret", async () => {
const handler = vi.fn(
async () =>
+7 -6
View File
@@ -224,14 +224,15 @@ export function withIdempotency<
// with, but if a future caller forgets we refuse to leak.
// `hlk_` = our access tokens
// `hlr_` = our refresh tokens
// `sk-` = OpenAI keys (also matches `sk-ant-` Anthropic keys)
// `sk-…` = OpenAI / Anthropic keys (full token form, not the
// raw substring — a 422 body explaining "task-id…"
// or any other word containing `sk-` would otherwise
// silently break idempotency for benign retries).
const SECRET_PATTERN =
/(?:\b(?:hlk_|hlr_)[A-Za-z0-9_-]+|\bsk-(?:ant-)?[A-Za-z0-9_-]{8,})/;
const cloned = response.clone();
const text = await cloned.text();
if (
!text.includes("hlk_") &&
!text.includes("hlr_") &&
!text.includes("sk-")
) {
if (!SECRET_PATTERN.test(text)) {
await persistCached(ctx, response, text);
}
}