Skip to content

release: signed universal app and installer package pipeline - #14

Merged
pahud merged 1 commit into
mainfrom
feat/downloadable-release
Sep 27, 2026
Merged

pahud merged 1 commit into
mainfrom
feat/downloadable-release

Conversation

@pahud

@pahud pahud commented Sep 27, 2026

Copy link
Copy Markdown
Contributor

Summary

Makes oab-instance-mcp downloadable without cloning/building the repo. A v* tag builds a universal app, Developer-ID signs + notarizes it, wraps it in a signed/notarized .pkg, verifies both, writes checksums, and publishes a GitHub Release.

Primary artifact: oab-instance-mcp-VERSION-universal.pkg. Also publishes the pre-signed .app.zip and SHA256SUMS.

Installer behavior

The package carries the signed app as payload and its postinstall enters the logged-in console user's GUI bootstrap namespace, drops root, then calls the same install-prebuilt.sh used by local deployment:

  • verifies bundle id/signature/team before stopping or replacing anything;
  • auto-detects Tailscale User[Self.UserID].LoginName + Self.DNSName from structured JSON;
  • installs atomically to the existing ~/.local/oab-instance-mcp/oab-instance-mcp.app path without re-signing;
  • creates the bearer token once (atomic lock, mode 600) and preserves it on updates;
  • writes/starts the Aqua LaunchAgent, adds the Playwright upstream when present, configures tailscale serve :8444.

The no-re-sign rule and exact team gate preserve Full Disk Access / Screen Recording / Accessibility across future releases. The first Apple-Development → Developer-ID transition may need one final re-grant.

deploy.sh now assembles/signs a temp app and delegates to the same installer, so local and release installs cannot drift.

CI / release trust

  • PR/main CI remains contents: read, no secrets, no pull_request_target.
  • PR CI adds a no-secret packaging smoke.
  • Release workflow runs only for v* tag pushes or manual retries of an existing tag, under the release environment with contents: write.
  • Signing material is imported into an ephemeral keychain; original keychain search list is restored and material is deleted in always() cleanup.
  • Identity names must be Developer ID Application/Installer and the signed app TeamIdentifier must be exactly 6LPQNY95AQ.

Validation

On macmini from a clean Swift build:

  • swift test --skip OsascriptToolTests: 88 tests, 0 failures
  • packaging smoke: unsigned input rejected by production gate; valid/malformed structured Tailscale fixtures; token persistence; LaunchAgent + upstream args; flat pkg expansion/scripts/payload — pass
  • fresh arm64 + x86_64 release builds → lipo universal — pass
  • universal app assembly + unsigned pkg payload smoke — pass
  • current active-team installed app accepted by dry installer; deprecated UM92U863A8 temp app rejected

Independent audit findings fixed before the PR: Tailscale parse diagnostics + fixture, explicit launchd-stop timeout before replacement, homes containing spaces, atomic token creation, and keychain-search-list restoration.

Signing blocker (expected)

No release is cut in this PR. The repo currently has no Actions secrets/environment, and no machine has Developer ID Application + Developer ID Installer certificates for active team 6LPQNY95AQ. The only Developer ID Application found is deprecated team UM92U863A8, and it is intentionally rejected.

Before the first tag, create active-team Developer ID Application/Installer assets and add the nine secrets listed in docs/releasing.md. Until then, ordinary CI is fully testable/green; signed notarization is correctly blocked rather than silently using the old team.

- assemble a stable app bundle and install prebuilt signed artifacts without re-signing (preserves TCC identity)
- build a flat pkg whose postinstall enters the console user's GUI namespace, creates/preserves the bearer token, installs LaunchAgent, detects pw-mcp, and configures tailscale serve
- add v* release workflow: universal arm64+x86_64, ephemeral Developer ID keychain, app+pkg notarization/stapling, verification, checksums, GitHub Release
- add no-secret packaging smoke to PR CI (signature gate, structured Tailscale fixture, token persistence, plist/pkg payload)
- document artifacts, installer behavior, TCC migration, release secrets and the active-team Developer ID blocker
@pahud
pahud merged commit bb4e008 into main Sep 27, 2026
4 checks passed
@pahud
pahud deleted the feat/downloadable-release branch September 27, 2026 11:55
chaodu-agent added a commit that referenced this pull request Sep 27, 2026
release: signed universal app and installer package pipeline
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant