Skip to content

ImagID — Modelo de Datos

Base de Datos

  • Nombre: imagy_subject
  • Usuario: imagy_subject_app (NOBYPASSRLS)
  • RLS: Habilitado en todas las tablas excepto subject_profiles

Diagrama ER

Tablas

subject_profiles (SIN RLS - Global)

Perfil unico y global de un sujeto. Una persona con un numero de documento tiene exactamente un registro aqui, sin importar cuantos tenants interactuen con ella.

ColumnaTipoDescripcion
idUUID PKIdentificador unico del sujeto
identifier_typeVARCHAR(50)Tipo de documento: cedula, pasaporte, nit, rut
identifier_valueVARCHAR(100)Numero de documento (unico por tipo)
full_nameVARCHAR(500)Nombre completo consolidado
emailVARCHAR(255)Email mas reciente conocido (nullable)
phoneVARCHAR(50)Telefono mas reciente conocido (nullable)
identity_dataJSONBDatos adicionales de identidad (fecha nacimiento, genero, etc.)
first_seen_atTIMESTAMPTZPrimera vez que aparecio en la plataforma
last_seen_atTIMESTAMPTZUltima interaccion en cualquier tenant
row_versionINTConcurrencia optimista
created_atTIMESTAMPTZFecha de creacion
updated_atTIMESTAMPTZUltima modificacion

Constraint unico: UNIQUE(identifier_type, identifier_value)

Importante: Esta tabla NO tiene tenant_id y NO tiene RLS. Es el unico punto global del sistema. Los datos aqui son minimos y no sensibles desde perspectiva de negocio.

subject_tenant_views (RLS por tenant_id)

Vista materializada de un sujeto dentro de un tenant especifico. Contiene metricas agregadas y el trust score calculado para ese tenant.

ColumnaTipoDescripcion
idUUID PKIdentificador unico
tenant_idUUIDTenant propietario (RLS)
subject_idUUID FKReferencia al perfil global
statusVARCHAR(30)active, inactive, flagged, blacklisted
trust_scoreDECIMAL(5,2)Puntaje de confianza 0.00 a 100.00
total_interactionsINTTotal de interacciones en este tenant
total_approvalsINTFlujos aprobados
total_rejectionsINTFlujos rechazados
total_defaultsINTCreditos en default
metrics_summaryJSONBMetricas adicionales agregadas
first_interaction_atTIMESTAMPTZPrimera interaccion en este tenant
last_interaction_atTIMESTAMPTZUltima interaccion en este tenant
row_versionINTConcurrencia optimista
created_atTIMESTAMPTZFecha de creacion
updated_atTIMESTAMPTZUltima modificacion

Constraint unico: UNIQUE(tenant_id, subject_id)

subject_events (RLS por tenant_id)

Timeline completo de eventos del sujeto dentro de un tenant. Cada evento consumido de otros dominios genera un registro aqui.

ColumnaTipoDescripcion
idUUID PKIdentificador unico
tenant_idUUIDTenant (RLS)
subject_idUUID FKReferencia al perfil global
event_typeVARCHAR(100)Tipo de evento original (ej: flow.execution.completed)
event_sourceVARCHAR(100)Dominio origen (ej: imagy-flow-engine)
source_event_idUUIDID del evento original (idempotencia)
event_dataJSONBPayload relevante del evento
device_infoJSONBInfo de dispositivo si aplica (nullable)
event_timestampTIMESTAMPTZTimestamp original del evento
created_atTIMESTAMPTZCuando se registro en ImagID

Constraint unico: UNIQUE(source_event_id) — garantiza idempotencia.

subject_devices (RLS por tenant_id)

Dispositivos desde los cuales un sujeto ha interactuado dentro de un tenant. Incluye dispositivos certificados (con keypair registrada para firma y autenticacion).

ColumnaTipoDescripcion
idUUID PKIdentificador unico
tenant_idUUIDTenant (RLS)
subject_idUUID FKReferencia al perfil global
device_fingerprintVARCHAR(255)Fingerprint del dispositivo
ip_addressINETDireccion IP
user_agentTEXTUser agent del navegador
geo_countryVARCHAR(100)Pais de geolocalizacion
geo_cityVARCHAR(200)Ciudad de geolocalizacion
geo_latitudeDECIMAL(10,7)Latitud
geo_longitudeDECIMAL(10,7)Longitud
access_countINTNumero de accesos desde este dispositivo
is_certifiedBOOLEANSi el dispositivo fue validado biometricamente
public_keyTEXTClave publica del dispositivo (nullable, solo si certified)
key_algorithmVARCHAR(50)Algoritmo de la clave (RSA-2048, EC-P256)
certified_atTIMESTAMPTZCuando se certifico (nullable)
certification_flow_idUUIDFlujo de ImagFlow que valido el dispositivo (nullable)
key_expires_atTIMESTAMPTZExpiracion de la clave (nullable, renovacion periodica)
is_revokedBOOLEANSi la clave fue revocada
revoked_atTIMESTAMPTZCuando se revoco (nullable)
first_seen_atTIMESTAMPTZPrimera vez visto
last_seen_atTIMESTAMPTZUltima vez visto
created_atTIMESTAMPTZFecha de creacion

Constraint unico: UNIQUE(tenant_id, subject_id, device_fingerprint)

Dispositivos certificados:

  • Un dispositivo certificado tiene is_certified = true y public_key no null
  • La certificacion requiere validacion biometrica previa via ImagFlow
  • La clave publica se usa para verificar firmas (ImagSign) y autenticacion (ImagAuth)
  • Las claves pueden expirar y requieren renovacion con nueva validacion
  • Un dispositivo revocado no puede usarse para firma ni autenticacion

subject_list_entries (RLS por tenant_id)

Entradas en listas de control (blacklist, whitelist, watchlist) por tenant.

ColumnaTipoDescripcion
idUUID PKIdentificador unico
tenant_idUUIDTenant (RLS)
subject_idUUID FKReferencia al perfil global
list_typeVARCHAR(30)blacklist, whitelist, watchlist
reasonTEXTRazon de inclusion
added_byUUIDActor que agrego (usuario o sistema)
added_by_typeVARCHAR(20)user, system, rule
metadataJSONBDatos adicionales (regla que lo agrego, evento trigger)
added_atTIMESTAMPTZCuando se agrego
expires_atTIMESTAMPTZExpiracion automatica (nullable = permanente)
removed_atTIMESTAMPTZCuando se removio (nullable = activo)
removed_byUUIDQuien lo removio (nullable)

Nota: Un sujeto puede estar en multiples listas simultaneamente. La entrada activa es aquella donde removed_at IS NULL y (expires_at IS NULL o expires_at > NOW()).

subject_alerts (RLS por tenant_id)

Alertas generadas por deteccion de patrones sospechosos.

ColumnaTipoDescripcion
idUUID PKIdentificador unico
tenant_idUUIDTenant (RLS)
subject_idUUID FKReferencia al perfil global
alert_typeVARCHAR(50)multiple_rejections, new_device_high_risk, velocity_anomaly, geo_anomaly, default_pattern
severityVARCHAR(20)low, medium, high, critical
statusVARCHAR(20)open, acknowledged, resolved, dismissed
titleVARCHAR(255)Titulo descriptivo de la alerta
descriptionTEXTDescripcion detallada
alert_dataJSONBDatos que dispararon la alerta
resolved_byUUIDQuien resolvio (nullable)
resolution_notesTEXTNotas de resolucion (nullable)
triggered_atTIMESTAMPTZCuando se detecto el patron
resolved_atTIMESTAMPTZCuando se resolvio (nullable)
created_atTIMESTAMPTZFecha de creacion

Tablas de Soporte

processed_events

sql
CREATE TABLE processed_events (
    event_id UUID PRIMARY KEY,
    event_type VARCHAR(100) NOT NULL,
    processed_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    source VARCHAR(100) NOT NULL
);

RLS Policies

sql
-- subject_profiles: SIN RLS (tabla global)
-- Razon: un sujeto es unico en toda la plataforma.
-- El acceso se controla a nivel de aplicacion, no de base de datos.

-- Todas las demas tablas: RLS habilitado
ALTER TABLE subject_tenant_views ENABLE ROW LEVEL SECURITY;
ALTER TABLE subject_events ENABLE ROW LEVEL SECURITY;
ALTER TABLE subject_devices ENABLE ROW LEVEL SECURITY;
ALTER TABLE subject_list_entries ENABLE ROW LEVEL SECURITY;
ALTER TABLE subject_alerts ENABLE ROW LEVEL SECURITY;

-- Politica estandar de aislamiento por tenant
CREATE POLICY tenant_isolation ON subject_tenant_views
    FOR ALL USING (tenant_id = get_current_tenant_id());

CREATE POLICY tenant_isolation ON subject_events
    FOR ALL USING (tenant_id = get_current_tenant_id());

CREATE POLICY tenant_isolation ON subject_devices
    FOR ALL USING (tenant_id = get_current_tenant_id());

CREATE POLICY tenant_isolation ON subject_list_entries
    FOR ALL USING (tenant_id = get_current_tenant_id());

CREATE POLICY tenant_isolation ON subject_alerts
    FOR ALL USING (tenant_id = get_current_tenant_id());

-- Acceso global para el servicio interno (event ingestion)
-- El servicio usa un rol especial para escribir en subject_profiles
CREATE POLICY global_write ON subject_profiles
    FOR ALL USING (true);

-- Politica para consultas cross-tenant (solo servicio interno)
CREATE POLICY service_cross_tenant ON subject_tenant_views
    FOR SELECT USING (
        current_setting('app.service_role', true) = 'imagy_subject_service'
    );

Indices

sql
-- Busqueda de perfil por documento (consulta mas frecuente)
CREATE UNIQUE INDEX idx_subject_profiles_identifier
    ON subject_profiles(identifier_type, identifier_value);

-- Busqueda de vista por tenant y sujeto
CREATE UNIQUE INDEX idx_tenant_views_tenant_subject
    ON subject_tenant_views(tenant_id, subject_id);

-- Busqueda de vistas por estado (para dashboards)
CREATE INDEX idx_tenant_views_status
    ON subject_tenant_views(tenant_id, status);

-- Timeline de eventos (paginacion por fecha)
CREATE INDEX idx_subject_events_timeline
    ON subject_events(tenant_id, subject_id, event_timestamp DESC);

-- Idempotencia de eventos
CREATE UNIQUE INDEX idx_subject_events_source_id
    ON subject_events(source_event_id);

-- Busqueda de dispositivos por fingerprint
CREATE UNIQUE INDEX idx_subject_devices_fingerprint
    ON subject_devices(tenant_id, subject_id, device_fingerprint);

-- Dispositivos por IP (deteccion de patrones)
CREATE INDEX idx_subject_devices_ip
    ON subject_devices(tenant_id, ip_address);

-- Listas activas (consulta critica para ImagLend e ImagFlow)
CREATE INDEX idx_list_entries_active
    ON subject_list_entries(tenant_id, subject_id, list_type)
    WHERE removed_at IS NULL;

-- Listas por tipo (para gestion administrativa)
CREATE INDEX idx_list_entries_type
    ON subject_list_entries(tenant_id, list_type)
    WHERE removed_at IS NULL;

-- Alertas abiertas (dashboard de operadores)
CREATE INDEX idx_alerts_open
    ON subject_alerts(tenant_id, status, severity)
    WHERE status IN ('open', 'acknowledged');

-- Alertas por sujeto
CREATE INDEX idx_alerts_subject
    ON subject_alerts(tenant_id, subject_id, triggered_at DESC);

-- Limpieza de eventos procesados
CREATE INDEX idx_processed_events_date
    ON processed_events(processed_at);

Estrategia de Trust Score

El trust score es un valor entre 0.00 y 100.00 que representa la confianza en un sujeto dentro de un tenant especifico. Se recalcula de forma incremental con cada evento relevante.

Formula Base

trust_score = base_score + sum(factor_weights * factor_values)

Factores de Calculo

FactorPesoEfectoEvento trigger
Flujo aprobado+5.0Positivoflow.execution.completed con result=approved
Flujo rechazado-10.0Negativoflow.execution.failed
Credito desembolsado+3.0Positivolending.credit.disbursed
Pago recibido+2.0Positivolending.payment.received
Credito en default-25.0Negativo fuertelending.credit.defaulted
Dispositivo nuevo-2.0Leve negativoPrimer acceso desde dispositivo desconocido
Multiples rechazos consecutivos-15.0Negativo3+ rechazos sin aprobacion intermedia
Antiguedad (meses activo)+1.0/mesPositivo gradualCalculado periodicamente

Reglas de Calculo

  • Score inicial: 50.00 (neutro)
  • Minimo: 0.00 (no puede ser negativo)
  • Maximo: 100.00
  • Se almacena en subject_tenant_views.trust_score
  • Se cachea en Valkey con TTL de 5 minutos para consultas frecuentes
  • Key en Valkey: tenant:{tenant_id}:subject:{subject_id}:trust_score

Umbrales de Accion

RangoClasificacionAccion automatica
80 - 100Alta confianzaWhitelist automatica sugerida
50 - 79NormalSin accion
25 - 49BajoWatchlist automatica, alerta generada
0 - 24CriticoBlacklist automatica, alerta critica

Cache en Valkey

Datos frecuentemente consultados se cachean en Valkey:

json
{
  "key": "tenant:{tenant_id}:subject:{subject_id}:trust_score",
  "ttl": 300,
  "value": {
    "score": 72.50,
    "status": "active",
    "last_calculated_at": "2026-05-18T10:30:00Z"
  }
}
json
{
  "key": "tenant:{tenant_id}:subject:{subject_id}:lists",
  "ttl": 60,
  "value": {
    "blacklisted": false,
    "whitelisted": false,
    "watchlisted": true,
    "checked_at": "2026-05-18T10:30:00Z"
  }
}

Reimagine Tech LLC — Documentacion Interna