feature fixes

This commit is contained in:
pj committed 2026-08-28 21:47:48 +05:30
1 parent 586ee946d0
commit c1c47bc513
63 files changed
+12083 -229

No files matched your search

+75 -17
View File
@@ -23,12 +23,16 @@ and `src-tauri/Cargo.toml` together, commits that to main, tags it, and builds t
whatever main happens to be by then.
It builds one universal macOS bundle and publishes nothing until it has landed. The last job
downloads `latest.json` and refuses to take the release out of draft unless `darwin-aarch64` and
`darwin-x86_64` are both present in it. One universal build writes both of those keys, pointing
them at the same archive and the same signature, because an installed copy asks the manifest for
the architecture it is running on and never for a universal one. A half-populated manifest is worse
than no release at all: the updater would offer an update to the platforms that made it and error
on the ones that did not.
downloads `latest.json` and refuses to take the release out of draft unless three things hold: the
version in the manifest is the version in the tag, `darwin-aarch64` and `darwin-x86_64` are both
present, and each of them has a signature as well as a url. One universal build writes both of
those keys, pointing them at the same archive and the same signature, because an installed copy
asks the manifest for the architecture it is running on and never for a universal one. A
half-populated manifest is worse than no release at all: the updater would offer an update to the
platforms that made it and error on the ones that did not. A manifest carrying the version before
this one is worse again, because it tells everybody the copy they are already running is the newest
there is, and an entry with an empty signature is an update every installed copy downloads and then
refuses.
Linux is not built. It was until recently, because this pipeline was copied from margin-calendar,
which ships on Linux. This app does not, so the row and the manifest key it required are gone and
@@ -38,17 +42,54 @@ Windows is not built. Nothing in `tauri.conf.json` targets it and the app has ne
## What the build needs
Two repository secrets: `TAURI_SIGNING_PRIVATE_KEY` and `TAURI_SIGNING_PRIVATE_KEY_PASSWORD`,
which sign the updater artifacts so an installed copy can tell a real update from anything else
offered at the same URL. The public half lives in `src-tauri/tauri.release.conf.json`, baked into
every build, so the private half can never be rotated without stranding everyone who has not
updated yet; back up the key and its password somewhere that is not the machine that generated
them. That file currently carries the placeholder `REPLACE_WITH_TAURI_SIGNER_PUBKEY`; generating
the real keypair and committing its public half in is a one-time step that has to happen before the
first signed release can go out.
Two repository secrets sign the updater artifacts, so that an installed copy can tell a real update
from anything else offered at the same URL: `TAURI_SIGNING_PRIVATE_KEY` and
`TAURI_SIGNING_PRIVATE_KEY_PASSWORD`. The public half lives in
`src-tauri/tauri.release.conf.json`, baked into every build, so the private half can never be
rotated without stranding everyone who has not updated yet; back up the key and its password
somewhere that is not the machine that generated them.
Beyond the signing key there is nothing to provision. Margin Docs talks to no external API and
holds no OAuth client, unlike margin-calendar, so there are no other repository secrets and nothing
That file currently carries the placeholder `REPLACE_WITH_TAURI_SIGNER_PUBKEY`, and the keypair
behind it does not exist yet. Making it is a one-time step, run once by whoever owns the repository
and never again:
```
pnpm tauri signer generate -w ~/.tauri/margin-docs.key
```
It asks for a password, writes the private key to that path and the public key beside it as
`margin-docs.key.pub`, and prints both. The public one replaces the placeholder in
`tauri.release.conf.json` and is committed. The private one is the contents of
`~/.tauri/margin-docs.key`, pasted into `TAURI_SIGNING_PRIVATE_KEY`, with its password in
`TAURI_SIGNING_PRIVATE_KEY_PASSWORD`. Neither the key file nor the password goes into the
repository.
Six more secrets codesign and notarize the bundle, and unlike the two above they are optional as
far as the workflow is concerned: with none of them set the build still runs, still publishes, and
produces an ad hoc signed app. `APPLE_CERTIFICATE` is the Developer ID Application certificate
exported from Keychain Access as a `.p12` and base64 encoded (`base64 -i certificate.p12`), with
the password it was exported under in `APPLE_CERTIFICATE_PASSWORD`. `APPLE_SIGNING_IDENTITY` is the
certificate's full name, which looks like `Developer ID Application: Your Name (TEAMID)`. The other
three are for notarization: `APPLE_ID` is the Apple account's email address, `APPLE_PASSWORD` is an
app-specific password made at appleid.apple.com rather than the account password itself, and
`APPLE_TEAM_ID` is the ten character team identifier.
Those six are all or nothing. A repository with a certificate but no notarization credentials fails
the build rather than warning, because a signed bundle that has not been notarized is one Gatekeeper
refuses on any machine that has not seen it before, and finding that out from a user is worse than
finding it out from a red run.
The bundle asks for the hardened runtime, which notarization requires, and for no entitlements at
all. That is worth a sentence because it nearly went the other way. Deleting a document goes to the
Trash through the `trash` crate, whose macOS default is to ask Finder over an Apple event, and the
hardened runtime blocks an Apple event unless the bundle carries
`com.apple.security.automation.apple-events` and the user agrees to a permission prompt about
controlling Finder. `src-tauri/src/fs.rs` asks for `trashItemAtURL:` instead, which needs none of
that. The cost is Put Back, which the Finder method leaves on the file and this one does not; the
file is still in the Trash and can still be dragged out of it.
Beyond signing there is nothing to provision. Margin Docs talks to no external API and holds no
OAuth client, unlike margin-calendar, so there are no other repository secrets and nothing
equivalent to a `google-credentials.json` to embed at build time.
## Updates
@@ -56,4 +97,21 @@ equivalent to a `google-credentials.json` to embed at build time.
Installed copies check
`https://github.com/priyanshujain/margin-docs/releases/latest/download/latest.json` and update
themselves from it. `--latest` on the publish step is what moves that pointer, so a release that
fails the manifest check stays a draft and no one is offered a broken update.
fails the manifest check stays a draft and no one is offered a broken update. The app checks that
URL once a day in the background and on the Check for Updates menu item, and either way what
happens next is a dialog rather than an install: the version, the release notes, the download with
a progress bar, and Later as a real answer.
Self-update does not work yet, and it will not until there is an Apple Developer ID certificate.
This is not a gap in the workflow, which is wired for one, or in the app, which is wired for the
whole flow. It is macOS: an update replaces the installed bundle with the downloaded one, and the
system will not let an ad hoc signed bundle take the place of a signed one, nor run a replacement
whose signature does not match what was there before. Every build this repository can currently
produce is ad hoc signed, so every self-update attempt ends in a bundle the system refuses to
launch. Until the certificate exists, updates are something to install by hand, and the honest
version of the feature is that the app will find the update, show it, download it, and fail on the
last step.
There is a second thing gated behind the same certificate. The build is not notarized either, so a
copy downloaded from the releases page is quarantined by the browser and refused on first launch
with the message about an unidentified developer. Both problems have the one fix.