# PROMPT SPRINT 1.1 — Auth + RBAC + Audit

> **Para Ricci:** Pegá este prompt completo en una sesión nueva de Claude Code (no en la sesión vieja de Fase 0). Asegurate de estar parado en `/c/proyectos/innovium`.

---

Hola Claude. Soy Ricci de Crono Systems. Continuamos con **Sprint 1.1** del proyecto Innovium.

## Estado actual

Fase 0 está completa (9 commits en `main`). El proyecto tiene estructura, Tailwind compilando, welcome page funcional. Lo confirmás leyendo `CLAUDE.md` y `git log --oneline`.

## Antes de tocar nada — lectura obligatoria

Leé en este orden:

1. `CLAUDE.md` — contexto del proyecto
2. `docs/ARQUITECTURA.md` — decisiones técnicas
3. `docs/sprint-1-1/SCHEMA_SISTEMA.md` — el schema explicado en castellano (te lo agrego al repo, copialo de los archivos que te pasa Ricci)
4. `docs/sprint-1-1/CRITERIOS_ACEPTACION_1_1.md` — qué tiene que pasar para considerar el sprint cerrado
5. `design-kit/mockups/v2_login.svg` — el login que tenés que replicar exacto
6. `design-kit/DESIGN_SYSTEM.md` sección 8.1 (botones), 8.2 (inputs), 9.1 (login layout)

**No empieces a crear archivos hasta haber leído todo lo anterior.**

## Alcance del sprint

Implementar las 8 tablas del schema de sistema + login funcional + RBAC básico + audit log.

**Específicamente entran:**

1. Migrations versionadas para las 8 tablas en `database/migrations/tenant/`
2. Comando CLI `innovium migrate:tenant <slug>` que aplica las migraciones a una BD tenant
3. Comando CLI `innovium db:create-demo` que crea la BD `innovium_demo` localmente y aplica migrations + seed
4. Seeders PHP que insertan: 6 roles, ~25 permisos, mapeo role-permissions, 6 usuarios demo (passwords con `password_hash` Argon2id), user_roles
5. `app/Core/Auth.php` — login, logout, currentUser(), check session
6. `app/Core/Csrf.php` — token por sesión, validación en POST/PUT/DELETE
7. `app/Core/AuditLog.php` — `record($accion, $entidad, $datos)`
8. `app/Middleware/AuthMiddleware.php` — bloquea rutas que requieren login
9. `app/Middleware/CsrfMiddleware.php`
10. `app/Middleware/RbacMiddleware.php` — chequea permisos
11. `app/Models/User.php`, `Role.php`, `Permission.php`, `Session.php`, `AuditLog.php`
12. `app/Controllers/AuthController.php` — `showLogin()`, `login()`, `logout()`
13. `app/Controllers/DashboardController.php` — `index()` placeholder con saludo + rol + botón logout
14. `app/Views/auth/login.php` — replicar `v2_login.svg` con Tailwind
15. `app/Views/dashboard/index.php` — placeholder simple pero con tipografía y paleta correcta
16. `app/Views/layouts/app.php` — layout base para vistas autenticadas
17. Rutas en el Router: `GET /login`, `POST /login`, `POST /logout`, `GET /dashboard`, `GET /admin/usuarios` (solo placeholder, sirve para test de RBAC)
18. Tests en `tests/`:
    - `tests/unit/AuthTest.php` — login con credenciales válidas/inválidas
    - `tests/unit/CsrfTest.php` — token genera/valida
    - `tests/unit/RbacTest.php` — permisos por rol
    - `tests/unit/AuditLogTest.php` — registra acciones

**Específicamente NO entran (Sprints siguientes):**

- TenantResolver multi-subdominio → Sprint 1.2
- Comando `tenant:create` → Sprint 1.2
- Recuperación de password por email → Sprint 2.x
- Lockout por intentos fallidos → Sprint 2.x
- Pantalla de gestión de usuarios completa → solo placeholder en este sprint

## Decisiones de diseño ya tomadas

- **Sesiones en BD** (no archivos). Tabla `sessions` con session_id de 64 chars random.
- **Argon2id** para password hashing: `password_hash($p, PASSWORD_ARGON2ID, ['memory_cost' => 65536, 'time_cost' => 4, 'threads' => 1])`.
- **CSRF token por sesión** (no por request). Se regenera al login.
- **Audit log INMUTABLE**: solo INSERT, nunca UPDATE/DELETE. Constraint físico no, convención clara.
- **RBAC por slugs**: `Auth::can('contratos.crear')` chequea contra `role_permissions`.
- **Foreign keys con `ON DELETE RESTRICT`** por defecto. Excepciones documentadas en `SCHEMA_SISTEMA.md`.
- **Soft delete** (`eliminado_en DATETIME NULL`) en `users`. Audit log NUNCA se borra.
- **Sin lockout en este sprint** — pero `audit_log` registra `user.login_fallido` para que en Sprint 2.x se pueda implementar lockout sobre esos datos.
- **Email genérico en errores de login**: nunca decir "el email no existe" ni "password incorrecta", siempre "credenciales inválidas". Previene enumeration attacks.
- **CSRF excepción**: el endpoint `POST /login` SÍ requiere CSRF (token generado al cargar la pantalla de login).

## Decisiones que tomar y consultarme antes de avanzar

Si te encontrás con alguna duda como:

- ¿Qué hacer si una migración falla a mitad? (idempotencia)
- ¿Cómo manejar timezone en `DATETIME`?
- ¿Las sesiones expiran por inactividad o solo por TTL absoluto?
- ¿Qué cookie attributes (`SameSite`, `Secure`, `HttpOnly`)?

→ Preguntá antes de decidir.

## Convenciones recordatorias

- PSR-4: `App\Core\`, `App\Controllers\`, etc.
- Tablas: `snake_case` plural (`users`, `audit_log`, `user_roles`)
- Columnas: `snake_case`
- Timestamps: `creado_en`, `actualizado_en`, `eliminado_en` (NO `created_at`)
- PHP: clases PascalCase, métodos camelCase
- Commits en español, atómicos por tarea, prefijo `feat(modulo):`, `chore:`, `style:`, `test:`, `docs:`

## Plan de commits sugerido

Como en Fase 0, atómicos:

1. `feat(db): migraciones de schema sistema (8 tablas)`
2. `feat(cli): comandos migrate:tenant y db:create-demo`
3. `feat(db): seeds de roles, permisos y usuarios demo`
4. `feat(core): Auth, Csrf, AuditLog`
5. `feat(middleware): AuthMiddleware, CsrfMiddleware, RbacMiddleware`
6. `feat(models): User, Role, Permission, Session`
7. `feat(controllers): AuthController, DashboardController`
8. `style(views): login replicando v2_login.svg`
9. `style(views): layout app + dashboard placeholder`
10. `test: tests de Auth, Csrf, Rbac, AuditLog`
11. `chore: sprint 1.1 cerrado`

## Cómo trabajar conmigo

1. Empezás leyendo los archivos de la sección "lectura obligatoria"
2. **Confirmá 5 puntos antes de tocar archivos:**
   - ¿Leíste el schema completo y entendiste las 8 tablas?
   - ¿Confirmas usar Argon2id para passwords con los parámetros indicados?
   - ¿Confirmas mensaje genérico "credenciales inválidas" para errores de login?
   - ¿Confirmas commits atómicos según el plan sugerido?
   - ¿Tenés clara la diferencia entre Sprint 1.1 (lo que hacemos ahora) y Sprint 1.2 (TenantResolver, viene después)?
3. Después de mi confirmación, arrancás con la primera migración
4. **Después de cada commit grande, mostrame qué hiciste y esperá mi OK antes de seguir**
5. Si tenés dudas técnicas, **preguntá** antes de inventar
6. Cuando termines todos los criterios técnicos del sprint, decímelo y yo levanto el server, valido en el navegador, y tomo screenshot para mandarle a Vene en el chat principal

¡Vamos! 🚀
