Skip to content

Arquitectura

Visión general de cómo encajan los 5 repos del proyecto. Para el detalle de cada decisión ver los ADRs; para levantar cada repo localmente ver Onboarding; para saber dónde corre todo en producción ver Infraestructura.

Los 5 repos

RepoQué esStack
camaroneras_backendAPI REST, única fuente de verdad de los datosNestJS + Prisma + PostgreSQL + Redis
camaroneras_adminPanel administrativo web de tenant (gestión desde PC)React 19 + Vite + TypeScript + Shadcn UI
camaroneras_platformPanel de plataforma (superadmin, cross-tenant)React 19 + Vite + TypeScript + Shadcn UI
camaroneras_mobileApp de campo iOS/Android, offline-firstFlutter + Drift + Riverpod
camaroneras_docsEste sitio — documentación del sistemaVitePress

Polyrepo: cada uno tiene su git propio y su propio CI. Una tarea que toca varios repos usa la misma rama feat/[tarea] en todos (ADR-0004, ADR-0025).

Multi-tenant

Cada camaronera / razón social es una organización independiente. Todos los datos se aíslan por organizationId, que el backend siempre lee del JWT — nunca del body ni de query params del cliente (ADR-0001, ADR-0007).

RBAC — permisos granulares

Los permisos son modulo:accion (ver / crear / editar / eliminar / exportar), definidos en un catálogo (src/modules/permissions/rbac.constants.ts en el backend). Roles v1: Administrador (todo), Técnico (operación de campo), Bodeguero (solo ver).

Los permisos no viajan en el JWT — el JWT solo lleva identidad + roleId. El PermissionGuard los resuelve en cada request contra Redis (con fallback a PostgreSQL), así que cambiar la matriz de permisos de un rol aplica al instante, sin re-emitir tokens (ADR-0015).

Cada módulo declara qué clientes lo usan (web, mobile, o ambos) — es el gate por cliente, y tanto el admin como mobile filtran su navegación con eso más los permisos del usuario (ADR-0002).

Contrato de API

Toda respuesta del backend sigue el mismo sobre:

json
{ "data": "...", "message": "...", "statusCode": 200 }

y en error: { "error": "...", "message": "...", "statusCode": 400 } (ADR-0006). Cada endpoint se documenta con decoradores Swagger (@nestjs/swagger); el spec OpenAPI resultante es la fuente de la API Reference de este sitio (ADR-0012).

Autenticación y tokens

  • Admin web: sin auto-registro público — toda cuenta nace por invitación (de tenant o de plataforma). La alta delegada de plataforma es la única en dos pasos: el superadmin invita sin nombrar la empresa y el cliente la nombra al aceptar (onboarding). Mobile no registra, solo hace login — las cuentas de técnico y bodeguero las crea un administrador.
  • Refresh token: cookie httpOnly en web, tabla local (Drift) en mobile. Access token solo en memoria, nunca en localStorage — mitiga XSS. (ADR-0013 superseded, ADR-0050 — retiro del signup público, ADR-0014).

Offline-first (mobile)

Patrón central: lectura desde Drift local, escritura requiere red. Toda pantalla lee de la base local; escribir exige conexión (si falla, mensaje "Sin conexión…") y tras escribir se re-sincroniza. Los valores derivados y summaries que calcula el backend se cachean en Drift para que la pantalla offline muestre exactamente lo mismo que la online (ADR-0021, ADR-0022).

Desde sync-offline-escrituras sí existe cola de escrituras offline (outbox) para los 6 módulos de registro de campo: se encolan en Drift y se reintentan al reconectar, con idempotencia best-effort en el backend (ADR-0055, ADR-0056). El CRUD administrativo (sectores, piscinas, ciclos) sigue exigiendo conexión a propósito.

Módulos de negocio

Orden de construcción por dependencias — cada uno se implementa backend → admin → mobile (ADR-0005):

PiscinasCiclos (siembra o transferencia) → Muestreos (biometría + sobrevivencia) → Alimentación (FCR acoplado al último muestreo con biomasa) → Parámetros de aguaEventosRaleos y cosecha final (cierra el ciclo).

Ver el contrato completo de cada uno en Módulos y las decisiones de modelado específicas en los ADRs 0027–0033.

Diagrama de flujo de datos

┌─────────────────┐     JWT + REST      ┌──────────────────┐
│  camaroneras_    │ ───────────────────▶│  camaroneras_    │
│  admin (web)     │◀─────────────────── │  backend (API)   │
└─────────────────┘   {data,message,     └────────┬─────────┘
                        statusCode}                │
┌─────────────────┐                                │
│  camaroneras_    │       REST (online)            │
│  mobile          │ ───────────────────────────────┘
│  (Drift local)   │
└─────────────────┘