# Sprint 2.5 — RBAC + Studio mínimo + Flash Console > Sprint nuevo añadido a petición del Super Admin (Álvaro). Cubre dos > requisitos que no estaban en el brief original: > > 1. Sistema de 4 roles (Super Admin / Engineer / Owner / User) con > capabilities específicas y verificación de doble factor para > operaciones críticas. > 2. Una "mini consola de Arduino" dentro del Studio que permita al > Engineer flashear firmware ESP32 con aprobación del Super Admin. ## Objetivo Dejar Studio bootable con login por PIN, RBAC funcional, y la Flash Console operativa. Engineer puede flashear firmware mostrando el PIN del Super Admin en una ventana de confirmación. Super Admin (solo Álvaro) flashea directamente sin segundo factor. ## Roles y capabilities | Capability | Super Admin | Engineer | Owner | User | |---|---|---|---|---| | Editar código Python del proyecto (arautopilot, tools, scripts) | ✅ | ❌ | ❌ | ❌ | | Editar código C++ del firmware (firmware/**) | ✅ | ✅ (sólo en su sandbox) | ❌ | ❌ | | **Flashear firmware ESP32** | ✅ directo | ✅ con SA approval (2-of-N) | ❌ | ❌ | | Editar gains PID base (IP del integrator) | ✅ | ❌ | ❌ | ❌ | | Editar comisionado (rudder limits, calibración) | ✅ | ✅ | ❌ | ❌ | | Editar preferencias operativas (rumbos fav, alarm vol, perfil) | ✅ | ✅ | ✅ | ❌ | | Crear/gestionar Users del barco | ✅ | ❌ | ✅ | ❌ | | Engage/disengage piloto | ✅ | ✅ | ✅ | ✅ | | Leer telemetría | ✅ | ✅ | ✅ | ✅ | | Acknowledge alarmas | ✅ | ✅ | ✅ | ✅ | | Ver audit log completo | ✅ | ✅ | parcial (sólo su barco) | ❌ | ## Plan de implementación ### 1. RBAC core (`arautopilot/core/rbac.py`) - Enum `Role`: SUPER_ADMIN / ENGINEER / OWNER / USER - Enum `Capability`: cada acción gateable (FLASH_FIRMWARE, EDIT_BASE_GAINS, EDIT_COMMISSIONING, EDIT_OPERATIONAL, MANAGE_USERS, ENGAGE_PILOT, READ_TELEMETRY, ACK_ALARMS, VIEW_AUDIT_LOG_FULL) - Matriz inmutable `_CAPABILITIES_BY_ROLE: dict[Role, frozenset[Capability]]` - Función `requires_dual_auth(cap: Capability) -> bool`: True para FLASH_FIRMWARE cuando el actor es Engineer - `has(role, capability) -> bool` ### 2. User model (`arautopilot/core/user.py`) - Pydantic v2 `User`: user_id (UUID), display_name, role, pin_hash (argon2 o pbkdf2), created_at, last_login_at, active (bool) - `set_pin(plain) / verify_pin(plain) -> bool` con hashing seguro ### 3. Audit log (`arautopilot/core/audit.py`) - `AuditEvent`: timestamp UTC, user_id, action, target, outcome (success/denied/failed), reason, secondary_user_id (si dual-auth) - `AuditLog` con append-only file en JSONL - Cada permission check produce un evento ### 4. Studio mínimo (`arautopilot/studio/app.py`) - Reemplaza el stub Sprint 0 - PySide6 QApplication + login window - Main window con 3 áreas: sidebar (rol + user), main area (placeholder para project editor), toolbar (acciones gateadas por rol) - Login = elegir user de lista + PIN - Persistencia local (SQLite o JSON) de la lista de users ### 5. Flash Console (`arautopilot/studio/flash_console.py`) - Widget dentro del Studio (no app separada) - Lista puertos serie (vía pyserial) - Combobox de variant (esp32-dev / esp32-debug) - Botones: "Compile only", "Compile + Flash", "Open Serial Monitor" - Para Engineer: al pulsar Flash, abre modal "Esperando aprobación del Super Admin" con form de PIN del SA. El SA introduce su PIN (si está presente) o el operario llama por teléfono y SA dicta un OTP que el SA generó desde otro Studio. Por simplicidad MVP: campo de PIN del SA en el modal. - Bajo el capó: corre `pio run -t upload --upload-port COMx` y stream del output al widget - Serial monitor: thread aparte que lee `pio device monitor` ### 6. Tests - `test_rbac.py`: cada rol tiene exactamente las capabilities esperadas; intentos de escalada rechazados; dual-auth requerido para Engineer flash. - `test_user.py`: PIN hash, verificación correcta/incorrecta, no se puede deserializar un User sin pin_hash. - `test_audit.py`: append es atómico, lectura es ordenada por timestamp. ## Restricciones - No requiere hardware ESP32 conectado para que arranque el Studio. - La Flash Console **no funciona** sin board conectada (pero arranca, muestra "no boards found"). Funcionalidad real verificable cuando el usuario conecte hardware. - PIN del Super Admin se introduce en cada flash (no se cachea). Sí se puede cachear PIN del operario actual durante la sesión. - El binario flasheado por el Engineer debe ser uno compilado por el SA y firmado (futuro Sprint 8). Sprint 2.5 hace la versión simple: Engineer compila + flashea con PIN del SA. ## Verificación - `pytest` verde (objetivo: 145+ tests) - `python studio_main.py` abre la ventana de login sin errores - Login con un user dummy de demo (`demo_users.json`) funciona - Flash Console widget se renderiza (incluso sin board)