Skip to content

ImagSign — Modelo de Datos

Base de Datos

  • Nombre: imagy_sign
  • Usuario: imagy_sign_app (NOBYPASSRLS)
  • RLS: Habilitado en todas las tablas con tenant_id

Diagrama ER

Tablas

signature_requests

Solicitud de firma sobre uno o mas documentos. Representa la unidad principal de trabajo.

ColumnaTipoDescripcion
idUUID PKIdentificador unico
tenant_idUUIDTenant propietario (RLS)
organization_idUUIDOrganizacion (nullable)
statusVARCHAR(30)created, pending_signature, signing_in_progress, signed, rejected, expired, revoked
signature_typeVARCHAR(30)digital_certificate, electronic_otp, electronic_biometric, electronic_acceptance
provider_codeVARCHAR(100)Codigo del proveedor a usar
signing_tokenVARCHAR(255) UNIQUEToken para acceso publico del firmante
signing_urlTEXTURL completa para el firmante
signer_nameVARCHAR(255)Nombre del firmante
signer_emailVARCHAR(255)Email del firmante (nullable)
signer_phoneVARCHAR(50)Telefono del firmante (nullable)
signer_identifierVARCHAR(100)Documento de identidad del firmante
callback_urlTEXTURL para notificar resultado (nullable, usado por ImagFlow/ImagLend)
origin_serviceVARCHAR(100)Servicio que origino la solicitud: standalone, imagflow, imaglend
origin_request_idUUIDID de la solicitud en el servicio origen (nullable)
metadataJSONBMetadata adicional (canal, contexto)
row_versionINTConcurrencia optimista
created_atTIMESTAMPTZFecha de creacion
expires_atTIMESTAMPTZFecha de expiracion
completed_atTIMESTAMPTZFecha de completado (nullable)
created_byUUIDActor que creo la solicitud

documents

Documentos asociados a una solicitud de firma. Se almacenan como referencias a S3, no inline.

ColumnaTipoDescripcion
idUUID PKIdentificador unico
signature_request_idUUID FKSolicitud de firma padre
statusVARCHAR(20)uploaded, pending_signature, signed, failed
file_nameVARCHAR(500)Nombre original del archivo
content_typeVARCHAR(100)MIME type (ej: application/pdf)
s3_bucketVARCHAR(255)Bucket de S3
s3_key_originalVARCHAR(1000)Key del documento original en S3
s3_key_signedVARCHAR(1000)Key del documento firmado en S3 (nullable, se llena al firmar)
file_size_bytesBIGINTTamano del archivo en bytes
checksum_sha256VARCHAR(64)Hash SHA-256 del documento original
document_orderINTOrden del documento en la solicitud
created_atTIMESTAMPTZFecha de subida
signed_atTIMESTAMPTZFecha en que se firmo (nullable)

Estrategia de almacenamiento:

  • Los documentos se almacenan en S3 con server-side encryption (SSE-S3).
  • La base de datos solo guarda referencias (bucket + key), nunca el contenido binario.
  • El key sigue el patron: tenants/{tenant_id}/signatures/{request_id}/original/{document_id}.pdf
  • El documento firmado se almacena en: tenants/{tenant_id}/signatures/{request_id}/signed/{document_id}.pdf
  • Se genera una URL pre-firmada (presigned URL) con TTL de 15 minutos para descarga.

signature_providers

Configuracion de proveedores de firma disponibles.

ColumnaTipoDescripcion
idUUID PKIdentificador unico
provider_codeVARCHAR(100) UNIQUECodigo unico del proveedor
provider_nameVARCHAR(255)Nombre legible
signature_typeVARCHAR(30)digital_certificate, electronic_otp, electronic_biometric, electronic_acceptance
countryVARCHAR(5)Codigo ISO del pais (ej: EC, CO)
connection_configJSONBConfiguracion de conexion (encrypted via KMS)
is_activeBOOLEANSi esta activo
row_versionINTConcurrencia optimista
created_atTIMESTAMPTZFecha de creacion

Nota: connection_config contiene API keys, endpoints y secrets del proveedor. Se almacena cifrado con KMS y solo el Signing Engine puede descifrarlo.

signature_certificates

Informacion del certificado digital usado en firmas de tipo digital_certificate.

ColumnaTipoDescripcion
idUUID PKIdentificador unico
signature_request_idUUID FKSolicitud de firma asociada
provider_codeVARCHAR(100)Proveedor que emitio/uso el certificado
certificate_serialVARCHAR(255)Numero serial del certificado
certificate_issuerVARCHAR(500)Autoridad certificadora emisora
certificate_subjectVARCHAR(500)Sujeto del certificado (nombre del firmante)
certificate_valid_fromTIMESTAMPTZInicio de validez del certificado
certificate_valid_toTIMESTAMPTZFin de validez del certificado
signature_algorithmVARCHAR(100)Algoritmo usado (ej: RSA-SHA256)
signed_hashTEXTHash firmado del documento
provider_metadataJSONBMetadata adicional del proveedor
created_atTIMESTAMPTZFecha de registro

signature_audit

Registro inmutable de todas las acciones sobre una solicitud de firma.

ColumnaTipoDescripcion
idUUID PKIdentificador unico
signature_request_idUUID FKSolicitud de firma asociada
actionVARCHAR(50)request_created, document_uploaded, signing_started, otp_sent, otp_verified, signature_executed, signature_completed, signature_rejected, request_expired, request_revoked
actor_typeVARCHAR(20)operator, signer, system, provider
actor_idVARCHAR(255)Identificador del actor
ip_addressVARCHAR(45)IP del actor (nullable)
user_agentVARCHAR(500)User-Agent del navegador (nullable)
detailsJSONBDetalles adicionales de la accion
created_atTIMESTAMPTZTimestamp de la accion

Tablas de Soporte

idempotency_keys

sql
CREATE TABLE idempotency_keys (
    key VARCHAR(255) NOT NULL,
    tenant_id UUID NOT NULL,
    response_status INT NOT NULL,
    response_body JSONB NOT NULL,
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    expires_at TIMESTAMPTZ NOT NULL DEFAULT NOW() + INTERVAL '24 hours',
    PRIMARY KEY (key, tenant_id)
);

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
-- Todas las tablas principales tienen RLS por tenant_id
ALTER TABLE signature_requests ENABLE ROW LEVEL SECURITY;
ALTER TABLE documents ENABLE ROW LEVEL SECURITY;
ALTER TABLE signature_certificates ENABLE ROW LEVEL SECURITY;
ALTER TABLE signature_audit ENABLE ROW LEVEL SECURITY;

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

CREATE POLICY tenant_isolation ON documents
    FOR ALL USING (
        signature_request_id IN (
            SELECT id FROM signature_requests
            WHERE tenant_id = get_current_tenant_id()
        )
    );

CREATE POLICY tenant_isolation ON signature_certificates
    FOR ALL USING (
        signature_request_id IN (
            SELECT id FROM signature_requests
            WHERE tenant_id = get_current_tenant_id()
        )
    );

CREATE POLICY tenant_isolation ON signature_audit
    FOR ALL USING (
        signature_request_id IN (
            SELECT id FROM signature_requests
            WHERE tenant_id = get_current_tenant_id()
        )
    );

-- Tabla global (sin RLS): signature_providers
-- Razon: configurada por platform admin, no pertenece a un tenant

-- Control plane (platform admin sin tenant context)
CREATE POLICY control_plane ON signature_requests
    FOR ALL USING (
        current_setting('app.current_tenant_id', true) IS NULL
        OR current_setting('app.current_tenant_id', true) = ''
    );

Indices

sql
-- Busqueda de solicitudes
CREATE INDEX idx_signature_requests_tenant_status ON signature_requests(tenant_id, status);
CREATE INDEX idx_signature_requests_signing_token ON signature_requests(signing_token);
CREATE INDEX idx_signature_requests_origin ON signature_requests(origin_service, origin_request_id);
CREATE INDEX idx_signature_requests_expires ON signature_requests(expires_at)
    WHERE status IN ('created', 'pending_signature', 'signing_in_progress');
CREATE INDEX idx_signature_requests_signer ON signature_requests(tenant_id, signer_identifier);

-- Busqueda de documentos
CREATE INDEX idx_documents_request ON documents(signature_request_id);
CREATE INDEX idx_documents_status ON documents(status);

-- Busqueda de certificados
CREATE INDEX idx_certificates_request ON signature_certificates(signature_request_id);

-- Auditoria
CREATE INDEX idx_audit_request ON signature_audit(signature_request_id);
CREATE INDEX idx_audit_created ON signature_audit(created_at);

-- Proveedores
CREATE UNIQUE INDEX idx_providers_code ON signature_providers(provider_code);

-- Limpieza
CREATE INDEX idx_idempotency_expires ON idempotency_keys(expires_at);
CREATE INDEX idx_processed_events_date ON processed_events(processed_at);

Estrategia de Almacenamiento de Documentos (S3)

Estructura de Keys

tenants/
  {tenant_id}/
    signatures/
      {request_id}/
        original/
          {document_id}.pdf
        signed/
          {document_id}.pdf

Politicas de S3

PoliticaValor
EncryptionSSE-S3 (AES-256)
VersionamientoHabilitado
LifecycleMover a Glacier despues de 365 dias
AccessSolo via presigned URLs (15 min TTL)
CORSRestringido a dominios de la plataforma
Bucket policyDeny public access

Flujo de Upload

  1. El cliente solicita una URL de upload (presigned PUT)
  2. ImagSign genera la URL con TTL de 10 minutos
  3. El cliente sube el archivo directamente a S3
  4. ImagSign recibe notificacion via S3 Event o el cliente confirma
  5. ImagSign registra el documento en la tabla documents con el checksum

Flujo de Download

  1. El cliente solicita descarga del documento (original o firmado)
  2. ImagSign valida permisos (RLS + rol)
  3. ImagSign genera presigned GET URL con TTL de 15 minutos
  4. El cliente descarga directamente de S3

Reimagine Tech LLC — Documentacion Interna