diff --git a/docs/COMMERCIAL-INSTALLER-BACKLOG.md b/docs/COMMERCIAL-INSTALLER-BACKLOG.md index bdaf41d..c710197 100644 --- a/docs/COMMERCIAL-INSTALLER-BACKLOG.md +++ b/docs/COMMERCIAL-INSTALLER-BACKLOG.md @@ -17,6 +17,7 @@ Repo now includes **authoring/docs scaffolds** for the two commercial gaps that | **WiX tray presence MSI skeleton** | [`platform/windows/wix/`](../platform/windows/wix/) — `VeraeTrayShortcuts.wxs`, `VeraeTrayShortcutsFragment.wxs`, [`README.md`](../platform/windows/wix/README.md); driver [`scripts/build-tray-msi.ps1`](../platform/windows/scripts/build-tray-msi.ps1) | Non-elevated **per-user** WiX v3 product + shortcut fragment: stages `verae-tray.ps1`, Start Menu `Programs\Verae\Verae Tray.lnk`, Startup `Verae Tray.lnk`. **ProductVersion** wired from `Get-VeraePackageVersion` → `internal/job.HelperVersion` (or `VERSION=` / `-Version`). `build-tray-msi.ps1` runs **candle/light** when present; otherwise prints WiX install tip (exit 0). | Full elevated commercial MSI (printers, Program Files, Authenticode, NSIS parity, CI-signed MSI in `dist/`). No MSI binary without the WiX toolset on the build host. | | **Menubar notarize checklist** | [`platform/macos/menubar/NOTARIZE-CHECKLIST.md`](../platform/macos/menubar/NOTARIZE-CHECKLIST.md) | Operator step list: unsigned build → codesign hardened runtime → `ditto` zip → `notarytool` (keychain profile **or** API key placeholders) → staple → `spctl`. No secrets. | Automated sign/notarize in `build-menubar-app.sh`, stapled `.app.zip`/DMG release, or live CI keychain import. | | **Menubar CI notary sketch** | [`platform/macos/menubar/ci-notarize.yml.example`](../platform/macos/menubar/ci-notarize.yml.example) | GHA/Forgejo **example** workflow: default **unsigned** `build-menubar-app.sh` + artifact; commented notarytool job gated `if: false`; secret **names** only (`APPLE_API_KEY_*`, `APPLE_CODESIGN_IDENTITY`, …). | Not a live workflow under `.github/`; no staple; not Gatekeeper-proven. | +| **Menubar notary dry-run** | [`platform/macos/menubar/notary-dry-run.sh`](../platform/macos/menubar/notary-dry-run.sh) | Local helper: if `notarytool` present print codesign/`ditto`/submit/staple recipe with env **names** only; else Xcode CLT tip (exit 0). Links [`ci-notarize.yml.example`](../platform/macos/menubar/ci-notarize.yml.example) + this backlog. **Never submits** unless `NOTARY_SUBMIT=1`. | Not live CI; does not codesign by default; not Gatekeeper-proven. | | **Full elevated MSI (StageFull + light)** | [`Product-Full.wxs`](../platform/windows/wix/Product-Full.wxs) + [`scripts/build-full-msi.ps1`](../platform/windows/scripts/build-full-msi.ps1) (+ outline, [`SILENT_PROPS.md`](../platform/windows/wix/SILENT_PROPS.md), [`CI-SIGN-NOTARY.md`](../platform/windows/wix/CI-SIGN-NOTARY.md), [`DUAL-SHIP.md`](../platform/windows/wix/DUAL-SHIP.md)) | Elevated WiX v3 product: perMachine, Feature/ComponentGroups for **bin** (`verae-print.exe` required), **scripts**, **docs**, Start Menu; silent public props; distinct UpgradeCode. `build-full-msi.ps1` creates `StageFull/{bin,scripts}`, copies or Go-builds EXEs, copies scripts/LICENSE/README, stamps **ProductVersion** from `Get-VeraePackageVersion`, runs candle/light → `VeraePrintStamp-windows-*-.msi`. WiX missing → **exit 1** + clear tip. Version defaults on build-windows / build-pkg / NSIS / build-installer aligned to HelperVersion. Commented deferred CA + `InstallExecuteSequence` stubs for `install-printer.ps1` (no binaries required). Dual-ship runbook documents NSIS vs MSI clean-VM gates + **thin-NSIS exit checklist**. | **Not** Authenticode-signed; printer CAs still **commented** (not scheduled/tested); properties not yet honored by live CAs; not Intune-proven; NSIS still primary full install; CI builds **unsigned** MSI only (sign step not live). | | **CI unsigned full MSI** | [`.github/workflows/windows-msi.yml`](../.github/workflows/windows-msi.yml) + DUAL-SHIP § CI artifact | `windows-latest`: install WiX v3 → `build-full-msi.ps1` → upload artifact `VeraePrintStamp-windows-msi-unsigned`. Future Authenticode secret **names** only in workflow comments / CI-SIGN-NOTARY. | No live `signtool`; no certs in git; not a production download channel. | @@ -40,6 +41,7 @@ Repo now includes **authoring/docs scaffolds** for the two commercial gaps that | **Offline dual-ship smoke** [`dual-ship-smoke.ps1`](../platform/windows/scripts/dual-ship-smoke.ps1) (prints A/B/C; **VM C blocked until CAs enabled**; `-VerifyArtifacts` → existence + `fill-manifest-sha256.ps1`) | Does **not** replace clean-VM sign-off; no install/sign/upload | | **Enable printer CAs** [`enable-printer-cas.ps1`](../platform/windows/scripts/enable-printer-cas.ps1) + wix README § Enable printer CAs | Unwraps `DEFERRED_PRINTER_CAS:OFF` in Product-Full for VM C; does **not** build/test/sign; default remains disabled | | **Authenticode dry-run** [`sign-dry-run.ps1`](../platform/windows/scripts/sign-dry-run.ps1) + [`CI-SIGN-NOTARY.md`](../platform/windows/wix/CI-SIGN-NOTARY.md) | Local verify + print sign cmds only (**no secrets**). Live CI signtool / Trusted Signing still **not** enabled | +| **Notary dry-run** [`notary-dry-run.sh`](../platform/macos/menubar/notary-dry-run.sh) + [`ci-notarize.yml.example`](../platform/macos/menubar/ci-notarize.yml.example) | Local print submit recipe (env **names**); tip if no notarytool; submit only if `NOTARY_SUBMIT=1`. Live notary CI still **not** enabled | **Still use for day-to-day presence (no WiX / no Apple certs):** Windows `scripts/build-tray-startmenu.ps1` + `install-tray-startup.ps1`; macOS `verae-print menubar --install` / unsigned `build-menubar-app.sh`. Full product install remains NSIS (`installer-windows.nsi`) and macOS `pkg/build-pkg.sh`. Optional: `build-tray-msi.ps1` (WiX tip exit 0); `build-full-msi.ps1` (needs WiX; exit 1 if missing). @@ -133,6 +135,7 @@ NSIS product already covers much of the *install experience* (files under Progra | **Unsigned** menu-bar `.app` builder | [`platform/macos/menubar/build-menubar-app.sh`](../platform/macos/menubar/build-menubar-app.sh) | Dev/local only; copies entitlements but **does not** codesign | | Notarization **documentation only** (menubar) | [`platform/macos/menubar/README.txt`](../platform/macos/menubar/README.txt) + [PACKAGING.md](PACKAGING.md) § Codesign + notarization | Manual steps; no automated menubar notarize | | **Notarize checklist** (menubar) | [`platform/macos/menubar/NOTARIZE-CHECKLIST.md`](../platform/macos/menubar/NOTARIZE-CHECKLIST.md) | **Scaffold shipped** — notarytool placeholders, staple, `spctl`; no secrets; automation still open | +| **Notary dry-run** (menubar) | [`platform/macos/menubar/notary-dry-run.sh`](../platform/macos/menubar/notary-dry-run.sh) | **Tool** — print submit recipe (env names) or Xcode tip; links `ci-notarize.yml.example` + this backlog; **no submit** unless `NOTARY_SUBMIT=1` | | Packaging smoke | [`platform/smoke-packaging-metadata.sh`](../platform/smoke-packaging-metadata.sh) | Version + “no elevated MSI” + IPP purity — not Gatekeeper | ### Missing for commercial notarized `.app` @@ -185,6 +188,7 @@ NSIS product already covers much of the *install experience* (files under Progra | Windows **MSI** full product (files + ARP) | **Yes authoring** (`Product-Full.wxs` + `build-full-msi.ps1` StageFull → light; CA schedule stubs commented) | **No commercial** — unsigned; printer CAs not live; NSIS still primary | | Dual-ship NSIS↔MSI runbook | **Yes** ([`DUAL-SHIP.md`](../platform/windows/wix/DUAL-SHIP.md)) | **Docs only** — clean-VM validation + thin-NSIS exit checklist still unchecked | | Menubar CI notary example | **Yes** ([`ci-notarize.yml.example`](../platform/macos/menubar/ci-notarize.yml.example)) | **Example only** — unsigned default; notary job `if: false` | +| Menubar notary dry-run | **Yes** ([`notary-dry-run.sh`](../platform/macos/menubar/notary-dry-run.sh)) | **Scaffold** — print recipe / tip; submit gated `NOTARY_SUBMIT=1` only | | Windows Authenticode pipeline | **Draft doc** (`wix/CI-SIGN-NOTARY.md`) + **dry-run** [`sign-dry-run.ps1`](../platform/windows/scripts/sign-dry-run.ps1) | **No** — no live signtool job (**do not claim shipped**) | | macOS menu bar LaunchAgent | Yes | Yes (dev/ops) | | macOS unsigned menubar `.app` | Yes | **No** (Gatekeeper) | @@ -209,6 +213,7 @@ NSIS product already covers much of the *install experience* (files under Progra - [`platform/macos/menubar/`](../platform/macos/menubar/) — menu bar + unsigned `.app` + notarize docs/checklist - [`platform/macos/menubar/NOTARIZE-CHECKLIST.md`](../platform/macos/menubar/NOTARIZE-CHECKLIST.md) — menubar notarytool step list - [`platform/macos/menubar/ci-notarize.yml.example`](../platform/macos/menubar/ci-notarize.yml.example) — GHA/Forgejo menubar CI sketch (unsigned default; secret names only) +- [`platform/macos/menubar/notary-dry-run.sh`](../platform/macos/menubar/notary-dry-run.sh) — local notarytool dry-run (print recipe; `NOTARY_SUBMIT=1` to submit) - [`docs/installer-registration-api.md`](installer-registration-api.md) — installer ↔ portal registration API - [`README.md`](../README.md) — top-level packaging pointers diff --git a/platform/macos/menubar/NOTARIZE-CHECKLIST.md b/platform/macos/menubar/NOTARIZE-CHECKLIST.md index fe3e994..79a5a35 100644 --- a/platform/macos/menubar/NOTARIZE-CHECKLIST.md +++ b/platform/macos/menubar/NOTARIZE-CHECKLIST.md @@ -152,12 +152,17 @@ spctl --assess --type execute -vv "$APP" - [x] CI workflow **example** (unsigned default; notary secret **names** only, gated off): [`ci-notarize.yml.example`](ci-notarize.yml.example) — copy into `.github/workflows/` or `.forgejo/workflows/` when enabling; do not treat the example as a live release job +- [x] Local **dry-run** (print submit recipe / tip; no submit unless gated): + [`notary-dry-run.sh`](notary-dry-run.sh) — if `notarytool` present prints codesign/`ditto`/submit/staple + with env **names** only; else Xcode CLT tip (exit 0). Links `ci-notarize.yml.example` + + [`docs/COMMERCIAL-INSTALLER-BACKLOG.md`](../../../docs/COMMERCIAL-INSTALLER-BACKLOG.md). + **Never submits** unless `NOTARY_SUBMIT=1`. - [ ] Wire `build-menubar-app.sh` (or shared `sign-and-notarize.sh`) to run the above when `SIGNING_ENV` / CI secrets exist; keep **unsigned default** for dev - [ ] Promote example → live CI macOS runner: import Developer ID + notary key → staple → checksums - [ ] Smoke: `spctl` + `stapler validate` on signed hosts only -Until live CI + script automation land, this checklist is the operator runbook. +Until live CI + automated sign path land, this checklist + `notary-dry-run.sh` are the operator runbook. --- diff --git a/platform/macos/menubar/README.txt b/platform/macos/menubar/README.txt index 95f61ce..0554eab 100644 --- a/platform/macos/menubar/README.txt +++ b/platform/macos/menubar/README.txt @@ -52,6 +52,9 @@ Codesign + notarization (document only — needs Apple certs) Operator steps: NOTARIZE-CHECKLIST.md CI sketch (unsigned default; notary secret names only): ci-notarize.yml.example Copy into .github/workflows or .forgejo/workflows when enabling; not live. +Local dry-run (print recipe; tip if no notarytool; never submits unless + NOTARY_SUBMIT=1): ./notary-dry-run.sh + Links ci-notarize.yml.example + docs/COMMERCIAL-INSTALLER-BACKLOG.md. You need an Apple Developer Program membership and a Developer ID Application certificate in the keychain. This project does not ship @@ -106,4 +109,7 @@ Files run-menubar.sh compile-or-interpret entry com.verae.timestamping.menubar.plist LaunchAgent template build-menubar-app.sh unsigned .app bundle builder + notary-dry-run.sh print notarytool recipe / tip (NOTARY_SUBMIT=1 to submit) + ci-notarize.yml.example GHA/Forgejo sketch (unsigned default) + NOTARIZE-CHECKLIST.md operator codesign + notary + staple steps README.txt this file (incl. notarization) diff --git a/platform/macos/menubar/notary-dry-run.sh b/platform/macos/menubar/notary-dry-run.sh new file mode 100755 index 0000000..7967cb0 --- /dev/null +++ b/platform/macos/menubar/notary-dry-run.sh @@ -0,0 +1,273 @@ +#!/usr/bin/env bash +# notary-dry-run.sh — menubar notarytool dry-run (Issue 1 commercial) +# +# Default: locate notarytool, report APP/ZIP presence, print submit/staple +# recipes using env **names** only. Does NOT codesign, submit, or staple. +# +# Live submit only when ALL of: +# NOTARY_SUBMIT=1 +# notarytool on PATH +# a zip (or ditto-able .app) exists +# Never prints .p8 contents, passwords, or real secret values. +# +# Related: +# ci-notarize.yml.example +# NOTARIZE-CHECKLIST.md +# platform/windows/wix/CI-SIGN-NOTARY.md +# docs/COMMERCIAL-INSTALLER-BACKLOG.md +# +# Usage: +# ./notary-dry-run.sh +# ./notary-dry-run.sh ~/Applications/Verae\ Menubar.app +# APP=… ZIP=… ./notary-dry-run.sh +# NOTARY_SUBMIT=1 ZIP=/tmp/VeraeMenubar.zip ./notary-dry-run.sh # gated submit +# +# Exit: 0 on dry-run success (including missing notarytool tip). +# 1 on bad args / failed gated submit. +set -euo pipefail + +DIR="$(cd "$(dirname "$0")" && pwd)" +ROOT="$(cd "$DIR/../../.." && pwd)" + +APP="${APP:-}" +ZIP="${ZIP:-}" +PROFILE="${NOTARY_KEYCHAIN_PROFILE:-verae-notary}" + +# Optional positional: path to .app or .zip +if [[ $# -gt 0 ]]; then + arg="$1" + case "$arg" in + *.zip|*.ZIP) + ZIP="$arg" + ;; + *.app|*.APP) + APP="$arg" + ;; + *) + if [[ -d "$arg" && "$arg" == *.app ]]; then + APP="$arg" + elif [[ -f "$arg" && "$arg" == *.zip ]]; then + ZIP="$arg" + else + echo "usage: $0 [path/to/Verae Menubar.app|.zip]" >&2 + echo " env: APP= ZIP= NOTARY_SUBMIT=1 NOTARY_KEYCHAIN_PROFILE=" >&2 + exit 1 + fi + ;; + esac +fi + +# Defaults when unset +if [[ -z "$APP" ]]; then + for cand in \ + "$DIR/Verae Menubar.app" \ + "$HOME/Applications/Verae Menubar.app" \ + "/Applications/Verae Menubar.app" + do + if [[ -d "$cand" ]]; then + APP="$cand" + break + fi + done +fi +if [[ -z "$ZIP" ]]; then + for cand in \ + "/tmp/VeraeMenubar.zip" \ + "$DIR/VeraeMenubar.zip" \ + "${TMPDIR:-/tmp}/VeraeMenubar.zip" + do + if [[ -f "$cand" ]]; then + ZIP="$cand" + break + fi + done +fi +ZIP="${ZIP:-/tmp/VeraeMenubar.zip}" + +echo "notary-dry-run — does NOT codesign or staple by default; submit only if NOTARY_SUBMIT=1." +echo "Repo: $ROOT" +echo "Docs: platform/macos/menubar/ci-notarize.yml.example" +echo " platform/macos/menubar/NOTARIZE-CHECKLIST.md" +echo " platform/windows/wix/CI-SIGN-NOTARY.md" +echo " docs/COMMERCIAL-INSTALLER-BACKLOG.md" +echo "" + +# --- notarytool presence --- +echo "==== notarytool ====" +NOTARYTOOL="" +if command -v xcrun >/dev/null 2>&1; then + if xcrun --find notarytool >/dev/null 2>&1; then + NOTARYTOOL="$(xcrun --find notarytool 2>/dev/null || true)" + fi +fi +if [[ -z "$NOTARYTOOL" ]] && command -v notarytool >/dev/null 2>&1; then + NOTARYTOOL="$(command -v notarytool)" +fi + +if [[ -z "$NOTARYTOOL" ]]; then + echo " notarytool: NOT FOUND" + echo "" + echo " Tip: install Xcode Command Line Tools (or full Xcode), then:" + echo " xcode-select --install" + echo " xcrun --find notarytool" + echo " Live CI notary stays gated off — see ci-notarize.yml.example (if: false)" + echo " and CI-SIGN-NOTARY.md. Exiting 0 (dry-run scaffold; no notarytool required)." + exit 0 +fi +echo " notarytool: $NOTARYTOOL" + +# --- artifacts --- +echo "" +echo "==== Artifacts ====" +if [[ -n "$APP" && -d "$APP" ]]; then + echo " APP: $APP" + if [[ -f "$APP/Contents/Resources/VERSION" ]]; then + echo " VERSION=$(tr -d '\r\n' < "$APP/Contents/Resources/VERSION")" + fi +else + echo " APP: (none found — build with ./build-menubar-app.sh)" + APP="" +fi +if [[ -f "$ZIP" ]]; then + echo " ZIP: $ZIP ($(wc -c < "$ZIP" | tr -d ' ') bytes)" +else + echo " ZIP: $ZIP (missing — ditto after codesign; see recipe below)" +fi + +# --- codesign / staple status (informational only) --- +echo "" +echo "==== Status (informational) ====" +if [[ -n "$APP" ]]; then + if command -v codesign >/dev/null 2>&1; then + if codesign --verify --deep --strict "$APP" >/dev/null 2>&1; then + echo " codesign verify: OK" + else + echo " codesign verify: FAIL / unsigned (expected until Developer ID applied)" + fi + else + echo " codesign: not on PATH" + fi + if command -v xcrun >/dev/null 2>&1 && xcrun --find stapler >/dev/null 2>&1; then + if xcrun stapler validate "$APP" >/dev/null 2>&1; then + echo " stapler validate: OK (ticket present)" + else + echo " stapler validate: no ticket (expected until notary Accepted + staple)" + fi + fi +else + echo " (skip — no APP)" +fi + +# --- env secret names + recipe --- +echo "" +echo "==== Submit recipe (env names only — no secrets) ====" +echo " Secret / env names (see CI-SIGN-NOTARY.md + ci-notarize.yml.example):" +echo " APPLE_API_KEY_P8_BASE64 # base64 of AuthKey_*.p8 (CI materialize only)" +echo " APPLE_API_KEY_ID" +echo " APPLE_API_ISSUER_ID" +echo " APPLE_TEAM_ID" +echo " APPLE_CODESIGN_IDENTITY # Developer ID Application: … (TEAMID)" +echo " APPLE_INSTALLER_IDENTITY # optional; product .pkg path" +echo " NOTARY_KEYCHAIN_PROFILE # laptop path (default print: $PROFILE)" +echo " NOTARY_KEY_PATH # path to AuthKey_*.p8 after materialize" +echo " NOTARY_KEY_ID / NOTARY_ISSUER_ID # aliases used in NOTARIZE-CHECKLIST" +echo "" +echo " # 0) Build unsigned (dev default)" +echo " ./build-menubar-app.sh \"\${APP:-\$HOME/Applications/Verae Menubar.app}\"" +echo "" +echo " # 1) Codesign hardened runtime (operator machine / gated CI — not this dry-run)" +echo " APP=\"\${APP:-\$HOME/Applications/Verae Menubar.app}\"" +echo " ENT=\"\$APP/Contents/Resources/entitlements.plist\"" +echo " codesign --force --deep --options runtime --timestamp \\" +echo " --entitlements \"\$ENT\" \\" +echo " --sign \"\$APPLE_CODESIGN_IDENTITY\" \\" +echo " \"\$APP\"" +echo " codesign --verify --deep --strict --verbose=2 \"\$APP\"" +echo "" +echo " # 2) Zip for notarytool" +echo " ZIP=\"\${ZIP:-/tmp/VeraeMenubar.zip}\"" +echo " rm -f \"\$ZIP\"" +echo " ditto -c -k --keepParent \"\$APP\" \"\$ZIP\"" +echo "" +echo " # 3a) Submit — keychain profile (laptops)" +echo " xcrun notarytool submit \"\$ZIP\" \\" +echo " --keychain-profile \"\${NOTARY_KEYCHAIN_PROFILE:-$PROFILE}\" \\" +echo " --wait" +echo "" +echo " # 3b) Submit — App Store Connect API key (CI-friendly)" +echo " xcrun notarytool submit \"\$ZIP\" \\" +echo " --key \"\$NOTARY_KEY_PATH\" \\" +echo " --key-id \"\${APPLE_API_KEY_ID:-\$NOTARY_KEY_ID}\" \\" +echo " --issuer \"\${APPLE_API_ISSUER_ID:-\$NOTARY_ISSUER_ID}\" \\" +echo " --wait" +echo "" +echo " # 4) Staple + Gatekeeper" +echo " xcrun stapler staple \"\$APP\"" +echo " xcrun stapler validate \"\$APP\"" +echo " spctl --assess --type execute -vv \"\$APP\"" +echo "" +echo " CI sketch (unsigned default; notary job if: false):" +echo " platform/macos/menubar/ci-notarize.yml.example" +echo " Backlog: docs/COMMERCIAL-INSTALLER-BACKLOG.md" +echo " This dry-run does not claim notarization shipped." + +# --- gated submit --- +echo "" +echo "==== Gated submit ====" +if [[ "${NOTARY_SUBMIT:-}" != "1" ]]; then + echo " NOTARY_SUBMIT is not 1 — no submit performed (print-only)." + echo " To submit for real: NOTARY_SUBMIT=1 ZIP=… [key env] $0" + exit 0 +fi + +echo " NOTARY_SUBMIT=1 — attempting notarytool submit --wait" +if [[ ! -f "$ZIP" ]]; then + if [[ -n "$APP" && -d "$APP" ]]; then + echo " ZIP missing; creating via ditto from APP…" + rm -f "$ZIP" + ditto -c -k --keepParent "$APP" "$ZIP" + else + echo " ERROR: NOTARY_SUBMIT=1 but no ZIP and no APP to ditto." >&2 + exit 1 + fi +fi + +# Prefer API key env if NOTARY_KEY_PATH set; else keychain profile +set +e +if [[ -n "${NOTARY_KEY_PATH:-}" || -n "${APPLE_API_KEY_ID:-}" ]]; then + KEY_PATH="${NOTARY_KEY_PATH:-}" + KEY_ID="${APPLE_API_KEY_ID:-${NOTARY_KEY_ID:-}}" + ISSUER="${APPLE_API_ISSUER_ID:-${NOTARY_ISSUER_ID:-}}" + if [[ -z "$KEY_PATH" || -z "$KEY_ID" || -z "$ISSUER" ]]; then + echo " ERROR: API-key submit needs NOTARY_KEY_PATH + APPLE_API_KEY_ID + APPLE_API_ISSUER_ID" >&2 + exit 1 + fi + echo " mode: API key (key-id=\$APPLE_API_KEY_ID — value not printed)" + xcrun notarytool submit "$ZIP" \ + --key "$KEY_PATH" \ + --key-id "$KEY_ID" \ + --issuer "$ISSUER" \ + --wait + rc=$? +else + echo " mode: keychain profile (${NOTARY_KEYCHAIN_PROFILE:-$PROFILE})" + xcrun notarytool submit "$ZIP" \ + --keychain-profile "${NOTARY_KEYCHAIN_PROFILE:-$PROFILE}" \ + --wait + rc=$? +fi +set -e + +if [[ $rc -ne 0 ]]; then + echo " notarytool submit failed (exit $rc)" >&2 + exit "$rc" +fi + +if [[ -n "$APP" && -d "$APP" ]]; then + echo " stapling $APP" + xcrun stapler staple "$APP" + xcrun stapler validate "$APP" || true +fi + +echo " submit path finished." +exit 0 diff --git a/platform/windows/wix/CI-SIGN-NOTARY.md b/platform/windows/wix/CI-SIGN-NOTARY.md index 06f1444..155b416 100644 --- a/platform/windows/wix/CI-SIGN-NOTARY.md +++ b/platform/windows/wix/CI-SIGN-NOTARY.md @@ -7,6 +7,8 @@ [`.github/workflows/windows-msi.yml`](../../../.github/workflows/windows-msi.yml), [`docs/COMMERCIAL-INSTALLER-BACKLOG.md`](../../../docs/COMMERCIAL-INSTALLER-BACKLOG.md), [`platform/windows/scripts/sign-dry-run.ps1`](../scripts/sign-dry-run.ps1) — local `signtool verify` + print real sign commands (**no secrets**; exit 0 if no signtool), +[`platform/macos/menubar/notary-dry-run.sh`](../../macos/menubar/notary-dry-run.sh) — local notarytool recipe / tip (**no secrets**; submit only if `NOTARY_SUBMIT=1`), +[`platform/macos/menubar/ci-notarize.yml.example`](../../macos/menubar/ci-notarize.yml.example), [`platform/macos/menubar/NOTARIZE-CHECKLIST.md`](../../macos/menubar/NOTARIZE-CHECKLIST.md), [`platform/macos/pkg/build-pkg.sh`](../../macos/pkg/build-pkg.sh). @@ -199,7 +201,9 @@ GHA/Forgejo copy-paste sketch (unsigned default, notary job gated off): [`ci-not **Live:** [`.github/workflows/windows-msi.yml`](../../../.github/workflows/windows-msi.yml) builds an **unsigned** full MSI when WiX is installed on `windows-latest` and uploads the artifact (see DUAL-SHIP § CI artifact). -**Local dry-run (no CI secrets):** [`../scripts/sign-dry-run.ps1`](../scripts/sign-dry-run.ps1) finds `signtool`, runs `verify /pa` on local MSI/EXE when present, and prints copy-paste `signtool sign` lines using the env **names** above only. Missing signtool → exit 0 + Windows SDK tip. Does **not** sign or import a PFX. +**Local dry-run (no CI secrets):** +- Windows: [`../scripts/sign-dry-run.ps1`](../scripts/sign-dry-run.ps1) finds `signtool`, runs `verify /pa` on local MSI/EXE when present, and prints copy-paste `signtool sign` lines using the env **names** above only. Missing signtool → exit 0 + Windows SDK tip. Does **not** sign or import a PFX. +- macOS menubar: [`../../macos/menubar/notary-dry-run.sh`](../../macos/menubar/notary-dry-run.sh) finds `notarytool`, prints codesign/`ditto`/submit/staple recipe (env **names** only), links [`ci-notarize.yml.example`](../../macos/menubar/ci-notarize.yml.example) + [`COMMERCIAL-INSTALLER-BACKLOG.md`](../../../docs/COMMERCIAL-INSTALLER-BACKLOG.md). Missing notarytool → exit 0 + Xcode CLT tip. **Never submits** unless `NOTARY_SUBMIT=1`. **Not done:**