IA-Ingeniería-MLOps · Documentación y ADRs

NutriTrack AI
Docs Arquitectónicas

Sistema de decisiones arquitectónicas, changelog y guías de documentación para el equipo de ingeniería — preparado para el lanzamiento v1.0.

📋 3 ADRs
📦 v1.0.0 Release
8/9 checks
🗓 2026-06-15
📐

Architecture Decision Records

El "por qué" detrás de cada decisión técnica crítica
ADR-001

PostgreSQL + Prisma como base de datos primaria

✓ Accepted 2026-03-12
Contexto
NutriTrack AI gestiona datos mixtos: un núcleo relacional fuerte (clínicas → nutricionistas → pacientes → planes de dieta) y datos semi-estructurados (logs nutricionales diarios con campos variables por tipo de alimento). El equipo es de 4 personas con capacidad de ops limitada. La regulación sanitaria exige auditoría e integridad transaccional de los cambios de estado de los planes.
Decisión
Usar PostgreSQL (Neon como managed hosting) con Prisma ORM para acceso tipado y gestión de migraciones. Los logs nutricionales se almacenan como columnas jsonb en PostgreSQL, eliminando la necesidad de una base de datos documental separada.
Alternativas evaluadas
Opción Pros Contras Veredicto
PostgreSQL + Prisma
ACID, jsonb nativo, full-text search, ecosistema maduro, Neon serverless Requiere schema migrations cuidadosas ✓ Elegida
MongoDB Atlas
Schema flexible, fácil onboarding inicial Datos relacionales complejos sin JOINs nativos; transacciones multi-documento costosas ✗ Rechazada
DynamoDB
Escala automática, sin servidor Queries relacionales imposibles sin GSIs complejos; vendor lock-in AWS; coste impredecible ✗ Rechazada
Consecuencias
Prisma genera tipos TypeScript desde el schema → cero errores de tipo en queries
Full-text search nativo para buscar alimentos en logs sin Elasticsearch adicional
Neon ofrece branching de base de datos para PRs de staging gratuitos
⚠️
Migraciones Prisma deben ejecutarse en CI/CD antes de desplegar pods nuevos
ADR-002

SDK Anthropic nativo para agentes IA (sin frameworks)

✓ Accepted 2026-04-03
Contexto
Los agentes de NutriTrack analizan historiales nutricionales de 7 a 90 días y generan recomendaciones personalizadas. La regulación sanitaria exige que cada decisión del agente quede auditada con: prompt exacto enviado, respuesta recibida, herramientas invocadas y timestamp. Necesitamos control total sobre el flujo de llamadas para cumplir con GDPR y normativa de software médico clase IIa (MDR).
Decisión
Usar el SDK de Anthropic directamente (claude-sonnet-4-5) sin frameworks de agentes intermedios. El loop agentico se implementa manualmente con un interceptor de auditoría que persiste cada llamada en la tabla agent_audit_logs antes y después de ejecutar herramientas. Esto nos da trazabilidad completa y evita cajas negras.
Alternativas evaluadas
Opción Pros Contras Veredicto
SDK Anthropic nativo
Control total, auditoría precisa, sin abstracciones opacas, menor dependencia externa Más código de plumbing; loop agentico manual ✓ Elegida
LangChain / LangGraph
Abstracciones listas, comunidad grande Versiones inestables, breaking changes frecuentes; difícil auditar el flujo interno; overhead de abstracción innecesario ✗ Rechazada
CrewAI
Orquestación multi-agente declarativa Demasiada "magia" para cumplimiento regulatorio; dificulta auditoría de herramientas; sobre-ingeniería para nuestro caso ✗ Rechazada
Consecuencias
Cada invocación de herramienta se persiste antes y después → trazabilidad completa para auditorías
Sin dependencia de frameworks de terceros inestables → upgrades controlados
⚠️
El loop agentico (~200 líneas) debe mantenerse en equipo; documentar con gotchas inline
Ver ADR-001: los logs de auditoría van en jsonb en PostgreSQL sin tabla aparte
ADR-003

Supabase Auth + RBAC multi-tenant para clínicas

✓ Accepted 2026-04-18
Contexto
El modelo de datos es multi-tenant: cada clínica es un tenant aislado, con nutricionistas y pacientes como sub-usuarios. Los roles son: admin_clinica (gestiona usuarios, ve todos los planes), nutricionista (crea/edita planes propios), paciente (solo lectura de su plan). La separación de datos entre clínicas es crítica por GDPR — una fuga entre tenants sería devastadora.
Decisión
Usar Supabase Auth para autenticación (ya tenemos Supabase en stack como alternativa a Neon para algunas queries). RBAC implementado con clinic_id en JWT custom claims y Row Level Security (RLS) de PostgreSQL como capa de enforcement — ni siquiera el código de aplicación puede acceder a datos de otro tenant aunque tenga un bug. Los roles se comprueban a nivel de RLS, no solo en el middleware.
Alternativas evaluadas
Opción Pros Contras Veredicto
Supabase Auth + RLS
RLS nativo en PostgreSQL, ya en stack, tenant isolation en base de datos, open source RLS puede ser compleja de debuggear en queries anidadas ✓ Elegida
Auth0
Enterprise-grade, UI de gestión excelente, muchos integraciones Coste elevado a escala; los roles/permisos a nivel de datos requieren lógica adicional; vendor externo para datos sensibles de salud ✗ Rechazada
JWT propio
Control total, sin dependencias Reinventar la rueda en criptografía/sesiones es un riesgo de seguridad inaceptable; coste de desarrollo + audit ✗ Rechazada
Consecuencias
Tenant isolation garantizado a nivel de base de datos, no solo middleware → defensa en profundidad
custom claims JWT incluyen clinic_id y role → propagación automática a RLS policies
⚠️
Las políticas RLS deben testearse con usuarios de diferentes tenants en cada PR que toque tablas compartidas
Supabase ofrece Audit Logs integrado para cambios de auth → cumple requisito MDR

Gotchas documentados inline

Trampas conocidas que deben quedar en el código para que agentes IA y nuevos devs no repitan errores
/** * IMPORTANT: initializeAgentAuditLog() DEBE llamarse ANTES de ejecutar cualquier herramienta. * Si se llama después, la entrada de auditoría queda sin tool_calls y viola el requisito MDR. * El agente puede parecer que funciona correctamente pero los logs serán incompletos. * * Correcto: await audit.start(callId); → executeTools(); → await audit.end(callId, result); * Incorrecto: executeTools(); → await audit.log(callId, everything); ← NO * * Ver ADR-002 para el razonamiento completo. */ export async function runAgentLoop( messages: MessageParam[], auditCtx: AuditContext ): Promise<AgentResult> { const callId = generateCallId(); // SIEMPRE inicializar audit antes de la llamada al modelo await audit.start(callId, { messages, auditCtx }); const response = await anthropic.messages.create({ ... }); // ... }
/** * GOTCHA — RLS y service_role key: * Las queries que usan supabaseAdmin (service_role) BYPASSAN las políticas RLS. * Usar supabaseAdmin SOLO para operaciones de sistema (cron jobs, webhooks internos). * Para todas las queries de usuario, usar supabaseClient con el JWT del usuario. * * Si usas supabaseAdmin en un endpoint de usuario, los datos de TODOS los tenants * serán visibles → fuga de datos entre clínicas. * * Ver ADR-003 para el diseño de tenant isolation. */ // ✅ CORRECTO — usuario autenticado const { data } = await supabaseClient(userJwt) .from('meal_plans') .select('*'); // RLS filtra por clinic_id automáticamente // ❌ INCORRECTO para endpoints de usuario const { data } = await supabaseAdmin .from('meal_plans') .select('*'); // Devuelve datos de TODAS las clínicas
📄

README — Sección Arquitectura

Fragmento listo para copiar en el README del repo
README.md
Preview

NutriTrack AI

Plataforma SaaS B2B para clínicas de nutrición. Analiza historiales nutricionales con agentes IA y genera planes de dieta personalizados con trazabilidad completa para cumplimiento sanitario (MDR clase IIa).

Quick Start

git clone https://github.com/nutritrack-ai/app npm install cp .env.example .env # rellenar DATABASE_URL, ANTHROPIC_API_KEY, SUPABASE_* npx prisma migrate dev npm run dev # http://localhost:3000

Comandos

ComandoDescripción
npm run devServidor de desarrollo (Next.js 15 + Turbopack)
npm testTests unitarios + integración (Vitest)
npm run test:e2eTests Playwright (requiere DB de test)
npm run buildBuild de producción
npx prisma migrate devAplicar migraciones de base de datos
npm run lintESLint + TypeScript type-check

Arquitectura

┌──────────────────────────────────────────────────────┐ │ NUTRITRACK AI │ └──────────────────────────────────────────────────────┘ Frontend Next.js 15 (App Router) · TypeScript · Tailwind Auth Supabase Auth + JWT custom claims + RLS (→ ADR-003) API Next.js Route Handlers · tRPC v11 para tipos E2E Agentes IA SDK Anthropic nativo · claude-sonnet-4-5 (→ ADR-002) Base de datos PostgreSQL (Neon) · Prisma ORM · jsonb para logs (→ ADR-001) Almacenamiento Supabase Storage · PDFs de planes de dieta Infra Vercel (frontend + API) · cron jobs en Vercel Functions ADRs en docs/decisions/ — leer antes de cambios arquitectónicos
📦

Changelog

Historial de cambios user-facing siguiendo Keep a Changelog
v1.0.0 — Launch
2026-06-20 (planned)
Added
  • Análisis nutricional con agente IA: historial de 7, 30 y 90 días con recomendaciones personalizadas #88
  • Panel multi-tenant para clínicas: gestión de nutricionistas y pacientes con RBAC completo #91
  • Generación automática de planes de dieta PDF firmados digitalmente #95
  • Dashboard de logs de auditoría del agente IA (cumplimiento MDR) exportables a CSV #98
  • Integración con bases de datos de alimentos: BEDCA (España), Open Food Facts #101
Fixed
  • Duplicación de registros de peso al hacer sync rápido desde app móvil #103
  • El agente fallaba silenciosamente cuando el historial tenía gaps de más de 14 días #107
Security
  • RLS policies auditadas por tercero — confirmada separación completa entre tenants #112
  • Headers HIPAA-aligned añadidos a todos los endpoints de datos de pacientes #114
v0.9.2 — Beta
2026-05-28
Changed
  • El agente ahora usa claude-sonnet-4-5 (era claude-3-haiku) → recomendaciones +40% más específicas según feedback beta #79
  • Paginación de historial nutricional: 90 días por defecto (era 30) para contexto completo del agente #82

Checklist de verificación

Estado actual de la documentación antes del lanzamiento v1.0
ADRs para decisiones críticas — PostgreSQL, agentes IA y auth documentados con contexto, alternativas y consecuencias
ADR
README cubre Quick Start y comandos — Instrucciones completas desde clone hasta dev
README
Sección de arquitectura en README — Stack completo y links a ADRs
README
Gotchas críticos documentados inline — Loop agentico y RLS con service_role key
Código
APIs internas con JSDocrunAgentLoop, createMealPlan, getPatientHistory documentadas con @param, @returns, @throws
API
Sin código comentado en main — Git history para referencias históricas
Código
CLAUDE.md actualizado — Convenciones del proyecto para agentes IA (RLS, audit log, tenant context)
Agentes
Changelog mantenido — v0.9.x y v1.0.0 con PR refs y categorías semánticas
Changelog
!
OpenAPI spec para REST hooks externos — Webhooks de eventos (plan_updated, goal_reached) pendientes de documentar antes de abrir acceso a integradores
Pendiente