Distribution Guide
How AngKorGit ships to users: signing, notarization, auto-updates, and package managers. Steps marked [owner] need the project owner’s accounts/keys and cannot be automated by contributors.
1. Versioning & releases (works today)
- Update the version in
apps/desktop/src-tauri/tauri.conf.json,apps/desktop/src-tauri/Cargo.toml, and root/apppackage.json. - Move
[Unreleased]items inCHANGELOG.mdunder the new version heading. - Commit, tag
vX.Y.Z, push the tag →.github/workflows/release.ymlbuilds macOS (universal), Windows, and Linux bundles viatauri-actionand attaches them to a draft GitHub release. Review, paste the changelog section, publish.
2. Distribution WITHOUT paid signing (the current, chosen approach)
AngKorGit ships unsigned — free and independent. Users get one extra step on first launch; document it prominently (README covers this):
- macOS: the app isn’t notarized, so Gatekeeper blocks the first open.
Either right-click the app → Open → Open, or on newer macOS:
System Settings → Privacy & Security → “AngKorGit was blocked” → Open Anyway.
Terminal alternative:
xattr -cr /Applications/AngKorGit.app(removes the quarantine flag). Tauri ad-hoc-signs the binary automatically, so it runs fine on Apple Silicon once past Gatekeeper. - Windows: SmartScreen shows “Windows protected your PC” → More info → Run anyway.
- Linux: AppImage:
chmod +x AngKorGit_*.AppImageand run;.debinstalls normally.
macOS Keychain prompts: account tokens live in the Keychain, and macOS
cannot durably trust an unsigned binary — “Always Allow” does not stick, so
the first git operation that needs a token asks for permission once per app
session (keyring reads are cached in-process; accounts.rs TOKEN_CACHE).
Click Allow (not “Always Allow” — it has no effect). One prompt per launch
is expected behavior for unsigned builds; a paid Developer ID signature is the
only way to make authorization permanent.
macOS folder-access prompts (Desktop/Documents/Downloads): consent is
keyed to the app’s code signature, so the bundle must carry one. Releases up to
0.15.0 shipped with only the linker’s throwaway signature on the arm64 slice and
no bundle signature at all (codesign -d -r- AngKorGit.app said “not signed at
all”), so tccd could not validate any stored grant (Security error -67062) and
asked again on every protected-folder access, discarding each Allow. Since
0.16.0 bundle.macOS.signingIdentity is "-": the bundler ad-hoc signs the
frameworks and the whole .app (both slices, Info.plist bound, resources
sealed). The stored requirement is the build’s cdhash, so one installed build
means one prompt per folder, and each update re-asks once. No grant can match
while the binary on disk differs from the running process (a dmg dragged over a
running app, or pnpm install:mac while the old instance is open, which is why
that script quits the app first), so relaunch after installing. Stale records:
tccutil reset All dev.angkorgit.app, then relaunch and Allow once. Users
must drag the app out of the dmg into /Applications — running it from inside
the dmg triggers app translocation, where grants can never persist. Possible
follow-up, untested: signing with a custom designated requirement
(identifier "dev.angkorgit.app") would let the grant survive updates, but it
needs a re-sign step after the bundler runs and a live tccd test first.
Security honesty: unsigned ≠ unsafe. Releases are built by public GitHub Actions from public source, updates are minisign-verified (§3), and users can always build from source. If the project later earns sponsorship, Apple notarization (~$99/yr) can be added — the workflow snippet lives in git history — purely to remove the first-launch step.
3. Auto-updates — ACTIVE ✅ (free, Apple-independent)
Updates are pull-based from GitHub releases and verified with the project’s own minisign key before installing — a tampered download will never run.
Already wired in the codebase:
- Keypair generated; private key:
~/.tauri/angkorgit.keyon the owner’s machine — BACK IT UP. If lost, existing installs can never update again. Public key: embedded intauri.conf.json → plugins.updater.pubkey. tauri-plugin-updater+tauri-plugin-processregistered; capabilityupdater:default,process:default;bundle.createUpdaterArtifacts: true.- Frontend: silent check 5s after startup (
features/updater/check.ts) → “Update available” toast with Update now (download, verify, relaunch); manual Check for updates in the Settings rail footer. release.ymlpassesTAURI_SIGNING_PRIVATE_KEY(_PASSWORD)to tauri-action, which then also generates and uploadslatest.json.
[owner] one-time — done: both GitHub secrets are configured (releases since
0.2.0 ship .sig files and latest.json):
TAURI_SIGNING_PRIVATE_KEY— the contents of~/.tauri/angkorgit.keyTAURI_SIGNING_PRIVATE_KEY_PASSWORD— set to an empty value (required: without the env var Tauri tries an interactive prompt and headless builds fail).
4. Homebrew cask [live — own tap]
Published at cheat2001/homebrew-tap (Casks/angkorgit.rb). Install:
brew install --cask cheat2001/tap/angkorgit
One command only: the cask runs xattr -cr on the installed app in a
postflight block, clearing the Gatekeeper quarantine automatically (needed
because the app is unsigned; recent Homebrew removed --no-quarantine).
Own-tap casks may do this — homebrew/cask proper would reject it, so when the
cask eventually moves there, signing/notarization must replace the postflight.
On every release the cask must be bumped: update version and sha256
(shasum -a 256 of the new universal dmg) in
cheat2001/homebrew-tap/Casks/angkorgit.rb. The cask sets auto_updates true
(the app self-updates), so tap users who installed once still get new versions
in-app; the bump matters for fresh installs. Add this to the release checklist.
Once the project has traction (75+ stars, 30+ forks) AND the app is
signed/notarized, submit to homebrew-cask proper for
brew install --cask angkorgit.
5. Website (live)
- Live at
https://angkorgit.app/(Astro, static, GitHub Pages via.github/workflows/website.yml; custom domain + HTTPS enforced). - Sections: hero with graph screenshot, features, gallery, performance, AI, install (per-OS download cards + terminal one-liners with copy buttons), open-source, final CTA.
- Docs are rendered on-site at
/docs/directly fromdocs/*.md(seeapps/website/src/content.config.ts) — edit a doc and the site updates on the next deploy; no duplication. - SEO: meta/OG/JSON-LD, sitemap, Google Search Console verified
(URL-prefix property),
robots.txt→sitemap-index.xml. - Launch/verification runbook:
docs/Launch-Checklist.md.