fix(license): abort on invalid or unvalidatable key instead of silent free fallback

A supplied license key the server rejects, or one that cannot be validated
(server unreachable, no cache), now raises instead of silently downloading the
free binary. No-key (keyless) and valid-key (Pro) paths unchanged. Python, JS,
and .NET, with mirror tests in each.
This commit is contained in:
CloakHQ committed 2026-08-27 00:22:05 +02:00
1 parent 0811704e7f
commit 8fb3350dd1
7 files changed
+113 -8

No files matched your search

+11 -2
View File
@@ -127,9 +127,18 @@ export async function ensureBinary(
);
}
} else if (info) {
console.log(`[cloakbrowser] License validation failed (plan=${info.plan}), using free tier`);
// Key supplied but rejected — abort, never downgrade to free.
throw new Error(
`CloakBrowser Pro: license key is invalid or expired (plan=${info.plan}). ` +
`Check CLOAKBROWSER_LICENSE_KEY, or unset it to use the free binary.`,
);
} else {
console.log("[cloakbrowser] License validation unavailable, using free tier");
// Key supplied but unvalidatable (server down, no cache) — abort.
throw new Error(
"CloakBrowser Pro: license could not be validated (server unreachable " +
"and no cached validation). Retry in a moment, or unset " +
"CLOAKBROWSER_LICENSE_KEY to use the free binary.",
);
}
}
+17
View File
@@ -547,6 +547,23 @@ describe("preview Pro selection", () => {
errSpy.mock.calls.some((c) => String(c[0]).includes("no preview build is available")),
).toBe(false);
});
it("aborts (never free) when the server rejects the key", async () => {
delete process.env.CLOAKBROWSER_DOWNLOAD_URL;
vi.spyOn(globalThis, "fetch").mockResolvedValue({
ok: true,
json: async () => ({ valid: false, plan: "solo", expires: null }),
} as Response);
await expect(ensureBinary("cb_bad")).rejects.toThrow(/invalid or expired/);
});
it("aborts (never free) when the key cannot be validated (server down, no cache)", async () => {
delete process.env.CLOAKBROWSER_DOWNLOAD_URL;
vi.spyOn(globalThis, "fetch").mockRejectedValue(new Error("network down"));
await expect(ensureBinary("cb_test")).rejects.toThrow(/could not be validated/);
});
});
describe("ensureBinary", () => {