449 lines
15 KiB
Markdown
449 lines
15 KiB
Markdown
# 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
|
|
|
|
1. Install dependencies:
|
|
|
|
```bash
|
|
npm install
|
|
```
|
|
|
|
2. Run the development server:
|
|
|
|
```bash
|
|
npm run dev
|
|
# then open http://localhost:3000
|
|
```
|
|
|
|
## Requisitos
|
|
|
|
- Node.js 18 LTS o superior
|
|
|
|
## Instalación y ejecución
|
|
|
|
1. Instala las dependencias:
|
|
|
|
```bash
|
|
npm install
|
|
```
|
|
|
|
2. Ejecuta el servidor de desarrollo:
|
|
|
|
```bash
|
|
npm run dev
|
|
# luego abre http://localhost:3000
|
|
```
|
|
|
|
## Dependencias
|
|
|
|
Las dependencias actuales (según `package.json`):
|
|
|
|
### Runtime
|
|
|
|
- `next` 15.5.6
|
|
- `react` 19.1.0
|
|
- `react-dom` 19.1.0
|
|
- `daisyui` 5.4.5
|
|
- `react-icons` 5.5.0
|
|
- `zustand` 5.0.8
|
|
|
|
### Desarrollo
|
|
|
|
- `typescript` 5
|
|
- `@types/node` 20
|
|
- `@types/react` 19
|
|
- `@types/react-dom` 19
|
|
- `eslint` 9
|
|
- `@eslint/eslintrc` 3
|
|
- `eslint-config-next` 15.5.6
|
|
- `tailwindcss` 4.1.17
|
|
- `@tailwindcss/postcss` 4.1.17
|
|
|
|
## Notas
|
|
|
|
- Para ejecutar el linter localmente:
|
|
|
|
```bash
|
|
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`):
|
|
|
|
```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
|
|
1. **Nunca escribirás claves o credenciales en texto plano**: El agente tiene estrictamente prohibido commitear archivos `.env` o variables con valores reales. Siempre utilizará variables de entorno.
|
|
2. **Respeto absoluto por el Middleware Server-Side**: Para proteger cualquier ruta o recurso, el agente DEBE usar el middleware centralizado `serverRequireAuth` desde `lib/auth/middleware.ts` en los Server Components. Bajo ninguna circunstancia omitirá este paso o creará validaciones ad-hoc.
|
|
3. **Cookies HTTP-Only y Secure**: Los tokens JWT nunca deben tocar el `localStorage` o `sessionStorage` del 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.
|
|
4. **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-logger` y `client-logger`.
|
|
* Todos los logs generados en componentes del cliente **deben enrutarse** hacia la API local `POST /api/logs` para asegurar que queden guardados en el archivo centralizado `logs/app.log`.
|
|
|
|
#### 🏗️ Desarrollo Incremental y Verificabilidad
|
|
* El agente debe mantener el archivo `STATE.md` y `ENGRAM.md` actualizados 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
|
|
|
|
1. **Login**: Usuario envía credenciales a `POST /api/auth/login`
|
|
2. **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)
|
|
3. **Frontend**: Cookies se establecen automáticamente (HTTP-only, Secure, SameSite=strict)
|
|
4. **Validación**: Cada petición a rutas protegidas valida el token server-side
|
|
5. **Logout**: `POST /api/auth/logout` limpia cookies
|
|
|
|
### Middleware de Autenticación
|
|
|
|
#### Server-Side (lib/auth/middleware.ts)
|
|
|
|
```typescript
|
|
// 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)
|
|
|
|
```typescript
|
|
'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
|
|
|
|
```typescript
|
|
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
|
|
|
|
```typescript
|
|
'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 `localStorage` o `sessionStorage`
|
|
- 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:
|
|
|
|
```typescript
|
|
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:
|
|
|
|
```java
|
|
// Permitir solo orígenes aprobados
|
|
@CrossOrigin(origins = "http://localhost:3000", allowCredentials = "true")
|
|
|
|
// SameSite=strict para cookies
|
|
cookie.setSameSite("strict");
|
|
```
|
|
|
|
## 🧪 Pruebas Manuales
|
|
|
|
### 1. Login Exitoso
|
|
|
|
1. Ir a `/login`
|
|
2. Ingresar credenciales válidas
|
|
3. **Esperado**: Redirige a `/dashboard`
|
|
4. **Log**: `[INFO] Login success | {"userId":"123"}`
|
|
|
|
### 2. Login Fallido
|
|
|
|
1. Ir a `/login`
|
|
2. Ingresar credenciales inválidas
|
|
3. **Esperado**: Muestra mensaje de error
|
|
4. **Log**: `[WARN] Login failed | {"email":"us***@example.com"}`
|
|
|
|
### 3. Acceso No Autorizado
|
|
|
|
1. Sin estar logueado, intentar acceder a `/dashboard`
|
|
2. **Esperado**: Redirige a `/login?redirect=/dashboard`
|
|
3. **Log**: `[WARN] Unauthorized access attempt | {"redirectTo":"/login"}`
|
|
|
|
### 4. Logout
|
|
|
|
1. Estando logueado, hacer click en "Cerrar Sesión"
|
|
2. **Esperado**: Cookies eliminadas, redirige a `/login`
|
|
3. **Log**: `[INFO] Logout user: 123`
|
|
|
|
## 📦 Build para Producción
|
|
|
|
```bash
|
|
# Build
|
|
npm run build
|
|
|
|
# Start production server
|
|
npm run start
|
|
```
|
|
|
|
### Variables de Entorno en Producción
|
|
|
|
Asegúrate de configurar:
|
|
|
|
```env
|
|
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: true` esté 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 `SameSite` en backend
|
|
- Revisa que `httpOnly: true` esté 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
|
|
|
|
- [Next.js 14 Documentation](https://nextjs.org/docs)
|
|
- [TailwindCSS](https://tailwindcss.com/docs)
|
|
- [daisyUI Components](https://daisyui.com/components/)
|
|
- [Zustand](https://docs.pmnd.rs/zustand/getting-started/introduction)
|
|
- [Kong Gateway](https://docs.konghq.com/)
|
|
|
|
## 🔧 Scripts Disponibles
|
|
|
|
```bash
|
|
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 */`:
|
|
|
|
1. **lib/cypher/encrypt.ts y decrypt.ts**: Reemplazar implementación placeholder con librería Kong real
|
|
2. **lib/auth/middleware.ts**: Ajustar headers según requerimientos del backend
|
|
3. **app/api/auth/me/route.ts**: Ajustar headers según backend
|
|
4. **app/login/LoginForm.tsx**: Ajustar payload y endpoint de login según backend
|
|
5. **Variables de entorno**: Reemplazar valores de ejemplo con valores reales
|
|
6. **Endpoints backend**: Verificar que coincidan con los del backend Spring Boot
|
|
|
|
## 🤝 Contribución
|
|
|
|
1. Crear una rama: `git checkout -b feature/nueva-funcionalidad`
|
|
2. Commit cambios: `git commit -am 'Agrega nueva funcionalidad'`
|
|
3. Push a la rama: `git push origin feature/nueva-funcionalidad`
|
|
4. 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. |