Callisto is a Catalyst app, mostly running iOS style code on a Mac. But there are some things that Catalyst apps can’t do – like run a python server as another process. But Mac apps can!

There are a lot of instructions around the Internet about how to use AppKit code within your Catalyst app to do those Mac things that Catalyst doesn’t cover yet. This article from Steve Troughton-Smith was our guide.

We also want to do auto-updates like a regular Mac app. We’re distributing outside the Mac App Store for Reasons, so we’re in charge of our own updates. Yep, dear reader, that means Sparkle, which should be fine, right? So we get the Sparkle framework and link it in to our AppKit bundle which is a plugin for our main app. Compile, run and 💥. This error is staring at us from the console.

code signature in (<full path redacted>/Sparkle.framework/Versions/A/Sparkle) not valid for use 
in process using Library Validation: not allowing mapping of development code into production process

What does that mean? After some furious googling, we’re left empty handed and confused. The worst kind of error is that special, new error that no one else has ever seen. Bollocks.

After some futile futzing around in the dark, I give up and burn a ‘code level’ support ticket with Apple. I send a fairly detailed outline of the problem and the next morning I get back a nice response asking for more details. In particular, how are the app and the framework code signed? (You can check that with codesign -vvvd <.app or .framework>.)

And immediately, I see it.

App Signature:

Authority=Developer ID Application: Oak City Labs, LLC (XXXXXXXXX)

Framework Signature:

Authority=Apple Development: Continuous Integration (YYYYYYYYY)

The app is signed with a production identity while the framework is signed with a development identity. That’s what that weird error meant about not allowing mapping of development code into production process. The codesign docs point out how frameworks and apps need to both be signed with the same Team ID (which I checked), but don’t mention this distinction between production / development signing identities.

I update Xcode so that the AppKit bundle was being signed with the same production identity and all is well! We are fully Sparkle enabled! Curiously, the AppKit bundle has always been signed with the development identity before, yet it loaded fine at runtime. That must be one of those fine distinctions between a bundle and a framework that I don’t quite understand.

But now we celebrate! 🎉🎉🎉