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:
@@ -80,6 +80,8 @@ docs/platform-flags.md what differs off Windows, and the gotchas that have c
|
||||
docs/manual-checks.md what no test can reach, and what to look for when checking by hand
|
||||
docs/android-port.md the Android head: what was decided, what is built, what is left
|
||||
scripts/ release-windows.ps1 — builds, packs and publishes the Windows client
|
||||
release-macos.sh — the same, signed and notarized, on a Mac
|
||||
build/macos/ the entitlements and Info.plist template the macOS bundle is built from
|
||||
```
|
||||
|
||||
Everything under `src/DodoSSH.Client.*` except the two heads and `Shell` is deliberately free of Avalonia.
|
||||
@@ -152,8 +154,32 @@ reinstalling asks for your passphrase rather than starting over. Use **Sign out*
|
||||
you want the machine to genuinely forget everything — an uninstall is not a sign-out, and does not withdraw
|
||||
this machine's device key from your account.
|
||||
|
||||
Cutting a release is `scripts/release-windows.ps1`, run by a person on a Windows machine. Deliberately not a
|
||||
CI job; ADR 0013 decision 3 explains why, and it is not only that the runners are Linux.
|
||||
## Installing on macOS
|
||||
|
||||
A `.pkg` on the same release page, for Apple Silicon. Everything above about where a client may come from,
|
||||
about the update check and about uninstalling applies unchanged; what differs is worth three short
|
||||
paragraphs.
|
||||
|
||||
**It is signed and notarized, so there is no warning to click past.** That is not generosity — macOS refuses
|
||||
to open an un-notarized download outright rather than warning about it, so unlike the Windows build there
|
||||
was never an unsigned option. If you *do* see "cannot be opened because Apple cannot check it for malicious
|
||||
software", the file did not come from the project's release page, and that is worth taking literally.
|
||||
|
||||
**Apple Silicon only for now.** An Intel package is a small amount of work and no one here has an Intel Mac
|
||||
to check it on, and this project does not ship desktop builds nobody has run — see
|
||||
[docs/manual-checks.md](docs/manual-checks.md). Under Rosetta the arm64 build will not run; there is no
|
||||
graceful version of that, and the honest answer is that the platform is not covered yet.
|
||||
|
||||
**Touch ID can stand in for your passphrase**, on a Mac with a Secure Enclave. The key that unwraps your
|
||||
device key is generated inside the enclave and never leaves it, and the enclave — not DodoSSH — is what
|
||||
requires your fingerprint or login password before it will use it. Cancel the prompt and you get the
|
||||
passphrase screen, always. The application lives at `/Applications/DodoSSH.Desktop.app` and your vault cache
|
||||
at `~/Library/Application Support/DodoSSH`, which are deliberately two different places so that removing the
|
||||
first never touches the second.
|
||||
|
||||
Cutting a release is `scripts/release-windows.ps1`, run by a person on a Windows machine, and
|
||||
`scripts/release-macos.sh` on a Mac. Deliberately not a CI job; ADR 0013 decision 3 explains why, and it is
|
||||
not only that the runners are Linux.
|
||||
|
||||
### The nightly desktop build
|
||||
|
||||
@@ -886,8 +912,18 @@ keychain plus a terminal — and the spike that gates all of it.
|
||||
[ADR 0013](docs/adr/0013-desktop-distribution-and-updates.md), and
|
||||
[Installing on Windows](#installing-on-windows) for what a user sees.
|
||||
|
||||
Still to do here: signing (the first release is unsigned, and the trigger for buying a certificate is the
|
||||
first release aimed at strangers), and macOS and Linux packaging.
|
||||
**The macOS half is built on the same machinery**, and signed from the start because Gatekeeper leaves no
|
||||
choice: `scripts/release-macos.sh` publishes, signs every native library, notarizes with Apple and staples
|
||||
the ticket before it will hand anything over, and refuses to upload until a person has installed it. The
|
||||
device key is held in the Secure Enclave behind Touch ID. CI publishes `osx-arm64` and builds the `.app`
|
||||
on every main build to prove it still packages, and uploads nothing. See
|
||||
[ADR 0013](docs/adr/0013-desktop-distribution-and-updates.md) decision 10 and
|
||||
[Installing on macOS](#installing-on-macos).
|
||||
|
||||
Still to do here: Windows signing (the first Windows release is unsigned, and the trigger for buying a
|
||||
certificate is the first release aimed at strangers), macOS on Intel, Linux packaging, and Phase 18 of the
|
||||
manual checks — the macOS build has never actually run, because there is no macOS runner in CI and
|
||||
everything above is verified only as far as the bundle.
|
||||
- **M5 — multi-provider OIDC**, identity key rotation, per-item content keys.
|
||||
|
||||
## Licence
|
||||
|
||||
Reference in New Issue
Block a user