wandres.dev
SEGURIDAD Y PRIVACIDAD · permisos y datos

Manifiestos de privacidad: declarar el dato, el motivo y la cadena de suministro

Desde 2024 una app no solo debe comportarse bien con los datos: debe declarar por escrito y en formato legible por máquina qué recoge, para qué, y por qué usa ciertas APIs capaces de fabricar huellas de dispositivo. Esta lección disecciona el archivo de manifiesto, la lógica de las APIs de motivo requerido, el porqué de las firmas de los SDK de terceros y la coherencia obligatoria entre lo que declaras, lo que respondes en la ficha de la tienda y lo que tu binario hace de verdad.

⏱ 18 min

Durante años la privacidad en la App Store fue una declaración de intenciones: un cuestionario que alguien rellenaba a mano el día del envío, a menudo sin hablar con quien había integrado el SDK de publicidad, y que nadie podía contrastar. El manifiesto de privacidad rompe ese esquema porque cambia el soporte de la promesa. Ya no es prosa dirigida a un revisor humano, es un documento estructurado, verificable y compuesto: lo firma cada actor de la cadena de suministro, Xcode lo agrega al archivar y el resultado es un informe que describe el comportamiento declarado de todo el binario, tuyo y de terceros. El cambio de fondo no es burocrático sino epistemológico: la privacidad deja de ser lo que dices que haces y pasa a ser lo que tu grafo de dependencias declara que hace, con tu firma respondiendo por el conjunto.

🎯 Al terminar esta lección sabrás
  • Leer y escribir un manifiesto de privacidad entendiendo la semántica de cada una de sus cuatro secciones.
  • Distinguir qué cuenta como recogida de datos y qué queda fuera por procesarse solo en el dispositivo.
  • Justificar el uso de las APIs de motivo requerido con el código de razón correcto y defendible.
  • Auditar la cadena de suministro: manifiestos de SDK, firmas y el informe agregado que produce Xcode.

Anatomía del archivo

El manifiesto es un archivo de lista de propiedades llamado PrivacyInfo.xcprivacy que se añade como recurso del objetivo, en la raíz del paquete de la app o del framework. Su estructura tiene cuatro claves de primer nivel y cada una responde a una pregunta distinta. NSPrivacyTracking es un booleano que declara si el código usa datos para seguimiento en el sentido estricto que define Apple. NSPrivacyTrackingDomains enumera los dominios de red que participan en ese seguimiento. NSPrivacyCollectedDataTypes describe qué se recoge, si se vincula a la identidad de la persona, si se usa para seguir y con qué finalidad. Y NSPrivacyAccessedAPITypes justifica el uso de un conjunto acotado de APIs que el sistema considera susceptibles de servir para construir huellas de dispositivo.

<key>NSPrivacyCollectedDataTypes</key>
<array>
  <dict>
    <key>NSPrivacyCollectedDataType</key>
    <string>NSPrivacyCollectedDataTypeCrashData</string>
    <key>NSPrivacyCollectedDataTypeLinked</key><false/>
    <key>NSPrivacyCollectedDataTypeTracking</key><false/>
    <key>NSPrivacyCollectedDataTypePurposes</key>
    <array><string>NSPrivacyCollectedDataTypePurposeAppFunctionality</string></array>
  </dict>
</array>

La palabra que hay que definir con precisión antes de rellenar nada es recoger. En el vocabulario de Apple, recoger significa transmitir los datos fuera del dispositivo de forma que persistan más allá del tiempo necesario para atender la petición en curso. De ahí se siguen dos consecuencias que ordenan buena parte del trabajo. La primera es que el procesamiento estrictamente local no es recogida: un modelo que analiza fotos en el dispositivo y guarda solo el resultado en el contenedor no genera ninguna fila del manifiesto. La segunda es que el tratamiento efímero tampoco lo es, siempre que el dato no se almacene, no se use para otra finalidad y no sirva para seguimiento ni publicidad. Esa asimetría convierte la arquitectura en una herramienta de cumplimiento: mover una inferencia al dispositivo no es solo una decisión de latencia, elimina literalmente una declaración y una respuesta del cuestionario de la tienda.

Los tres atributos por tipo de dato tienen consecuencias muy distintas y conviene no despacharlos con un valor por defecto. Vinculado significa que el dato se asocia a la identidad de la persona a través de una cuenta, un identificador de dispositivo o cualquier otra clave; su respuesta cambia lo que la ficha de la tienda muestra al usuario antes de descargar. Usado para seguimiento es la casilla que activa toda la maquinaria del capítulo siguiente y no debe marcarse a la ligera. Y las finalidades, que van de la funcionalidad de la app a la analítica, la personalización o la publicidad de terceros, son la parte que un auditor contrasta contra el contrato con tu proveedor: declarar analítica cuando tu proveedor se reserva el derecho de usar los datos para su propio negocio es una declaración falsa aunque tú no lo supieras.

⚠️
Lo que declaras es lo que responderás en la ficha

El manifiesto y el cuestionario de privacidad de App Store Connect describen el mismo hecho en dos formatos. Si divergen, el envío se rechaza o la ficha publicada contradice tu propio archivo, que es peor. Trata el manifiesto como la fuente de verdad y genera el cuestionario a partir de él, nunca al revés.

Las APIs de motivo requerido

La cuarta sección es la que más resistencia genera y la que mejor explica la filosofía del sistema. Apple identificó un conjunto de APIs perfectamente legítimas cuyo valor de retorno resulta, sin embargo, extraordinariamente útil para fabricar una huella estable de un dispositivo concreto sin identificadores explícitos. Marcas de tiempo de archivos, tiempo transcurrido desde el arranque del sistema, espacio libre en disco, teclados activos y el propio almacén de preferencias del usuario. Ninguna es peligrosa por sí misma; combinadas producen un vector de altísima entropía que permite reconocer al mismo dispositivo en apps distintas. La respuesta no fue prohibirlas, que habría roto medio ecosistema, sino exigir que cada uso venga acompañado de un código de razón tomado de una lista cerrada, publicada por Apple, que describe el propósito admitido.

<key>NSPrivacyAccessedAPITypes</key>
<array>
  <dict>
    <key>NSPrivacyAccessedAPIType</key>
    <string>NSPrivacyAccessedAPICategoryUserDefaults</string>
    <key>NSPrivacyAccessedAPITypeReasons</key>
    <array><string>CA92.1</string></array>
  </dict>
</array>

Ese diseño es más inteligente de lo que parece y merece explicarse. Una lista cerrada de razones convierte una intención inverificable en una afirmación falsable: el código CA92.1 significa acceder a preferencias que solo esa app puede leer, y si el análisis estático del binario muestra que ese acceso alimenta una llamada de red hacia un dominio de terceros, la declaración es refutable sin necesidad de leer tu mente. La lista canónica de categorías y códigos vive en la documentación de Apple y cambia con el tiempo, así que la regla profesional no es memorizarla sino consultarla en cada revisión y elegir el código más específico que describa el uso real, jamás el que resulte más cómodo de justificar. Un código elegido por conveniencia es exactamente el tipo de detalle que convierte un rechazo automático en una conversación desagradable con el equipo de revisión.

🕒

Marcas de tiempo

Fechas de creación y modificación de archivos. Legítimo para mostrar información al usuario o gestionar el contenedor propio; sospechoso cuando se leen rutas del sistema fuera de tu ámbito.

⏱️

Tiempo de arranque

El reloj monótono desde el encendido. Legítimo para medir duraciones dentro de la app; combinado entre apps identifica el dispositivo con una precisión notable.

💾

Espacio en disco

Comprobar el espacio antes de escribir o informar al usuario son usos admitidos. Enviarlo a un servidor junto a otras señales es fabricar una huella.

⌨️

Teclados y preferencias

La lista de teclados activos filtra idiomas y hábitos; el almacén de preferencias solo es admisible para el ámbito propio o el del grupo de la app.

Cadena de suministro y agregación

Queda la mitad del problema que ningún equipo controla directamente: el código de terceros. La mayor parte de la recogida real en una app media no la escribe su equipo, la escribe un SDK de analítica, de publicidad, de mapas, de pagos o de captura de fallos. Por eso el mecanismo no se limitó a las apps. Apple publicó una lista de SDK de uso frecuente que deben cumplir dos requisitos adicionales al distribuirse: incluir su propio manifiesto de privacidad y venir firmados criptográficamente por su autor. La firma no cifra nada ni protege el código de la copia; su función es la trazabilidad. Vincula un binario concreto y su manifiesto a una identidad de desarrollador verificable, de modo que la declaración no pueda alterarse por el camino y exista un responsable nombrado detrás de cada afirmación.

Xcode cierra el círculo en el momento de archivar. Recorre el grafo de dependencias, recoge el manifiesto de la app y el de cada framework incluido, y produce un informe agregado que resume los tipos de datos, las finalidades, los dominios de seguimiento y las razones de API declaradas por el conjunto del binario. Ese informe es el insumo con el que se rellena la ficha de privacidad de la tienda, y es también el momento en que muchos equipos descubren, con cara de sorpresa, que su app declara recoger identificadores de dispositivo para publicidad de terceros porque un SDK integrado hace tres años lo declara por ellos. La lección operativa es que la revisión del manifiesto agregado debe formar parte de la lista previa a cada versión, no del pánico de la semana de lanzamiento.

flowchart LR
a[Manifiesto de la app] --> d[Agregacion al archivar]
b[Manifiestos de SDK firmados] --> d
c[APIs de motivo requerido] --> d
d --> e[Informe de privacidad]
e --> f[Ficha de privacidad en la tienda]
f --> g[Revision y contraste con el binario]
g --> a
💡
Convierte la dependencia en una decisión con precio

Antes de añadir un SDK, abre su manifiesto y léelo como leerías una cláusula contractual. Si declara identificadores vinculados con finalidad de publicidad de terceros, ese SDK no cuesta lo que dice su licencia: cuesta además una fila permanente en tu ficha de privacidad, una casilla de seguimiento y, probablemente, un diálogo de consentimiento adicional para todos tus usuarios.

Operar el manifiesto a lo largo del tiempo

Un manifiesto correcto el día del lanzamiento se degrada solo, y por eso la parte más valiosa de este tema no es escribirlo sino mantenerlo sincronizado con un código que cambia cada semana. La primera medida es tratarlo como código: vive en el repositorio, se revisa en la solicitud de cambios como cualquier otro archivo y cualquier modificación exige que quien la propone explique qué comportamiento nuevo la motiva. Un cambio en el manifiesto sin cambio en el código, o al revés, es una señal de que alguien está describiendo algo que no ocurre o haciendo algo que no describe, y ambas direcciones acaban en el mismo sitio.

La segunda medida es cubrir todos los objetivos, no solo la app. Las extensiones —de compartir, de notificación, de widget, de teclado— son binarios independientes con su propio manifiesto, y a menudo son precisamente ellas las que tocan las APIs de motivo requerido: una extensión de widget que consulta el espacio en disco o lee las preferencias del grupo compartido necesita declararlo por su cuenta. Lo mismo aplica a los paquetes locales del propio equipo cuando se distribuyen como binarios. La regla que evita el olvido es que cada artefacto que se incrusta en el paquete final necesita su propio archivo, y que la agregación no inventa lo que ninguno declaró.

La tercera es distinguir con cuidado los casos límite que producen falsos positivos y falsas tranquilidades. El caso más frecuente es el del identificador de dispositivo generado por tu app, guardado en el llavero y enviado a tu propio servidor: no es seguimiento, porque no se cruza con nadie, pero sí es recogida de un identificador de dispositivo vinculado y debe declararse. El segundo es la telemetría de fallos, que casi siempre incluye datos de diagnóstico y a veces identificadores, y que muchos equipos omiten por considerarla infraestructura. El tercero, en sentido contrario, es la falsa declaración por prudencia: marcar como recogidos datos que solo se procesan en el dispositivo empeora tu ficha, confunde al usuario y contradice el propio comportamiento del binario, lo que en una auditoría cuidadosa cuenta como inexactitud igual que la omisión.

<key>NSPrivacyTracking</key><false/>
<key>NSPrivacyTrackingDomains</key>
<array/>
<key>NSPrivacyAccessedAPITypes</key>
<array>
  <dict>
    <key>NSPrivacyAccessedAPIType</key>
    <string>NSPrivacyAccessedAPICategorySystemBootTime</string>
    <key>NSPrivacyAccessedAPITypeReasons</key>
    <array><string>35F9.1</string></array>
  </dict>
</array>

Queda por señalar el punto donde el manifiesto se encuentra con el resto del marco jurídico, porque conviene no confundir capas. El manifiesto es una obligación de plataforma, no una norma legal: cumplirlo no acredita el cumplimiento del reglamento europeo de protección de datos ni de ninguna ley estatal de privacidad, y esas normas exigen cosas que el manifiesto ni siquiera menciona, como la base jurídica del tratamiento, los plazos de conservación, los encargados y los derechos de acceso y supresión. La relación útil entre ambos mundos es de insumo: el inventario que hay que construir para escribir un manifiesto honesto es exactamente el mismo registro de tratamientos que exige la norma, de modo que un equipo que hace bien lo primero tiene ya hecha la mitad de lo segundo.

ℹ️
Automatiza la detección, no solo la declaración

El análisis estático del binario puede señalar las llamadas a APIs de motivo requerido y a los símbolos de red de tus dependencias. Integrar esa comprobación en la canalización de integración continua convierte una revisión manual que se olvida en una alerta que aparece en la solicitud de cambios que introdujo el problema, que es el único momento en que arreglarlo es barato.

El manifiesto no describe tu app: describe tu grafo de dependencias, y tú firmas por él

El error de perspectiva que comete casi todo el mundo la primera vez es leer el manifiesto como un formulario y no como lo que realmente es: la materialización legible por máquina de la superficie de datos de tu binario completo, tuyo y ajeno, con tu certificado respondiendo por el total. Ese desplazamiento tiene tres consecuencias que reordenan la ingeniería. La primera es que la privacidad se vuelve componible: si cada actor declara con veracidad, la declaración del conjunto se calcula por unión en lugar de negociarse, y por eso las firmas son imprescindibles, porque una composición solo es fiable si cada término es atribuible a alguien. La segunda es que introduce un precio visible donde antes no lo había: hasta 2024 integrar un SDK invasivo era gratis para el equipo y caro para el usuario, y ahora ese coste aparece en tu ficha, en tu diálogo de consentimiento y en tu tasa de conversión, lo que alinea por fin el incentivo del desarrollador con el interés de la persona. Y la tercera, la más profunda, es que convierte una decisión de arquitectura en una decisión de cumplimiento: mover una inferencia al dispositivo, agregar antes de enviar, sustituir un identificador persistente por uno rotatorio o cambiar un SDK por una llamada a tu propio backend no son optimizaciones técnicas con un efecto lateral legal, son la forma directa de reducir el tamaño del documento que tienes que firmar. Quien entiende esto deja de rellenar manifiestos y empieza a diseñarlos, que es exactamente lo que el mecanismo pretendía provocar.

📝
Lo esencial

El archivo PrivacyInfo.xcprivacy declara seguimiento, dominios de seguimiento, tipos de datos recogidos con su vinculación y finalidad, y las razones de uso de las APIs de motivo requerido con códigos de una lista cerrada. Recoger significa transmitir fuera del dispositivo de forma persistente, así que lo local y lo efímero no se declaran. Los SDK de uso frecuente deben traer manifiesto y firma, Xcode agrega todo al archivar y del informe resultante sale la ficha de la tienda, que debe coincidir con el comportamiento real del binario.

⚔️ Auditar la superficie declarada
  1. Genera el informe de privacidad de tu app desde un archivado real y compáralo línea a línea con las respuestas actuales del cuestionario de la tienda; documenta cada divergencia y su causa.
  2. Enumera tus dependencias binarias y comprueba cuáles traen manifiesto y firma válida; para las que no, decide entre actualizar, sustituir o eliminar, con fecha.
  3. Localiza en tu código cada uso de una API de motivo requerido, asigna el código de razón más específico que describa el uso real y anota en el propio código por qué ese y no otro.
  4. Elige un tipo de dato que hoy declares como recogido y diseña una alternativa que lo procese en el dispositivo o lo agregue antes de enviarlo; estima cuántas filas del manifiesto desaparecen.
  5. Redacta la lista de comprobación previa a cada versión que incluya la regeneración del informe agregado y hazla obligatoria en la definición de terminado del equipo.