Modelo de Identidad
La analítica de Percus nunca almacena PII del viewer. Los viewers se identifican mediante un hash anónimo, por organización computado en el navegador, más un session id por carga. El identificador de recipient de la página host (recipient_code — típicamente un id de CRM) es siempre solo una entrada al hash y nunca sale de la página.
viewer_hash
viewer_hash = SHA-256( organization_id : recipient_code : org_salt ) // hex en minúsculas
- Computado en el cliente, en el SDK del embed, vía la Web Crypto API
(
crypto.subtle.digest('SHA-256', …)). Elrecipient_codenunca se envía a Percus por la red, nunca se loguea, y nunca se escribe a S3 — solo el hash resultante viaja con los eventos. org_saltes un valor por organización entregado al player en el manifest del embed (ver más abajo). Como cada organización tiene un salt distinto, el mismorecipient_codeproduce hashes distintos entre organizaciones — los hashes no pueden correlacionarse cross-org.organization_ides parte del input y, del lado del servidor, se vincula de forma independiente desde el share token firmado al momento de la ingesta, así un cliente alterado no puede atribuir eventos a otra organización.
session_id y playback_id
session_id— un UUID v4 generado una vez por carga del iframe. Refrescar el iframe produce un nuevosession_id.playback_id— un entero opcional que se incrementa por replay dentro de una sesión (1 en la primera reproducción, 2 en la siguiente, …). Permite que una sola sesión de visualización contenga múltiples reproducciones distintas.
Salt por organización: derivación y rotación
org_salt se deriva, no se almacena por organización:
org_salt = HMAC-SHA256( master_salt, organization_id )
- Un único
master_saltde alta entropía vive en AWS Secrets Manager. El servicio campaign lo lee una vez al iniciar y deriva el salt de cada organización en tiempo de resolución del manifest. El SDK solo recibe el salt derivado por org — el master nunca sale del servidor. - Es zero-touch: dar de alta una nueva organización no requiere ningún paso
de provisioning de salt; cualquier
organization_idmapea deterministicamente a un salt.
Rotación anual hard
Rotar el único master_salt anualmente. Como el salt de cada organización
se deriva de él, la rotación es hard: todos los salts derivados cambian de
una vez, por lo que el viewer_hash de cada viewer cambia.
- El análisis de cohortes no atraviesa una rotación. Un viewer visto antes y después de una rotación aparece como dos hashes distintos; la continuidad cross-rotación de cohortes no se preserva intencionalmente.
- Este trade-off se acepta a cambio de un modelo más simple y con mayor privacidad: un solo secreto que gestionar, sin identificadores por viewer de larga duración, y sin forma de re-vincular viewers a través de un límite de rotación.
Para rotar: generar un nuevo valor de alta entropía para el secret master_salt
y redeploy/refrescar el servicio campaign para que tome el nuevo valor. No se
requiere migración de datos — los eventos históricos conservan sus hashes
anteriores; los eventos nuevos usan los nuevos.
Qué almacena Percus vs. qué nunca ve
| Valor | ¿Almacenado por Percus? |
|---|---|
recipient_code (id de CRM) | Nunca — solo entrada del hash en el cliente |
master_salt | Solo en Secrets Manager; nunca enviado a los clientes |
org_salt (derivado) | Entregado al cliente en el manifest; no persistido con los eventos |
viewer_hash | Sí — anónimo, por organización, no reversible sin el salt |
session_id / playback_id | Sí — anónimos |