Saltar a contenido

Stack técnico

Inventario completo de tecnologías del stack de Custodiam por capa, con versiones mínimas y referencias cruzadas a las ADRs que justifican cada elección.

Frontend (custodiam-app)

Componente Versión Decisión
Flutter SDK 3.x Estándar multiplataforma del proyecto
Dart 3.6+ Sealed classes para Result<T>
flutter_riverpod ^2.6 State management — ADR-012
go_router ^17.1 Navegación con StatefulShellRoute.indexedStack
http ^1.2 Cliente HTTP — ADR-004
oauth2 ^2.0.3 OAuth2 + PKCEADR-010
flutter_secure_storage ^10.0 Almacenamiento de refresh tokens
firebase_messaging ^16.x Push notifications principales
sqflite ^2.4 BD local + caché offline — ADR-005

Arquitectura interna Clean estricta + Feature-first (ADR-013 y ADR-014) con tres capas (domain / data / presentation) más infrastructure cross-cutting. Design System propio con prefijo App* (ADR-018) y configuración por entorno vía String.fromEnvironment (ADR-015). Versión mínima de iOS soportada: 15.0 (ADR-022).

Backend (custodiam-api)

Componente Versión Decisión
Python 3.13 Gestión vía uv
uv 0.9+ Package manager — ADR-026
fastapi ^0.115 Web framework
uvicorn[standard] ^0.34 ASGI server
sqlmodel ^0.0.22 ORM unificado — ADR-002
sqlalchemy ^2.0 Engine subyacente de SQLModel
psycopg[binary] ^3.1 Driver PostgreSQL — ADR-008
alembic ^1.14 Migraciones de schema — ADR-003
PyJWT[crypto] ^2.11 Validación local de JWTADR-010
pydantic ^2.10 Validación de schemas
pydantic-settings ^2.7 Configuración desde .env
httpx ^0.28 Cliente HTTP (llamadas a Keycloak Admin API)
ruff ^0.8 Linter + formatter
pytest ^8.3 Tests

Estructura app/{core,models,schemas,routers,services}. Sesión SQLModel inyectada vía Depends(get_session). RBAC implementado con un Permission enum y un factory require_permission(Permission.X) espejado en el cliente Flutter (ADR-013).

Infraestructura (custodiam-infra)

Componente Versión Decisión
Docker Compose 2.x Orquestador local
PostgreSQL 15-alpine BD relacional (ADR-009 — dos BDs lógicas)
Keycloak 26+ IdP OIDC (ADR-010)
Resend (SMTP) Emails transaccionales del realm (ADR-021)
Nginx Alpine latest Servidor de la PWA (ADR-006)
ntfy latest Notificaciones de respaldo (Notificaciones)
n8n latest Automatización (post-MVP, profile full)
Cloudflare Tunnel latest Exposición HTTPS sin abrir puertos
Mock OIDC server 2.1.10 Tests del cliente OIDC en custodiam-app (profile test)
sops + age latest Gestión de secretos cifrados (ADR-019)
just 1.40+ Command runner (interfaz preferida)

Tres modos de despliegue (dev / tunnel / prod) mutuamente excluyentes con guard de cross-mode (ADR-020). Imágenes publicadas en GHCR (ghcr.io/custodiam/custodiam-api, ghcr.io/custodiam/custodiam-web) por el workflow de CI de cada repo (ADR-007).

Documentación pública (custodiam-book)

Componente Versión Decisión
Material for MkDocs ^9.5 Theme + engine (ADR-027)
mkdocs-mermaid2-plugin ^1.2 Renderizado nativo Mermaid
mkdocs-d2-plugin ^1.7 Diagramas D2 con shape: sql_table y crow's foot
mike ^2.1 Versionado de docs (instalado, sin activar de inicio)
pymdown-extensions ^10.13 Admonitions, tabs, code blocks
Python + uv 3.13 + 0.9+ Mismo stack que custodiam-api

Hosted en GitHub Pages directo (vendor-lock-free) con dominio propio docs.custodiam.es vía CNAME en Cloudflare DNS modo DNS only. Workflow CI con astral-sh/setup-uv + mkdocs build + peaceiris/actions-gh-pages@v4.

Diagrama del stack (alto nivel)

ClientesEdge (Cloudflare)Stack autoalojado (Docker Compose)ExternosApp Android(Flutter release)App iOS(Flutter release)PWAapp.custodiam.esCloudflare Tunnel(api, auth, app, ntfy.custodiam.es)Cloudflare Pages(/privacy, /delete legales)custodiam-webNginx Alpine sirviendo PWAFastAPIcustodiam-apiKeycloak 26realm custodiamPostgreSQL 152 BDs: custodiam, custodiam_kcntfy(backup push)Firebase FCM(canal principal push)Resend SMTP(emails transaccionales Keycloak) HTTPSHTTPSHTTPS pushpushpushfallback

Diagrama detallado por flujo (autenticación OAuth, propagación de eventos, etc.) en Diagramas del sistema.

Referencias

  • Empezar — cómo levantar el stack completo.
  • ADRs — registro de decisiones técnicas con justificación.