← Todos los artículos

El Mac App Store no deja existir a los gestores de ventanas. Igual publiqué uno.

Un ingeniero del Developer Technical Support de Apple me dijo que mi aplicación era imposible: «No es posible usar las APIs de Accessibility desde una aplicación en sandbox… tu único camino posible es distribuir la aplicación directamente».1 La aplicación era un organizador de ventanas en mosaico, la API de Accessibility es aquello sobre lo que se construye cualquier gestor de ventanas, y toda aplicación del Mac App Store se ejecuta dentro del sandbox que la prohíbe. La semana pasada, 941 Tiles llegó igual al Mac App Store: un clic en la barra de menús y todas las ventanas dispersas de una aplicación encajan en una cuadrícula pareja. La regla del sandbox nunca cedió. El truco fue notar que macOS ya contiene un movedor de ventanas privilegiado, con la bendición completa de Apple, y que acepta JSON.

TL;DR

  • App Sandbox bloquea de forma categórica las llamadas de Accessibility entre aplicaciones, ningún entitlement lo desbloquea y toda aplicación del Mac App Store tiene que estar en sandbox. La categoría de los gestores de ventanas quedó cerrada en la práctica para los recién llegados desde junio de 2012; los organizadores que siguen en la tienda son anteriores a esa obligación y se ejecutan fuera del sandbox para siempre.134
  • La puerta autorizada: una aplicación en sandbox puede manejar el motor Shortcuts de Apple mediante Apple events, y Shortcuts incluye las acciones Find Windows / Move Window / Resize Window, que mueven las ventanas de otras aplicaciones con los privilegios propios de Apple.25 Mi aplicación calcula adónde debe ir cada ventana; un Shortcut complementario hace el movimiento. Delegación, no permiso.
  • La ingeniería que lo volvió real: generar por programa el archivo .shortcut complementario como una plist binaria de WFWorkflowActions, un contrato de carga útil JSON con los marcos, indexado según el orden de profundidad de las ventanas, defensas contra ventanas fantasma y desbordes de índice, y una base de código con dos motores que usa Accessibility directo en las compilaciones Developer ID y delegación en Shortcuts en las compilaciones para la tienda.
  • Primera ejecución exitosa en la máquina que había hecho fracasar cinco compilaciones para la tienda: cuatro ventanas de terminal dispersas colocadas en los marcos exactos de los cuadrantes en 0,6 segundos.
  • El crédito donde corresponde: el mecanismo está probado en la práctica por snApp (código abierto, 2023) y Align (2024). Leer el código fuente de snApp fue lo que convirtió el «imposible» en un plan de desarrollo.2

El muro

La primera versión de 941 Tiles era un organizador de ventanas clásico en la barra de menús. macOS tiene un sistema Accessibility que, con permiso del usuario, deja que una aplicación enumere y mueva las ventanas de otra (AXUIElementSetAttributeValue sobre los atributos de posición y tamaño de las ventanas). Construida sobre eso, la aplicación funcionó sin una sola falla durante semanas de desarrollo. Ya tenía preparada toda la ficha de App Store Connect: metadatos en 17 idiomas, capturas de pantalla, precio, 21 compilaciones subidas.

Después, una compilación de TestFlight llegó a una segunda Mac. Permiso de Accessibility concedido, la aplicación informando que el acceso estaba activo, y podía leer cero ventanas.

No era un error. Toda aplicación del Mac App Store se ejecuta dentro del App Sandbox de Apple, una regla de contención según la cual una aplicación solo puede tocar sus propias cosas, justamente para que no pueda espiar ni interferir con el resto de tu Mac.4 Meter la mano en las ventanas de otra aplicación es exactamente lo que el sandbox existe para impedir. Las compilaciones de desarrollo se ejecutan fuera del sandbox, y por eso todo funcionó durante semanas; la compilación para la tienda aplicó la regla que yo venía ignorando. Ningún diálogo de permiso, ningún entitlement, ninguna configuración la desbloquea. Cuando le pregunté a Apple directamente, la respuesta del DTS fue la que abre este artículo: distribuir fuera de la tienda.1

Una categoría cerrada desde 2012

Lo que vuelve interesante al muro es quién está parado del otro lado. Magnet, Moom, BetterSnapTool: herramientas de ventanas que hoy mismo puedes comprar en el Mac App Store. Sus fichas son anteriores a la obligación de sandbox de junio de 2012, así que se ejecutan fuera del sandbox amparadas por una cláusula de antigüedad que no se transfiere a nadie más. Todo gestor de ventanas nacido después de 2012 (Rectangle, Swish, Loop, BetterTouchTool, Amethyst) se distribuye fuera de la tienda. Apple también hizo valer la línea en el sentido contrario: PopClip, casi 13 años en la tienda, se fue en marzo de 2024 después de que la revisión le dijera a su desarrollador que una nueva funcionalidad basada en Accessibility no podía publicarse en una actualización en sandbox.3

Quiero ser claro con mi lectura: la regla del sandbox es razonable. Una aplicación capaz de leer y mover en silencio cada ventana de tu pantalla es una aplicación capaz de vigilarte, y «confía en mí» no es un modelo de seguridad. La promesa de la tienda es que nada de lo que instales ahí puede hacer eso. La injusticia es estrecha y específica: los que ya estaban conservan una capacidad que los recién llegados no pueden ganarse con ninguna cantidad de consentimiento del usuario. La categoría no quedó prohibida; quedó fosilizada.

El giro

El veredicto del DTS tenía una falla: la tienda ya contenía contraejemplos. Align (2024) y snApp (2023) organizan ventanas en mosaico, ambos viven en el Mac App Store y ambos nacieron mucho después de 2012. snApp es de código abierto, así que el mecanismo no es un secreto: es un repositorio.2

La aplicación en sandbox nunca toca las ventanas de otra aplicación. Maneja Shortcuts, la propia aplicación de automatización de Apple, a través de dos entitlements declarados:

<key>com.apple.security.automation.apple-events</key>
<true/>
<key>com.apple.security.temporary-exception.apple-events</key>
<array>
  <string>com.apple.shortcuts.events</string>
</array>

Desde macOS 12, Shortcuts incluye acciones llamadas Find Windows, Move Window y Resize Window.5 A Shortcuts se le permite mover ventanas porque es de Apple. Entonces la aplicación calcula adónde debe ir cada ventana, le entrega ese plan a un Shortcut complementario instalado por el usuario, y el propio motor de Apple hace el movimiento. El sandbox nunca se viola, porque el proceso en sandbox nunca ejecuta el acto privilegiado. Delegación, no permiso.

Hay algo casi arquitectónico en la forma de todo esto: la frontera de seguridad se queda exactamente donde Apple la trazó, y la capacidad cruza esa frontera viajando por el único proceso del sistema que la posee legítimamente.

La construcción

Conocer el mecanismo y publicarlo son semanas distintas. Las piezas que lo volvieron apto para producción:

Generar el Shortcut por programa. Los usuarios no deberían armar a mano un flujo de 12 acciones. El archivo .shortcut complementario es una plist binaria de WFWorkflowActions que la aplicación genera y firma en tiempo de compilación con shortcuts sign -m anyone, de modo que instalarlo es un clic dentro de la aplicación Shortcuts. El contrato en tiempo de ejecución es una carga útil JSON que pasa por el shortcut.run(withInput:) de ScriptingBridge:

{"app": "Ghostty", "frames": [{"x": 0, "y": 38, "w": 1280, "h": 771}, ...]}

La identidad de una ventana es su orden de profundidad. La acción Find Windows del Shortcut indexa las ventanas de adelante hacia atrás, y CGWindowList las enumera en ese mismo orden. Así, la posición i de la carga útil lleva simplemente el marco de la ventana i, y al asignar celdas por rango de posición la cuadrícula reproduce aquello de «las ventanas se quedan cerca de donde estaban». Ningún identificador de ventana cruza la frontera, porque del otro lado no existe ninguno.

Defensas. Un recorte Items in Range acotado por Count evita que una carga útil vieja indexe más allá de la lista real de ventanas. Un filtro de tamaño mínimo (120×80) excluye los paneles fantasma estacionados que CGWindowList reporta y que la vieja verificación de rol de Accessibility solía ocultar. Y un dato que me sorprendió: listar ventanas no requiere permiso alguno; CGWindowList es legal dentro del sandbox. Solo mover estuvo prohibido alguna vez.

Una base de código, dos motores. La aplicación detecta el sandbox al arrancar mediante la variable de entorno APP_SANDBOX_CONTAINER_ID. Las compilaciones para la tienda organizan las ventanas a través de Shortcuts; las de Developer ID y de desarrollo usan la vía directa de Accessibility. Misma interfaz, mismos cálculos, distinto movedor.

Modo de vigilancia sin notificaciones. La función opcional de reorganización automática normalmente se suscribiría a las notificaciones de ventanas de Accessibility, que el sandbox también quita. Sobrevive como sondeo del servidor de ventanas: comparaciones baratas de CGWindowList y reorganización cuando algo cambia.

El costo, dicho con honestidad

El usuario paga un impuesto de configuración por única vez: instalar el Shortcut complementario (un clic) y conceder un diálogo de consentimiento de automatización (el aviso estándar «941 Tiles quiere controlar Shortcuts», localizado en los 17 idiomas mediante InfoPlist.xcstrings). Después de eso, la experiencia es idéntica a la de un organizador con API directa: clic en el ícono de cuadrícula, clic en una aplicación, las ventanas aterrizan. La ejecución de Shortcuts es invisible y tarda bastante menos de un segundo.

No voy a fingir que ese impuesto no es nada; es una pantalla más de las que muestra Magnet. También es el precio completo de existir dentro del sandbox, en lugar de pedirles a los usuarios que esquiven Gatekeeper por una descarga notarizada en la que todavía no tienen motivos para confiar.

La recompensa

La misma Mac Intel que había hecho fracasar cinco compilaciones para la tienda: instalación, configuración del Shortcut, consentimiento, y cuatro ventanas dispersas de Ghostty encajadas en los marcos exactos de los cuadrantes en 0,6 segundos, en la primera ejecución. Después vino la pasada de internacionalización (String Catalogs, reglas de plural de CLDR incluidas las seis categorías del árabe), la ficha localizada y el envío. Tras un rechazo en revisión y una nueva revisión de unos 30 minutos, 941 Tiles está en vivo: 4,99 USD de pago único, macOS 15+, 17 idiomas, cero recolección de datos, sin acceso a la red.

Qué se generaliza

El patrón es más grande que el mosaico de ventanas. Cuando una plataforma encierra una capacidad detrás de una frontera, la respuesta rara vez es pelear contra la frontera; es inventariar qué procesos nativos ya poseen esa capacidad y exponen una interfaz autorizada para llegar a ella. En macOS, ese inventario apunta cada vez más a un solo lugar: Shortcuts, que en silencio se convirtió en el intermediario de automatización privilegiada del sistema, alcanzable desde dentro del sandbox por diseño. Mi guía de Shortcuts cubre esa superficie en profundidad, y el caso de estudio de 941 Tiles recorre esta misma historia con los diagramas de arquitectura.

El sandbox hizo su trabajo. La aplicación se publicó igual. Las dos frases son verdaderas, y la puerta entre ellas era de la propia Apple.

Preguntas frecuentes

¿Puede una aplicación de Mac en sandbox usar las APIs de Accessibility?

No. App Sandbox bloquea de forma categórica las llamadas de Accessibility entre aplicaciones, y ningún entitlement, diálogo de permiso ni configuración lo desbloquea. La respuesta que el propio DTS de Apple me dio fue: «No es posible usar las APIs de Accessibility desde una aplicación en sandbox… tu único camino posible es distribuir la aplicación directamente». Las compilaciones de desarrollo se ejecutan fuera del sandbox, y por eso un organizador puede funcionar durante semanas y después leer cero ventanas en una compilación para la tienda.14

¿Cómo puede publicarse un gestor de ventanas en el Mac App Store?

Delegando el acto privilegiado. Una aplicación en sandbox puede manejar el motor Shortcuts de Apple mediante Apple events, y Shortcuts incluye las acciones Find Windows, Move Window y Resize Window desde macOS 12. Mi aplicación calcula adónde debe ir cada ventana y le entrega ese plan a un Shortcut complementario instalado por el usuario, que hace el movimiento con los privilegios propios de Apple. El sandbox nunca se viola, porque el proceso en sandbox nunca ejecuta el acto privilegiado.25

¿Por qué Magnet y Moom están en la tienda si los gestores de ventanas no pueden estar?

Sus fichas son anteriores a la obligación de sandbox de junio de 2012, así que se ejecutan fuera del sandbox amparadas por una cláusula de antigüedad que no se transfiere a nadie más. Todo gestor de ventanas nacido después de 2012, incluidos Rectangle, Swish, Loop, BetterTouchTool y Amethyst, se distribuye fuera de la tienda. PopClip se fue en marzo de 2024 después de que la revisión le dijera a su desarrollador que una nueva funcionalidad de Accessibility no podía publicarse en una actualización en sandbox. La categoría no quedó prohibida; quedó fosilizada.34

¿Qué le cuesta al usuario la delegación en Shortcuts?

Un impuesto de configuración por única vez: instalar el Shortcut complementario con un clic y después conceder un diálogo de consentimiento de automatización. Luego la experiencia es idéntica a la de un organizador con API directa: clic en el ícono de cuadrícula, clic en una aplicación, las ventanas aterrizan, y la ejecución de Shortcuts queda invisible, bastante por debajo del segundo. Es una pantalla más de las que muestra Magnet, y es el precio completo de existir dentro del sandbox.

¿Cómo soporta una sola base de código las compilaciones en sandbox y las directas?

La aplicación detecta el sandbox al arrancar mediante la variable de entorno APP_SANDBOX_CONTAINER_ID. Las compilaciones para la tienda organizan las ventanas a través de Shortcuts; las de Developer ID y de desarrollo usan la vía directa de Accessibility. Misma interfaz, mismos cálculos, distinto movedor. El modo de vigilancia también se adapta: el sandbox quita las notificaciones de ventanas de Accessibility, así que la reorganización automática opcional sobrevive como un sondeo barato de CGWindowList que compara y reorganiza cuando algo cambia.

Referencias


  1. Apple Developer Forums, hilo 805556 (octubre de 2025), respuesta del DTS de Apple: «No es posible usar las APIs de Accessibility desde una aplicación en sandbox… tu único camino posible es distribuir la aplicación directamente firmándola con un Developer ID». ↩↩↩↩

  2. Om Chachad, snApp en GitHub (2023), el organizador de ventanas de código abierto del Mac App Store cuyo código fuente documenta el mecanismo de delegación en Shortcuts: los entitlements de destino de scripting com.apple.security.automation.apple-events más un Shortcut complementario construido con las acciones de ventana de Apple. ↩↩↩↩

  3. Michael Tsai, «PopClip Leaving the Mac App Store» (21 de marzo de 2024), sobre la revisión de Apple que exigió quitar una nueva funcionalidad basada en Accessibility de una actualización en sandbox, tras casi 13 años en la tienda. ↩↩↩

  4. Apple, documentación de App Sandbox, el modelo de contención que todas las aplicaciones del Mac App Store están obligadas a adoptar desde junio de 2012. ↩↩↩↩

  5. Apple, Guía de uso de Shortcuts para Mac, que documenta las acciones Find Windows, Move Window y Resize Window disponibles desde macOS 12. ↩↩↩

Artículos relacionados

The Shader Gallery That Lied: Debugging 216 WebGL Presets

A user said the shader playground looked broken. Pixel-readback testing found 30 dead presets, 11 that never compiled, a…

13 min de lectura

Recrear MacPaint en el navegador: el código fuente de 1984 es la especificación

Reconstruí MacPaint 1.3 en el navegador y contrasté cada herramienta con el código fuente Pascal que Bill Atkinson liber…

15 min de lectura

Filosofía de ingeniería: Sophie Wilson

Sophie Wilson diseñó el conjunto de instrucciones de ARM, hoy en casi todos los teléfonos, con un equipo diminuto y una …

23 min de lectura