Skip to content

ci: notarize Mac builds with the team App Store Connect API key - #16291

Merged
lawrencecchen merged 3 commits into
mainfrom
feat-notarize-asc-api-key
Oct 1, 2026
Merged

lawrencecchen merged 3 commits into
mainfrom
feat-notarize-asc-api-key

Conversation

@lawrencecchen

@lawrencecchen lawrencecchen commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Mac notarization in release.yml, nightly.yml (nightly and RC) and the v0.64.25 repair workflow authenticated notarytool with an Apple ID and an app-specific password. Those two secrets have no source of truth we can read back, which blocks moving production secrets into the release environment. Notarization now uses the team App Store Connect API key that the iOS lanes already use: notarytool --key <p8> --key-id $ASC_API_KEY_ID --issuer $ASC_API_ISSUER_ID.

scripts/ci/lib/notary-auth.sh decodes ASC_API_KEY_P8_BASE64 into a mode-600 file inside the caller's private temp dir and builds the auth arguments. Every caller removes that dir with an EXIT trap, so the key does not outlive the step. notarize-nightly-dmg.sh and notarize-computer-use-helper.sh stop before any upload when a key value is missing. The ASC_API_* secrets stay repo-level (iOS jobs need them), and repo-level secrets reach the release environment jobs. After this lands, CI no longer reads APPLE_ID, APPLE_APP_SPECIFIC_PASSWORD or APPLE_TEAM_ID. The local scripts/build-sign-upload.sh still uses the Apple ID path.

Testing

  • e84eb7302ba adds the failing tests: bash tests/test_notarize_nightly_dmg.sh exited 1 and python3 tests/test_notarize_computer_use_helper.py had 11 failures. With 835366bc7a4 both pass (3 shell checks, 14 Python tests). The fake xcrun asserts each notarytool call has --key pointing at a mode-600 file with the decoded content, the expected key ID and issuer, and no --apple-id/--password/--team-id; the tests then check the key file is gone and that a missing key value stops before notarytool runs.
  • tests/test_ci_self_hosted_guard.sh passes, actionlint is clean on the three workflows, python3 scripts/verify-local.py --affected origin/main passed 15/15.
  • xcrun notarytool history with a team API key from the maintainer's machine authenticated and listed the team's nightly submissions, which shows a team key has notary access.
  • Not verified before merge: a real notarization with the repository's ASC_API_* values. The notarize jobs run in the release environment, whose branch policy allows only main and v* tags, so a branch dispatch can't reach them. The first nightly on main after merge is the live check.

Changelog

none

🤖 Generated with Claude Code


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.


Summary by cubic

Mac notarization now authenticates notarytool with the team App Store Connect API key instead of an Apple ID and app-specific password across release.yml, nightly.yml/RC, and the v0.64.25 repair workflow.

  • New scripts/ci/lib/notary-auth.sh decodes ASC_API_KEY_P8_BASE64 into a mode-600 temp file that each caller deletes on exit.
  • CI now uses ASC_API_KEY_ID, ASC_API_ISSUER_ID, and ASC_API_KEY_P8_BASE64; it no longer reads APPLE_ID, APPLE_APP_SPECIFIC_PASSWORD, or APPLE_TEAM_ID. Local scripts/build-sign-upload.sh keeps the Apple ID path.
  • The ASC_API_* secrets stay repo-level, which also lets them flow into the release environment jobs.
  • Tests assert notarytool receives the key and deletes it, and that missing secrets stop before any upload. A real notarization with repo secrets isn't verified until the next nightly on main after merge.

Written for commit 0050a10. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • Release Improvements
    • Nightly, standard, and repair builds now use App Store Connect API keys for macOS notarization. Existing acceptance checks, stapling, and verification remain in place.
  • Documentation
    • Release guidance now distinguishes signing credentials from CI notarization credentials; local build uploads continue to use Apple ID credentials.
  • Reliability
    • Notarization credentials are validated before submission, and temporary key files are removed after use. Missing or invalid credentials stop notarization before an upload is attempted.

lawrencecchen and others added 2 commits September 30, 2026 16:35
The nightly DMG and Computer Use helper notarization tests now require
notarytool to authenticate with --key/--key-id/--issuer, a mode-600 key
file decoded from ASC_API_KEY_P8_BASE64, no Apple ID credentials, and
deletion of the decoded key on exit.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Release, nightly/RC and the v0.64.25 repair workflow now authenticate
notarytool with --key/--key-id/--issuer instead of an Apple ID and
app-specific password. scripts/ci/lib/notary-auth.sh decodes
ASC_API_KEY_P8_BASE64 into a mode-600 file inside the caller's private
temp dir, which an EXIT trap deletes. The notarize scripts fail before
any upload when a key value is missing.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

All contributors have signed the CLA ✍️ ✅
Posted by the CLA Assistant Lite bot.

@coderabbitai

coderabbitai Bot commented Sep 30, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

Note

Repository guideline files applied to this review (2)
.github/review-bot-rules/test-determinism.md — configured
.github/review-bot-rules/source-control-artifacts.md — configured

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository: manaflow-ai/cmux/.coderabbit.yaml

Review profile: ASSERTIVE

Plan: Advanced

Run ID: 0a28d0f1-902d-46cb-8c2e-5d402fb672d0

📥 Commits

Reviewing files that changed from the base of the PR and between 835366b and 0050a10.

📒 Files selected for processing (1)
  • tests/test_notarize_nightly_dmg.sh

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 4 remain after this review.


📝 Walkthrough

Walkthrough

CI notarization scripts and workflows now use App Store Connect API key credentials. A shared helper validates credentials, decodes the private key with restrictive permissions, and supplies authentication arguments to notarytool. Tests verify credential use, validation, and key cleanup.

Changes

Notarization authentication

Layer / File(s) Summary
Shared API key authentication
scripts/ci/lib/notary-auth.sh
Adds a shared helper that validates API key credentials, decodes the key into a private directory, sets its mode to 600, and prepares NOTARY_AUTH_ARGS.
Notarization script migration
scripts/ci/notarize-computer-use-helper.sh, scripts/ci/notarize-nightly-dmg.sh, tests/test_notarize_computer_use_helper.py, tests/test_notarize_nightly_dmg.sh
Standalone scripts use the shared arguments for notarization calls. Tests check API key use, required credentials, key permissions, and cleanup.
Workflow credential migration
.github/workflows/nightly.yml, .github/workflows/release.yml, .github/workflows/repair-v0-64-25-helper-rpaths.yml, skills/cmux-release/SKILL.md
Notarization steps use API key credentials. The release guidance distinguishes CI notarization credentials from signing credentials and local upload credentials.

Priority: ➖ Normal

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Refactor

Merge Risk: ⚪ Minimal · up to 0050a

CI notarization now uses App Store Connect API-key credentials instead of Apple ID credentials; no concrete merge-blocking failure is established in the supplied change context.

Security Architecture Review

Security architecture risk: 🔵 Low · up to 0050a

Private key-file permissions, early credential validation, and normal-exit cleanup limit exposure. The shared credential connects Mac notarization and iOS operations, however, and its actual permissions and release-environment eligibility remain unverified.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • inferred — Compromise of a secret-bearing Mac notarization process could expose the shared ASC key and permit operations within its externally granted App Store Connect authority, potentially including iOS operations. This expands the key's consumer set, but greater effective privilege than the former Apple ID cannot be established without both identities' permissions.

Trust Boundaries and Controls

  • observed — The decoded key resides inside caller-created temporary directories with restrictive permissions, and EXIT cleanup is installed before authentication initialization. Authentication arguments contain a key-file path rather than private-key contents. These controls restrict filesystem exposure but do not isolate credentials from code executing with the same process or runner identity.

Resilience and Maintainability Implications

  • inferred — Centralized authentication limits credential-contract drift across submit, wait, and log. EXIT traps cover normal completion and ordinary shell errors, but cannot guarantee key deletion after SIGKILL or host loss; effective runner teardown and recovery cleanup remain external coverage gaps.

Hardening Proposals

  • proposed — Verify and document the shared key's effective permissions, release-environment eligibility for nightly and RC, and runner cleanup after abrupt termination. Consider a separate notarization key if shared iOS authority exceeds the intended Mac release boundary.
🚥 Pre-merge checks | ✅ 24 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 15 functions across 5 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (24 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely identifies the main change: using the team App Store Connect API key for Mac notarization in CI.
Description check ✅ Passed The description includes a detailed Summary, Testing results, and Changelog entry. The omitted Demo Video is not relevant to this CI-only change. The checklist is also omitted, but the required techni…
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Cmux Cloud Persistent Session And Early Input ✅ Passed PASS. The PR changes macOS notarization credentials, temporary API-key handling, workflows, documentation, and related tests. The authoritative diff contains no Cloud terminal creation, persistent cmu…
Cmux Swift Actor Isolation ✅ Passed PASS: The pull request changes only GitHub workflows, shell scripts, documentation, and tests. The review-scoped diff contains no .swift files and no Swift actor-isolation constructs such as `@MainA…
Cmux Swift Blocking Runtime ✅ Passed PASS: The authoritative PR diff changes only YAML, shell, Markdown, and Python files. It contains no .swift or Package.swift paths and introduces no production Swift change. The Swift blocking-run…
Cmux Browser Automation Off-Main ✅ Passed PASS: The PR changes CI notarization scripts, workflows, documentation, and notarization tests only. It does not modify Sources/TerminalController.swift, the socket execution policy, worker browser …
Cmux Expensive Synchronous Load ✅ Passed The reviewed diff contains no Swift, Objective-C, or other production Swift changes. It only changes GitHub workflows, shell notarization scripts, documentation, and tests. Therefore, it does not add …
Cmux Cache Substitution Correctness ✅ Passed The authoritative PR diff changes only GitHub Actions YAML, shell scripts, Markdown, and Python tests. It contains no production Swift, TypeScript, or JavaScript changes, so the cache-substitution cor…
Cmux No Hacky Sleeps ✅ Passed PASS. The diff adds no fixed sleep, timer, delayed dispatch, or new polling logic in production shell/runtime code. The existing Gatekeeper polling loop and sleep "$GATEKEEPER_ASSESS_DELAY_SECONDS" …
Cmux Algorithmic Complexity ✅ Passed PASS. The production changes only replace notarization credentials, decode one key file, build a fixed argument array, and clean up temporary directories. The diff adds no scalable collection scans, n…
Cmux Swift Concurrency ✅ Passed PASS: The pull request changes only GitHub Actions workflows, shell scripts, documentation, and Python/shell tests. The authoritative diff contains no Swift or Swift project files, so it does not intr…
Cmux Swift @Concurrent ✅ Passed PASS: The authoritative PR diff changes only workflow YAML, shell scripts, documentation, and tests. It contains no Swift files or Swift source changes, so the Swift @concurrent rule is not applicable…
Cmux Swift Package Boundaries ✅ Passed PASS: The pull request changes only GitHub Actions workflows, shell scripts, documentation, and tests. The authoritative diff contains no Swift files and introduces no Swift package or app-target prod…
Cmux Swiftpm Lockfiles ✅ Passed PASS. The PR changes only notarization workflows, CI shell scripts, release documentation, and notarization tests. The authoritative diff contains no Package.swift, Package.resolved, .gitignore,…
Cmux Swift Logging ✅ Passed PASS. The pull request changes only YAML, shell, Python, and Markdown files. It adds no Swift or app/runtime source changes, and the changed lines contain no prohibited Swift logging statements.
Cmux User-Facing Error Privacy ✅ Passed PASS: The diff changes CI workflows, notarization scripts, tests, and release documentation. Their new messages and command output go to CI or developer/operator diagnostics. The repository references…
Cmux Full Internationalization ✅ Passed The PR changes only CI workflows, notarization scripts, tests, and an operational release skill. The diff adds no Swift UI text, app catalogs or Info.plist entries, web UI or message files, API respon…
Cmux Swiftui State Layout ✅ Passed PASS: The reviewed diff changes only workflows, shell scripts, documentation, and tests. It contains no Swift or SwiftUI files and no SwiftUI state, GeometryReader, lazy/list, or render-time mutation …
Cmux Architecture Rethink ✅ Passed PASS: The pull request changes only YAML, shell, Markdown, and Python files. The authoritative diff contains no Swift files and introduces none of the Swift architectural patterns covered by the rule.…
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed PASS: The pull request changes CI workflows, shell scripts, documentation, and tests only. The authoritative diff contains no Swift files or Swift window code, so the auxiliary-window close-shortcut r…
Cmux Source Artifacts ✅ Passed The pull request changes only workflow configuration, CI shell scripts, release documentation, and notarization tests. The sole added path, scripts/ci/lib/notary-auth.sh, is hand-written source. Tem…
Cmux No Test Or Debug Seam In Production Source ✅ Passed The authoritative PR diff contains no Swift files and no files under a production **/Sources/** path. The check is therefore not applicable, and the PR cannot introduce a test or debug seam in produ…
  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Autopilot is currently an internal CodeRabbit preview.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

CI failure attribution

CI passes on 0050a10edd (run 36793618179 attempt 1).

Written by scripts/ci/classify_failures.py (ci-failure-attribution.yml); signatures are its SIGNATURES table. A machine verdict is the runner's fault, not this PR's.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@lawrencecchen
lawrencecchen merged commit 4e9d779 into main Oct 1, 2026
57 checks passed
@lawrencecchen
lawrencecchen deleted the feat-notarize-asc-api-key branch October 1, 2026 00:07
@github-actions

github-actions Bot commented Oct 1, 2026

Copy link
Copy Markdown
Contributor

Merge receipt for 0050a10edd: every check was green at merge (13 verified; 14 skipped by policy). Full suite runs on main after merge.

rustybret pushed a commit to rustybret/bmux that referenced this pull request Oct 1, 2026
4e9d779 ci: notarize Mac builds with the team App Store Connect API key (manaflow-ai#16291)
b520727 Make Stop cancel Agent Chat before startup acknowledgement (manaflow-ai#16058)
a66a8bb Exempt authorized DEV clients from relay rate limits (manaflow-ai#12229)
ca831d4 fix: restore main compile (OpenCodePaths in CLI, Codex auto-naming scope) (manaflow-ai#16260)

# Conflicts:
#	.github/workflows/nightly.yml
#	.github/workflows/release.yml
#	.github/workflows/repair-v0-64-25-helper-rpaths.yml
lawrencecchen added a commit that referenced this pull request Oct 1, 2026
* test(ci): notarization must use the team App Store Connect API key

The nightly DMG and Computer Use helper notarization tests now require
notarytool to authenticate with --key/--key-id/--issuer, a mode-600 key
file decoded from ASC_API_KEY_P8_BASE64, no Apple ID credentials, and
deletion of the decoded key on exit.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* ci: notarize Mac builds with the team App Store Connect API key

Release, nightly/RC and the v0.64.25 repair workflow now authenticate
notarytool with --key/--key-id/--issuer instead of an Apple ID and
app-specific password. scripts/ci/lib/notary-auth.sh decodes
ASC_API_KEY_P8_BASE64 into a mode-600 file inside the caller's private
temp dir, which an EXIT trap deletes. The notarize scripts fail before
any upload when a key value is missing.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* test(ci): read the fake notary key mode on Linux and macOS

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
(cherry picked from commit 4e9d779)
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