Skip to content

Procedimiento de Retención y Eliminación Segura de Datos

Documento: DOC-DATA-RET-01 Versión: 1.0 Fecha de aprobación: 2026-07-29 Owner: Security Lead + DPO Frecuencia de revisión: Anual Referencias PCI DSS: Req 3.2.1, Req 3.3.1, Req 9.4 Cuestionario ControlCase: Pregunta 25


1. Propósito

Definir el procedimiento operativo y automatizado para (a) mantener la retención de datos protegidos al mínimo necesario y (b) eliminarlos de forma segura al final de su ciclo de vida.

2. Alcance

Aplica a todos los datos clasificados en COVERED-INFORMATION-DATA-MATRIX.md, incluyendo:

  • CHD (PAN, cardholder name, exp) almacenado en card_vault.stored_cards
  • SAD (CVV) en RAM del tokenization-service
  • Backups de Postgres
  • Logs de aplicación e infraestructura
  • Snapshots de Vault
  • Media físico decomisionado

3. Principios

  1. Mínima retención: solo se retiene el dato mientras exista justificación de negocio activa
  2. Purge irreversible: eliminación cripto o físicamente irreversible (no soft delete)
  3. Auditabilidad: toda ejecución del purge genera evento en audit log inmutable
  4. Verificabilidad: el QSA puede reproducir el conteo de datos borrados en cualquier momento

4. Retenciones definidas

Ver COVERED-INFORMATION-DATA-MATRIX.md §7 para la tabla autoritativa.

5. Procedimientos de eliminación

5.1 SAD (CVV) — purge continuo

Frecuencia: cada 60 segundos + inmediato post-autorización.

Mecanismo dual:

  1. Immediate purge post-authorization

    • tokenization-service recibe respuesta del payment processor
    • Independiente del resultado (aprobada/declinada/error) → invalida tok_cvv_* inmediatamente
    • Emite evento Kafka fintrix.security.sad.purged con token_id, reason=post_auth, timestamp
  2. Cron sweeper (safety net)

    • Cronjob sad-purge-sweeper corre cada 60 seg
    • Query Vault kv-v2: lista tokens tok_cvv_* con lease > 15 min
    • Ejecuta vault kv delete secret/data/sad/{token_id}
    • Emite evento Kafka fintrix.security.sad.purged con reason=ttl_sweep

Ubicación del código: backend/apps/tokenization-service/src/sad/sad-purge.service.ts (SEC-019, pendiente de implementación)

Evidencia auditable:

  • Vault audit log: entries type=revoke path=sad/*
  • Kafka topic fintrix.security.sad.purged con retention 7 años
  • Dashboard Grafana SAD Purge Metrics con eventos/hora

5.2 PAN de tarjetas canceladas — purge diario

Frecuencia: diaria, 03:00 UTC (baja demanda).

Trigger: una tarjeta pasa a deleted_at IS NOT NULL cuando:

  • El cliente elimina el payment method desde el dashboard
  • La suscripción asociada se cancela y no queda otra suscripción activa con esa tarjeta
  • El fraud team marca la tarjeta como comprometida

Ventana de gracia: 30 días desde deleted_at (para chargeback disputes).

Cronjob: pan-purge-canceled-cards

sql
-- Ejecutado por el cronjob (audit-logged):
BEGIN;
  DELETE FROM card_vault.stored_cards
  WHERE deleted_at IS NOT NULL
    AND deleted_at < now() - interval '30 days'
  RETURNING id, deleted_at;
  -- rows returned se loguean con SHA-256 hash antes de commit
COMMIT;

-- Post-commit:
VACUUM FULL card_vault.stored_cards;
-- Fuerza reescritura del tablespace → dato en filesystem se sobrescribe

Ubicación del código: backend/apps/card-vault-service/src/purge/pan-purge.service.ts (SEC-020, pendiente de implementación)

Evidencia auditable:

  • Postgres audit log (pgAudit extension) con DELETE statements + row counts
  • Kafka topic fintrix.security.pan.purged con card_id_hash, purged_at, days_since_deletion
  • Job artifact en Kubernetes: kubectl -n pci-cde logs job/pan-purge-canceled-cards-<date>

5.3 Backups >90 días

Frecuencia: automática vía DO Spaces object lifecycle policy.

Policy configurada en bucket fintrix-db-backup-nyc3:

json
{
  "Rules": [
    {
      "ID": "PurgeBackupsOlderThan90Days",
      "Status": "Enabled",
      "Filter": { "Prefix": "postgres/" },
      "Expiration": { "Days": 90 }
    }
  ]
}

Verificación:

bash
# Listar backups actuales con edad
s3cmd ls s3://fintrix-db-backup-nyc3/postgres/ | awk '{print $1, $NF}'
# Alerta si se encuentra archivo > 90 días

5.4 Logs >365 días

Frecuencia: automática vía Loki retention + Spaces lifecycle.

  • Loki: retention_period: 2160h (90 días online)
  • DO Spaces archive: lifecycle policy con expiration a 275 días adicionales
  • Total: 365 días máximo, cumple PCI DSS Req 10.5.1

5.5 Media físico decomisionado

Aplica si un droplet, disco físico, o dispositivo sale del CDE.

Procedimiento (MEDIA-DISPOSAL-RUNBOOK.md):

  1. Backup pre-decomiso (si aún se necesita el dato)
  2. Wipe con shred -uvfz -n 3 /dev/sdX o equivalente
  3. Overwrite verificable con patterns aleatorios (mínimo 3 pases)
  4. Para SSD: blkdiscard + verificación de erase con hdparm --security-erase
  5. Destrucción física del disco (drill o triturado industrial) por vendor certificado
  6. Certificate of Destruction firmado por el vendor
  7. Archivar CoD en drive legal + evento fintrix.security.media.destroyed a SIEM

Vendor autorizado en Colombia: [TO_DEFINE] (Iron Mountain o similar)

5.6 Vault snapshots

Retención: 30 días de snapshots diarios + 12 snapshots mensuales (para RTO/RPO).

Cronjob en el cluster Vault:

bash
# Diario 04:00 UTC
vault operator raft snapshot save /var/backups/vault-$(date +%Y%m%d).snap
# Upload a Spaces WORM (immutable)
s3cmd put /var/backups/vault-*.snap s3://fintrix-vault-audit-nyc3/snapshots/
# Purge locales > 7 días
find /var/backups/vault-*.snap -mtime +7 -delete
# Spaces lifecycle purga > 30 días automáticamente

6. Verificación de ejecución (evidencia auditable)

Todo purge debe generar evidencia verificable por el QSA. Las evidencias se archivan en:

PurgeEvidencia primariaUbicaciónRetención evidencia
SAD sweeperVault audit log entriess3://fintrix-vault-audit-nyc3/audit/ (WORM)3 años
PAN canceledPostgres pgAudit + Kafka eventLoki + Kafka topic7 años
Backup lifecycleSpaces access logss3://fintrix-logs-archive-nyc3/spaces-access/1 año
Logs retentionLoki retention metricsPrometheus loki_ingester_streams_removed_total1 año
Media disposalCertificate of Destruction (PDF)Drive legal + escrow notarialVida del sistema
Vault snapshotsS3 access log + snapshot listSpaces WORM3 años

7. Roles y responsabilidades

RolResponsabilidad
Security LeadAprobar cambios al procedimiento, revisar evidencia mensualmente
DPOVerificar cumplimiento GDPR/Ley 1581 (retención = minimización)
DevOpsMantener cronjobs, monitorear alerts de purge fallido
DBAEjecutar VACUUM FULL, verificar libertad de dead tuples
QSA (externo)Verificar evidencia trimestralmente y en assessment anual

8. Métricas y alertas

Dashboard Grafana: PCI Data Retention Compliance

MétricaAlertaEscalación
sad_tokens_older_than_15_min> 0 durante > 5 minPagerDuty → Security oncall
pan_purge_job_last_success_timestamp> 26 h agoPagerDuty → DevOps oncall
backup_older_than_90_days_count> 0Email → DevOps
logs_older_than_365_days_count> 0Email → DevOps
vault_snapshot_last_uploaded_timestamp> 26 h agoPagerDuty → Security

9. Runbook para failed purge

Si un purge falla (ej: constraint violation, deadlock, Vault sealed):

  1. Alerta dispara → oncall recibe
  2. Oncall revisa logs del cronjob: kubectl -n pci-cde logs job/{name}
  3. Diagnóstico común:
    • Vault sealed → escalar a custodios para unseal ceremony
    • deadlock detected → identificar tx en conflicto + retry manual
    • pg connection refused → verificar salud del Postgres primary
  4. Ejecutar purge manual con audit trail:
    bash
    kubectl -n pci-cde create job --from=cronjob/pan-purge-canceled-cards \
      pan-purge-manual-$(date +%Y%m%d-%H%M)
  5. Documentar incidente en INCIDENTS/YYYY-MM-DD-purge-failure.md
  6. Post-mortem obligatorio si downtime > 24 h

10. Testing anual

Cada Q4 (previo a la re-certificación):

  1. Test de purge: insertar 100 registros dummy con deleted_at = now() - interval '31 days', ejecutar cronjob manual, verificar 0 rows post-ejecución
  2. Test de restauración de backup: restaurar snapshot de hace 30 días a cluster de staging, verificar integridad
  3. Test de recuperación Vault: unseal ceremony completa desde snapshot de Spaces
  4. Test de shred: wipe de disco de prueba + intento de recovery con photorec — debe fallar

Resultados archivados en docs/pci-dss/annual-tests/YYYY/.

11. Aprobaciones

RolNombreFirmaFecha
CTO[TO_FILL]
Security Lead[TO_FILL]
DPO[TO_FILL]

Documentación Confidencial — Solo para uso interno y auditoría PCI DSS