Saltar al contenido

lección 7

Protección de datos para ingenieros

Qué es un dato personal y cuál es sensible, guardar solo lo que hace falta, por qué un hash con hashlib no basta y cómo se hace un código con clave secreta (HMAC), y cómo se borra a quien lo pide de todas partes y se comprueba que se hizo.

⏱ 45 min

## El usuario 4417749

El 4 de agosto de 2006, el departamento de investigación de AOL publicó en internet unos 20 millones de búsquedas hechas por unas 650.000 personas durante tres meses. Querían ayudar a los investigadores. Antes de publicarlas hicieron lo que a casi todo el mundo le parece suficiente: quitaron el nombre de usuario y pusieron un número en su lugar.

Cinco días después, dos periodistas del New York Times llamaron a la puerta de Thelma Arnold, una viuda de 62 años de Lilburn, en Georgia. Era el usuario 4417749. Bastó con leer sus búsquedas juntas: «jardineros en Lilburn», varias personas apellidadas Arnold, dolencias de una mujer de su edad. Cada búsqueda sola no decía nada; todas juntas, con el mismo número, eran una persona con nombre y dirección. AOL retiró los datos, despidió a dos personas y su directora de tecnología dejó la empresa.

Esta lección va de no ser AOL. Un contrato de datos te dice qué columnas llegan; no te dice cuáles deberías dejar entrar. Aquí aprendes lo que se hace en el pipeline, no en un despacho de abogados. Son cuatro cosas: reconocer un dato personal y uno sensible, guardar solo lo que hace falta, convertir un email en un código con clave secreta, y borrar a quien lo pide de todas partes, sabiendo demostrar que se hizo.

## Qué es un dato personal

En Europa la regla es el Reglamento General de Protección de Datos (RGPD), que se aplica desde el 25 de mayo de 2018; en España lo completa la Ley Orgánica 3/2018 (LOPDGDD). Su definición es más amplia de lo que se suele pensar: un dato personal es toda información sobre una persona física identificada o identificable. Identificable significa que se puede llegar a saber quién es, directa o indirectamente, con medios razonables.

La palabra que importa es «identificable». El nombre y el email son obvios. Lo que no es obvio es que una combinación de datos inocentes también identifica. En el año 2000, la investigadora Latanya Sweeney mostró que el código postal, la fecha de nacimiento y el sexo bastaban para señalar a una sola persona en el 87 % de la población de Estados Unidos. Ninguna de las tres columnas es un nombre. Las tres juntas casi siempre lo son.

Columna (tienda online de bicicletas)¿Dato personal?Por qué
email, nombre, teléfonoSíIdentifican directamente
dirección de envíoSíLleva a una casa y a quien vive en ella
IP de la última visitaSíEl Tribunal de Justicia de la UE lo confirmó en 2016 (caso Breyer): con los registros del operador se llega a la persona
fecha de nacimiento + código postalSíJuntas reducen a muy pocas personas
talla de cuadro, en la fila de un clienteSíCualquier dato que cuelga de una persona identificable es personal
nota libre de atención al clienteCasi siempreQuien la escribe pone nombres, emails, teléfonos y hasta dolencias, y ninguna columna lo avisa
precio del modelo, en el catálogoNoDescribe una bicicleta, no a una persona
stock del almacén de ZaragozaNoDescribe un almacén
La talla de cuadro es la que más sorprende: no identifica a nadie por sí sola, pero en la tabla de clientes dice algo de alguien concreto. La nota libre es la que más se olvida: su nombre de columna no dice nada de lo que lleva dentro.

## Datos sensibles: las categorías especiales

Dentro de los datos personales hay un grupo con protección reforzada. El artículo 9 del RGPD los llama categorías especiales y en el día a día se les dice «datos sensibles»: origen étnico o racial, opiniones políticas, convicciones religiosas o filosóficas, afiliación sindical, datos genéticos, datos biométricos usados para identificar a alguien (una huella para abrir un torniquete), datos de salud y datos sobre la vida sexual o la orientación sexual. Tratarlos está prohibido por defecto, salvo las excepciones que enumera el propio artículo, como el consentimiento explícito o la asistencia sanitaria que presta un profesional obligado a guardar secreto.

El peligro no suele estar en la columna que se llama «diagnóstico», sino en lo que se deduce. En 2012, el New York Times contó cómo una cadena de grandes almacenes de Estados Unidos calculaba una «puntuación de embarazo» a partir de compras como crema sin perfume o suplementos de calcio. Ninguna columna decía «embarazada». Un dato de salud deducido sigue siendo un dato de salud.

Una tabla de compras de una farmacia online es, en la práctica, una tabla de salud: las tiras de glucosa dicen «diabetes» aunque ninguna columna lo diga. Antes de cruzar compras con personas, pregúntate qué se puede deducir del cruce, no solo qué dicen las columnas.

Hay datos que el artículo 9 no incluye y que aun así se tratan como si lo hicieran, porque su fuga hace mucho daño: el DNI, el IBAN, la ubicación precisa del móvil, los datos de menores o las contraseñas.

## Minimizar: guardar solo lo que hace falta para la pregunta

Piensa en el portero de una discoteca. Su pregunta es «¿tiene dieciocho años?». Mira el DNI y te lo devuelve. No lo fotocopia, no apunta tu dirección y no se queda con tu número de soporte «por si acaso». Necesita un sí o un no, y se queda con un sí o un no.

El RGPD lo llama minimización (artículo 5): los datos tienen que ser adecuados, pertinentes y limitados a lo necesario para el fin. En un pipeline se traduce en una costumbre muy concreta: se parte de la pregunta de negocio y se baja hasta las columnas, nunca al revés. Si la pregunta es «cuánto se vende por provincia y tramo de edad», no necesitas el email, ni el nombre, ni la fecha de nacimiento exacta, ni la calle.

  • Elige las columnas a mano. Una lista explícita de columnas en la ingesta, no «todo lo que venga». Lo que no está en la lista no entra.
  • Generaliza. La fecha de nacimiento se queda en tramo de edad; el código postal, en provincia (en España, las dos primeras cifras); la IP, en país; la hora exacta, en día.
  • Limita el tiempo. Minimizar también es no guardar para siempre. El mismo artículo 5 pide conservar los datos solo el tiempo necesario: decide cuánto y bórralo después.
1import pandas as pd
2
3# Lo que manda la tienda: todo lo que tiene
4pedidos_crudos = pd.DataFrame({
5 "pedido": [101, 102, 103],
6 "email": ["ana@correo.es", "luis@correo.es", "eva@correo.es"],
7 "nombre": ["Ana Ruiz", "Luis Gil", "Eva Sanz"],
8 "fecha_nacimiento": ["1991-04-12", "1978-11-30", "2001-07-02"],
9 "codigo_postal": ["28012", "08024", "46005"],
10 "ip": ["83.44.10.7", "88.12.200.3", "95.20.1.18"],
11 "importe": [349.0, 1290.0, 89.9],
12 "fecha": ["2026-10-01", "2026-10-01", "2026-10-02"],
13})
14
15# La pregunta: ¿cuánto se vende por provincia y tramo de edad?
16COLUMNAS_NECESARIAS = ["pedido", "fecha_nacimiento", "codigo_postal", "importe", "fecha"]
17pedidos = pedidos_crudos[COLUMNAS_NECESARIAS].copy()
18
19# Generalizar: la pregunta no necesita el día exacto ni la calle
20edad = 2026 - pd.to_datetime(pedidos["fecha_nacimiento"]).dt.year
21pedidos["tramo_edad"] = pd.cut(edad, bins=[0, 29, 44, 64, 120],
22 labels=["<30", "30-44", "45-64", "65+"])
23pedidos["provincia"] = pedidos["codigo_postal"].str[:2]
24pedidos = pedidos.drop(columns=["fecha_nacimiento", "codigo_postal"])
25
26print(pedidos.to_string(index=False))
27# pedido importe fecha tramo_edad provincia
28# 101 349.0 2026-10-01 30-44 28
29# 102 1290.0 2026-10-01 45-64 08
30# 103 89.9 2026-10-02 <30 46

De ocho columnas a cinco, y dos de ellas generalizadas. La tabla responde a la misma pregunta y ya no dice quién compró.

Consejo de senior: lo que no guardas no se te puede filtrar, no te lo pueden pedir borrar y no tienes que explicar por qué lo tenías. Cada vez que alguien diga «guárdalo por si acaso», pregunta para qué pregunta. Si nadie sabe contestar, no entra.

## Seudonimizar no es anonimizar

Lo que hizo AOL tiene nombre: seudonimizar. Es sustituir lo que identifica (el nombre de usuario) por un código (el número), de forma que sin información adicional, guardada aparte, no se sepa quién es. Anonimizar es otra cosa: transformar los datos de manera que ya nadie, con medios razonables, pueda volver a la persona. La diferencia no es de matiz. La Agencia Española de Protección de Datos (AEPD) lo dice sin rodeos: un dato seudonimizado sigue siendo un dato personal y se le sigue aplicando el RGPD entero. Solo el dato anonimizado de verdad queda fuera.

Fíjate en dónde cae el HMAC: es la mejor de las técnicas de la zona roja, pero sigue en la zona roja. Seudonimizar mueve el punto hacia la derecha; no le hace cruzar la frontera.

¿Por qué el seudónimo no basta para salir? Porque el código es siempre el mismo para la misma persona, así que junta todas sus filas. Y las filas juntas cuentan una vida: le pasó a AOL, y en 2008 al concurso de Netflix, cuyos usuarios «anónimos» se reidentificaron cruzando sus valoraciones con reseñas públicas en IMDb. Y porque quien tiene la información adicional (la tabla de correspondencias, la clave) puede deshacerlo.

Entonces, ¿para qué seudonimizar? Para reducir el riesgo, que no es poco: quien analiza cuenta clientes y cruza tablas sin ver jamás un email, y una tabla de códigos filtrada hace mucho menos daño que una de emails. El propio RGPD la cita como medida de seguridad. Solo hay que ser honesto con lo que es.

Nunca escribas «tabla anonimizada» en la documentación de una tabla seudonimizada. Las palabras tienen consecuencias legales: quien lea «anónimo» puede decidir compartirla con un proveedor o guardarla para siempre, y ninguna de las dos cosas está permitida con un dato personal.

## Por qué un hash simple no basta

Una función hash convierte cualquier texto en una huella de longitud fija. SHA-256, publicada por el NIST de Estados Unidos en 2001, convierte «ana@correo.es» en 64 caracteres hexadecimales. El mismo texto da siempre la misma huella, dos textos distintos dan huellas distintas y no hay fórmula para volver de la huella al texto. En Python viene de serie, en el módulo `hashlib` de la biblioteca estándar: `hashlib.sha256("ana@correo.es".encode()).hexdigest()`, sin instalar nada. Es tan cómodo que tanta gente concluye: «si no se puede invertir, mi email está protegido».

El fallo es que nadie necesita invertirla: basta con adivinar. Quien tiene una lista de emails o de móviles candidatos calcula el hash de cada uno y compara. Los emails siguen patrones (nombre.apellido@proveedor) y los móviles españoles son nueve cifras que empiezan casi siempre por 6 o 7; un ordenador normal calcula millones de SHA-256 por segundo. La AEPD y el Supervisor Europeo de Protección de Datos dedicaron un documento entero a esto: el hash solo seudonimiza si el atacante no puede recorrer los valores posibles.

1import hashlib
2import time
3
4# En la tabla «seudonimizada» aparece este hash de un móvil
5hash_filtrado = hashlib.sha256("612345678".encode()).hexdigest()
6
7# El atacante no invierte nada: prueba. Supongamos que sabe el prefijo
8# (6123...) y le faltan 5 cifras: 100.000 candidatos.
9inicio = time.perf_counter()
10for resto in range(100_000):
11 candidato = f"6123{resto:05d}"
12 if hashlib.sha256(candidato.encode()).hexdigest() == hash_filtrado:
13 print("Encontrado:", candidato)
14 break
15print(f"Intentos: {resto + 1:,}".replace(",", "."))
16print(f"Tiempo: {time.perf_counter() - inicio:.2f} s")
17# Encontrado: 612345678
18# Intentos: 45.679
19# Tiempo: 0.04 s

Cuarenta y cinco mil intentos en unas centésimas de segundo. Con los 200 millones de móviles posibles, un portátil tarda minutos; una tarjeta gráfica, menos de un segundo.

La reacción habitual es añadir una «sal», un texto que se pega al email antes del hash. Si es aleatoria y distinta por fila, el mismo email da códigos distintos y ya no puedes cruzar tablas ni contar personas, que era el objetivo. Si es fija y está escrita en el código, es una clave mal guardada: la tiene cualquiera con acceso al repositorio. Lo que necesitas es una clave, bien hecha y bien guardada. Muchos equipos la siguen llamando «sal». El nombre da igual; lo que importa es que no esté en el código.

## HMAC: un código con clave secreta

En 1996, Mihir Bellare, Ran Canetti y Hugo Krawczyk propusieron HMAC, que en 1997 se publicó como estándar de internet (RFC 2104). Nació para demostrar que un mensaje viene de alguien que conoce una clave y que nadie lo ha tocado, pero su forma es justo la que buscamos: código = HMAC(clave, email). Mismo email y misma clave, mismo código; sin la clave, no se puede calcular. En Python está en otro módulo de la biblioteca estándar, `hmac`, que usa por dentro la función hash que le digas. Con `hashlib.sha256` el resultado se llama HMAC-SHA256, el nombre que vas a ver escrito en casi todas partes.

Piénsalo como un molde. Un hash simple es un molde que vende cualquier ferretería: el atacante se compra uno, prueba emails y compara. HMAC es un molde que solo tiene tu empresa, guardado en una caja fuerte. El atacante puede tener la lista de emails más completa del mundo; sin el molde, sus huellas no se parecen en nada a las tuyas.

El atacante es el mismo y tiene la misma lista. Lo único que cambia es la pieza que le falta abajo: sin la clave no puede fabricar huellas comparables con las tuyas.
1import hashlib
2import hmac
3import os
4
5clave = os.environ.get("CLAVE_SEUDONIMO", "").encode("utf-8")
6if not clave:
7 raise RuntimeError("Falta CLAVE_SEUDONIMO: la carga no sigue sin ella")
8
9
10def normalizar(email: str) -> str:
11 return email.strip().lower()
12
13
14def codigo(email: str) -> str:
15 mensaje = normalizar(email).encode("utf-8")
16 return hmac.new(clave, mensaje, hashlib.sha256).hexdigest()
17
18
19print(codigo("ana@correo.es")[:16])
20print(codigo(" Ana@Correo.es ")[:16]) # el mismo: se normaliza antes

Las tres piezas: la clave se lee de fuera del código, el email se normaliza y el código es un HMAC-SHA256 en hexadecimal (64 caracteres).

La clave vive fuera del código: en una variable de entorno que el sistema pone antes de arrancar la carga o, mejor, en el gestor de secretos de tu proveedor de nube, que la entrega solo al proceso que la necesita y deja registro de quién la ha pedido. Nunca en el repositorio: lo que entra en el historial de Git se queda ahí aunque lo borres en el siguiente commit. Para generar una clave buena y ponerla en tu terminal:

1# Generar una clave aleatoria de 32 bytes (igual en Windows y Mac)
2python -c "import secrets; print(secrets.token_hex(32))"
3
4# Windows (PowerShell): solo para esta sesión de la terminal
5$env:CLAVE_SEUDONIMO = "pega-aqui-la-clave-generada"
6
7# Mac (Terminal/zsh): solo para esta sesión de la terminal
8export CLAVE_SEUDONIMO="pega-aqui-la-clave-generada"

En tu máquina, para probar. En producción la pone el orquestador o el gestor de secretos, nunca una persona a mano.

Tres errores que he visto en producción. Uno: leer la variable con un valor por defecto, como «clave123», por si no está; el día que alguien olvide configurarla, esa será la clave real y nadie se enterará. Si falta la clave, la carga se para. Dos: imprimir la clave en el log «para depurar»; los logs se copian a muchos sitios. Tres: dar la clave a quien analiza: con la clave y una lista de emails se deshacen los códigos.

Cambiar la clave cambia todos los códigos, y rompe todos los cruces con datos históricos igual que renombrar una columna en un contrato de datos. Se planifica, se avisa y se recalcula todo a la vez, como explica «Contratos de datos: definir qué esperas ANTES de que lleguen», de este mismo módulo. Y usa una clave distinta en cada entorno: si la copia de pruebas usa la de producción, un código visto en pruebas reconoce a la persona en producción.

## Normalizar antes del código

HMAC es exacto hasta el último byte. Un espacio al final o una mayúscula producen un código completamente distinto, no uno parecido: se llama efecto avalancha y es una virtud cuando proteges un mensaje. Cuando lo que quieres es reconocer a la misma persona en dos sistemas, es un problema. El formulario de la web guarda «ana@correo.es»; el CRM, que lo tecleó alguien en una tienda, guarda « Ana@Correo.es». Es la misma persona y, sin normalizar, son dos códigos.

Mismo email, misma clave. A la izquierda las flechas no se tocan nunca: para tus tablas son dos personas. A la derecha se juntan. Los códigos son los primeros ocho caracteres reales de cada HMAC.

La normalización mínima es quitar los espacios de los extremos y pasar a minúsculas. El estándar del correo permite en teoría distinguir mayúsculas antes de la arroba, pero ningún proveedor grande lo hace; la decisión se deja escrita. Lo que no conviene es inventar reglas de un proveedor, como quitar los puntos en Gmail: si te equivocas, juntas a dos personas en un mismo código, que es peor que separar a una.

Y la normalización es un contrato en sí misma: todos los procesos que calculan códigos usan exactamente la misma función, que vive en un único módulo compartido y lleva sus pruebas automáticas. Una de ellas comprueba que el mismo email escrito de dos formas da el mismo código.

## El derecho a borrar

En 2010, Mario Costeja se quejó ante la AEPD: al buscar su nombre en Google salía un anuncio de 1998 sobre la subasta de un inmueble suyo por unas deudas que ya había saldado. El Tribunal de Justicia de la Unión Europea le dio la razón el 13 de mayo de 2014. Se le llamó «derecho al olvido», y el RGPD lo recogió en su artículo 17 como derecho de supresión. Una persona puede pedir que borres sus datos cuando ya no son necesarios, cuando retira su consentimiento o cuando se trataron sin base legal.

El plazo es corto y está escrito: sin dilación y como mucho en un mes desde que llega la petición. Se puede ampliar dos meses más si es compleja o hay muchas, avisando a la persona dentro del primer mes y explicándole por qué. Planifica para un mes, y que ese mes lo consuma la gestión, no buscar dónde están los datos.

## Antes de borrar: el inventario

La persona no vive en una tabla. Vive en la base de origen, en la zona raw del lago, en el almacén, en el extracto que se mandó a marketing el martes, en el entorno de pruebas que alguien llenó con una copia de producción y en las copias de seguridad. Y vive en sitios sin columna de email: la nota de atención al cliente, el log que imprimió la fila entera. Por eso el primer paso no es un DELETE: es un inventario. Es la lista de cada sitio con datos personales, cómo se reconoce en él a la persona (email, código, dentro de un texto) y qué se hace. Se mantiene cada vez que nace una tabla, y el día de la petición se recorre, no se improvisa.

Cinco barras cortas y una larga. Lo que se puede editar se limpia en una noche; las copias de seguridad no se editan y son la barra que cruza la línea del mes.

Consejo de senior: diseña para el borrado desde el primer día. Si cada tabla que toca a personas lleva la misma columna de código, el inventario es corto y borrar es un filtro repetido en un bucle. Si cada equipo identificó a la gente a su manera (email aquí, teléfono allá, un id interno en el tercer sitio), mal asunto. El día de la primera petición vas a pasar una semana buscando, y el mes corre.

## Borrar, anonimizar, nullificar o bloquear

«Suprimir» no es una sola operación. Son cuatro, y cada sitio del inventario se lleva la suya según para qué sirven sus datos sin la persona:

  • Borrar: la fila desaparece. Para lo que no vale nada sin la persona: su ficha, la foto de su DNI, el extracto que se hizo para una campaña.
  • Anonimizar: la fila se queda y pierde para siempre el vínculo con la persona. El código pasa a vacío y lo demasiado exacto se generaliza (la hora al día, el importe redondeado). Para lo que sigue sirviendo como estadística: las ventas del mes, las visitas de cada día.
  • Nullificar: una columna de texto libre se vacía entera (NULL). No se resume ni se tachan nombres. «La clienta, profesora en el instituto del barrio, que vive con su madre» señala a alguien sin nombrarlo, y ningún filtro caza todas las maneras de contarlo.
  • Bloquear: la fila se queda tal cual, pero apartada. Para lo que una ley obliga a conservar, como las facturas.
Sitio (tienda de bicicletas)Cómo aparece la personaQué se hace
clientesemail y códigoBorrar
pedidoscódigo del clienteAnonimizar: el código a vacío, y las ventas por mes siguen cuadrando
facturascódigo, nombre y NIFBloquear hasta que venza el plazo legal
tickets de atención al clientedentro del textoNullificar la columna del texto
extracto de marketing del martesemailBorrar, y que marketing borre su copia
copias de seguridadtodo lo anteriorDejar que caduquen; si se restaura una, repasar la lista
Solo dos filas dicen «borrar»: la mayor parte del trabajo es decidir qué se puede quedar y en qué condiciones.

Bloquear es la que más se confunde. Llega alguien con buena intención: «si vais a anonimizar a ese cliente, pasadme sus datos para el estudio». No se anonimiza nada. Una factura anonimizada ya no se puede atribuir a nadie y deja de servir para lo que la ley pide conservarla, así que anonimizarla es incumplir la obligación. Y bloqueado no es «apartado pero disponible para estadística»: solo se usa para esa obligación, ante Hacienda o un juez (en España lo regula el artículo 32 de la LOPDGDD). En el pipeline es una fecha en la fila (`bloqueado_desde`) y unas vistas del día a día que la excluyen. Solo un rol con base legal puede leerla, y una carga la borra o la anonimiza cuando vence el plazo.

Qué se conserva, por qué ley y hasta cuándo no lo decide el pipeline ni quien lo programa. Lo decide la persona responsable de protección de datos, y el pipeline lo aplica. Y quien pidió el borrado tiene derecho a saberlo: se le contesta por escrito qué se ha borrado, qué se conserva, por qué ley y hasta cuándo.

Así se monta en un pipeline. La petición entra en una lista de supresión que guarda el código, no el email. Guardar el email de quien pide que lo olvides sería crear otra tabla de datos personales. Cada noche, la carga recorre el inventario, aplica a cada sitio su acción y escribe un registro con el código, las fechas y cuántas filas trató. El email solo hace falta durante la carga, para buscarlo en los textos libres; por eso tantas ingestas no dejan pasar la columna de notas al almacén.

Las copias de seguridad no se abren para borrar una fila: se dejan caducar. Su política de conservación (por ejemplo, 35 días) dice qué día habrá desaparecido la persona también de ahí, y esa fecha va al registro. Mientras tanto no se usan, y si hay que restaurar una, lo primero es volver a pasar la lista de supresión, o restaurar sería resucitar a quien pidió irse. Los logs son una tabla más: conservación corta y escrita. Las versiones antiguas de las tablas con historial se purgan aparte; lo ves en «Time travel y versionado: volver al pasado de tus datos», del módulo «Data Lakes y formatos modernos».

## Comprobar que se hizo

Un borrado que nadie comprueba es una promesa. La comprobación es una tabla con una fila por sitio del inventario: lo esperado, lo obtenido al volver a buscar y OK o FALLO. Donde se borró, quedan tantas filas menos como se trataron; donde se anonimizó, nullificó o bloqueó, las mismas que antes, porque si faltan has borrado de más. Y en todas, cero filas que sigan señalando a la persona: ni su código, ni su email dentro de un texto, ni una fila suya sin la marca de bloqueo. Con un solo FALLO, la carga se marca como fallida y avisa a alguien.

Busca con los datos copiados de la petición y del registro, nunca escritos de memoria ni sacados del ticket. Un email mal tecleado devuelve cero filas, y cero filas parece un éxito: es la forma más fácil de certificar un borrado que no se hizo.

## Lo que te llevas

  1. 01.Un dato personal es cualquier información sobre alguien identificable, y las combinaciones identifican. Las categorías especiales (salud, biometría, ideología…) llevan protección reforzada, también cuando se deducen.
  2. 02.Minimizar es partir de la pregunta: columnas elegidas a mano, datos generalizados y un plazo para borrarlos.
  3. 03.Seudonimizar no es anonimizar: el código sigue siendo un dato personal.
  4. 04.Un hash simple con `hashlib` se adivina probando candidatos. Un HMAC-SHA256 con `hmac` y una clave guardada fuera del código no, mientras la clave no salga de donde está.
  5. 05.Normaliza antes de calcular el código, siempre con la misma función y con pruebas que lo demuestren.
  6. 06.Quien pide que lo borren desaparece de todas partes en menos de un mes. Inventario, una acción por sitio (borrar, anonimizar, nullificar o bloquear), copias que caducan y una comprobación que lo demuestra, sin volver a guardar su email.

Todo esto corre de noche, sin nadie mirando. Una carga que debía borrar a tres personas y borró a cero no da ningún error: simplemente no hace nada. Y la comprobación que escribe FALLO no sirve de mucho si nadie la lee. Por eso lo siguiente que necesita un pipeline serio no es otra regla, sino alguien que se entere cuando algo no ha pasado.

## Fuentes

Regístrate para guardar tu progreso.