Arquitectura¶
Custodiam sigue una arquitectura polyrepo con tres repositorios de código independientes coordinados desde un cuarto de orquestación + un quinto de documentación pública.
Repositorios del proyecto¶
custodiam-workspace/
├── custodiam-app/ ← Flutter (Android + iOS + Web) · github.com/custodiam/custodiam-app
├── custodiam-api/ ← FastAPI + SQLModel + PostgreSQL · github.com/custodiam/custodiam-api
├── custodiam-infra/ ← Docker Compose + Keycloak + Tunnels · github.com/custodiam/custodiam-infra
└── custodiam-book/ ← Documentación pública (este sitio) · github.com/custodiam/custodiam-book
Existe además un quinto repositorio privado (rodrigomulero/DOCUMENTACION) con la documentación interna del equipo: backlog operativo, seguimiento de sprints, memoria académica del TFG y lecciones operativas. El book público es una vista curada del material de ese repo apta para el público; el sync es manual y controlado (ADR-027).
Recorridos por la arquitectura¶
-
:material-stack-overflow: Stack técnico
Tecnologías concretas por capa: Flutter, FastAPI, SQLModel, PostgreSQL, Keycloak, Docker, Cloudflare.
-
:material-graph: Diagrama del sistema
Diagrama de componentes y flujos principales del sistema (auth, API, notificaciones).
Principios de diseño¶
- Polyrepo (ADR-001): tres repos independientes evitan el "monorepo monstruo" y permiten ciclos de release desacoplados (
custodiam-appcon releases semver para stores,custodiam-apicon su propio versionado,custodiam-infracon tags por entorno). - Clean Architecture estricta en
custodiam-app(ADR-013): tres capasdomain/data/presentation. Domain es Dart puro sin dependencias de framework. Data devuelveResult<T>siempre, no lanza excepciones cross-layer (ADR-014). - SQLModel en
custodiam-api(ADR-002): unifica SQLAlchemy 2.0 + Pydantic en una sola clase. Unatabla=Truees modelo de BD Y schema de API en un único punto. - Resiliencia documentada: matriz de fallos del sistema con planes de degradación (FCM caído → ntfy backup, Cloudflare Tunnel caído → modo dev local, Keycloak caído → degradación graceful con error 503).
- Notificaciones redundantes: Firebase Cloud Messaging como canal principal + ntfy como backup. Si FCM falla, las alertas críticas se entregan vía ntfy.
- Auth basado en estándares: OAuth2 + PKCE (RFC 7636) contra Keycloak (ADR-010, ADR-023). JWT validación local en backend con PyJWT (ADR-010). RBAC con 12 roles jerárquicos + 40 permisos definidos en
RBAC_v0.1.0.
Stack resumido¶
| Capa | Tecnología | Versión | Decisión |
|---|---|---|---|
| App móvil/web | Flutter + Dart | 3.x | ADR-001, ADR-022 (iOS 15+) |
| State management | Riverpod | 2.6+ | ADR-012 |
| Backend | Python + FastAPI | 3.13 + 0.115+ | ADR-026 (uv) |
| ORM | SQLModel + Alembic | 0.0.22+ | ADR-002 |
| BD | PostgreSQL + psycopg3 | 15 + 3.1+ | ADR-008 (psycopg3), ADR-009 (2 BDs separadas) |
| Auth | Keycloak | 26+ | ADR-010, ADR-023 |
| Push notif | Firebase FCM + ntfy | — | ADR-005 (notif redundantes) |
| Infra local | Docker Compose | 2.x | ADR-007 |
| Tunnel + CDN | Cloudflare Tunnel + Pages | — | ADR-022, ADR-028 (pendiente) |
| Documentación pública | Material for MkDocs | 9.x | ADR-027 |
Referencias¶
- ADRs públicos — registro completo de decisiones arquitectónicas con justificación y alternativas evaluadas.
- Empezar — cómo levantar el stack completo en local.