Repository navigation
Developer ID sign and notarize the macOS standalone CLI binaries - #1226
Conversation
Hardened runtime blocks same-user debugger attach to the varlock process. allow-jit is the only granted exception: without it JavaScriptCore's JIT is disabled and CPU-bound JS runs ~10x slower. The stable identifier dev.varlock.cli lets the enclave daemon verify and display the caller.
|
The changes in this PR will be included in the next version bump.
|
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
varlock-website | 8a22142 | Commit Preview URL Branch Preview URL |
Oct 14 2026, 01:28 AM |
varlock
@varlock/native-helper-darwin
@varlock/native-helper-linux-arm64
@varlock/native-helper-linux-x64
@varlock/native-helper-win32-x64
commit: |
There was a problem hiding this comment.
Important
The macOS release job can publish a CLI binary even when Apple rejects its notarization. Require an Accepted status before uploading the archives.
Reviewed changes: Reviewed the macOS signing workflow, its integration into both release paths, the binary build script, entitlements, and installation documentation.
- macOS release build: Adds Developer ID signing, hardened runtime, notarization submission, signature and archive verification, and an arm64 smoke test.
- Release integration: Builds the other five targets on Linux and merges the macOS archives into the cosign-signed checksum manifest for normal releases and manual re-cuts.
- Build controls: Adds target selection and signing flags, signs local macOS builds ad-hoc by default, and computes checksums in TypeScript.
- User documentation: Documents standalone macOS signature verification and its distinction from npm installations.
Live signing and notarization were not executed in this Linux review environment; the notarization contract was checked against Apple documentation and existing tooling.
gpt-6.1-sol | 𝕏
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes: Reviewed the notarization acceptance gate added since the previous review.
- Required Apple acceptance: Changed both architecture submissions to JSON output and blocked archive publication unless each returns
Accepted. - Added rejection diagnostics: Printed the submission response and attempted to retrieve its notarization log, while retaining a fatal exit if log retrieval fails.
Exercised the actual workflow shell block with mocked notarization responses and real jq. All seven cases passed, covering acceptance, rejection of either architecture, failed diagnostic retrieval, missing fields, malformed JSON, and command failure. Live Apple signing and notarization were not run in this Linux environment.
gpt-6.1-sol | 𝕏
The daemon now reads the peer's audit token (LOCAL_PEERTOKEN) and derives the peer pid from it. A new describe-caller action returns the caller chain with each process's signing identity: the direct peer resolved by audit token, ancestors by pid as display-only. Access is still gated by the binary-name allowlist so npm installs keep working.
📦 Bundle size
dist/ only; native binaries are versioned separately and not counted here. |
There was a problem hiding this comment.
Important
The new caller-identity inspector reports signature validation failures as non-Apple certificate chains instead of invalid signatures.
Reviewed changes: Reviewed the caller-identity functionality added since 942c526.
- Added caller descriptions: Introduced audit-token inspection of the direct IPC peer and bounded, display-only ancestor traversal.
- Added signing classification: Reported signature category, signing metadata, hardened runtime, and varlock identity through the new Swift target.
- Connected IPC and client types: Passed resolved peer information to daemon handlers and added
describe-callerwithDaemonClient.describeCaller(). - Added unit coverage: Covered chain traversal, audit-token lookup selection, identity matching, and JSON serialization with fake inspectors.
Swift tests could not run on this Linux runner: swift test --scratch-path /tmp/opencode/varlock-caller-review --filter CallerChainTests failed with no such module 'Darwin'. Checked the relevant Security-framework contracts against Apple's public headers and implementation.
gpt-6.1-sol | 𝕏
Parked on the enclave-caller-identity branch.
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes: Reviewed the caller-identity rollback in dea601b since the previous review at 96183d3.
- Removed caller inspection: Removed the Swift signing inspector, caller-chain builder, package targets, and associated tests.
- Restored session IPC: Restored the optional session-ID handler contract and removed the audit-token peer wrapper.
- Removed client API: Removed
describe-caller,DaemonClient.describeCaller(), and related TypeScript types without leaving source references.
Validated the Swift package manifest with swift package dump-package and checked session-ID propagation through the restored handler. Live macOS runtime, signing, and notarization tests were not run on this Linux runner.
gpt-6.1-sol | 𝕏
* Pin remaining GitHub Actions to commit SHAs and enforce it in CI #1226 branched before #1229 and reintroduced tag refs in the macOS binary build plus two download-artifact steps. Pin those, and add a CI check that fails on any remote action not pinned to a full SHA with a ref comment. * Drop custom pin check in favor of GitHub's require-SHA-pinning setting



Replaces #1012, rebuilt against the current release flow.
What
The macOS
varlockbinaries in the standalone archives (and homebrew) are now Developer ID signed with hardened runtime, a stable identifier (dev.varlock.cli), and notarized. Today they only carry bun's ad-hoc linker signature.Why
lldb -pagainstvarlock run: ad-hoc attaches, ad-hoc + runtime is refused.install.shuse curl, so no quarantine), but it is cheap once we are signing.Entitlements
Only
com.apple.security.cs.allow-jitis granted. #1012 granted nothing, which runs, but hardened runtime then disables JavaScriptCore's JIT: a CPU-bound loop went from 1.1s to 11.8s.allow-jitrestores full speed and still blocks debugger attach (verified). All other exceptions are listed as<false/>, and CI fails if the granted set is anything other thanallow-jit.CI shape
build-cli-binaries-macos.yamlbuilds the two macOS archives onmacos-latest, signs, notarizes, verifies signature/identifier/team/entitlements, checks the archive round-trip (no AppleDouble files, bundled.appsignature intact), and smoke tests the arm64 binary.release.yamlandbinary-release.yamlbuild the other five targets on linux with--targets=, download the macOS archives, and append their checksums before cosign signschecksums.txt.binary-release.yaml(re-cuts) now needs a macOS runner and the Apple credentials, since the signed CLI binary can't be recovered from npm. It pulls the darwin helper from@varlock/native-helper-darwin.build-binaries.ts
--targets=to build a subset,--sign <identity>for Developer ID (ad-hoc otherwise),--no-signto skip (needed to debug a local build).sha256sum, which macOS lacks.