Skip to main content

Sistema de Gestio de Consentiment

Documentacio tecnica del sistema de consentiment legal de LDP.

Arquitectura

Taules

  • legal_documents: Versions dels documents legals (ToS, Privacy Policy, Cookie Policy)
  • user_consents: Registre de cada acceptacio/retirada amb audit trail complet

Flux de registre

  1. Frontend envia tosAccepted=true, tosVersion, privacyAccepted=true, privacyVersion
  2. Backend valida edat >= 14 (LOPDGDD Art. 7)
  3. Backend valida que els documents existeixen i estan actius
  4. Es crea UserConsent amb timestamp, IP, User-Agent per cada document
  5. Es registra ageVerifiedAt + ageVerificationMethod=SELF_DECLARED

Flux de re-consentiment (login)

  1. ConsentService.hasRequiredConsents(userId) verifica si l'usuari te els consentiments vigents
  2. Si un document ha canviat de versio des de l'ultima acceptacio, retorna false
  3. Frontend mostra ConsentRenewalModal amb els documents pendents
  4. L'usuari ha d'acceptar abans de poder continuar

Flux de retirada (GDPR Art. 7.3)

  1. DELETE /api/users/me/consents/{documentType}
  2. Es crea un registre UserConsent amb consentType=WITHDRAWAL
  3. La retirada es tan facil com l'acceptacio (requisit legal)

Flux d'esborrat (GDPR Art. 17)

  1. POST /api/users/me/data-erasure
  2. DataErasureService anonimitza l'usuari (veure ADR-004 per detalls de cascada)
  3. UserConsent es manté com a prova legal

Endpoints

EndpointMetodeAccesProposit
/api/legal/documents/currentGETPublicDocuments vigents
/api/legal/platform-infoGETPublicInfo LSSI-CE Art. 10
/api/users/me/consentsGETAutenticatEstat consentiments
/api/users/me/consentsPOSTAutenticatAcceptar el CONJUNT de documents (T-515)
/api/users/me/consents/{type}DELETEAutenticatRetirar consentiment
/api/users/me/data-erasurePOSTAutenticatSol·licitud esborrat

Audit Trail

Cada UserConsent registra:

  • user_id: Usuari
  • legal_document_id: Document i versio acceptats
  • consent_type: ACCEPTANCE o WITHDRAWAL
  • given_at: Timestamp exacte
  • ip_address: IP del client (X-Forwarded-For si proxy)
  • user_agent: Navegador/client
  • superseded_at: Quan aquesta declaracio va quedar sense efecte per una de signe contrari POSTERIOR sobre el MATEIX document. NULL = declaracio vigent (T-515)
  • metadata: JSONB per informacio addicional futura

Idempotencia i integritat del registre (T-515)

El registre de consentiments es l'evidencia que exigeix l'art. 7.1 del RGPD: «el responsable ha de poder DEMOSTRAR que l'interessat va consentir». Per aixo hi ha dues regles que el codi fa complir, i no depenen que ningu les recordi:

1. Una acceptacio, una fila. POST /api/users/me/consents es idempotent: si aquella persona ja te una acceptacio vigent d'aquell document, tornar-la a enviar NO escriu res i NO toca la fila que ja hi es. La data, la IP i el navegador que hi consten son els del moment en que el consentiment es va donar de veritat, no els del reintent. La retirada tambe ho es.

2. El conjunt s'escriu sencer o no s'escriu. La peticio porta TOTS els documents d'una pantalla i el servidor els escriu en una sola transaccio. Abans el navegador n'enviava una per document i, si en fallava una pel mig, en quedaven de desades i d'altres no: un registre a mitges, que no demostra res, mentre l'usuari llegia que no s'havia desat res.

Qui ho garanteix:

  • uk_user_consent_effective (V151) — index PARCIAL UNIQUE (user_id, legal_document_id, consent_type) WHERE superseded_at IS NULL. Substitueix uk_user_consent (V68), que era UNIQUE (..., given_at) i no podia impedir cap duplicat: given_at es l'instant exacte, i dues files nomes hi xocaven si es desaven al mateix microsegon. Tenia nom de garantia i no en donava cap.
  • ConsentIdempotencyIT — exerceix el reintent, el tot-o-res, la sequencia legitima «acceptar → retirar → tornar a acceptar» (que NO es un duplicat i s'ha de conservar sencera), i que la base de dades refusa un duplicat escrit sense passar pel servei.

Nota sobre el cos de la peticio. El POST accepta el conjunt ({"consents": [...]}) i, com a pont de desplegament, tambe la forma antiga d'un sol document. El pont existeix perque la web es redesplega sola a cada fusio a main i l'API es desplega a ma: sense ell, l'ordre dels dos desplegaments obriria una finestra en que acceptar els termes respondria 400. Es pot retirar quan cap client enviï la forma antiga.