From 28f4a212e0947c10c30819ba2c7528e6aec2ca54 Mon Sep 17 00:00:00 2001 From: Daniel Young Date: Thu, 6 Aug 2026 09:53:37 -0400 Subject: [PATCH] [tacet] Strip quarantine before anything execs the bundle MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Casks quarantine by default. For tacet that is fatal rather than annoying: nothing launches this bundle through LaunchServices — launchd starts it, and install-server.sh execs it to verify the install. Exec'ing a quarantined bundle directly blocks in _dyld_start waiting on a first-launch consent decision that has no UI to answer it, so the app deadlocks before running a line of its own code. Notarization does not help, which is what made this confusing: the gate is consent, not assessment, and `spctl -a` accepts the exact bundle that hangs. /Applications was never the variable either — a quarantined copy in ~/Applications hangs identically. The first blocked launch then wedges the path, not the file. Removing the xattr afterward does not recover it and neither does replacing the file; only a different path does. So the strip has to happen in postflight, before launchd or the installer can touch the binary. Solves: DRYCodeWorks/tacet#25 Tests: brew style + brew audit --cask clean; mechanism isolated against the published v0.1.1 artifact (quarantined -> rc=124 in _dyld_start, unquarantined -> rc=2) across five paths --- Casks/tacet.rb | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/Casks/tacet.rb b/Casks/tacet.rb index 08f75bc..3a2e15b 100644 --- a/Casks/tacet.rb +++ b/Casks/tacet.rb @@ -17,6 +17,24 @@ app "Tacet.app" + # Casks quarantine by default, and for tacet that is fatal rather than merely + # annoying. Nothing ever launches this bundle through LaunchServices — launchd + # starts it, and install-server.sh execs it to verify the install. Exec'ing a + # quarantined bundle directly blocks in _dyld_start waiting on a first-launch + # consent decision that has no UI to answer it, so the app deadlocks before it + # runs a line of its own code. Notarization does not help: the gate is consent, + # not assessment, and `spctl -a` accepts the exact bundle that hangs. + # + # Worse, that first blocked launch wedges the *path*. Removing the xattr after + # the fact does not recover it, and neither does replacing the file — only a + # different path does. So this has to run before anything execs the binary. + # + # See DRYCodeWorks/tacet#25 for the isolation. + postflight do + system_command "/usr/bin/xattr", + args: ["-dr", "com.apple.quarantine", "#{appdir}/Tacet.app"] + end + # Deliberately NOT `depends_on formula: "whisper-cpp"`. One bundle plays two # roles: the menu-bar agent, and `tacet serve`, which is the only part that # needs whisper. Making it a hard dependency would build a large formula on