veritas-kanban/docs/DESKTOP-RELEASE.md

22 KiB

Veritas Kanban Desktop Release

For the 6.2.0 candidate, retain local verification and exact package/media provenance. The owner authorized existing GitHub CI capacity without purchases or spending changes. Release and advisory publication are approved. Signing and publication still require verification. Installed-app replacement and public writing remain separate owner decisions. Follow the current candidate gate.

This guide covers desktop packaging paths for macOS GA artifacts and Linux/Windows preview artifact scaffolding: unsigned PR artifacts, signed release artifacts, update metadata, and smoke testing.

For v6 GA, macOS is the only supported desktop release target. Linux and Windows artifacts are unsigned preview artifacts for post-GA validation unless a later release guide explicitly promotes the platform.

Local Commands

Run these from the repository root:

pnpm desktop:package:mac:dir
pnpm desktop:package:mac:unsigned
pnpm desktop:package:linux:unsigned
pnpm desktop:package:windows:unsigned
pnpm desktop:release:mac
pnpm desktop:release:linux
pnpm desktop:release:windows
pnpm desktop:smoke:mac:local

desktop:package:mac:dir creates an unpacked local app for fast inspection. desktop:package:mac:unsigned creates unsigned DMG/ZIP artifacts and update metadata for PR validation. desktop:package:linux:unsigned creates preview x64 AppImage, deb, and rpm artifacts. desktop:package:windows:unsigned creates preview x64 NSIS installer and ZIP artifacts.

desktop:release:mac expects Apple signing and notarization credentials and stages artifacts with publishing disabled. It does not upload a release; the Desktop Release workflow owns the verified upload path. desktop:release:linux is reserved for post-GA Linux preview validation until checksum, provenance, install, and update policy requirements are promoted. desktop:release:windows expects a Windows code-signing certificate available to electron-builder before a supported Windows release is cut.

The package step builds the workspace, stages the production server runtime in desktop/.desktop-release/server, stages the built web app in desktop/.desktop-release/web, and writes artifacts to desktop/release/. Both staging and release directories are ignored by git.

pnpm desktop:smoke:mac:local runs the macOS directory packaging path and then asserts that root dev tooling such as Prettier, ESLint, and the desktop electron-builder dependency still exist. Use it after package-script changes that touch production staging or pnpm deploy behavior. The staging deploy runs from an isolated temporary workspace so pnpm deploy --prod cannot rewrite the live repository install into a production-only dependency state.

GitHub Workflows

Desktop Artifacts runs only for a pull request carrying ci:full or through manual dispatch. Ordinary pull requests and main pushes do not package desktop applications. A release candidate keeps ci:full applied through its final synchronization so the artifacts correspond to the reviewed head. The workflow builds unsigned artifacts on:

  • macos-15: DMG, ZIP, blockmap, and update YAML.
  • ubuntu-24.04: x64 AppImage, deb, rpm, blockmap, and update YAML.
  • windows-2025: x64 NSIS installer, ZIP, blockmap, and update YAML.

Unsigned artifact jobs do not require platform signing credentials.

For v6 GA, the Linux and Windows jobs are preview signals only. They keep packaging paths and artifact names exercised, but they are not supported release deliverables and must not be linked from stable release notes as install targets.

Desktop Release uses two explicit manual dispatches. Leave promote_run_id empty to build, sign, notarize, and capture the release candidate. That run also checks the 100/1,000/5,000-task boards and captures the focused large-board comparison from the signed app. It retains the signed distribution, native and large-board evidence, and original documentation captures in signed-macos-release-candidate; it does not upload release assets. Download and inspect the captures, commit the exact reviewed media and guide references in a documentation-only commit, and create the release tag/body at that publication commit. Then dispatch from that commit with promote_run_id set to the successful capture run ID. Promotion verifies and uploads the retained distribution without rebuilding or recapturing. Publishing a GitHub release alone no longer starts a second build.

Native gate before macOS upload

The signed workflow uses --publish never, finalizes the distribution assets, then extracts the actual release ZIP into a temporary directory. Signature and Gatekeeper checks precede the packaged macOS matrix. The runner records the exact app digest, commit, version, native window dimensions, 144 states, and six injected fault probes. Native screenshots and distribution checksums are retained as workflow artifacts even when a check fails.

Promotion accepts only a successful explicitly dispatched capture from this repository's Desktop Release workflow. It binds the capture/native reports to that run's commit, rejects unsafe archives, rechecks the signed distribution checksums, and verifies signatures on the extracted app. Immediately before gh release upload, full release validation verifies the native report against the original build and the media publication record against the clean publication checkout. Only permitted documentation-only changes may separate those commits. Missing, stale, failed, incomplete, wrong-commit, changed-package, or modified-screenshot evidence stops upload. The destination release tag must resolve to publication HEAD, including annotated-tag peeling, and its body must match the reviewed release source exactly. Retaining diagnostic artifacts does not turn a failed matrix into a passing release.

Full local release validation now requires explicit candidate paths:

pnpm validate:release -- --native-evidence /absolute/path/evidence.json --native-app /absolute/path/veritas-kanban.app --media-evidence /absolute/path/capture/publication.json

For source and published-body checks before a candidate exists, use --source-only --skip-build-output (plus --github when checking the published body). Its success message is explicitly source preflight, never release acceptance. --skip-build-output alone does not bypass native or media evidence. Source-only mode rejects candidate evidence arguments instead of silently ignoring them.

Browser verification, packaged candidate verification, installed-app verification, signing/notarization, documentation-media review, and publication are separate results. Report the exact boundary and evidence for each; pending or blocked work remains pending or blocked. The documentation media contract requires original capture provenance, file hashes, committed-byte checks, and a maintained-reference scan. This proves freshness, not visual quality or GIF semantics. Actual playback and visual inspection remain required. The capture job records media once from the extracted distribution app and retains it even on failure. The promotion job uses scripts/docs-media/publish.mjs to verify those same files and refuses app-source changes, altered capture records, and changed published bytes. Follow the capture and publication workflow; do not promote old preparation output or still-image montages.

Homebrew Cask

The supported packaged install path is the dedicated BradGroux tap:

brew tap BradGroux/tap
brew install --cask veritas-kanban

The cask lives in BradGroux/homebrew-tap/Casks/veritas-kanban.rb and tracks the signed, notarized GitHub release ZIP. After publishing a stable macOS release, update the cask version and SHA256, then validate from the registered tap checkout:

brew style --cask bradgroux/tap/veritas-kanban
brew audit --cask --strict --online bradgroux/tap/veritas-kanban
brew install --cask --dry-run bradgroux/tap/veritas-kanban
brew livecheck bradgroux/tap/veritas-kanban

Required Release Secrets

Configure Developer ID signing secrets before running Desktop Release:

  • MACOS_CSC_LINK: base64 encoded .p12 Developer ID Application certificate or a secure URL accepted by electron-builder CSC_LINK.
  • MACOS_CSC_KEY_PASSWORD: password for the .p12 signing identity.

Then configure exactly one complete notarization credential set. The workflow fails before packaging if neither set is complete, if either set is partial, or if both sets are configured at the same time.

Preferred: App Store Connect API-key notarization

  • APPLE_API_KEY_BASE64: base64 encoded App Store Connect API .p8 key.
  • APPLE_API_KEY_ID: App Store Connect API key ID.
  • APPLE_API_ISSUER: App Store Connect API issuer UUID.

The workflow decodes APPLE_API_KEY_BASE64 into a temporary private-key file and maps it to electron-builder/notarytool as APPLE_API_KEY. The key file is created under the runner temp directory and is not written to the repository.

Fallback: Apple ID app-specific-password notarization

  • APPLE_ID: Apple developer account email address.
  • APPLE_APP_SPECIFIC_PASSWORD: app-specific password for notarization.
  • APPLE_TEAM_ID: Apple Developer Team ID.

The workflow maps those values to electron-builder/notarytool only when the API key credential set is absent. Do not configure both notarization modes in the same repository environment; that is treated as a release-preflight error so CI cannot silently use the wrong credential path.

Windows releases need a separate code-signing certificate before the first supported Windows artifact is published. Use WINDOWS_CSC_LINK and WINDOWS_CSC_KEY_PASSWORD as the repository secret names when the Windows release job is enabled. Linux AppImage/deb/rpm artifacts remain preview-only until checksum verification, GitHub release provenance, platform install smoke, and update policy requirements are promoted into the supported release path.

Desktop Support Boundary

Platform v6 GA stance Validation matrix Artifact formats Update stance
macOS Supported desktop GA target macOS 14+ Apple Silicon signed DMG, ZIP Supported through signed electron-updater metadata
Linux Preview only; not a GA target Ubuntu 24.04 x64 and Fedora 40+ x64 smoke hosts unsigned AppImage, deb, rpm Deferred until Linux release policy is promoted
Windows Preview only; not a GA target Windows 11 23H2+ x64 smoke host unsigned NSIS installer, ZIP Blocked until Windows code signing and smoke pass

Linux and Windows support is post-GA. Do not mention Linux/Windows as v6 GA install targets until the corresponding release artifact has passed the smoke matrix below and the compatibility policy has been updated to promote the platform.

Update Channels

The app uses electron-updater with manual download/install behavior:

  • stable: default packaged release channel.
  • beta: prerelease/test channel.
  • dev: explicit development channel for controlled test metadata.

Set VERITAS_UPDATE_CHANNEL=stable|beta|dev in release workflows or local packaged test runs. Dev-mode update checks remain unsupported unless VERITAS_DESKTOP_UPDATER_FORCE_DEV=true is set with a valid dev update config.

The native desktop bridge exposes update status events for checking, available, downloading, ready, failed, and unsupported states. The menu enables download only when an update is available and install only when an update has downloaded.

The full v6 channel, staged rollout, version-skew, stale-client, and rollback policy is tracked in v6 Compatibility And Release Policy.

Release Checklist

  • Bump all workspace package versions together.
  • Update CHANGELOG.md.
  • Run pnpm typecheck, pnpm lint:budget, pnpm build, and pnpm test:unit.
  • Confirm pnpm desktop:check:electron-artifacts passes. The emitted main and preload bundles must import Electron's runtime API and must not contain the npm install/download shim.
  • Run pnpm desktop:smoke:mac:local to verify local packaging does not prune root dev tooling.
  • Run pnpm desktop:test:readiness and confirm the bounded readiness helper rejects a stale version and reports a useful timeout.
  • Run pnpm desktop:package:mac:unsigned and inspect artifact names.
  • Run pnpm desktop:package:linux:unsigned on Linux or the Desktop Artifacts Linux job and inspect preview artifact names. This is not a v6 GA release gate.
  • Run pnpm desktop:package:windows:unsigned on Windows or the Desktop Artifacts Windows job and inspect preview artifact names. This is not a v6 GA release gate.
  • Apply ci:full to the release-candidate pull request, then download the uploaded DMG/ZIP/update metadata from its Desktop Artifacts run.
  • Edit docs/releases/vX.Y.Z.md, run pnpm validate:release -- --version X.Y.Z --native-evidence /absolute/path/evidence.json --native-app /absolute/path/veritas-kanban.app --media-evidence /absolute/path/capture/publication.json, and publish that exact file with gh release create --notes-file or gh release edit --notes-file. Do not hand-author or repair the live body separately.
  • Use one logical source line per prose paragraph and let GitHub wrap it to the available width. Keep release structure to level-two headings. Prefer one cohesive full-width paragraph for a handful of related changes. Use Markdown lists only when every item is concise enough to avoid multi-line hanging indentation; the format gate caps list items at 160 source characters. Never stack bold-led paragraphs or long labeled list items that look like accidental carriage returns.
  • Run Desktop Release only after Developer ID signing secrets and exactly one complete notarization credential set are configured.
  • Inspect the rendered release on both the releases index and tag page. Confirm prose uses natural page-width wrapping, lists remain compact, and no ragged hanging-indent block, unmarked paragraph stack, or sentence-sized fragment was introduced.
  • Confirm notarization succeeds with the intended credential mode and the DMG installs without Gatekeeper warnings on a clean Mac.
  • Confirm a first run creates the profile/workspace app data directories.
  • Confirm startup/auth/setup surfaces are draggable while their controls remain clickable, and a populated isolated SQLite profile offers Use Existing Data with representative counts before password setup.
  • Confirm the Web To Mac Desktop Migration decision tree matches the shipped onboarding labels and Maintenance import behavior.
  • Confirm update check, download, install, failed-download, and rollback paths on the selected channel.
  • For a Homebrew upgrade, confirm open -a followed by pnpm desktop:wait:ready -- --expected-version <version> tolerates normal startup delay and proves the packaged server owns 3001.
  • Confirm full pnpm validate:release passes with --native-evidence, --native-app, and --media-evidence, verifying candidate-bound macOS evidence, documentation-media freshness, root/shared/server/web/CLI/MCP/desktop package versions, and required v6 release docs. A source-only preflight is not this gate.

Smoke Tests

Unsigned PR artifact:

  1. Download veritas-kanban-mac-unsigned from the workflow run.
  2. Mount the DMG and drag Veritas Kanban into /Applications.
  3. For unsigned local artifacts only, use right-click Open or remove quarantine with xattr -dr com.apple.quarantine "/Applications/Veritas Kanban.app".
  4. Launch the app and confirm the desktop status page reaches the local app.
  5. Confirm app data appears under ~/Library/Application Support/@veritas-kanban/desktop/profiles/default/workspaces/local/.

Signed release artifact:

  1. Install the DMG on a clean Mac.
  2. Launch normally. There should be no Gatekeeper warning.
  3. Confirm local server health through the desktop UI and logs.
  4. Check for updates from the native menu.
  5. Publish a higher test-channel build, then confirm available, downloading, ready, and install states.

Linux preview unsigned artifact:

These steps generate post-GA readiness evidence only. They are not v6 GA install instructions.

  1. Download veritas-kanban-linux-unsigned from the workflow run.
  2. On Ubuntu 24.04 x64, install the deb with sudo apt install ./Veritas\ Kanban-*-linux-x64.deb and launch from the app menu.
  3. On Fedora 40+ x64, install the rpm with sudo dnf install ./Veritas\ Kanban-*-linux-x64.rpm and launch from the app menu.
  4. Run the AppImage with chmod +x followed by ./Veritas\ Kanban-*-linux-x64.AppImage.
  5. Confirm local server health through the desktop UI, logs, backup/import paths, and app data under ~/.config/@veritas-kanban/desktop/.
  6. Confirm uninstall removes the app but preserves user data unless the user explicitly deletes the app data directory.

Windows preview unsigned artifact:

These steps generate post-GA readiness evidence only. They are not v6 GA install instructions.

  1. Download veritas-kanban-windows-unsigned from the workflow run.
  2. On Windows 11 23H2+ x64, run the NSIS installer and accept expected unsigned publisher warnings only for PR artifacts.
  3. Launch from the Start menu and confirm the desktop status page reaches the local app.
  4. Confirm the local server binds to loopback, Windows Firewall prompts are documented if shown, and app data appears under %APPDATA%\@veritas-kanban\desktop\.
  5. Confirm backup/import, logs, and uninstall behavior. Uninstall should remove the app and preserve user data unless explicitly deleted by the user.
  6. For supported release artifacts, confirm the installer is code-signed before enabling update checks or recommending the artifact to users.

Rollback:

  1. Quit Veritas Kanban.
  2. Install the previous signed DMG.
  3. Launch and confirm the existing profile/workspace data is preserved.
  4. If an update artifact is bad, remove or supersede the affected GitHub release assets and publish corrected update metadata.

Platform Notes

Linux and Windows packages are intentionally not v6 GA blockers. The post-GA artifact jobs keep artifact naming and update-channel conventions portable, but Windows release and update support stay blocked until code signing and signed-installer smoke coverage are in place. Linux release and updater support are deferred until the project has clear checksum, provenance, install, and AppImage/deb/rpm update policies.

Native menu verification

The packaged native UI gate exercises New Task, Settings, Search, Command Center, Import, Export, Create Backup, and Create Debug Bundle through Electron's installed menu and the mounted renderer. File data commands and Debug Bundle open the existing Maintenance flow; they do not automatically export, restore, or create files. Renderer commands wait for an acknowledgement. Finish setup and unlock the workspace before using them; unavailable actions display a reason instead of reporting success.

On macOS, Command-W closes the window while the managed server stays running. Reopen the window from the Dock. Command-Q quits and stops the managed server. Standard Hide, Hide Others, Show All and Services commands are available in the application menu; View provides text zoom and full screen.

Saved window bounds are fitted to the current display work areas at launch or reopen. If a monitor was disconnected, the window returns to the primary display. Maximized windows retain their previous normal bounds for unmaximizing.

The custom header follows the macOS title-bar double-click preference (zoom/fill, minimize, or no action). Configure it in Desktop & Dock settings. The native gate records the current preference and verifies its action without changing the operator's system preferences.

Settings window ownership

On macOS, Settings and Command-comma focus one reusable, modeless native window. The main board remains usable. Browser clients and other desktop platforms retain the shared modal presentation. Settings links and native Import, Export, Backup, and Debug Bundle commands select the corresponding shared section after the authenticated renderer acknowledges the request.

The native window uses the existing isolated, sandboxed preload with Node integration disabled. Bridge calls and command receipts are restricted to owned top-level renderers at the current application origin; generated startup status pages are a separate main-window-only case. Settings navigation stays in the settings surface, and external links use the existing validated OS opener.

Closing Settings hides its renderer and restores focus to the board, retaining pending edits and failed writes for retry. Reopening restores that session. Quit waits for its serialized settings writes before stopping the local server. A failed or stalled save keeps the app open and directs the user back to Settings. Normal native close, minimize, restore, and focus controls apply to this window independently of the board's saved bounds.

The two windows share the existing browser profile. Appearance uses the existing local preference store. Settings/configuration changes send same-origin invalidation notices, without values or credentials, and each renderer refetches through its authenticated API. Sign-in changes refresh each window's auth guard; workspace selection follows the shared profile. Hidden Settings continues to receive updates and remains subject to the same server permissions.