ImagLend — Modelo de Legal Consent
Proposito
El modelo de Legal Consent gestiona la aceptacion de documentos legales por parte de los solicitantes durante el pipeline de originacion. Garantiza evidencia completa e inmutable de cada aceptacion, cumpliendo con requisitos regulatorios de proteccion de datos y transparencia contractual.
Principios
- Inmutabilidad: Una vez registrada, la aceptacion no puede modificarse ni eliminarse
- Versionamiento: Los documentos legales tienen versiones inmutables. Un cambio genera nueva version
- Evidencia completa: Cada aceptacion registra IP, fingerprint, timestamp, hash del documento y user-agent
- Granularidad: Cada documento se acepta individualmente (no un checkbox global)
- Auditabilidad: Se puede reconstruir exactamente que acepto el usuario, cuando y desde donde
Modelo de Datos
Diagrama ER
Tabla: legal_documents
Catalogo de documentos legales versionados por tenant.
| Columna | Tipo | Descripcion |
|---|---|---|
id | UUID PK | Identificador unico |
tenant_id | UUID | Tenant propietario (RLS) |
code | VARCHAR(50) | Codigo unico del documento (ej: privacy_policy, terms_conditions) |
version | VARCHAR(20) | Version semantica (ej: 2.0, 3.1) |
title | VARCHAR(200) | Titulo legible del documento |
content_url | TEXT | URL al PDF del documento (S3 presigned o CDN) |
content_hash | VARCHAR(64) | SHA-256 del contenido del documento |
status | VARCHAR(20) | draft, published, archived |
published_at | TIMESTAMPTZ | Fecha de publicacion |
created_at | TIMESTAMPTZ | Fecha de creacion |
Constraints:
- UNIQUE(
tenant_id,code,version) - Solo una version
publishedporcodepor tenant
Ciclo de vida:
Tabla: legal_consents
Registro inmutable de cada aceptacion individual.
| Columna | Tipo | Descripcion |
|---|---|---|
id | UUID PK | Identificador unico |
tenant_id | UUID | Tenant (RLS) |
application_id | UUID FK | Solicitud de credito asociada |
user_id | UUID FK | Usuario que acepto |
document_id | UUID FK | Documento aceptado |
document_code | VARCHAR(50) | Codigo del documento (desnormalizado para consulta rapida) |
document_version | VARCHAR(20) | Version aceptada (desnormalizado) |
document_hash | VARCHAR(64) | Hash del documento al momento de aceptacion |
ip_address | VARCHAR(45) | IP del usuario (IPv4 o IPv6) |
device_fingerprint | VARCHAR(255) | Fingerprint del dispositivo |
user_agent | TEXT | User-Agent del navegador |
geo_location | JSONB | Geolocalizacion aproximada por IP |
accepted_at | TIMESTAMPTZ | Timestamp exacto de aceptacion |
Inmutabilidad:
-- No se permite UPDATE ni DELETE
REVOKE UPDATE, DELETE ON legal_consents FROM imagy_lending_app;
CREATE TRIGGER trg_prevent_consent_modification
BEFORE UPDATE OR DELETE ON legal_consents
FOR EACH ROW EXECUTE FUNCTION prevent_modification();Flujo de Aceptacion
Evidencia Capturada
Cada aceptacion registra:
| Campo | Fuente | Ejemplo |
|---|---|---|
ip_address | Header X-Forwarded-For o conexion directa | 190.25.100.50 |
device_fingerprint | FingerprintJS en frontend | fp-a1b2c3d4e5f6 |
user_agent | Header User-Agent | Mozilla/5.0 (iPhone; CPU iPhone OS 17_0) |
geo_location | Resolucion por IP (MaxMind) | {"country": "EC", "city": "Quito"} |
document_hash | SHA-256 del PDF al momento de aceptar | sha256:abc123def456... |
accepted_at | Timestamp del servidor (no del cliente) | 2026-05-18T10:30:00.123Z |
Versionamiento de Documentos
Cuando un documento legal cambia:
- Se crea nueva version (
privacy_policyv2.0 → v2.1) - Se calcula el hash del nuevo contenido
- Se publica la nueva version (status →
published) - La version anterior se archiva automaticamente (status →
archived) - Las aceptaciones existentes siguen validas — referencian la version que aceptaron
- Nuevas solicitudes usan la version publicada actual
Verificacion de Integridad
Al registrar una aceptacion, el backend verifica que el hash del documento no haya cambiado:
// Verificar integridad antes de registrar consent
var document = await _repo.GetById(request.DocumentId);
var currentHash = await _storage.ComputeHash(document.ContentUrl);
if (currentHash != document.ContentHash)
throw new IntegrityException("Document content has been modified");Esto previene que un documento sea modificado despues de publicado sin crear nueva version.
Consulta de Consentimientos
Para el usuario (Client Portal)
GET /my/consents
Authorization: Bearer {jwt}Retorna todos los documentos que el usuario ha aceptado con fechas.
Para el operador (Panel Admin)
GET /api/v1/applications/{id}/consents
Authorization: Bearer {jwt}Retorna los consentimientos de una solicitud especifica con evidencia completa.
Para auditoria/compliance
GET /api/v1/consents?document_code=privacy_policy&from=2026-01-01&to=2026-05-31
Authorization: Bearer {jwt}Retorna todos los consentimientos de un documento en un periodo (para reportes regulatorios).
Reglas de Negocio
| ID | Regla | Descripcion |
|---|---|---|
| RN-001 | Todos los required | El usuario debe aceptar TODOS los documentos marcados como required |
| RN-002 | Aceptacion individual | Cada documento se acepta por separado (no checkbox global) |
| RN-003 | Inmutabilidad | Los consents no se pueden modificar ni eliminar |
| RN-004 | Hash match | El hash del documento debe coincidir al momento de aceptar |
| RN-005 | Una version activa | Solo una version published por codigo de documento por tenant |
| RN-006 | Evidencia obligatoria | IP y timestamp son obligatorios; fingerprint es best-effort |
| RN-007 | Validez por version | Un consent es valido para la version que se acepto, no para versiones futuras |
Indices
CREATE UNIQUE INDEX idx_legal_docs_tenant_code_version
ON legal_documents(tenant_id, code, version);
CREATE INDEX idx_legal_docs_tenant_published
ON legal_documents(tenant_id, code, status)
WHERE status = 'published';
CREATE INDEX idx_consents_application
ON legal_consents(tenant_id, application_id);
CREATE INDEX idx_consents_user
ON legal_consents(tenant_id, user_id, accepted_at DESC);
CREATE INDEX idx_consents_document
ON legal_consents(tenant_id, document_code, accepted_at DESC);Documentos Relacionados
- Originacion Pipeline — Paso
legal_consenten el pipeline - Guia: Configurar Pipeline — Como configurar documentos legales
- ADR-006: Pipeline Configurable