15 KiB
Internet Banking - Aplicación Web Segura
Aplicación web de Internet Banking construida con Next.js 14 (App Router), TypeScript, TailwindCSS + daisyUI, y Zustand para gestión de estado. El backend está desarrollado en Java 25 Spring Boot y protegido por Kong Gateway.
🚀 Características
- ✅ Autenticación segura con tokens JWT en cookies HTTP-only
- ✅ Server Components de Next.js para máximo rendimiento
- ✅ Middleware de autenticación server-side
- ✅ Sistema de logs centralizado (escribe en archivo .txt)
- ✅ Encriptación Kong para datos sensibles
- ✅ UI moderna con TailwindCSS y daisyUI
- ✅ TypeScript para type-safety completo
- ✅ Zustand para estado cliente (no Redux)
- ✅ Sin useEffect/useContext innecesarios (server-first)
Internet Banking (Next.js)
This repository contains a Next.js application scaffolded with create-next-app.
Getting started
- Install dependencies:
npm install
- Run the development server:
npm run dev
# then open http://localhost:3000
Requisitos
- Node.js 18 LTS o superior
Instalación y ejecución
- Instala las dependencias:
npm install
- Ejecuta el servidor de desarrollo:
npm run dev
# luego abre http://localhost:3000
Dependencias
Las dependencias actuales (según package.json):
Runtime
next15.5.6react19.1.0react-dom19.1.0daisyui5.4.5react-icons5.5.0zustand5.0.8
Desarrollo
typescript5@types/node20@types/react19@types/react-dom19eslint9@eslint/eslintrc3eslint-config-next15.5.6tailwindcss4.1.17@tailwindcss/postcss4.1.17
Notas
- Para ejecutar el linter localmente:
npm run lint
🤖 Infraestructura de Ingeniería AI-Native (Agentes y Esquema MCP)
Esta aplicación está diseñada desde sus cimientos para el desarrollo asistido por Agentes de Inteligencia Artificial Autónomos mediante el protocolo MCP (Model Context Protocol), asegurando consistencia arquitectónica, memoria persistente entre sesiones y navegación contextual ultra-rápida.
1. El Esquema de Servidores MCP (mcp_config.json)
Para iniciar el entorno de desarrollo con soporte de IA y permitir que los agentes se auto-direccionen, debes registrar los siguientes servidores en el archivo de configuración global de tu entorno de ejecución (ej. ~/.gemini/antigravity/mcp_config.json):
{
"mcpServers": {
"engram": {
"command": "engram",
"args": [
"mcp",
"--tools=agent"
]
},
"graphify": {
"command": "d:\\Jess\\agent\\graphify\\.venv\\Scripts\\python.exe",
"args": [
"-m",
"graphify.serve",
"d:/Jess/agent/frontend-ai/graphify-out/graph.json"
]
}
}
}
- Engram (Memoria Persistente): Servidor escrito en Go que expone herramientas para almacenar decisiones, resúmenes de sesión (
mem_save) y recuperar contexto de sesiones previas (mem_search,mem_context), evitando la pérdida de contexto sobre las reglas de negocio críticas o decisiones pasadas. - Graphify (Grafo del Repositorio): Servidor que mapea todo el código, layouts de Next.js, API routes y documentación en un grafo semántico. Permite al agente responder preguntas de arquitectura mediante consultas directas en lugar de hacer lecturas completas de archivos, optimizando drásticamente la ventana de contexto.
2. Reglas de Comportamiento para Agentes de IA (AGENTS.md / CLAUDE.md)
Cualquier agente que trabaje en esta base de código está estrictamente obligado a seguir las siguientes directrices y reglas operativas integradas en el proyecto:
🔐 Seguridad y Autenticación Primero
- Nunca escribirás claves o credenciales en texto plano: El agente tiene estrictamente prohibido commitear archivos
.envo variables con valores reales. Siempre utilizará variables de entorno. - Respeto absoluto por el Middleware Server-Side: Para proteger cualquier ruta o recurso, el agente DEBE usar el middleware centralizado
serverRequireAuthdesdelib/auth/middleware.tsen los Server Components. Bajo ninguna circunstancia omitirá este paso o creará validaciones ad-hoc. - Cookies HTTP-Only y Secure: Los tokens JWT nunca deben tocar el
localStorageosessionStoragedel cliente. Si el agente diseña flujos de autenticación en el cliente, debe delegar el almacenamiento y la gestión de la cookie al navegador y al backend. - Encriptación de Datos Sensibles: Cualquier dato altamente confidencial (ej. números de cuenta, saldos, datos personales) que viaje por el cliente debe encriptarse usando el módulo placeholder de Kong Gateway (
lib/cypher/encrypt.ts).
📝 Sistema de Logs Centralizado
- El agente debe loguear activamente todas las acciones críticas (inicios de sesión, accesos denegados, errores de comunicación con el backend, llamadas a la API) usando los módulos
server-loggeryclient-logger. - Todos los logs generados en componentes del cliente deben enrutarse hacia la API local
POST /api/logspara asegurar que queden guardados en el archivo centralizadologs/app.log.
🏗️ Desarrollo Incremental y Verificabilidad
- El agente debe mantener el archivo
STATE.mdyENGRAM.mdactualizados en cada punto de control (Checkpoint) para evitar la degradación de la memoria y la ventana de contexto del modelo. - Después de realizar cualquier cambio estructural en el código, el agente ejecutará localmente
graphify update .para asegurar que el grafo de conocimiento del proyecto refleje los nuevos módulos inmediatamente.
🏗️ Estructura del Proyecto
internet-banking/
├── app/ # Next.js App Router
│ ├── page.tsx # Página principal
│ ├── layout.tsx # Layout principal
│ ├── ClientAuthProvider.tsx # Provider para hidratación de auth
│ ├── globals.css # Estilos globales
│ ├── about/ # Sección "Acerca de"
│ │ ├── page.tsx
│ │ ├── layout.tsx
│ │ ├── components/
│ │ │ ├── aboutHeader.tsx
│ │ │ └── aboutContent.tsx
│ │ ├── service/
│ │ │ └── fetchAbout.ts
│ │ └── hooks/
│ │ └── useAboutData.ts
│ ├── login/ # Página de login
│ │ ├── page.tsx
│ │ └── LoginForm.tsx
│ ├── dashboard/ # Dashboard protegido
│ │ └── page.tsx
│ ├── model/ # Modelos TypeScript
│ │ └── cuenta.ts
│ └── api/ # API Routes
│ ├── logs/
│ │ └── route.ts # POST /api/logs
│ └── auth/
│ ├── me/
│ │ └── route.ts # GET /api/auth/me
│ └── logout/
│ └── route.ts # POST /api/auth/logout
├── components/
│ └── ui/ # Componentes UI reutilizables
│ ├── button.tsx
│ ├── input.tsx
│ ├── header.tsx
│ └── table.tsx
├── lib/
│ ├── auth/ # Autenticación
│ │ ├── middleware.ts # Middleware server-side
│ │ └── client/
│ │ └── useAuthStore.ts # Zustand store
│ ├── logger/ # Sistema de logs
│ │ ├── server-logger.ts # Logger server-side
│ │ └── client-logger.ts # Logger client-side
│ └── cypher/ # Encriptación Kong
│ ├── encrypt.ts
│ └── decrypt.ts
├── logs/
│ └── app.log # Archivo de logs (no en git)
├── middleware.ts # Next.js Edge Middleware
├── package.json
├── tsconfig.json
├── tailwind.config.ts
├── next.config.js
└── README.md
🔐 Autenticación
Flujo de Autenticación
- Login: Usuario envía credenciales a
POST /api/auth/login - Backend: Spring Boot valida y devuelve tokens en cookies HTTP-only:
access_token: Token de acceso (corta duración)refresh_token: Token de refresco (larga duración)
- Frontend: Cookies se establecen automáticamente (HTTP-only, Secure, SameSite=strict)
- Validación: Cada petición a rutas protegidas valida el token server-side
- Logout:
POST /api/auth/logoutlimpia cookies
Middleware de Autenticación
Server-Side (lib/auth/middleware.ts)
// Proteger una página (Server Component)
import { serverRequireAuth } from '@/lib/auth/middleware';
export default async function ProtectedPage() {
const user = await serverRequireAuth(); // Redirige si no autenticado
return <div>Hola {user.name}</div>;
}
// Check opcional (no redirige)
import { checkAuth } from '@/lib/auth/middleware';
const authResult = await checkAuth();
if (authResult.isAuthenticated) {
// Usuario logueado
}
Edge Middleware (middleware.ts)
Automáticamente redirige rutas protegidas (/dashboard, /profile, etc.) si no hay token.
Zustand Store (Client-Side)
'use client';
import { useAuthStore } from '@/lib/auth/client/useAuthStore';
function MyComponent() {
const { user, isAuthenticated, logout } = useAuthStore();
return (
<div>
{isAuthenticated && <p>Hola {user?.name}</p>}
<button onClick={logout}>Logout</button>
</div>
);
}
IMPORTANTE: El store Zustand NO guarda tokens, solo datos del usuario y flags UI.
📝 Sistema de Logs
Todos los logs se escriben server-side en logs/app.log.
Desde Server Components / API Routes
import { logInfo, logWarn, logError } from '@/lib/logger/server-logger';
logInfo('User logged in', { userId: '123' });
logWarn('Failed login attempt', { email: 'user@example.com' });
logError('Database connection failed', { error: err.message });
Desde Client Components
'use client';
import { logInfo, logWarn, logError } from '@/lib/logger/client-logger';
// Estos envían logs a /api/logs que los escribe server-side
logInfo('Button clicked', { action: 'submit' });
logError('Form validation failed', { field: 'email' });
Formato de Logs
[2024-11-07T10:30:00.000Z] [INFO] Login success | {"userId":"123","email":"user@example.com"}
[2024-11-07T10:31:00.000Z] [WARN] Unauthorized access attempt | {"path":"/dashboard"}
[2024-11-07T10:32:00.000Z] [ERROR] Backend connection failed | {"error":"ECONNREFUSED"}
🔒 Seguridad
Tokens HTTP-Only
- Los tokens JWT nunca se almacenan en
localStorageosessionStorage - Se usan cookies HTTP-only, Secure (en producción), SameSite=strict
- No accesibles desde JavaScript del cliente
Encriptación Kong
Para datos sensibles que necesitan encriptación:
import { kongEncrypt, kongDecrypt } from '@/lib/cypher/decrypt';
// Encriptar
const encrypted = kongEncrypt('sensitive-data');
// Desencriptar
const decrypted = kongDecrypt(encrypted);
// TODO: Reemplazar con la librería Kong real una vez proporcionada
CORS y CSRF
Asegúrate de configurar en tu backend Spring Boot:
// Permitir solo orígenes aprobados
@CrossOrigin(origins = "http://localhost:3000", allowCredentials = "true")
// SameSite=strict para cookies
cookie.setSameSite("strict");
🧪 Pruebas Manuales
1. Login Exitoso
- Ir a
/login - Ingresar credenciales válidas
- Esperado: Redirige a
/dashboard - Log:
[INFO] Login success | {"userId":"123"}
2. Login Fallido
- Ir a
/login - Ingresar credenciales inválidas
- Esperado: Muestra mensaje de error
- Log:
[WARN] Login failed | {"email":"us***@example.com"}
3. Acceso No Autorizado
- Sin estar logueado, intentar acceder a
/dashboard - Esperado: Redirige a
/login?redirect=/dashboard - Log:
[WARN] Unauthorized access attempt | {"redirectTo":"/login"}
4. Logout
- Estando logueado, hacer click en "Cerrar Sesión"
- Esperado: Cookies eliminadas, redirige a
/login - Log:
[INFO] Logout user: 123
📦 Build para Producción
# Build
npm run build
# Start production server
npm run start
Variables de Entorno en Producción
Asegúrate de configurar:
NODE_ENV=production
NEXT_PUBLIC_API_URL=https://api.tudominio.com/api
API_URL_SERVER=https://api-internal.tudominio.com/api
KONG_SECRET_KEY=<tu-clave-secreta-real>
🚨 Solución de Problemas
Error: "Failed to fetch"
- Verifica que el backend esté corriendo
- Verifica las URLs en
.env.local - Revisa los logs en
logs/app.log
Error: "Unauthorized"
- Verifica que las cookies se estén estableciendo correctamente
- Revisa la configuración CORS del backend
- Asegúrate que
withCredentials: trueesté en las peticiones fetch
Error: Cookies no se establecen
- En desarrollo: Asegúrate que frontend y backend estén en el mismo dominio (localhost)
- Verifica configuración
SameSiteen backend - Revisa que
httpOnly: trueesté configurado correctamente
Logs no se escriben
- Verifica que
ENABLE_SERVER_LOGS=true - Asegúrate que la carpeta
logs/tenga permisos de escritura - Revisa los logs de consola para errores
📚 Documentación Adicional
🔧 Scripts Disponibles
npm run dev # Desarrollo
npm run build # Build producción
npm run start # Servidor producción
npm run lint # ESLint
npm run type-check # TypeScript type checking
📝 TODOs Pendientes
Los siguientes TODOs están marcados en el código con /* TODO */:
- lib/cypher/encrypt.ts y decrypt.ts: Reemplazar implementación placeholder con librería Kong real
- lib/auth/middleware.ts: Ajustar headers según requerimientos del backend
- app/api/auth/me/route.ts: Ajustar headers según backend
- app/login/LoginForm.tsx: Ajustar payload y endpoint de login según backend
- Variables de entorno: Reemplazar valores de ejemplo con valores reales
- Endpoints backend: Verificar que coincidan con los del backend Spring Boot
🤝 Contribución
- Crear una rama:
git checkout -b feature/nueva-funcionalidad - Commit cambios:
git commit -am 'Agrega nueva funcionalidad' - Push a la rama:
git push origin feature/nueva-funcionalidad - Crear Pull Request
📄 Licencia
Este proyecto es privado y confidencial.
👥 Equipo
Desarrollado para el sistema de Internet Banking.
Nota de Seguridad: Nunca commitear archivos con claves reales, tokens, o credenciales. Usar siempre variables de entorno y mantener .env.local fuera del control de versiones.