diff --git a/src/routes/api/downloads/[filename].ts b/src/routes/api/downloads/[filename].ts index 0bd28d1..dd77cd0 100644 --- a/src/routes/api/downloads/[filename].ts +++ b/src/routes/api/downloads/[filename].ts @@ -8,7 +8,10 @@ import { env } from "~/env/server"; * * Handles: * - Full DMG files: /api/downloads/Gaze-0.2.2.dmg, /api/downloads/InputHalo-0.1.0.dmg - * - Delta updates: /api/downloads/Gaze3-2.delta, /api/downloads/InputHalo3-2.delta + * - Delta updates: /api/downloads/Gaze3-2.delta, /api/downloads/Nook17-9.delta + * + * The Nook delta files are named after the app bundle ("Nook"), not the DMG + * ("TheNook"), so both prefixes must be allowed (NOOK-337). * * URL: https://freno.me/api/downloads/[filename] */ @@ -24,7 +27,7 @@ export async function GET(event: APIEvent) { }); } - const validPrefixes = ["Gaze", "InputHalo", "TheNook"]; + const validPrefixes = ["Gaze", "InputHalo", "TheNook", "Nook"]; const isValidPrefix = validPrefixes.some((prefix) => filename.startsWith(prefix)); if ( !isValidPrefix || diff --git a/src/routes/api/downloads/filename.test.ts b/src/routes/api/downloads/filename.test.ts new file mode 100644 index 0000000..79d5544 --- /dev/null +++ b/src/routes/api/downloads/filename.test.ts @@ -0,0 +1,38 @@ +/** + * Regression test for the downloads proxy filename allowlist (NOOK-337). + * + * The v0.10.0 publish failed its CI enclosure check because Sparkle names + * delta files after the app bundle ("Nook17-9.delta") while the DMG is named + * "TheNook-*.dmg" — and "Nook" was missing from the allowlist, so every Nook + * delta request 400'd with "Invalid file format" while the DMG passed. + * + * The route hits S3 and cannot be unit-tested under bun:test, so this is a + * STATIC SOURCE AUDIT — the same pattern the downloads.test.ts regressions + * use. + */ +import { describe, it, expect } from "bun:test"; +import { readFileSync } from "node:fs"; +import { join } from "node:path"; + +const SOURCE = readFileSync( + join(import.meta.dir, "[filename].ts"), + "utf8" +); + +describe("Downloads proxy filename allowlist (NOOK-337)", () => { + it("allows the Nook app-bundle prefix used by Sparkle delta names", () => { + expect(SOURCE).toContain('"Nook"'); + }); + + it("still allows every previously served prefix", () => { + for (const prefix of ["Gaze", "InputHalo", "TheNook"]) { + expect(SOURCE).toContain(`"${prefix}"`); + } + }); + + it("still serves the extensions Sparkle fetches", () => { + for (const ext of [".dmg", ".delta", ".zip"]) { + expect(SOURCE).toContain(`"${ext}"`); + } + }); +});