📋 Tabla de Contenidos
- El problema: 5 meses para implementar lo que nadie sabe cómo hacer
- Sistema de consentimiento granular open source
- Cifrado en reposo y en tránsito con herramientas open source
- Anonimización y pseudonimización: la línea que separa dato personal de dato anónimo
- RAT automatizado: El Registro de Actividades de Tratamiento que no te tomará meses
- Notificación de brechas: el sistema que la ley exige y pocos tienen
- Stack completo de compliance open source
- Conclusión: La ventana se cierra en 5 meses
1. El problema: 5 meses para implementar lo que nadie sabe cómo hacer
En la Parte 1 de esta saga vimos que el DPO que las pymes chilenas necesitan no existe en el mercado laboral, y que un AI Agent especializado en compliance puede suplirlo por 40x menos costo.
En la Parte 2 recorrimos los 7 Puntos Críticos de Control (PCC) para campañas de marketing y prospección, con checklist de adecuación y tabla de bases legales.
Hoy cerramos la trilogía con lo que ninguna guía de compliance te dice: cómo implementar técnicamente cada exigencia de la Ley 21.719 usando herramientas open source que ya existen, que no cuestan licencias y que cualquier pyme con un VPS puede desplegar.
⚠️ El reloj corre
1 de diciembre de 2026. Faltan exactamente 5 meses para que la Fase 2 de la Ley 21.719 entre en vigencia plena: derechos ARCO+, consentimiento, DPO, evaluaciones de impacto. Las multas arrancan en 2027, pero las obligaciones empiezan a regir AHORA. No esperes a noviembre.
Lo que sigue no es teoría. Es código, configuraciones y arquitecturas que cualquier pyme puede desplegar hoy. Todo open source. Todo sin costos de licencia.
2. Sistema de consentimiento granular open source
La Ley 21.719 exige que el consentimiento sea libre, específico, informado e inequívoco (Art. 5 y siguientes). Esto implica:
- Granularidad: el titular debe poder consentir para finalidades específicas, no un "todo o nada"
- Revocabilidad: debe poder retirar el consentimiento tan fácil como lo otorgó
- Evidencia: la organización debe poder demostrar que obtuvo consentimiento válido
- Registro: cada consentimiento debe quedar registrado con timestamp, finalidad y medio
Sistema de consentimiento con PostgreSQL + n8n
No necesitas un CRM enterprise ni un plataforma de consentimiento SaaS. Con PostgreSQL + n8n (del stack open source) puedes construir un sistema de consentimiento auditable en horas:
-- Esquema de consentimiento granular para Ley 21.719
CREATE TABLE consentimientos (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
titular_id UUID NOT NULL REFERENCES titulares(id),
finalidad VARCHAR(100) NOT NULL, -- 'marketing', 'analytics', 'prospeccion', 'compartir_terceros'
base_legal VARCHAR(50) NOT NULL, -- 'consentimiento', 'interes_legitimo', 'ejecucion_contractual'
estado VARCHAR(20) NOT NULL DEFAULT 'activo', -- 'activo', 'revocado', 'expirado'
ip_origen INET,
user_agent TEXT,
medio VARCHAR(50), -- 'web_form', 'email', 'whatsapp', 'presencial'
consentido_el TIMESTAMPTZ NOT NULL DEFAULT NOW(),
revocado_el TIMESTAMPTZ,
expira_el TIMESTAMPTZ,
evidencia_hash TEXT, -- hash del registro de consentimiento original
CONSTRAINT consentimiento_unico UNIQUE (titular_id, finalidad)
);
-- Índices para consultas rápidas de la Agencia
CREATE INDEX idx_consentimientos_titular ON consentimientos(titular_id);
CREATE INDEX idx_consentimientos_estado ON consentimientos(estado);
CREATE INDEX idx_consentimientos_finalidad ON consentimientos(finalidad);
✅ Esto cumple con:
Art. 5 (Consentimiento), Art. 12 (Deber de información), Art. 14 (Derechos del titular). Cada consentimiento tiene trazabilidad completa: quién, cuándo, para qué, por qué medio, y si fue revocado.
API de consentimiento con FastAPI
Para que tus formularios web, APIs y sistemas puedan registrar consentimiento de forma estandarizada:
# microservicio-consentimiento/api.py
from fastapi import FastAPI, HTTPException, Request
from pydantic import BaseModel
import hashlib, hmac
from datetime import datetime, timezone
app = FastAPI(title="API de Consentimiento - Ley 21.719")
class ConsentimientoRequest(BaseModel):
titular_email: str
finalidad: str
base_legal: str = "consentimiento"
medio: str
acepta_terminos: bool
@app.post("/v1/consentimiento")
async def registrar_consentimiento(data: ConsentimientoRequest, request: Request):
if not data.acepta_terminos:
raise HTTPException(400, "El consentimiento no fue otorgado")
# Generar evidencia hash inmutable
evidencia_raw = f"{data.titular_email}|{data.finalidad}|{datetime.now(timezone.utc).isoformat()}|{data.medio}|{request.client.host}"
evidencia_hash = hashlib.sha256(evidencia_raw.encode()).hexdigest()
# Registrar en PostgreSQL (via n8n o directo)
# ... insert into consentimientos ...
return {
"status": "ok",
"evidencia_hash": evidencia_hash,
"mensaje": "Consentimiento registrado exitosamente"
}
@app.post("/v1/consentimiento/{titular_email}/revocar")
async def revocar_consentimiento(titular_email: str, finalidad: str = None):
# Revocar todos o por finalidad específica
# ... update consentimientos set estado='revocado', revocado_el=now() ...
return {"status": "ok", "mensaje": "Consentimiento revocado"}
@app.get("/v1/consentimiento/{titular_email}")
async def obtener_consentimientos(titular_email: str):
# Retorna todos los consentimientos del titular con su estado
# ... select * from consentimientos where titular_email = ...
return {"consentimientos": [...]}
🔧 Despliegue con n8n
Puedes conectar formularios web (Typeform, Google Forms, o HTML propio) → n8n → PostgreSQL sin escribir una línea de código. n8n maneja el webhook, la validación y el registro. Tiempo de implementación: 2-4 horas.
3. Cifrado en reposo y en tránsito con herramientas open source
La Ley 21.719 establece un deber de seguridad (Art. 15) que exige "medidas técnicas y organizativas apropiadas para garantizar la seguridad de los datos personales". En la práctica, esto se traduce en:
- Cifrado en reposo (at-rest): los datos almacenados deben ser ilegibles sin la clave
- Cifrado en tránsito (in-transit): TLS 1.3 para todas las comunicaciones
- Gestión de claves: las claves de cifrado deben estar separadas de los datos
- Segregación de datos sensibles: los datos especialmente protegidos requieren capas adicionales
Cifrado en reposo con SeaweedFS + LUKS
Si usas SeaweedFS (como en el stack de Wagner Solutions) para almacenamiento de archivos, puedes habilitar cifrado a nivel de volumen:
# Configuración SeaweedFS con cifrado en reposo
# weed master - Volume Server con cifrado
# 1. Crear volumen cifrado con LUKS
sudo cryptsetup luksFormat /dev/sdb
sudo cryptsetup open /dev/sdb seaweed_crypt
sudo mkfs.ext4 /dev/mapper/seaweed_crypt
# 2. Montar y configurar SeaweedFS volume server
# weed volume -dir=/mnt/seaweed_crypt -mserver=master:9333 -port=8080
# 3. Cifrado a nivel de aplicación con AES-256-GCM
# En cada upload, el archivo se cifra antes de almacenarse
openssl enc -aes-256-gcm -salt -in archivo.pdf -out archivo.pdf.enc -pass file:/etc/keys/datos.key
Cifrado en PostgreSQL a nivel de columna
Para datos sensibles como RUT, email, teléfono, salud financiera — PostgreSQL tiene extensiones nativas:
-- Cifrado a nivel de columna con pgcrypto
CREATE EXTENSION IF NOT EXISTS pgcrypto;
-- Crear clave maestra de cifrado (almacenada fuera de la DB)
-- La clave se obtiene de HashiCorp Vault o variable de entorno segura
-- Datos sensibles cifrados con AES-256
CREATE TABLE datos_sensibles (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
titular_id UUID REFERENCES titulares(id),
rut_cifrado BYTEA, -- pgp_sym_encrypt('12345678-9', 'clave_maestra')
email_cifrado BYTEA, -- pgp_sym_encrypt('user@email.com', 'clave_maestra')
telefono_cifrado BYTEA,
datos_salud_cifrados BYTEA, -- cifrado con clave derivada
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- Insertar con cifrado
INSERT INTO datos_sensibles (titular_id, rut_cifrado, email_cifrado)
VALUES (
'uuid-del-titular',
pgp_sym_encrypt('12.345.678-9', current_setting('app.encryption_key')),
pgp_sym_encrypt('cliente@email.com', current_setting('app.encryption_key'))
);
-- Leer solo cuando sea necesario (y auditado)
-- SELECT pgp_sym_decrypt(rut_cifrado, current_setting('app.encryption_key')) FROM datos_sensibles WHERE id = ...;
⚠️ Importante: Gestión de claves
La clave de cifrado nunca debe estar en el mismo servidor que los datos cifrados. Usa HashiCorp Vault (open source) o un servicio de gestión de claves. Si pierdes la clave, pierdes los datos. La Ley 21.719 exige que demuestres que implementaste medidas técnicas — tener la clave separada de los datos es una de ellas.
Cifrado en tránsito: TLS 1.3 con Traefik
Traefik (el proxy inverso open source) maneja TLS 1.3 con Let's Encrypt automáticamente:
# docker-compose.yml - Traefik con TLS 1.3 forzado
services:
traefik:
image: traefik:v3.1
command:
- "--providers.docker=true"
- "--entrypoints.websecure.address=:443"
- "--certificatesresolvers.letsencrypt.acme.tlschallenge=true"
- "--certificatesresolvers.letsencrypt.acme.email=admin@tudominio.cl"
- "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
# Forzar TLS 1.3 exclusivamente
- "--entrypoints.websecure.http.tls.options=modern@file"
ports:
- "443:443"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
- "./letsencrypt:/letsencrypt"
- "./dynamic.yml:/dynamic.yml" # Config TLS moderna
# dynamic.yml - Opciones TLS modernas (solo TLS 1.3)
tls:
options:
modern:
minVersion: VersionTLS13
sniStrict: true
🔐 Esto te cubre:
TLS 1.3 forzado en todas las comunicaciones → cifrado en tránsito. Certificados renovados automáticamente con Let's Encrypt. Sin costos. Sin mantenimiento manual. Listo para auditoría.
4. Anonimización y pseudonimización: la línea que separa dato personal de dato anónimo
La Ley 21.719 define dato personal como "cualquier información relativa a una persona natural identificada o identificable". Si un dato es anónimo (no permite identificar a la persona), no le aplica la ley. Esta es la clave estratégica: anonimizar bien es la mejor forma de cumplir.
Diferencia legal crítica
| Técnica | ¿Reversible? | ¿Aplica Ley 21.719? | Caso de uso |
|---|---|---|---|
| Anonimización | 🚫 Irreversible | ❌ No aplica | Estadísticas, BI, investigación |
| Pseudonimización | 🔑 Reversible con clave | ✅ Sí aplica (pero reduce riesgo) | Producción, analytics con seudónimo |
| Cifrado | 🔐 Reversible con clave | ✅ Sí aplica | Almacenamiento seguro de datos activos |
Pipeline de anonimización con Python + PostgreSQL
Un pipeline automatizado que corre diariamente (vía cron o n8n) para anonimizar datos operacionales antes de pasarlos a BI:
# pipeline_anonimizacion.py
import hashlib, re, random, string
import psycopg2
from datetime import datetime
def anonimizar_rut(rut):
"""Reemplaza RUT real por RUT ficticio preservando formato"""
return f"{random.randint(10,99)}.{random.randint(100,999)}.{random.randint(100,999)}-{random.choice('0123456789K')}"
def anonimizar_email(email):
"""Ofusca email: usuario***@dominio.cl"""
local, dominio = email.split('@')
return f"{local[:2]}{'*' * (len(local)-2)}@{dominio}"
def pseudonimizar_email(email, salt):
"""Pseudonimización determinística: mismo input → mismo seudónimo"""
hash_obj = hashlib.sha256(f"{email}{salt}".encode())
return f"user_{hash_obj.hexdigest()[:12]}@anon.local"
def anonimizar_telefono(telefono):
"""Mantiene prefijo, ofusca el resto: +56 9 **** 1234"""
digito = re.sub(r'\D', '', telefono)
return f"+56 {digito[2:3]} **** {digito[-4:]}" if len(digito) > 8 else "***"
# Pipeline diario: datos de producción → tabla anónima para BI
def ejecutar_pipeline_anonimizacion():
conn = psycopg2.connect("dbname=produccion user=...")
cur = conn.cursor()
# 1. Pseudonimizar tabla de clientes para analytics
cur.execute("""
INSERT INTO clientes_anonimizados (id_seudonimo, edad, region, segmento)
SELECT
encode(sha256((email || 'salt_anual_2026')::bytea), 'hex') as id_seudonimo,
EXTRACT(YEAR FROM AGE(fecha_nacimiento))::int as edad,
region,
segmento
FROM clientes
WHERE updated_at > NOW() - INTERVAL '1 day'
""")
# 2. Anonimizar RAT histórico (irreversible)
cur.execute("""
UPDATE logs_tratamiento
SET rut_anon = '*********' || RIGHT(rut, 1),
email_anon = SPLIT_PART(email, '@', 1) || '@dominio-anonimo.local'
WHERE procesado_para_bi = false
""")
conn.commit()
cur.close()
conn.close()
print(f"[{datetime.now()}] Pipeline de anonimización completado")
# Programar en cron: 0 3 * * * python3 pipeline_anonimizacion.py
💡 Estrategia recomendada
Pseudonimiza en producción (para conservar funcionalidad operativa) y anonimiza para BI/analytics (donde solo importan tendencias, no individuos). La Ley 21.719 permite el tratamiento de datos pseudonimizados, pero con obligaciones reducidas. Documenta el proceso para demostrarlo ante la Agencia.
5. RAT automatizado: El Registro de Actividades de Tratamiento que no te tomará meses
La Ley 21.719 exige que responsables y encargados mantengan un Registro de Actividades de Tratamiento (RAT) con: finalidad, base legal, categorías de titulares, destinatarios, plazos de conservación y medidas de seguridad (Art. 17).
Hacerlo en Excel es un desastre. Hacerlo con Metabase + PostgreSQL + n8n es tener un RAT vivo, auditable y actualizado automáticamente:
-- Esquema RAT para Ley 21.719
CREATE TABLE rat_registro (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
responsable VARCHAR(200) NOT NULL, -- nombre de la organización responsable
encargado VARCHAR(200), -- si aplica
finalidad VARCHAR(500) NOT NULL, -- para qué se tratan los datos
base_legal VARCHAR(100) NOT NULL, -- consentimiento, interés legítimo, etc.
categorias_titulares TEXT[], -- {'clientes', 'proveedores', 'empleados'}
categorias_datos TEXT[], -- {'nombre', 'email', 'RUT', 'salud'}
destinatarios TEXT[], -- {'ERP Odoo', 'Proveedor Cloud X'}
plazos_conservacion VARCHAR(200), -- '5 años desde última interacción'
medidas_seguridad TEXT[], -- {'cifrado AES-256', 'TLS 1.3', '2FA'}
transferencia_internacional BOOLEAN DEFAULT FALSE,
pais_destino VARCHAR(100),
activo BOOLEAN DEFAULT TRUE,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);
-- Automatizar con n8n: cada nuevo proceso de datos → registro RAT automático
-- Trigger en PostgreSQL para mantener updated_at
CREATE OR REPLACE FUNCTION update_rat_timestamp()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = NOW();
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER trg_rat_updated
BEFORE UPDATE ON rat_registro
FOR EACH ROW EXECUTE FUNCTION update_rat_timestamp();
📊 Dashboard RAT en Metabase
Conecta Metabase a esta tabla y tendrás un dashboard de cumplimiento en vivo: qué datos tratas, con qué base legal, qué medidas de seguridad tienes, y cuándo se actualizó. Cualquier fiscalización se responde abriendo una URL. No más búsquedas en carpetas compartidas.
6. Notificación de brechas: el sistema que la ley exige y pocos tienen
La Ley 21.719 exige notificar a la Agencia de Protección de Datos dentro de 72 horas de conocida una brecha de seguridad (Art. 16). Y a los titulares afectados "sin dilación indebida". Sin un sistema automatizado, cumplir este plazo es imposible.
Sistema de detección y notificación con Wazuh + n8n
Wazuh (SIEM open source) monitorea logs del sistema en tiempo real. Cuando detecta un evento de seguridad, dispara un webhook a n8n, que ejecuta el protocolo de notificación:
# n8n workflow simplificado (representación)
# [Wazuh] → [Webhook] → [n8n Workflow]
# Paso 1: Recibir alerta de Wazuh
{
"rule_id": "5712",
"description": "Multiple failed login attempts - possible brute force",
"agent": {"name": "servidor-produccion"},
"data": {"src_ip": "185.220.101.x"},
"timestamp": "2026-07-02T03:15:22Z",
"risk_level": "critical"
}
# Paso 2: n8n evalúa si es brecha de datos personales
# Si el servidor contiene datos personales → activa protocolo
# Paso 3: Enviar notificación a Agencia (API o correo certificado)
# - Descripción de la brecha
# - Categorías de datos afectados
# - Número de titulares afectados
# - Medidas adoptadas
# - Contacto del DPO
# Paso 4: Notificar a titulares afectados
# - Email automático a cada titular
# - Qué datos fueron comprometidos
# - Qué medidas tomar
# - Canal de contacto
# Paso 5: Registrar en tabla de brechas (auditable)
CREATE TABLE brechas_seguridad (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
detectada_el TIMESTAMPTZ NOT NULL DEFAULT NOW(),
notificada_agencia BOOLEAN DEFAULT FALSE,
notificada_agencia_el TIMESTAMPTZ,
notificados_titulares INT DEFAULT 0,
tipo_brecha VARCHAR(100),
severidad VARCHAR(20), -- 'baja', 'media', 'alta', 'crítica'
datos_afectados TEXT[],
num_titulares_afectados INT,
medidas_adoptadas TEXT,
estado VARCHAR(20) DEFAULT 'abierta', -- 'abierta', 'cerrada', 'investigando'
created_at TIMESTAMPTZ DEFAULT NOW()
);
⚡ Tiempo real de implementación
Wazuh + n8n + PostgreSQL = 2 días de configuración. Esto te da: detección automática de brechas, protocolo de notificación en 72 horas, registro auditable y dashboard en Metabase. Sin licencias. Sin costos operativos recurrentes.
7. Stack completo de compliance open source
Aquí está la arquitectura completa que cumple con los requisitos técnicos de la Ley 21.719 usando solo herramientas open source que puedes desplegar en un VPS de Hetzner o similar:
| Requisito Ley 21.719 | Herramienta Open Source | Función | Costo |
|---|---|---|---|
| Consentimiento granular | PostgreSQL + n8n + FastAPI | Registro, evidencia, revocación | $0 |
| Cifrado en reposo | LUKS + SeaweedFS + pgcrypto | Volúmenes cifrados + cifrado columna | $0 |
| Cifrado en tránsito | Traefik + Let's Encrypt | TLS 1.3 forzado, certs automáticos | $0 |
| Gestión de claves | HashiCorp Vault | Claves separadas de datos | $0 |
| Anonimización | Python pipeline + cron/n8n | Pipeline diario automatizado | $0 |
| RAT (Registro Actividades) | PostgreSQL + Metabase | Registro vivo + dashboard fiscalización | $0 |
| Notificación brechas 72h | Wazuh + n8n | SIEM + workflow notificación | $0 |
| DPO / Compliance | AI Agent (DeepSeek V4) | Respuesta ARCO+, EIPD, monitoreo | ~$18/mes |
| Gestión de titulares | Odoo CRM | Pipeline consentimientos + derechos | $0 |
| Logs y auditoría | Grafana + Loki + Promtail | Traza de accesos a datos personales | $0 |
| TOTAL | Stack completo | Cumplimiento Ley 21.719 | ~$18/mes |
🏗️ Esto es exactamente el stack que puedes desplegar con Wagner Solutions
No es teoría. Es el mismo stack que usamos para operar nuestra infraestructura, nuestros clientes, y nuestros propios flujos de datos. Todo corre sobre VPS Hetzner, todo es open source, todo se automatiza con n8n. Si puedes ejecutar un docker-compose, puedes implementar compliance de nivel GDPR/Ley 21.719.
8. Conclusión: La ventana se cierra en 5 meses
La Ley 21.719 no es una opción. El 1 de diciembre de 2026, las obligaciones de la Fase 2 entran en vigencia. Las multas llegan hasta 20.000 UTM (~$1.300 millones CLP) para infracciones gravísimas.
Pero aquí está la buena noticia: no necesitas un presupuesto de compliance corporativo para cumplir.
Con $18/mes (lo que cuesta operar un AI Agent en DeepSeek V4 Flash) y las herramientas open source que recorrimos hoy, cualquier pyme chilena puede tener:
- ✅ Sistema de consentimiento granular auditable
- ✅ Cifrado AES-256 en reposo y TLS 1.3 en tránsito
- ✅ Pipeline de anonimización automatizado
- ✅ RAT vivo con dashboard en Metabase
- ✅ Detección y notificación de brechas en 72 horas
- ✅ AI Agent de compliance operando 24/7
📅 Lo que deberías hacer esta semana
- Día 1-2: Desplegar el esquema de consentimiento en PostgreSQL + conectar con n8n
- Día 3-4: Configurar cifrado en reposo (LUKS + pgcrypto) y forzar TLS 1.3 en Traefik
- Día 5-6: Implementar pipeline de anonimización y dashboard RAT en Metabase
- Día 7: Configurar Wazuh + n8n para notificación de brechas
Una semana de trabajo. Eso es lo que separa a una empresa que cumple de una que enfrenta multas millonarias en 2027.
¿Necesitas implementar compliance Ley 21.719 en tu empresa?
En Wagner Solutions AI desplegamos el stack completo de protección de datos que viste en este artículo. Sin licencias enterprise. Sin consultorías interminables. Un AI Agent de compliance + infraestructura open source operativa en días.
🚀 Agenda un diagnóstico gratuito de 15 minPrimeros 5 diagnósticos de julio sin costo · No requerimos contratos anuales
📚 Saga completa: Ley 21.719 para pymes chilenas
Parte 1 → El DPO que no existe: AI Agent de compliance
Parte 2 → Meta Ads, Cold Outreach y los 7 PCC
Parte 3 → Implementación técnica: Cifrado, Consentimiento, Anonimización 👈 Estás aquí
Wagner Solutions AI · Transformación digital soberana para LATAM · Stack 100% open source
wagnersolutionsai.com · hub.wagnersolutionsai.com
Chile · Julio 2026 · Publicado bajo licencia Creative Commons BY-SA 4.0