fix(download): fall back to free binary on macOS when Pro 404s

A Pro license on macOS currently has no binary to download. Rather than
hard-failing a paying customer, fall back to the free binary with a clear
notice. Scoped to the 404 case only: transient and checksum-verification
failures still hard-fail (no silent downgrade), and once the macOS Pro
build ships the 404 disappears and Pro is served automatically.

JS side adds DownloadHttpError to carry the HTTP status through fetch's
generic error path so the 404 can be distinguished from transient failures.
This commit is contained in:
CloakHQ
2026-06-23 10:41:04 +02:00
parent 6acd9fe277
commit 343a3e8e28
2 changed files with 67 additions and 17 deletions
+25 -8
View File
@@ -143,14 +143,31 @@ def ensure_binary(license_key: str | None = None) -> str:
# Authenticity could not be confirmed — surface verbatim.
raise
except Exception as e:
# Transient failure with no cached Pro binary to use — surface a
# clear error rather than silently downloading the free binary.
raise RuntimeError(
f"Pro binary unavailable: {e}. Your license is valid but the "
f"Pro binary could not be downloaded right now. Retry in a "
f"moment. To use the free binary instead, unset "
f"CLOAKBROWSER_LICENSE_KEY."
) from e
# macOS has no Pro binary yet. Rather than hard-failing a paying
# customer, fall back to the free binary with a clear notice.
# Scoped to the 404 (binary-not-found) case so that (a) transient
# and verification failures still hard-fail — no silent downgrade —
# and (b) the moment the macOS Pro build ships, the 404 disappears
# and Pro is served automatically with no wrapper change.
if (
get_platform_tag().startswith("darwin")
and isinstance(e, httpx.HTTPStatusError)
and e.response.status_code == 404
):
logger.warning(
"macOS Pro binary is not available yet — using the free "
"binary for now. Your license stays valid and you'll get "
"the Pro binary on macOS automatically once the build ships."
)
else:
# Transient failure with no cached Pro binary to use — surface a
# clear error rather than silently downloading the free binary.
raise RuntimeError(
f"Pro binary unavailable: {e}. Your license is valid but the "
f"Pro binary could not be downloaded right now. Retry in a "
f"moment. To use the free binary instead, unset "
f"CLOAKBROWSER_LICENSE_KEY."
) from e
elif info:
logger.warning("License validation failed (plan=%s), using free tier", info.plan)
else: