Saltar a contenido

ADRs — Architecture Decision Records

Los ADRs son el registro permanente de las decisiones arquitectónicas tomadas durante el desarrollo. Cada uno documenta el contexto, la decisión, las alternativas evaluadas y las implicaciones operativas.

Patrón estructural común

Todas las ADRs siguen el mismo esquema:

  1. Contexto — qué problema operativo motiva la decisión.
  2. Decisión — qué se eligió concretamente.
  3. Justificación — argumentos a favor (típicamente 3-5 razones).
  4. Alternativas evaluadas y descartadas — qué se consideró y por qué no se eligió.
  5. Implicaciones operativas — qué cambia para el equipo, el código y la infra.
  6. Referencias — enlaces a estándares, otros ADRs relacionados, documentación oficial.

ADRs publicados

ID Título Decisión clave Fecha
ADR-001 Estructura polyrepo Tres repos de código independientes (app, api, infra) bajo organización GitHub custodiam 25-ene-2026
ADR-003 Alembic para migraciones de BD Alembic con autogeneración a partir de modelos SQLModel; data migrations versionadas en repo 27-ene-2026
ADR-004 Cliente HTTP del cliente Flutter Paquete oficial http + wrapper ApiClient con interceptors propios; sin dio ni code generation 28-ene-2026
ADR-005 sqflite como BD local de la app SQLite nativo vía plugin oficial para Android/iOS; cola offline + caché de listas grandes 28-ene-2026
ADR-006 Nginx Alpine como servidor de la PWA nginx:alpine ligero (~25 MB) con cabeceras de cache diferenciadas para bootstrap files y assets hasheados 29-ene-2026
ADR-007 GitHub Container Registry para imágenes Docker GHCR para custodiam-api y custodiam-web; integración nativa con Actions, sin rate limits, gratuito en repos públicos 30-ene-2026
ADR-002 SQLModel como ORM unificado Una sola clase es tabla SQL + schema Pydantic; elimina duplicación entre app/models/ y app/schemas/ 05-feb-2026
ADR-008 psycopg3 como driver PostgreSQL psycopg[binary] ≥3.1 con prefijo postgresql+psycopg://; sucesor moderno de psycopg2 con asincronía nativa 10-feb-2026
ADR-009 Dos bases de datos PostgreSQL separadas custodiam (negocio, Alembic) y custodiam_kc (Keycloak); evita que --autogenerate toque las ~70 tablas de Keycloak 11-feb-2026
ADR-010 OAuth 2.0 + PKCE + Keycloak + PyJWT Authorization Code + PKCE para clientes públicos; validación JWT local con azp check (RFC 9068) 12-feb-2026
ADR-011 Estrategia de deep links Custom scheme es.custodiam://callback para OAuth + App Links / Universal Links HTTPS para emails y notificaciones 18-feb-2026
ADR-012 Riverpod como state management flutter_riverpod ≥2.6 para DI + estado reactivo; reglas duras de uso (Provider/StateProvider/Notifier/AsyncNotifier) 20-feb-2026
ADR-013 RBAC en lockstep front/back Matriz rol→permisos replicada en código (Python + Dart); JWT solo transporta roles 24-feb-2026
ADR-014 Result<T> sealed + jerarquía Failure Repositorios devuelven Result<T>, nunca lanzan cross-layer; pattern matching exhaustivo en consumidor 25-feb-2026
ADR-015 Configuración por entorno con String.fromEnvironment Clase EnvConfig + --dart-define en build; sin JSON files ni hardcoded URLs 26-feb-2026
ADR-016 Logging estructurado con dev.log dart:developer con name: por subsistema ('API', 'Auth', ...); cero dependencias externas 27-feb-2026
ADR-017 SplashPage Flutter + AppStartupUseCase Primera ruta con branding consistente; use case testeable decide destino tras restaurar sesión 28-feb-2026
ADR-018 Design System propio con prefijo App* Componentes en lib/core/ui/ que envuelven Material 3; tokens + ThemeData + ThemeExtension separados por responsabilidad 02-mar-2026
ADR-025 Modelo de datos extensible Patrón "catálogo + instancias + JSONB + enum discriminador" para entidades con tipos predefinidos ampliables 10-mar-2026
ADR-019 Gestión de secretos con sops + age docker/.env.sops cifrado con sops + age multidestinatario; clave personal por miembro, archivo versionado en repo 08-abr-2026
ADR-020 Tres modos de despliegue Stack en exactamente uno de dev / tunnel / prod; tres scripts simétricos con guard de cross-mode 05-may-2026
ADR-021 SMTP transaccional con Resend Resend (AWS SES eu-west-1) para emails transaccionales del realm Keycloak; tracking opt-in OFF preserva los App Links 12-may-2026
ADR-022 Versión mínima de iOS soportada iOS 15.0 como mínimo (Podfile + project.pbxproj); forzado por Firebase iOS SDK 12.x 15-may-2026
ADR-023 OAuth + PKCE en SPA web vs móvil Dos implementaciones de AuthService por kIsWeb + persistencia del code_verifier en sessionStorage 20-may-2026
ADR-024 Patrol como framework E2E unificado Patrol 4.6+ sustituye integration_test; pirámide en tres capas (unit / integración / E2E) 22-may-2026
ADR-026 uv como gestor de paquetes Python pyproject.toml PEP 621 + uv.lock + Python 3.13 gestionado por uv; ~10× más rápido que pip 24-may-2026
ADR-027 Material for MkDocs + GitHub Pages Book público en repo separado; hosting GitHub Pages directo + dominio docs.custodiam.es vía Cloudflare DNS modo DNS only 26-may-2026
ADR-028 Catálogo central de ValueKeys para tests Clase K en lib/app/test_keys.dart como fuente única del string de cada key; importable desde producción, tests de widget y E2E 28-may-2026
ADR-031 Modelo de asignación de material a vehículo CheckConstraint ternario ("exactamente uno de tres destinos") + FK vehiculo_id + enum DOTACION_VEHICULO para la dotación fija; material temporal inferido por servicio 28-may-2026

Sobre la numeración

La numeración de los ADRs sigue el orden cronológico en que se tomaron las decisiones. Algunos números pueden corresponder a decisiones cuyo diseño está cerrado pero cuya implementación llega en fases posteriores; cada uno se publica cuando se materializa. Las decisiones futuras se añaden siguiendo el mismo patrón estructural.

Para contribuidores

Si quieres proponer una decisión arquitectónica que afecte al proyecto, abre primero un issue en el repo relevante con la propuesta y el análisis de alternativas. Tras discusión, redacta el ADR siguiendo el patrón común y abre PR. El proceso de aceptación está descrito en Contribuir.