skills/rust-app-distribution/SKILL.md
Distribution pipeline for signed Rust desktop applications -- code signing, notarization, auto-updates, and package manager distribution. Activate on: code signing, macOS notarization, Apple Developer, Authenticode, Windows signing, auto-updater, Homebrew formula, winget manifest, Scoop bucket, Tauri updater, app distribution, release pipeline. NOT for: library crate publishing (use crates.io docs), web deployment (use devops-automator).
npx skillsauth add curiositech/windags-skills rust-app-distributionInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Ship signed Rust desktop applications to users on macOS and Windows. This skill covers the full distribution pipeline: code signing certificates, Apple notarization, Windows Authenticode, auto-updater mechanisms, and publishing to package managers (Homebrew, winget, Scoop).
IF macOS distribution needed:
IF Windows distribution AND budget < $50/month:
IF CI platform is GitHub Actions:
IF simple GitHub-hosted releases:
cargo tauri signer generatehttps://github.com/ORG/REPO/releases/latest/download/latest.jsonIF custom release infrastructure needed:
IF enterprise deployment with restricted internet:
IF macOS users AND want simple install:
komac or manuallyIF Windows users AND mainstream distribution:
komac for manifest generationIF Windows power users OR faster approval:
Detection rule: xcrun notarytool returns "The entitlements in the app are invalid" or similar entitlement errors.
Symptom: Notarization fails despite valid signing.
Diagnosis:
Fix:
# Check current entitlements
codesign -d --entitlements - MyApp.app
# Remove Mac App Store entitlements, keep only:
# - com.apple.security.cs.allow-jit (if needed)
# - com.apple.security.cs.allow-unsigned-executable-memory (if needed)
# - com.apple.security.cs.disable-library-validation (if needed)
# - com.apple.security.network.client (for network access)
Detection rule: Windows users report "Windows protected your PC" even with valid EV certificate.
Symptom: Valid signature but SmartScreen still warns about unknown publisher.
Diagnosis:
Fix:
Detection rule: Update check succeeds but installation fails with signature verification error.
Symptom: App downloads update but refuses to install.
Diagnosis:
Fix:
# Verify signature manually
cargo tauri signer verify \
--public-key-path ~/.tauri/myapp.pub \
--signature-path release.sig \
--file MyApp-setup.exe
# Check manifest format
curl -s https://releases.myapp.com/latest.json | jq .
# Re-sign update if signature invalid
cargo tauri signer sign \
--private-key-path ~/.tauri/myapp.key \
--file MyApp-setup.exe
Detection rule: CI builds start failing with "certificate not found" or "certificate expired" errors.
Symptom: Previously working builds suddenly fail during signing step.
Diagnosis:
Fix:
Detection rule: Package manager users report "architecture not supported" or binary won't launch.
Symptom: Installer downloads but app won't run on user's architecture.
Diagnosis:
Fix:
# Ensure complete architecture matrix
strategy:
matrix:
include:
- os: macos-latest
target: aarch64-apple-darwin
- os: macos-13 # Intel runner
target: x86_64-apple-darwin
- os: windows-latest
target: x86_64-pc-windows-msvc
# Verify binary architecture
file target/release/myapp # Should show correct arch
lipo -info target/release/myapp # macOS universal binary check
Scenario: Setting up automated releases for a Tauri app "DevTools" that needs macOS and Windows distribution.
Step 1 - Certificate Setup:
# Generate Apple Developer ID (via Apple Developer portal)
# Download .p12 file, encode for CI:
base64 -i ~/Downloads/certificates.p12 -o apple_cert.txt
# For Windows - setup Azure Trusted Signing:
# 1. Create account at codesigning.azure.net
# 2. Create certificate profile "production"
# 3. Note tenant ID, client ID, account name
Expert catches: Novices often skip the app-specific password step or try to use their Apple ID password directly. Expert immediately generates app-specific password at appleid.apple.com.
Step 2 - Auto-Updater Keys:
# Generate signing keypair
cargo tauri signer generate -w ~/.tauri/devtools.key
# Output shows:
# Private key: ~/.tauri/devtools.key (keep secret!)
# Public key: dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWdu... (embed in app)
Expert catches: The public key goes in tauri.conf.json under plugins.updater.pubkey, NOT as a file. Novices often try to reference a pubkey file path.
Step 3 - CI Configuration:
name: Release
on:
push:
tags: ["v*"]
jobs:
build:
strategy:
matrix:
include:
- os: macos-latest
target: aarch64-apple-darwin
- os: windows-latest
target: x86_64-pc-windows-msvc
runs-on: ${{ matrix.os }}
steps:
- uses: tauri-apps/tauri-action@v0
env:
# Apple secrets
APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }}
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_PASSWORD: ${{ secrets.APPLE_APP_PASSWORD }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
# Windows secrets
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
# Update signing
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
with:
tagName: v__VERSION__
releaseName: "DevTools v__VERSION__"
Expert catches: The APPLE_SIGNING_IDENTITY must match the certificate name exactly, including the team ID in parentheses. Novices often forget the team ID or get the format wrong.
Decision point navigated: Since this is a GitHub Actions setup with Windows distribution, expert chose Azure Trusted Signing over EV certificate for cost and simplicity. For a GitLab CI setup, would have chosen traditional EV cert.
Step 4 - Testing Update Flow:
// In the app frontend
import { check } from "@tauri-apps/plugin-updater";
async function testUpdate() {
console.log("Checking for updates...");
const update = await check();
if (update) {
console.log(`Found update: ${update.version}`);
// Expert validates signature is checked automatically by Tauri
await update.downloadAndInstall();
}
}
Expert catches: The updater automatically validates signatures using the embedded public key. Novices often try to add manual signature verification, which is redundant and error-prone.
Pre-release validation checklist:
codesign -dv MyApp.app)spctl --assess --type exec -v MyApp.app)signtool verify /pa MyApp.exe)Do NOT use this skill for:
cargo publish and crates.io documentation insteaddevops-automator skill for containerized deploymentrust-tauri-development skill for app development and local buildingDelegate to other skills:
devops-automatorrust-tauri-developmentcross-platform-desktopdata-ai
license: Apache-2.0 NOT for unrelated tasks outside this domain.
development
Use when designing caching strategies (cache-aside, write-through, write-behind), implementing distributed locks, building rate limiters, leaderboards, real-time streams (XADD/consumer groups), pub/sub, or tuning eviction policies. Triggers: thundering-herd on cache miss, dogpile on key expiry, Redlock vs SET-NX-PX choice, sliding-window rate limiter, hot-key on a single cluster slot, big-key blowup, MULTI/EXEC across slots, KEYS in production. NOT for Redis Cluster operations/admin (different domain), embedded KV (SQLite, leveldb), in-process LRU caches, or Memcached.
tools
Drawing the `'use client'` boundary correctly in React Server Components apps (Next.js App Router, RSC frameworks) — leaf-pushing, slot composition, serialization rules, and environment poisoning prevention. Grounded in react.dev and Next.js 16 docs.
development
Use when designing rate limiting for an API, choosing between token bucket / sliding window / leaky bucket / fixed window, implementing it in Redis, deciding edge (Cloudflare/Upstash) vs origin enforcement, sizing per-user vs per-IP vs per-endpoint quotas, returning the right 429 response with Retry-After, or fixing the boundary-burst bug in fixed-window limiters. Triggers: 429 too many requests, INCR + EXPIRE, ZADD + ZREMRANGEBYSCORE + ZCARD, X-RateLimit-Remaining header, Cloudflare WAF rate limiting rules, Upstash @upstash/ratelimit, leaky bucket shaping vs policing, distributed rate limiter consistency. NOT for DDoS mitigation specifically (different scale), CAPTCHA / bot management, full WAF design, or per-user quota billing.