Notarizar una app de Mac: lo que aprendimos publicando Altillo, Pegote y Cajón

Durante cuatro meses publicamos nuestras apps gratuitas de Mac sin notarizar, y cada descarga terminaba en un cartel de Apple. En noviembre de 2026 notarizamos las tres. Qué es, qué cuesta y los errores que cometimos.

Notarizar una app de Mac es enviarle a Apple el programa ya firmado con un certificado de Developer ID para que lo escanee en busca de software malicioso y devuelva un ticket. Con ese ticket pegado a la app, macOS la abre con la pregunta de siempre ("¿seguro que quieres abrirla?") en vez de un cartel que dice que Apple no puede comprobar si contiene malware. Cuesta la cuenta de Apple Developer (99 dólares al año, precio de Apple), una tarde de trabajo la primera vez y unos minutos por cada versión nueva. Durante cuatro meses publicamos Altillo y Pegote sin hacerlo. El 3 de noviembre de 2026 notarizamos las tres apps de Studio, con Cajón recién salida. Esto es lo que aprendimos, errores incluidos.

Primero, por qué lo evitamos. En julio de 2026 publicamos Pegote (un historial del portapapeles) y Altillo (el notch de la Mac convertido en estante) gratis, como herramientas para regalar. Las firmamos "ad hoc", que es la firma que cualquier Mac puede hacer sin cuenta de desarrollador, y decidimos no pagar los 99 dólares todavía. Era una apuesta razonable para dos apps que no sabíamos si alguien iba a usar. El costo lo pagaba quien descargaba: al abrir el zip, macOS avisa que no puede comprobar la app, y hay que ir a Ajustes, Privacidad y seguridad, y pulsar "Abrir igualmente". Lo documentamos en cada página de descarga, con capturas, en un bloque que se llamaba "¿No te abre?". Funcionaba. Pero cada persona que se frenaba delante de ese cartel era una descarga perdida, y de esas no hay forma de contar cuántas fueron.

Lo que no habíamos calculado es lo que pasa después. Una firma ad hoc cambia con cada compilación: para macOS, cada versión de Altillo era una app distinta. Y Altillo pide permisos delicados (Accesibilidad para ordenar ventanas, Grabación de pantalla para las capturas), así que con cada actualización macOS olvidaba lo concedido y volvía a pedirlo, aunque en Ajustes figurara como activo. Terminamos programando un reparador de permisos de un clic dentro de la app. Ingeniería para esquivar una cuenta de 99 dólares. En octubre llegó el segundo aviso: alguien del coworking no pudo instalar Altillo 1.6. El zip estaba compilado solo para chips de Apple y para macOS 26, y la firma no sellaba el paquete entero. Nada de eso era culpa de la notarización, pero nos obligó a rehacer la receta de construcción (universal, macOS 13 o posterior, firma del paquete completo, zip solo con la app), y con la receta ordenada, notarizar era un paso más.

El 3 de noviembre, con Cajón lista para salir, dejamos de postergarlo. La cuenta de Apple Developer se paga por la web; Apple avisa que puede tardar hasta 48 horas en activarla y la nuestra estuvo activa unos diez minutos después. Un detalle que ahorra días: la cuenta como persona física sale en el día; la cuenta como empresa pide un número D-U-N-S y tarda bastante más. Después vienen el certificado "Developer ID Application" (se pide desde Acceso a Llaveros con una solicitud de firma), una contraseña de app para que la herramienta de notarización entre con tu Apple ID, y un perfil guardado en el llavero con xcrun notarytool store-credentials. Esa misma tarde publicamos Altillo 1.8, Pegote 1.1.1 y Cajón 1.0 notarizadas, y al día siguiente Cajón 1.1. El bloque "¿No te abre?" desapareció de las tres páginas.

  1. Firma el paquete entero, con runtime endurecido y sello de tiempo La notarización exige las dos cosas: codesign --options runtime --timestamp, con la identidad de Developer ID y sobre el paquete completo, no solo sobre el binario. Todo lo que vaya dentro de Resources (en nuestro caso, los textos de los permisos en español e inglés) tiene que estar copiado antes de firmar: la firma sella esa carpeta, y un archivo agregado después la rompe. Los permisos que la app necesita bajo ese runtime (cámara, micrófono, automatización) van en un archivo de entitlements.
  2. Arma un zip que lleve solo la app Sin archivos ocultos de macOS, sin atributos extendidos y sin nada al lado. Nosotros al principio metíamos un LEEME junto a la app, y eso tiene un efecto que nadie espera: Safari descomprime el zip en una carpeta, y quien arrastra esa carpeta entera a Aplicaciones se queda con la app corriendo "translocada" desde una ubicación temporal, que no conserva permisos ni ajustes. El zip se arma con ditto sin recursos ni atributos, y toma su nombre definitivo recién cuando todas las comprobaciones pasaron.
  3. Envía y lee el estado, no solo el código de salida xcrun notarytool submit Cajon.zip --keychain-profile tresojotas --wait sube el zip y espera el veredicto. Ojo: la herramienta puede terminar sin error aunque Apple rechace el envío. Nuestro script lee el estado de la respuesta y corta si no dice "Accepted"; con un rechazo, notarytool log cuenta qué faltó. Los tiempos varían: Altillo y Pegote volvieron esa misma tarde; la primera de Cajón tardó más de una hora.
  4. Grapa el ticket y vuelve a armar el zip xcrun stapler staple pega el ticket a la app, y stapler validate lo comprueba. Sin grapar, la app abre igual, pero la primera vez macOS tiene que consultar a Apple por internet. Y el zip que enviaste no lleva el ticket, así que hay que armarlo de nuevo con la app ya grapada.
  5. Comprueba como lo haría cualquiera Descomprime el zip final en una carpeta limpia y verifica la firma ahí, no sobre la copia que tienes en el repo. spctl --assess sobre una app descargada tiene que decir "Notarized Developer ID". Es la única prueba que vale: la que pasa por el mismo camino que recorre quien la descarga.

El error más tonto lo cometimos con Cajón. Mientras Apple revisaba el zip, abrimos la app para seguir probándola, aceptamos su propio aviso de "Mover a Aplicaciones" y el original se fue a la Papelera. Cuando el ticket volvió, no había nada que grapar. Notariza siempre desde una copia que nadie vaya a tocar hasta que el proceso termine. La segunda lección es menos visible pero más cara: con la identidad estable del Developer ID, los permisos que la persona concede se conservan entre versiones, así que el reparador de permisos que habíamos programado quedó de reserva. Si hubiéramos pagado la cuenta en julio, no habría hecho falta escribirlo.

Qué cambia para quien descarga, según la propia Apple: con una app de un desarrollador identificado, macOS solo pregunta si de verdad quieres abrirla; con una app que Apple no pudo comprobar, el botón principal es "Mover a la papelera" y no hay opción de abrir. Y según la guía de notarización de Apple para empresas, en una Mac administrada por una organización esa excepción puede estar bloqueada: ahí una app sin notarizar directamente no entra. Vale la pena saberlo si lo que publicas es una herramienta para equipos.

Si vas a publicar una app de Mac fuera de la App Store, no hagas lo que hicimos: paga la cuenta antes de la primera versión. Lo que ahorras en 99 dólares lo gastas en capturas de "Abrir igualmente", en permisos que se pierden con cada actualización y en descargas que nunca sabrás que perdiste. La notarización no es una revisión de la app ni un sello de calidad: es un escaneo de malware y una identidad estable. Pero para quien descarga es la diferencia entre "la abro" y "mejor no". Las tres apps, ya notarizadas, están en Studio.