🔍
Escáner de Base de Código / nutritrack-app
✓ FULL SCAN project-doc.md AGENTS.md
📋 project-doc.md GENERADO
🕐 2026-06-15T09:14:22Z 📦 Modo: FULL SCAN 📁 Repo: nutritrack-app 🔢 Archivos escaneados: 147
📄
project-doc.md
✓ Actualizado
🤖
AGENTS.md
✓ Generado
📁
Archivos re-escaneados
N/A (full scan)
🧪
Cobertura de tests
62%
project-doc.md
AGENTS.md
Resumen de escaneo
✅  Escaneo completo (FULL) — project-doc.md y AGENTS.md generados correctamente. Estado actualizado en state.json → checkpoints.scan = "completed"
Tech Stack
Runtime
Node.js
v20.11 LTS
Lenguaje
TypeScript
5.4.x (strict)
Framework
Next.js
14 App Router
Base de datos
PostgreSQL
via Prisma 5.x
Estilos
Tailwind CSS
3.4 + shadcn/ui
Estado global
Zustand
4.5.x
Data fetching
React Query
TanStack v5
Autenticación
NextAuth.js
v5 (multitenant)
Pagos
Stripe
webhooks + checkout
Email
Resend
transaccional
Tests unitarios
Vitest
2.x
Tests E2E
Playwright
1.44.x
🏛️
Patrón de Arquitectura
🔧 Feature-Based + Repository Pattern (multitenant)
inferido del código

El proyecto sigue una arquitectura Feature-Based combinada con el patrón Repository. La lógica de negocio reside exclusivamente en /lib/services/, separada en dominios. Los componentes de UI no acceden a la base de datos directamente. Todo flujo de autenticación y aislamiento de datos está condicionado por tenantId.

Cliente
Browser
React + shadcn/ui
App Router
Next.js 14
RSC + API Routes
Services
lib/services/
Business logic
ORM
Prisma
Data access layer
DB
PostgreSQL
RLS por tenant
📁
Estructura de Carpetas
nutritrack-app/ ├── app/ # App Router — páginas y layouts │ ├── (auth)/ # Rutas protegidas con middleware NextAuth │ ├── (dashboard)/ # Panel principal por clínica (tenantId) │ │ ├── patients/ # CRUD pacientes │ │ ├── diet-plans/ # Planes nutricionales │ │ └── reports/ # Informes y analytics │ ├── api/ # API Routes (solo orquestación, sin lógica) │ └── layout.tsx ├── components/ │ ├── ui/ # shadcn/ui — componentes base sin lógica de negocio │ ├── patients/ # Componentes dominio pacientes │ ├── diet-plans/ # Componentes dominio planes │ └── shared/ # Componentes transversales (DataTable, Charts) ├── lib/ │ ├── services/ # ⭐ Toda la lógica de negocio aquí │ │ ├── patients/ │ │ ├── diet-plans/ │ │ └── reports/ # ⚠️ N+1 conocido en nutrition-summary.ts │ ├── db/ # Prisma client singleton (lib/db/index.ts) │ └── auth/ # NextAuth config — ZONA CRÍTICA ├── types/ # [domain].ts — tipos TypeScript por dominio ├── hooks/ # Custom React hooks (use[Domain]Query) ├── prisma/ │ └── schema.prisma # Esquema con RLS por tenantId ├── __tests__/ # Vitest — tests unitarios de services └── e2e/ # Playwright — flujos críticos E2E
📏
Convenciones de Código
📋 Patrones inferidos del código fuente
Aspecto Convención detectada Ejemplo
Exports Named exports (default exports: 0 encontrados) export function getPatientsService()
Nombre de archivos kebab-case para todo nutrition-summary.ts
Nombre de hooks use[Dominio][Acción] usePatientsQuery
Tipos Un archivo por dominio en /types/ types/patient.ts
Imports Alias @/ para rutas internas import { db } from "@/lib/db"
Async/await Siempre async/await (sin .then/.catch raw) const patients = await getPatients(tenantId)
Validación Zod schemas en entrada de API patientSchema.parse(body)
🗄️
Arquitectura de Datos
🔑 Entidades principales (Prisma schema)
multitenant por tenantId
// prisma/schema.prisma — relaciones clave detectadas model Clinic { // Tenant root id String @id @default(cuid()) patients Patient[] dietPlans DietPlan[] subscription Subscription? } model Patient { id String @id clinicId String // → tenantId isolation clinic Clinic @relation(...) dietPlans DietPlan[] logs NutritionLog[] } model DietPlan { id String @id patientId String clinicId String // redundante por RLS meals Meal[] @@index([clinicId, patientId]) } ⚠️ N+1 detectado: lib/services/reports/nutrition-summary.ts → Carga NutritionLog por paciente dentro de un loop → Corrección sugerida: incluir via Prisma .include() o batch query
🧪
Cobertura de Tests
📊 Vitest + Playwright — Estado actual
⚠ 62% — por debajo del objetivo 80%
Cobertura global 62%
Objetivo mínimo 80%
Módulo Cobertura Estado
lib/services/patients/ 84% ✓ OK
lib/services/diet-plans/ 78% ⚠ Cerca
lib/services/reports/ 31% ✗ Crítico
lib/auth/ 72% ⚠ Zona crítica
app/api/ (handlers) 45% ✗ Bajo
e2e/ (Playwright) checkout, login, patient CRUD ✓ Flujos clave
🤖
AGENTS.md — Reglas para agentes IA GENERADO
ℹ️  El archivo AGENTS.md se escribe en la raíz del repositorio. Todos los agentes del pipeline lo leen antes de comenzar cualquier tarea. NO copiar de project-doc.md — está reescrito como instrucciones directas.
📐 Stack Context
Next.js 14 App Router + Prisma 5 + PostgreSQL + Tailwind + shadcn/ui + Vitest + Playwright Multitenant SaaS (tenantId = clinicId) · Auth: NextAuth.js v5 · Pagos: Stripe webhooks
✅ / 🚫 Reglas de Código
  • DO usar named exports en todos los archivos. Los default exports están prohibidos en este proyecto.
  • 🚫 DON'T añadir lógica de negocio en API route handlers. Delegar siempre a /lib/services/[dominio]/
  • 🚫 DON'T consultar la DB directamente desde componentes o páginas. El acceso a datos es exclusivo de /lib/services/
  • DO incluir tenantId (clinicId) en TODAS las queries a la DB. Sin excepción. Filtrado obligatorio en capa de servicio.
  • DO usar alias @/ para imports internos. Nunca usar rutas relativas que suban más de 1 nivel (../../).
  • ⚠️ N+1 conocido en lib/services/reports/nutrition-summary.ts — no agravar. Usar .include() de Prisma o batch queries al modificar este módulo.
  • 🚫 DON'T usar .then()/.catch() raw. Este codebase usa exclusivamente async/await con try/catch.
👥
Instrucciones por Agente
🎯
Orchestrator
  • ¿El cambio toca el payment flow (Stripe)? Si sí → requiere revisión humana obligatoria.
  • ¿El cambio afecta a /lib/auth/? → marcar automáticamente como 🔴 Crítico.
  • ¿Existe tenantId en todas las queries del PR? → validar antes de pasar al Developer.
  • ¿El PR añade nuevas rutas API? → verificar que no contienen lógica de negocio inline.
🏗️
Architect
  • N+1 conocido en reports/nutrition-summary.ts — evitar patrones similares en nuevas queries.
  • No crear directorios fuera del patrón feature-based sin aprobación humana.
  • PostgreSQL RLS como segunda capa de tenant isolation — no saltarla con queries raw.
  • Zustand solo para estado UI efímero. Datos de servidor → React Query únicamente.
💻
Developer
  • Usar dayjs para fechas. moment está baneado (no está en package.json).
  • Validación de entrada obligatoria con Zod en todas las API routes.
  • Emails transaccionales via Resend SDK. No fetch directo a la API.
  • React Query para todo data fetching desde cliente. No usar fetch() raw en componentes.
🔍
PR Reviewer
  • 🔴 Crítico: cualquier cambio en /lib/auth/ — requiere aprobación humana explícita.
  • 🔴 Crítico: webhook handler de Stripe sin verificación de firma (stripe.webhooks.constructEvent).
  • 🟡 Should Fix: queries sin tenantId filter.
  • 🟡 Should Fix: componentes que importan desde @/lib/db directamente.
🧪
QA Agent
  • Cobertura actual: 62%. Todo código nuevo debe incluir tests. Objetivo mínimo por módulo: 80%.
  • Flujos críticos E2E siempre: login multitenant → gestión paciente → generación informe → pago Stripe.
  • Probar siempre: estado vacío (0 pacientes), estado de carga, error de red, y sesión expirada.
  • Módulo lib/services/reports/ con cobertura 31% → prioridad máxima en nuevos tests.
  • Tests de integración usan DB real (Postgres test container) — no usar mocks de DB.
🔒 Reglas de Seguridad — Todos los agentes
OBLIGATORIO
  • 🚫 Nunca hardcodear secrets, tokens o credenciales. Solo variables de entorno (process.env.*).
  • 🚫 Nunca exponer el modelo Prisma o errores de DB directamente en respuestas de API.
  • ⚠️ Todo código que toque auth o payments → flagear inmediatamente para revisión humana.
  • Verificar firma de webhooks Stripe con stripe.webhooks.constructEvent() antes de procesar cualquier evento.