Saltar al contenido principal

Modelo de Datos

Distribución por base de datos

  • PostgreSQL — 40 tablas con datos estructurados, JOINs frecuentes, ACL, embeddings RAG (pgvector).
  • MongoDB — 6 collections con schemas dinámicos (expedientes, documentos, comentarios, walks de doc-flow Layer 2, tareas, timeline de tareas).
  • MinIO — archivos binarios identificados por SHA-256 (content-addressed).
  • Typesense — replica indexada para búsqueda full-text typo-tolerant.
  • Redis — sesiones, parámetros en caché (TTL 3600s), colas BullMQ.

Tablas PostgreSQL (40)

Identidad y multitenancy

TablaDescripción
tenantsMulti-tenancy: 1 fila por organismo, 1 realm Keycloak asociado
usersPerfiles locales — caché de usuarios validados en Keycloak
service_clientsClientes M2M (machine-to-machine) con credenciales OAuth client-credentials

Permisos (RBAC)

TablaDescripción
modulesCatálogo de módulos del sistema (dossier, flow, share, etc.)
permissions132 permisos granulares organizados por módulo
rolesRoles por tenant (tenant_admin, manager, etc.)
role_permissionsAssignment role→permission
user_rolesCaché de roles del user (fuente: claim realm_access.roles del JWT)

Cuentas y expedientes (lado relacional)

TablaDescripción
account_typesEsquemas + metadata por tipo de cuenta
accountsCuentas titulares/firmantes/deudores
account_linksVínculos entre cuentas (ej. titular ↔ firmante)
dossier_typesTemplates de expediente con metadata schemas y campos por estado
document_typesTipos de documento con MIME asociados y metadata schemas
dossier_accountsVinculación expediente ↔ cuentas
dossier_auditsAuditoría de cambios sobre expedientes
dossier_documentsVinculación expediente ↔ documentos (con tipo y estado)
document_auditsAuditoría de cambios sobre documentos

Configuración del sistema

TablaDescripción
parameter_definitionsDefinición de parámetros globales y por tenant
parameter_valuesValores efectivos (con caché Redis 3600s)

Integraciones

TablaDescripción
external_systemsSistemas externos (URL base + credencial)
credentialsCredenciales cifradas AES-256-GCM. direction=OUTBOUND (Kuatia llama afuera) o INBOUND (afuera llama a Kuatia, ej. para Shares)
endpointsOperaciones REST/SOAP configurables (métodos, paths, schemas, retries)
endpoint_executionsLog de ejecuciones de endpoints (request/response truncados)
ui_endpointsIntegraciones de UI embebida (iframe/popup/redirect/internal) con SSO

Flujos

TablaDescripción
flow_versionsVersionado de definiciones de flujo por DossierType y por DocumentType (doc-flows Layer 2)
flow_waitsPausas de flujo por webhook/tiempo, con token único — barridas por la cola flow-timeout

Tareas y bulk

TablaDescripción
task_remindersRecordatorios + escalation, cola task-lifecycle
bulk_import_jobsTracking de imports CSV/XLSX, cola bulk-operations
data_export_jobsTracking de exports tenant-wide, cola bulk-operations

MIME y procesamiento

TablaDescripción
mime_handlersExtractores + visores custom por tenant (WEBHOOK / ENDPOINT / REACT_COMPONENT / IFRAME_URL)

Shares (acceso filesystem-like)

TablaDescripción
sharesConfiguración de share con toggles por protocolo (WebDAV/SFTP/FTPS/SMB/S3), scope (TENANT/ACCOUNT/DOSSIER), mapeo MIME→DocumentType

Reportes

TablaDescripción
scheduled_reportsReportes cron-driven con distribución por email, cola scheduled-reports

ACL fino

TablaDescripción
access_rulesReglas finas a nivel Account/Dossier/Document
access_rule_auditsAudit chain de cambios sobre access_rules
acl_denial_logRegistro de denegaciones para análisis y troubleshooting

Asistente AI + RAG

TablaDescripción
ai_conversationsHistorial del Asistente AI por user/tenant
document_chunksChunks vectorizados con columna embedding (pgvector) para búsqueda semántica RAG

Bandeja, indexación y procesadores

TablaDescripción
inbox_saved_viewsVistas guardadas per-user en la bandeja (filtros + nombre + orden)
indexation_tasksCola de re-indexación tiered por MIME para el MimeIndexerService
specialized_processorsCatálogo de procesadores invocables desde el nodo extract_with_processor (con outputSchema Ajv)

Collections MongoDB (6)

CollectionSchemaNotas
dossiersDossierJerárquicos (parentId + path[]), schema variable por dossierTypeId, contiene instanceData del flow
documentsDocument_id = SHA-256 del contenido (deduplicación nativa). Versiones via versionHistory[]
document_commentsDocumentCommentComentarios anclados a documentos
document_flow_walksDocumentWalkEstado del walk del doc-flow Layer 2 (currentNodeId + context + tasks[] + history[])
tasksTaskTareas humanas + sistema, schema variable por taskType, incluye uiEndpointId para tareas con UI embebida
task_activitiesTaskActivityTimeline append-only de la tarea (create/claim/attach/comment/complete/…)

Reglas de distribución

Si...Va a...
El schema varía por tipo o tenantMongoDB
Estructura fija con JOINs frecuentesPostgreSQL
Archivo binarioMinIO
Requiere búsqueda full-textTypesense (réplica)
Requiere búsqueda semánticapgvector (vía RAG)
Estado efímero / cachéRedis

Document — Content-addressed storage

El campo _id de Document en MongoDB es el hash SHA-256 del contenido del archivo, no un UUID generado. Esto permite deduplicación automática:

El métrico kuatia_document_dedup_hits_total mide cuántas subidas evitaron almacenamiento por dedup.

Dossier — Jerarquía

Los dossiers son jerárquicos: cada uno puede tener un parentId apuntando a otro dossier. El campo path[] contiene todos los ancestros para queries eficientes de árbol completo. Contenedores (sub-dossiers) son la base de doc-flows Layer 2.

Cuenta Corriente #123
├── Depósito Enero 2026
│ ├── comprobante.pdf
│ └── recibo.pdf
└── Depósito Febrero 2026
└── comprobante.pdf

Indexación

Toda consulta se diseña para escalar a millones de filas por tenant. Reglas:

  • Todo índice empieza con tenantId.
  • Si además se filtra por otro campo (accountId, state, etc.), el índice es compuesto (tenantId, campo).
  • Sin excepciones: si una query nueva no tiene índice apropiado, no se mergea.

Cifrado de credenciales

credentials.config se cifra con AES-256-GCM usando una key de env (sin fallback). Los GET nunca devuelven el ciphertext ni el plaintext — solo hasSecret: boolean. La key vive en CRYPTO_KEY y el sistema NO arranca si falta.