Public Access
Give the desktop a macOS head, signed from the first release
The same application, the same Velopack and the same two-phase person-run release as Windows, with four things forced to differ. Signing is a precondition rather than an improvement: Gatekeeper refuses an un-notarized download outright instead of warning about it, so there was never the "unsigned for now" that ADR 0013 decision 8 argues for on Windows, and release-macos.sh refuses to start without the identities. The packaging split is narrower than it first looked, and the old claim at the foot of ci.yml is why it was worth checking rather than assuming. vpk cross-compiles when told to: 'vpk [osx] bundle' builds a real .app on any platform, and CI now publishes osx-arm64 and bundles it on every main and tag build, which is what catches a restore graph with no macOS native asset. There is no '[osx] pack' off a Mac, and that part is correct — pack drives codesign, notarytool and stapler, which exist nowhere else. The dylib signing loop in the script looks redundant beside vpk's own pass and is not. vpk signs with 'codesign --deep', which is the shape Apple documents as wrong for nested code, and platform-flags has recorded a notarization rejection that names no file since before any of this existed. Signing each native binary inside-out first leaves that pass nothing to get wrong. MacDeviceKeyStore reaches ADR 0007's conclusion through different hardware: a P-256 key in the Secure Enclave under an access control requiring user presence, so the platform enforces the gate rather than this process — which is the whole point of that ADR's amendment. The enclave holds no other kind of key, hence ECIES where Windows uses RSA-OAEP, and the shape that falls out is better than the Windows one: sealing needs only the public half and is silent, so only unlock prompts. IsSupported probes rather than infers, because three ordinary Macs answer no — an Intel machine without a T2, one with no login password, and every unsigned development build, since enclave keys need a signing identity. Two decisions worth stating because they are reversible. arm64 only: a second channel is small work and nobody here has an Intel Mac to walk Phase 18 on, and an x64 package would be the only artefact in this repository reaching users unverified. And the pack id stays DodoSSH.Desktop even though vpk names the bundle after it, so /Applications holds DodoSSH.Desktop.app: decision 2's reasoning binds harder here, because a pack id of DodoSSH would put Velopack's install root on top of ClientPaths.DataDirectory and let an uninstall take the user's un-synced outbox with it. CFBundleDisplayName puts the product name back in front of a person. Measured rather than assumed, since none of it is obvious: the publish and the bundle were both run, LSMinimumSystemVersion is 12.0 because that is the minos in the apphost's own LC_BUILD_VERSION, and vpk copies a custom Info.plist verbatim with no substitution at all — which is why the plist is a template the script renders and not a committed file. What is not done is the half that needs the hardware. There is no macOS runner, so nothing past "it bundles" has ever run. Phase 18 is the whole of the verification, and the two checks most likely to fail are the terminal against WKWebView and the enclave interop, neither of which has executed once.
This commit is contained in:
@@ -228,6 +228,44 @@ changes.
|
||||
token, and it puts a compellable third party in the signing path — which is ADR 0011 rule 3's shape one
|
||||
layer down, declined there for reasons that do not stop applying because the vendor changed.
|
||||
|
||||
**This rule is Windows-only, and macOS gets the opposite one.** See decision 10: there is no "unsigned for
|
||||
now" available on that platform at any price, because Gatekeeper refuses rather than warns.
|
||||
|
||||
### 10. macOS is a second desktop platform on the same machinery, signed from the start
|
||||
|
||||
The macOS head is the same application, the same Velopack, and the same two-phase person-run release. Four
|
||||
things differ, and each is forced rather than chosen.
|
||||
|
||||
**Signing is a precondition, not an improvement.** Decision 8's whole argument — one dialog per user per
|
||||
lifetime, buy a certificate when a stranger is invited to install — has no macOS equivalent. An
|
||||
un-notarized download is refused outright, so the Developer ID certificate and the notarization round trip
|
||||
are the price of the package existing. `scripts/release-macos.sh` therefore refuses to run without the
|
||||
signing identities, where the Windows script refuses nothing.
|
||||
|
||||
**The channels are `osx` and `osx-nightly`, and they are separate for decision 9's reason.** Four channels
|
||||
now publish to one repository, and the only thing keeping a Mac from being offered a Windows package is
|
||||
that it never reads that index. The macOS nightly channel is named and has no publisher: CI builds and
|
||||
bundles the macOS head to prove it still builds, and uploads nothing, exactly as it does for the Windows
|
||||
release channel.
|
||||
|
||||
**The pack id is shared with Windows, and on macOS it is visible.** vpk names the bundle after the pack id,
|
||||
so `/Applications` holds `DodoSSH.Desktop.app`. Decision 2's reasoning applies with more force here rather
|
||||
than less: a pack id of `DodoSSH` would put Velopack's install root on `~/Library/Application
|
||||
Support/DodoSSH`, which is `ClientPaths.DataDirectory`, and an uninstall would take the user's un-synced
|
||||
outbox with it. `CFBundleDisplayName` puts the product name back in front of a person; the directory keeps
|
||||
the id.
|
||||
|
||||
**arm64 only, because the check is the scarce thing.** Velopack keys a channel to one architecture, and an
|
||||
Intel package would be the only artefact in this repository reaching users without somebody having walked
|
||||
Phase 18 against it. The engineering for a second channel is small and is described in the release script;
|
||||
what is missing is an Intel Mac to verify on, and shipping blind is the thing this project's manual-check
|
||||
discipline exists to refuse.
|
||||
|
||||
**And one thing that does not differ, which is worth saying because it is the expensive half.** The
|
||||
capability to publish still lives on a person's machine and never in CI. Notarization does not change that:
|
||||
Apple's ticket says this build came from this developer account, and says nothing about whether the build
|
||||
should have been made. Velopack clients still apply what their feed serves. Rule 3 is untouched.
|
||||
|
||||
### 9. There is a second desktop channel, published by CI, and it is a second application
|
||||
|
||||
[ADR 0014](0014-android-updates.md) gave the phone a nightly channel and rule 3 above gives the desktop
|
||||
|
||||
Reference in New Issue
Block a user