- Las aplicaciones de macOS tienen componentes más complejos que un programa de línea de comandos, y administran recursos de interfaz como ventanas y menús en una estructura separada
- En Classic Mac OS, el código ejecutable y los recursos se almacenaban en el resource fork del archivo, pero desde Mac OS X se pasó a una estructura de bundle
- El bundle de una app se organiza alrededor del directorio Contents, con subcarpetas como MacOS, Resources y Frameworks, además de archivos clave como Info.plist
- Más adelante se añadieron firma de código, recibos de App Store y notarización, evolucionando hacia una estructura que refuerza la seguridad y la integridad
- Esta estructura autosuficiente del app bundle se convirtió en la base clave para simplificar la instalación, actualización y eliminación, además de mejorar la seguridad y la eficiencia de mantenimiento
Estructura de las apps en Classic Mac OS
- En las primeras versiones de Mac OS, los recursos de UI como ventanas y menús se separaban del ejecutable y se guardaban en el resource fork
- Como ejemplo, los recursos de QuarkXPress 4.11 se muestran en ResEdit
- El código ejecutable se incluía en el recurso CODE, y también se almacenaba información de tipo (type) y creador (creator) para que Finder pudiera reconocerlo
Estructura de bundle en Mac OS X
- Mac OS X adoptó la estructura de bundle originada en NeXTSTEP
- Una app es un directorio con extensión
.app, que incluye internamente la carpeta Contents
- La carpeta MacOS contiene el ejecutable de la app con GUI y herramientas de línea de comandos
- La carpeta Resources almacena archivos de recursos como el ícono de la app y componentes de la GUI
- Algunas apps incluyen una carpeta Frameworks para incorporar dylib (bibliotecas dinámicas)
- El archivo Info.plist es obligatorio y define el nombre del ejecutable, el ícono, la versión mínima de macOS, los tipos de documento, los números de versión y más
- El archivo PkgInfo conserva la información de tipo y creador de Classic Mac OS, aunque no es obligatorio
- Al ejecutar una app, launchd inicia el código ejecutable, mientras LaunchServices y RunningBoard realizan el proceso de inicialización con base en la información de Info.plist
Seguridad y expansión en macOS
- Desde Mac OS X 10.5 Leopard (2007) se introdujo la firma de código (Code Signature), agregando la carpeta
_CodeSignature
- El archivo CodeResources incluye el hash del directorio de código (CDHash) para verificar la integridad de la app
- Las apps distribuidas por App Store incluyen un recibo de la tienda en la carpeta
_MASReceipt
- Desde 2018, se introdujo la notarización, y Apple puede emitir un ticket que se puede staplear al bundle mediante el archivo CodeResources
- Los bundles de apps modernas incluyen por sí mismos componentes que antes se instalaban en carpetas del sistema
- Carpeta Library: LaunchDaemons, LoginItems, etc.
- Carpeta XPCServices: servicios ejecutables separados usados por la app
- Carpetas Plugins / Extensions: extensiones de la app y App Intents
- Algunas apps también incluyen un archivo version.plist
Ventajas del app bundle
- Al integrar todos los componentes dentro del bundle, la instalación, actualización y eliminación se vuelven más sencillas
- Se reduce la posibilidad de que falten componentes y se refuerza la seguridad mediante la protección por firma y notarización
- Las apps de App Store añaden además recibos y tickets de notarización para asegurar su confiabilidad
- No hay diferencias estructurales entre las arquitecturas Intel y Arm; el ejecutable Mach-O se almacena como un binario universal (fat) que contiene código para ambas plataformas
- En el mismo archivo también existen las firmas (signatures) correspondientes a cada arquitectura
Resumen visual de la estructura de una app
- En el diagrama, el amarillo claro indica componentes obligatorios o presentes en casi todas las apps
- El verde indica elementos presentes solo en apps distribuidas por App Store, y el azul representa el ticket de notarización opcional
- Además, pueden incluirse elementos adicionales como workflows de Automator y scripts
- En conjunto, las apps de macOS han evolucionado hacia una estructura autosuficiente y centrada en la seguridad
1 comentarios
Comentarios de Hacker News
La parte marcada en azul es el notarisation ticket (ticket de notarización), y en la práctica no es opcional
Las apps no notarizadas resultan demasiado incómodas para los usuarios, así que al final hay que pagar la cuota de registro de desarrollador de Apple de $99 al año
Si solo compilas y ejecutas para uso personal, está bien, pero si es para distribución, macOS muestra advertencias y hace que la app parezca rota
Antes se podía abrir con clic derecho, pero ahora hay que entrar hasta Configuración del sistema para permitirlo
Se pueden ver capturas relacionadas en la documentación de soporte de Apple y en noticias para desarrolladores
Me gusta la filosofía de seguridad de Apple, pero creo que el sistema de notarización para apps fuera de la App Store perjudica a todas las partes
No he encontrado casos reales en los que la notarización haya evitado un problema de seguridad
Pensaba que la notarización en macOS era molesta, pero cuando intenté distribuir en Windows vi que era aún peor
Para ganarse la confianza de Windows Defender hay que comprar un certificado, y tanto empresas como personas deben pasar por una verificación de identidad profunda
Hay que firmar con un token de hardware, así que solo una persona puede distribuir releases
Encima, la autoridad certificadora puede bloquear la llave arbitrariamente, y si eso pasa cuando necesitas publicar un parche de seguridad, es terrible
En ese sentido, el ecosistema de macOS se siente mucho mejor
Estoy desarrollando un lenguaje de programación que compila para varias plataformas, y la firma y la notarización no encajan para nada con ese proceso
Estos sistemas de firma son solo un mecanismo de control y corren el riesgo de abuso, como en el caso de Epic
Si no es posible ejecutar binarios no firmados de forma razonable, considero que la plataforma es cerrada y no la soporto
Las plataformas cerradas como iOS o Android se pueden reemplazar hasta cierto punto con PWA
Aun así, cada vez confío menos en que Google siga permitiendo ejecutar apps autofirmadas
Solo conozco dos casos en que Apple revocó certificados de apps fuera de la App Store
Uno fue la Research App de Facebook, y el otro fue Screenwise Meter de Google
Ambas eran apps con características de spyware dirigidas a adolescentes, y la revocación del certificado también dejó inservibles herramientas internas
Después de eso, parece que Screenwise Meter volvió a aparecer en la App Store
Artículos relacionados: Wired, EFF
Aproximadamente la mitad de las apps en mi carpeta de aplicaciones no están notarizadas, y en la práctica no pasa nada grave
Después de la notarización, el stapled ticket (ticket adjunto) sí es opcional
Si no adjuntas el ticket, el usuario necesita conexión a Internet para verificar el estado de notarización
Mientras desarrollaba AppBundler.jl, acumulé muchas quejas sobre la estructura de las apps de macOS
La obligación de usar la estructura de la carpeta Frameworks se ve ordenada, pero en la práctica complica el bundling y por eso estoy usando la carpeta Libraries como alternativa
El mayor problema es la firma de código: se siente como un desperdicio tener que firmar todos los binarios
Cuesta entender por qué hacen esto tan complicado cuando bastaría con reunir los hashes de archivos y firmar una sola vez
Además, que los entitlements solo se apliquen al binario launcher también es ineficiente
Como los criterios de notarización se endurecen con el tiempo, puede pasar que más adelante una app deje de aprobar de repente
Me uní al Apple Developer Program para firmar y notarizar una app de Tauri, y llevo 3 semanas fracasando
Como no tengo una Mac, lo intenté con GitHub Actions, pero dicen que es común que la primera notarización tarde mucho
Ya gasté casi $100 solo en GitHub y todavía no logro notarizarla
El equipo de soporte de Apple se negó a ayudarme porque no tengo una Mac y uso Tauri
El proceso de autenticación del API de notarización también es una pesadilla: hay que generar un JWT con PKCS8, pero casi no hay documentación y tuve que escribir yo mismo un programa en Node
Ha sido la peor experiencia de desarrollador (DX) que he tenido hasta ahora
Intentar resolver esto sin hardware de Apple es una pérdida de tiempo
Al ver la primera captura del sistema operativo se me encogió el corazón
Antes tenía una UI práctica y limpia, pero ahora solo desperdicia espacio con esquinas redondeadas e íconos tipo burbuja
Aun así, la calidad del hardware de Mac es tan buena que no logro cambiarme a ThinkPad
En realidad, las esquinas redondeadas son una característica favorable para la visión humana
Hay estudios que dicen que las esquinas angulosas provocan fatiga visual
Artículo relacionado: Round Rects Are Everywhere
A mí tampoco me gusta mucho el macOS actual, pero esa captura tampoco es perfecta
Tiene demasiadas líneas y le falta color, así que dispersa la atención
Personalmente, la Aqua UI de la era Leopard tenía un buen equilibrio entre densidad de información y profundidad visual
Si se mide por proporción de píxeles, la UI antigua en realidad ocupa más espacio
Tomando como referencia la resolución 5K, la MacBook Pro moderna es más eficiente
Las Mac clásicas ya tenían un poco de esquinas redondeadas
Referencia: Infinite Mac
Las computadoras no son solo herramientas de trabajo, también son herramientas para el disfrute
Aun así, da la impresión de que la UI actual se ha alejado demasiado de lo práctico
La mayor parte de la pantalla es información inútil tipo 101101, así que cuesta verla como algo práctico
Es incorrecto decir que en macOS launchd es quien ejecuta las herramientas de línea de comandos
En realidad, como en otros sistemas UNIX, se ejecutan desde el shell con fork/spawn
El sistema de bundles de NeXTSTEP inspiró el diseño de los archivos JAR de Java
En el Mac OS clásico, las apps de Power Mac guardaban el código PPC en el data fork
Lo mismo pasaba con los binarios CFM-68K; los recursos CODE se usaban solo en el viejo código 68K
Recuerdo con cariño la época en que modificábamos apps con ResEdit
Como en el último diagrama, que la burocracia explote no es una buena señal
Me da todavía menos razones para “actualizar” a macOS 26
Aunque esta estructura actual es el “estándar” de macOS, no es la única forma
Si configuras bien RPATH, puedes poner bibliotecas en subcarpetas arbitrarias y aun así pasar la notarización
Por ejemplo, también funciona una ruta como AppName.App/Contents/Libraries
Aun así, esta forma casi no tiene ventajas prácticas, y entre las más de 100 apps de mi sistema no hay ni una sola que use la carpeta /Libraries
En lugar de .dylib, hay que usar obligatoriamente el formato .framework, y esa es una regla no documentada
Puede detectarse automáticamente al enviar la app y causar un rechazo