ADR-007: Storage como Adapter en Provider Gateway
Estado: Aceptada
Fecha: 2026-05-18
Autor: Equipo de Arquitectura
Contexto
Multiples servicios de la plataforma necesitan almacenamiento de archivos:
- ImagFlow: imagenes biometricas capturadas durante validacion de identidad
- ImagSign: documentos PDF generados y firmados
- ImagLend: comprobantes de desembolso, recibos, documentos del solicitante
- ImagGuard: logs de auditoria exportados, reportes de compliance
Las opciones evaluadas son:
- Un servicio centralizado de storage (
imagy-storage) - Cada servicio gestiona su propio bucket S3 directamente
- Storage como un adapter dentro del patron Provider Gateway existente
Adicionalmente, algunos tenants tienen requisitos regulatorios que exigen que los datos residan en proveedores especificos (ej: un banco en Mexico podria requerir almacenamiento en una region especifica de AWS, mientras que un tenant europeo podria necesitar Azure por compliance con su infraestructura existente).
Decision
El almacenamiento de archivos se implementa como un adapter dentro del Provider Gateway. El Provider Gateway ya es el punto de integracion con servicios externos; storage es un proveedor mas.
Proveedores Soportados
| Proveedor | Uso |
|---|---|
| AWS S3 | Default para produccion |
| Azure Blob Storage | Tenants con requisitos Azure |
| Google Cloud Storage | Tenants con requisitos GCP |
| MinIO | Desarrollo local y testing |
Interfaz del Adapter
typescript
interface StorageAdapter {
upload(params: UploadParams): Promise<StorageResult>;
download(key: string): Promise<ReadableStream>;
getSignedUrl(key: string, expiresIn: number): Promise<string>;
delete(key: string): Promise<void>;
list(prefix: string): Promise<StorageObject[]>;
}
interface UploadParams {
key: string;
body: Buffer | ReadableStream;
contentType: string;
metadata?: Record<string, string>;
encryption?: EncryptionConfig;
}
interface StorageResult {
key: string;
bucket: string;
url: string;
size: number;
checksum: string;
}Configuracion por Tenant
json
{
"tenant_id": "banco-xyz",
"storage": {
"provider": "s3",
"config": {
"bucket": "banco-xyz-documents",
"region": "us-east-1",
"encryption": "aws:kms",
"kms_key_id": "arn:aws:kms:us-east-1:123456:key/abc-123"
},
"lifecycle": {
"documents": { "retention_days": 3650 },
"biometrics": { "retention_days": 90 },
"temp": { "retention_days": 1 }
}
}
}Flujo de Invocacion
Organizacion de Keys
{tenant_id}/{domain}/{entity_id}/{filename}
Ejemplos:
banco-xyz/lending/credit-123/comprobante-desembolso.pdf
banco-xyz/sign/contract-456/contrato-firmado.pdf
banco-xyz/flow/validation-789/selfie.jpgAlternativas Consideradas
| Alternativa | Pros | Contras |
|---|---|---|
Servicio dedicado imagy-storage | Separacion clara, equipo dedicado | Otro servicio que mantener, latencia adicional, single point of failure |
| Cada servicio habla con S3 directamente | Simple, sin dependencias | Duplicacion de logica, no soporta multi-provider, cada servicio gestiona credenciales |
| Storage como adapter en Provider Gateway (elegida) | Interfaz consistente, multi-provider, configuracion por tenant | Provider Gateway se vuelve dependencia para operaciones de archivos |
Consecuencias
Positivas
- Interfaz unica para todos los servicios: no importa si el tenant usa S3, Azure o GCS
- Configuracion por tenant permite cumplir requisitos regulatorios de residencia de datos
- No se agrega un servicio adicional a la infraestructura
- Encryption y lifecycle policies centralizados y consistentes
- MinIO para desarrollo local elimina dependencia de cloud en dev
Negativas
- Provider Gateway se convierte en dependencia critica para operaciones de archivos
- Si Provider Gateway tiene un outage, ningun servicio puede leer/escribir archivos
- Mayor complejidad en Provider Gateway (mas adapters que mantener)
Riesgos
- Cuello de botella de performance si muchos servicios suben archivos grandes simultaneamente (mitigacion: signed URLs para uploads directos)
- Vendor lock-in en la interfaz del adapter si no se abstrae correctamente
- Provider Gateway como single point of failure (mitigacion: alta disponibilidad, circuit breaker)