From 285e555d30a893c554268187ae234d1046f2d879 Mon Sep 17 00:00:00 2001 From: Elmehdi Aitbrahim Date: Thu, 20 Aug 2026 17:26:20 -0400 Subject: [PATCH] docs(desktop): Windows is unsigned too, and the no-warning path goes first Two corrections and one reordering. WINDOWS SIGNING IS DROPPED AS WELL, and it was left as "a separate decision, still open" one round too long. Azure Trusted Signing is ~$120/yr -- MORE than Apple's $99 -- and since 2024 an EV certificate no longer grants an instant SmartScreen pass: reputation accrues from download volume over time, so a new certificate on a young project leaves the warning in place for a while regardless. Paying more to still be warned about is the worst of the three options. Every place that named only the Apple cost now names both, because a page that mentioned one would leave a reader assuming the other had simply been forgotten. THE NO-WARNING PATH LEADS. Someone reading this page is deciding whether to proceed past a security warning, and the first thing they should meet is that there is a route with no warning at all -- the README's "Try it in five minutes", where pip and uv fetch the published wheels and nothing is downloaded as an application, so no operating system objects. It is honest about the trade rather than selling it: that path needs a terminal and Python 3.11+, which is exactly the friction the desktop app exists to remove. AND THE INSTRUCTIONS ARE ACTUALLY INSTRUCTIONS. "Click Open Anyway" is not one. Someone who has never done this needs to be told where the setting is, that it takes two confirmations, and that on macOS Sequoia and later the right-click-Open shortcut no longer works -- Apple removed it deliberately, and a page still recommending it sends people in a circle. Windows gets the step that actually matters and is easy to miss: Unblock the .zip in Properties BEFORE extracting. Skip it and Windows marks every extracted file, so the prompt returns on a later launch and the user concludes the first bypass did not take. It also says to extract somewhere the user owns and NOT into Program Files -- keel does not need administrator rights and should not be given them. Reflected in all three places a downloader meets: the READ ME FIRST inside the .dmg (rebuilt and mounted to confirm), docs/desktop-install.md, and the release notes. 4041 passed, 3 skipped (4 new pins: both prices named, the no-warning path first, and the per-OS steps present). ruff clean repo-wide. Refs #438, #18. Co-Authored-By: Claude Opus 5 (1M context) --- .github/workflows/release.yml | 28 +++++++-- docs/desktop-install.md | 101 +++++++++++++++++++++----------- packaging/macos_app.sh | 33 +++++++---- tests/test_desktop_packaging.py | 36 +++++++++++- 4 files changed, 147 insertions(+), 51 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index cbbf2b1..eca1faa 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -214,9 +214,15 @@ jobs: echo "## Desktop app (macOS / Windows)" echo echo "⚠️ **These builds are not code-signed, so your computer will warn you.**" - echo "Apple's certificate costs \$99/yr and keel cannot currently afford it. There" - echo "is no cheaper tier and no free option, and a certificate we made ourselves" - echo "would do nothing — macOS trusts only certificates Apple issued." + echo "Apple's certificate is \$99/yr and Azure Trusted Signing is ~\$120/yr, and" + echo "keel cannot currently afford either. There is no cheaper tier and no free" + echo "open-source option on either platform. (Windows is worse value than it looks:" + echo "since 2024 even an EV certificate no longer grants an instant SmartScreen" + echo "pass — reputation is earned from download volume over time.)" + echo + echo "**Prefer no warning at all?** Install from the wheels above instead — nothing" + echo "is downloaded as an application, so nothing objects. Needs a terminal and" + echo "Python 3.11+." echo echo "Full explanation, including how to check what you downloaded:" echo "" @@ -261,10 +267,20 @@ jobs: # # THESE ARTIFACTS ARE NOT CODE-SIGNED, AND THAT IS A DECISION RATHER THAN AN OVERSIGHT. # - # Apple notarisation requires a Developer ID certificate, which requires the $99/yr Developer - # Program. There is no free path: a free Apple account signs only for local development, and a + # NEITHER PLATFORM IS SIGNED, and both are decisions with the same cause. + # + # macOS: notarisation requires a Developer ID certificate, which requires the $99/yr Developer + # Program. There is no free path -- a free Apple account signs only for local development, and a # self-signed certificate buys nothing because Gatekeeper trusts Apple-issued Developer IDs and - # nothing else. keel is open source on a small budget and has chosen not to pay it. + # nothing else. + # + # Windows: Azure Trusted Signing is ~$120/yr, MORE than Apple's, and it does not even buy the + # same thing. Since 2024 an EV certificate no longer grants an instant SmartScreen pass; + # reputation accrues from download volume over time, so a new certificate on a young project + # leaves the warning in place for a while regardless. Paying more to still be warned about is + # the worst of the three options. + # + # keel is open source on a small budget and has chosen not to pay either. # # What that costs the user is real and is documented rather than hidden: a `.dmg` downloaded # from the internet carries a quarantine flag, so macOS refuses the first open until they go to diff --git a/docs/desktop-install.md b/docs/desktop-install.md index c073e66..a645b05 100644 --- a/docs/desktop-install.md +++ b/docs/desktop-install.md @@ -3,35 +3,80 @@ If you downloaded keel for macOS or Windows and your computer refused to open it, nothing is broken. This page explains exactly what happened, why, and what to do about it. +## Would you rather not deal with this at all? + +There is a path with no warning on any platform, because nothing is downloaded as an application: +the install-from-source route in the README's **"Try it in five minutes"**. `pip` and `uv` fetch +the published wheels directly, and no operating system objects to that. + +``` +pip install --find-links . ./keel_trader--py3-none-any.whl +keel versions +``` + +It needs a terminal and Python 3.11 or later — which is exactly the friction the desktop app +exists to remove, so this is not the recommendation for everyone. But if you already have both, it +is the shorter road and the rest of this page does not apply to you. + ## The short version -**keel's desktop builds are not code-signed.** Code signing is a paid certificate from Apple or -Microsoft that tells your operating system who built a program. +**keel's desktop builds are not code-signed, on either platform.** Code signing is a paid +certificate from Apple or Microsoft that tells your operating system who built a program. + +**We cannot currently afford either one.** + +| | cost | what it would buy | +|---|---|---| +| Apple Developer Program | **$99/yr** | removes the macOS warning | +| Azure Trusted Signing | **~$120/yr** | *does not* remove the Windows warning by itself | + +There is no cheaper tier and no free option for open-source projects on either platform, and a +certificate we made ourselves would do nothing at all — macOS trusts only certificates Apple +issued. -**We cannot currently afford it.** Apple's certificate costs **$99 per year**, every year, and it -is the only way to remove the warning — there is no cheaper tier, no free option for open-source -projects, and a certificate we made ourselves would do nothing at all, because macOS only trusts -certificates Apple issued. keel is an open-source project with essentially no budget, and that -$99/yr is not something it can commit to today. +Windows is worth a sentence of its own: since 2024, even an expensive EV certificate no longer +buys an instant SmartScreen pass. Reputation is earned from download volume over time, so a new +certificate on a young project would leave the warning in place for a while anyway — for more +money than Apple's. -So your computer sees a program from a developer it cannot identify, and it does the right thing: -it stops and asks you. +keel is an open-source project with essentially no budget. So your computer sees a program from a +developer it cannot identify, and it does the right thing: it stops and asks you. -## What to do +## macOS — step by step -**macOS** +1. Open the downloaded `.dmg`. A window appears with **keel.app** and a **READ ME FIRST** file. +2. Drag **keel.app** into your **Applications** folder. +3. Eject the disk image (drag it to the Trash, or press ⌘E). +4. Open **Applications** and double-click **keel**. macOS refuses, saying it cannot be opened + because the developer cannot be verified. Click **Done**. +5. Open **System Settings** → **Privacy & Security**. +6. Scroll down to the **Security** section. There is a line saying *"keel was blocked to protect + your Mac"*, with an **Open Anyway** button beside it. Click it. +7. Authenticate with Touch ID or your password, then click **Open Anyway** once more in the + dialog that follows. -1. Double-click keel. macOS refuses, saying it cannot verify the developer. -2. Open **System Settings → Privacy & Security**. -3. Scroll down. There is a message about keel being blocked, with an **Open Anyway** button. -4. Click it, and confirm. +keel opens, and your browser opens with it. **You only do this once** — every later launch is a +normal double-click. -You only do this once. keel opens normally afterwards. +> On macOS Sequoia (15) and later, right-clicking the app and choosing *Open* no longer works as a +> shortcut for this. Apple removed that path deliberately. System Settings is the only way. -**Windows** +## Windows — step by step -1. Run the installer. SmartScreen says "Windows protected your PC". -2. Click **More info**, then **Run anyway**. +The download is a `.zip`, and Windows marks files that came from the internet. + +1. **Before extracting**, right-click the downloaded `.zip` → **Properties**. +2. At the bottom of the **General** tab, if there is an **Unblock** checkbox, tick it and click + **OK**. This saves you a warning on every file inside. +3. Right-click the `.zip` → **Extract All…**, and choose a folder you own — for example + `C:\Users\\keel`. Do not extract into `C:\Program Files`; keel does not need + administrator rights and should not be given them. +4. Open the extracted folder and double-click **keel.exe**. +5. If SmartScreen appears — *"Windows protected your PC"* — click **More info**, then + **Run anyway**. + +> If you skipped step 2, you may see the SmartScreen prompt again on a later launch. Doing the +> Unblock on the `.zip` first is what avoids that. ## Please check what you downloaded first @@ -62,21 +107,9 @@ built, and no amount of clicking "Open Anyway" makes that safe. - It does **not** mean the app behaves differently once open. A signed and an unsigned build of the same release are the same program. -## Would you rather avoid this entirely? - -Install keel the way developers do, from the release wheels, and no warning appears at all: - -``` -pip install --find-links . ./keel_trader--py3-none-any.whl -keel versions -``` - -That path needs a terminal and a working Python. The desktop app exists precisely so that it does -not have to be the only option. - ## If this changes If keel ever has the budget, signing is a small change on our side — the release pipeline is -already built to accept it — and this page will be replaced by a sentence saying the builds are -signed. Until then, we would rather tell you the truth about what you are downloading than say -nothing and let your computer deliver the news. +already built to accept it, on both platforms — and this page will be replaced by a sentence +saying the builds are signed. Until then, we would rather tell you the truth about what you are +downloading than say nothing and let your computer deliver the news. diff --git a/packaging/macos_app.sh b/packaging/macos_app.sh index 5bcd527..c7d6368 100755 --- a/packaging/macos_app.sh +++ b/packaging/macos_app.sh @@ -14,11 +14,12 @@ # `keel.app/Contents/Resources/keel/keel ` and get the full CLI. One artifact, both # audiences, no second build. # -# THIS OUTPUT IS UNSIGNED, AND STAYS UNSIGNED. Apple notarisation requires a Developer ID -# certificate, which requires the $99/yr Developer Program; a free Apple account signs only for -# local development, and a self-signed certificate buys nothing because Gatekeeper trusts -# Apple-issued Developer IDs and nothing else. keel is open source on a small budget and has -# chosen not to pay it. +# THIS OUTPUT IS UNSIGNED, AND STAYS UNSIGNED -- as does the Windows artifact. Apple notarisation +# requires a Developer ID certificate ($99/yr); Azure Trusted Signing is ~$120/yr and, since 2024, +# does not even buy an instant SmartScreen pass. A free Apple account signs only for local +# development, and a self-signed certificate buys nothing because Gatekeeper trusts Apple-issued +# Developer IDs and nothing else. keel is open source on a small budget and has chosen not to pay +# either. # # So Gatekeeper WILL refuse the first open of a downloaded copy, and the release notes say so and # say what to do about it (System Settings -> Privacy & Security -> Open Anyway). What replaces @@ -97,7 +98,8 @@ IF MACOS REFUSES TO OPEN THIS APP, NOTHING IS BROKEN. keel is not code-signed. Code signing is a paid certificate from Apple that tells macOS who built a program. It costs \$99 per year, there is no cheaper tier and no free option for open-source projects, and a certificate we made ourselves would do nothing at all -- -macOS trusts only certificates Apple issued. +macOS trusts only certificates Apple issued. (Windows is not signed either, for the same +reason: that certificate costs even more.) keel is an open-source project with essentially no budget, and that yearly cost is not something it can commit to today. So macOS sees a program from a developer it cannot @@ -106,11 +108,22 @@ identify, and does the right thing: it stops and asks you. TO OPEN IT 1. Drag keel.app to your Applications folder. - 2. Double-click it. macOS refuses. - 3. Open System Settings -> Privacy & Security. - 4. Scroll down to the message about keel and click "Open Anyway". + 2. Eject this disk image. + 3. Open Applications and double-click keel. macOS refuses; click Done. + 4. Open System Settings -> Privacy & Security. + 5. Scroll to the Security section. There is a line saying keel was blocked, with an + "Open Anyway" button beside it. Click it. + 6. Authenticate, then click "Open Anyway" once more in the dialog that follows. -You only do this once. +You only do this once. Note that on macOS Sequoia (15) and later, right-clicking the app +and choosing Open no longer works as a shortcut -- Apple removed that path deliberately. + +PREFER NO WARNING AT ALL? + +Install from the release wheels instead. Nothing is downloaded as an application, so +nothing objects -- but it needs a terminal and Python 3.11 or later: + + pip install --find-links . ./keel_trader--py3-none-any.whl BEFORE YOU DO, PLEASE CHECK WHAT YOU DOWNLOADED diff --git a/tests/test_desktop_packaging.py b/tests/test_desktop_packaging.py index 218fcc8..d5edebd 100644 --- a/tests/test_desktop_packaging.py +++ b/tests/test_desktop_packaging.py @@ -202,6 +202,40 @@ def test_the_script_runs_no_signing_command() -> None: _INSTALL_DOC = _ROOT / "docs" / "desktop-install.md" +def test_the_install_note_covers_both_platforms_and_both_prices() -> None: + """Windows was left as "a separate decision, still open" for one round. It is not: Azure + Trusted Signing is ~$120/yr, MORE than Apple's, and since 2024 an EV certificate no longer + grants an instant SmartScreen pass -- so it buys less for more. A page that named only the + Apple cost would leave a reader assuming Windows was simply forgotten.""" + text = _INSTALL_DOC.read_text(encoding="utf-8") + assert "$99" in text + assert "120" in text + assert "SmartScreen" in text + assert "either" in text + + +def test_the_install_note_leads_with_the_path_that_has_no_warning() -> None: + """Someone on this page is deciding whether to proceed. The first thing they should read is + that there is a route with no warning at all -- not four paragraphs about certificates.""" + text = _INSTALL_DOC.read_text(encoding="utf-8") + body = text[text.index("\n## ") :] + first_heading = body.split("\n")[1] + assert "not deal with this at all" in first_heading, first_heading + assert body.index("Try it in five minutes") < body.index("The short version") + + +def test_the_install_note_gives_real_per_os_steps() -> None: + """ "Open Anyway" alone is not instructions. Someone who has never done this needs to be told + where the setting is, that Sequoia removed the right-click shortcut, and -- on Windows -- to + Unblock the zip BEFORE extracting, which is what stops the prompt returning.""" + text = _INSTALL_DOC.read_text(encoding="utf-8") + assert "Privacy & Security" in text + assert "Sequoia" in text + assert "Unblock" in text + assert "Extract All" in text + assert "Program Files" in text # and why not to use it + + def test_the_install_note_exists_and_states_the_actual_reason() -> None: """The reason is a budget, and saying so is better than "not signed at this time". @@ -210,7 +244,7 @@ def test_the_install_note_exists_and_states_the_actual_reason() -> None: they can weigh -- and it is the truth.""" text = _INSTALL_DOC.read_text(encoding="utf-8") assert "$99" in text - assert "cannot currently afford" in text + assert "cannot currently afford" in text.replace("either one", "") assert "no cheaper tier" in text or "no free option" in text # A self-signed certificate is the obvious "why not just..." and must be answered. assert "made ourselves" in text or "self-signed" in text