Skip to content

fix(bootstrap): copy macOS app with ditto so it isn't reported as damaged#2391

Merged
benjaminshafii merged 1 commit into
devfrom
fix/bootstrap-app-install-ditto
Jun 28, 2026
Merged

fix(bootstrap): copy macOS app with ditto so it isn't reported as damaged#2391
benjaminshafii merged 1 commit into
devfrom
fix/bootstrap-app-install-ditto

Conversation

@benjaminshafii

@benjaminshafii benjaminshafii commented Jun 28, 2026

Copy link
Copy Markdown
Member

Symptom

After openwork-bootstrap install app, launching the app showed:

"OpenWork" is damaged and can't be opened. You should move it to the Trash.

Root cause

It wasn't signing or quarantine. The DMG asset the manifest resolves is correctly signed + notarized (Developer ID: Different AI inc.). The install copy corrupted the bundle.

installDmg / installFromDirectory used cpSync(..., { recursive: true }) to copy OpenWork.app out of the mounted DMG. Node's recursive copy preserved framework symlinks but pointed them at the temporary DMG mount path, which is unmounted right after install:

Squirrel.framework/Versions/Current -> /private/var/folders/.../T/openwork-app-install-.../mount/OpenWork.app/.../Versions/A   (dangling)

Dangling framework links break the code signature, so Gatekeeper reports the app as "damaged."

Fix

  • Copy .app bundles with ditto on macOS (Apple-supported; preserves relative framework symlinks + signature), with a cp -R fallback.
  • Strip com.apple.quarantine on the freshly installed (already-notarized) app so first launch isn't blocked.
  • Applies to both the DMG and zip/tar.gz install paths (they shared the same cpSync).

Verification

Fresh install via the prod manifest:

  • framework symlinks are now relative: Squirrel -> Versions/Current/Squirrel, Current -> A
  • codesign --verify --deep --strictvalid on disk, satisfies its Designated Requirement (exit 0)
  • spctl --assess --type executeaccepted, source=Notarized Developer ID, Different AI inc. (F5DJWB4CCV)
  • no quarantine attribute

pnpm --filter openwork-bootstrap check and test pass.

Note: the landing serves bin/openwork.mjs at /openwork-bootstrap.mjs via a prebuild copy, so this reaches the installer on the next landing deploy.

Review in cubic

Installing the desktop app used cpSync to copy OpenWork.app out of the mounted
DMG. Node's recursive copy left framework symlinks (e.g. Squirrel.framework
Versions/Current) pointing at the temporary DMG mount path, which is unmounted
right after install. The dangling links break the bundle's code signature, so
macOS Gatekeeper reports 'OpenWork is damaged and can't be opened.'

Fix: copy .app bundles with ditto (Apple-supported, preserves relative
framework symlinks + signature), with a cp -R fallback, and strip the
com.apple.quarantine flag on the freshly installed (already-notarized) app.

Verified: a fresh install now passes codesign --verify --deep --strict
(valid on disk, satisfies Designated Requirement) and spctl --assess
(accepted, source=Notarized Developer ID).
@vercel

vercel Bot commented Jun 28, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
openwork-app Ready Ready Preview, Comment Jun 28, 2026 12:36am
openwork-den Ready Ready Preview, Comment Jun 28, 2026 12:36am
openwork-den-worker-proxy Ready Ready Preview, Comment Jun 28, 2026 12:36am
openwork-landing Ready Ready Preview, Comment, Open in v0 Jun 28, 2026 12:36am

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 1 file

Re-trigger cubic

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