PrintToVeraeTimeStamp/platform/windows/wix/OPERATOR-READY.md
George Lambert 778763737e
Some checks failed
windows-msi / full-msi-unsigned (push) Has been cancelled
docs: OPERATOR-READY package for MSI/notary external legs
Consolidate Authenticode, Apple notary, VM C, and digest-paste into
platform/windows/wix/OPERATOR-READY.md (runbook + commands + secret
names only). Cross-link from CI-SIGN-NOTARY, VM-C-ONE-PAGER, PACKAGING,
and COMMERCIAL-INSTALLER-BACKLOG. Live enable remains blocked only on
org secret store / clean VM — no secret values invented.
2026-10-14 04:17:07 -04:00

9.2 KiB
Raw Blame History

OPERATOR-READY — commercial MSI / notary / dual-ship

Status: software + dry-runs complete. Live sign / notary / VM C / CDN digests are READY: blocked only on org secret/VM (no missing in-repo steps).

Audience: release operator with org secret-store + clean Windows VM access.
Does not invent secrets. Names only. Values stay in org CI / keychain / operator home.

Item Blocker In-repo ready
Org Authenticode / Trusted Signing Org secret store values Yes — names + example workflow + dry-run
Live Apple notary submit/staple Apple API key / keychain profile Yes — names + checklist + dry-run
Clean VM C after enable-printer-cas Physical/clean VM sign-off Yes — one-pager + dual-ship smoke
Real sha256 in DOWNLOADS-MANIFEST Signed blobs on CDN first Yes — hash helper + paste runbook

Canonical siblings: CI-SIGN-NOTARY.md · VM-C-ONE-PAGER.md · DUAL-SHIP.md · VM-DUAL-SHIP-CHECKLIST.md · docs/PUBLISH-DIGESTS.md · platform/macos/menubar/NOTARIZE-CHECKLIST.md · .github/workflows/windows-msi-sign.yml.example · platform/macos/menubar/ci-notarize.yml.example


0) Preconditions (already in repo)

# From PrintToVeraeTimeStamp repo root
go test ./internal/pdfcert ./internal/statuslang -count=1
./platform/smoke-packaging-metadata.sh
./platform/macos/menubar/notary-dry-run.sh          # exit 0; no submit
# Windows builder:
powershell -NoProfile -ExecutionPolicy Bypass -File platform\windows\scripts\sign-dry-run.ps1
powershell -NoProfile -ExecutionPolicy Bypass -File platform\windows\scripts\dual-ship-smoke.ps1

Unsigned MSI CI is live: .github/workflows/windows-msi.yml.
Sign/notary jobs stay gated (if: false) until secrets exist.


1) Org CI secrets — Authenticode / Trusted Signing

READY: blocked only on org secret/VM

Secret / var names (never commit values)

Name Kind Purpose
WINDOWS_CERT_PFX_BASE64 secret Base64 PFX for Path A (signtool)
WINDOWS_CERT_PFX_PASSWORD secret PFX password
WINDOWS_CERT_THUMBPRINT secret Optional /sha1 after import
WINDOWS_SIGN_TIMESTAMP_URL var RFC 3161 TSA (e.g. https://timestamp.digicert.com)
WINDOWS_TRUSTED_SIGNING_TENANT_ID secret Path B Azure Trusted Signing
WINDOWS_TRUSTED_SIGNING_CLIENT_ID secret Path B
WINDOWS_TRUSTED_SIGNING_CLIENT_SECRET secret Omit when OIDC id-token: write
WINDOWS_TRUSTED_SIGNING_ENDPOINT var e.g. https://cus.codesigning.azure.net
WINDOWS_TRUSTED_SIGNING_ACCOUNT var Trusted Signing account name
WINDOWS_TRUSTED_SIGNING_CERTIFICATE_PROFILE var Certificate profile name

Operator commands

# A) Add the names above to org GitHub/Forgejo secret store (values out-of-band).
# B) Copy example → live workflow (same secret names on Forgejo):
cp .github/workflows/windows-msi-sign.yml.example .github/workflows/windows-msi-sign.yml
#    — or .forgejo/workflows/windows-msi-sign.yml with your Windows runs-on label
# C) Flip job gate: if: false  →  if: true  (only after secrets exist)
# D) workflow_dispatch; download signed MSI artifact
# E) Local verify (Windows SDK):
powershell -NoProfile -ExecutionPolicy Bypass -File platform\windows\scripts\sign-dry-run.ps1 `
  -Path .\path\to\signed.msi

Do not claim SmartScreen reputation until clean-VM install proof.
Do not upload PFX as a workflow artifact.


2) Live notary submit / staple (macOS)

READY: blocked only on org secret/VM

Secret / env names

Name Purpose
APPLE_API_KEY_P8_BASE64 App Store Connect API key .p8 (base64; CI materialize only)
APPLE_API_KEY_ID Key ID
APPLE_API_ISSUER_ID Issuer UUID
APPLE_TEAM_ID Team ID for identity selection
APPLE_CODESIGN_IDENTITY Developer ID Application: … (TEAMID)
APPLE_INSTALLER_IDENTITY Developer ID Installer: … (TEAMID) (product .pkg)
NOTARY_KEYCHAIN_PROFILE Laptop profile (default print: verae-notary)
NOTARY_KEY_PATH / NOTARY_KEY_ID / NOTARY_ISSUER_ID Checklist aliases after materialize

Operator commands (menubar accessory)

# Dry-run first (always safe; no submit):
./platform/macos/menubar/notary-dry-run.sh

# Build unsigned → codesign → ditto → notarytool → staple
# (full steps: platform/macos/menubar/NOTARIZE-CHECKLIST.md)
./platform/macos/menubar/build-menubar-app.sh "$HOME/Applications/Verae Menubar.app"
# codesign with $APPLE_CODESIGN_IDENTITY + entitlements (see checklist)
ditto -c -k --keepParent "$APP" /tmp/VeraeMenubar.zip
xcrun notarytool submit /tmp/VeraeMenubar.zip \
  --keychain-profile "${NOTARY_KEYCHAIN_PROFILE:-verae-notary}" --wait
# or API key: --key "$NOTARY_KEY_PATH" --key-id "$APPLE_API_KEY_ID" --issuer "$APPLE_API_ISSUER_ID"
xcrun stapler staple "$APP" && xcrun stapler validate "$APP"
spctl --assess --type execute -vv "$APP"

Product .pkg (already scripted)

# When operator signing.env / CI secrets present:
# platform/macos/pkg/build-pkg.sh  (codesign + notarytool --wait + stapler)

CI enable

cp platform/macos/menubar/ci-notarize.yml.example .github/workflows/macos-menubar-notarize.yml
# Flip menubar-notarize job if: false → true only after Apple secrets exist.

Never set NOTARY_SUBMIT=1 in shared CI without secrets + intentional release.


3) Clean VM C sign-off (enable-printer-cas)

READY: blocked only on org secret/VM

Host (Windows builder) — unlock + rebuild

# From repo root
powershell -NoProfile -ExecutionPolicy Bypass -File platform\windows\scripts\enable-printer-cas.ps1 -Status
powershell -NoProfile -ExecutionPolicy Bypass -File platform\windows\scripts\enable-printer-cas.ps1
powershell -NoProfile -ExecutionPolicy Bypass -File platform\windows\scripts\build-full-msi.ps1
powershell -NoProfile -ExecutionPolicy Bypass -File platform\windows\scripts\dual-ship-smoke.ps1 -VerifyArtifacts
powershell -NoProfile -ExecutionPolicy Bypass -File platform\windows\scripts\sign-dry-run.ps1
# Re-disable files-only tree when done authoring:
#   enable-printer-cas.ps1 -Disable

Clean VM C (operator physical/VM)

Printable ticks: VM-DUAL-SHIP-CHECKLIST.md § VM C. Narrative: DUAL-SHIP.md. One-pager: VM-C-ONE-PAGER.md.

  1. Install elevated full MSI (default or VERAE_SKIP_PRINTERS=0).
  2. Confirm files under Program Files + IPP/127.0.0.1:8631 + Verae Print Helper task.
  3. One-page PDF stamp → receipt/CID ≠ jobId (hold is never evidence).
  4. Uninstall clean; parity with VM A (NSIS).
  5. Sign off checklist; keep NSIS primary until thin-NSIS exit A–D.

dual-ship-smoke.ps1 prints steps offline — it does not replace VM C sign-off.


4) Upload signed blobs → real sha256 in DOWNLOADS-MANIFEST

READY: blocked only on org secret/VM

Order (fail closed) — docs/PUBLISH-DIGESTS.md:

  1. Build NSIS +/or full MSI (build-full-msi.ps1 / windows-msi.yml).
  2. Sign (section 1) when shipping Windows trust.
  3. Upload the same bytes to CDN under reserved 0.3.6 leaf names.
  4. Hash (no upload in script):
powershell -NoProfile -ExecutionPolicy Bypass -File platform\windows\scripts\fill-manifest-sha256.ps1 `
  -Path .\dist\VeraePrintStamp-windows-amd64-0.3.6-setup.exe,
        .\platform\windows\wix\out\VeraePrintStamp-windows-amd64-0.3.6.msi `
  -Format both

POSIX shape if no pwsh:

shasum -a 256 VeraePrintStamp-windows-amd64-0.3.6-setup.exe \
  VeraePrintStamp-windows-amd64-0.3.6.msi
# lowercase hex; two spaces; leaf name
  1. Paste over TBD in site/printit.verae.ai/DOWNLOADS-MANIFEST.txt + .md.
  2. Verify re-download from public URL matches pasted digest.

Do not paste digests for unsigned-only CI smoke MSIs into production rows.

Reserved 0.3.6 leaves:

Leaf Channel
VeraePrintStamp-windows-amd64-0.3.6-setup.exe NSIS primary
VeraePrintStamp-windows-arm64-0.3.6-setup.exe NSIS arm64
VeraePrintStamp-windows-amd64-0.3.6.msi Full MSI dual-ship
VeraePrintStamp-windows-arm64-0.3.6.msi Full MSI arm64
verae-print-windows-amd64-0.3.6.exe Optional bare helper

Quick enable checklist (operator)

  • Org secrets set (names in §1 / §2) — values never in git
  • Copy windows-msi-sign.yml.example → live; flip if: false
  • Copy ci-notarize.yml.example → live when Apple secrets exist; flip gate
  • enable-printer-cas.ps1 + build-full-msi.ps1 on Windows builder
  • Clean VM C ticks (checklist) signed off
  • CDN upload of signed 0.3.6 blobs
  • fill-manifest-sha256.ps1 → paste TBD → re-download verify

Until every box above is done by a human with secrets/VM, commercial claims stay: software-complete, READY: blocked only on org secret/VM.


License

UNLICENSED © Verae — operator runbook; not a redistributable binary.