Saltar a contenido

Matriz de roles y permisos

Documento RUP — 2026-06-07

Define quién puede hacer cada acción en el sistema IslaBox. Esta matriz es la fuente única de verdad para autorización. Se referencia desde el backend (middleware de permisos), desde el frontend (ocultar/mostrar botones) y desde el contrato API (filtros de scope por token).


Roles del sistema

Rol Código Descripción
Usuario Final user Persona radicada en EE.UU. que se registra y opera la app móvil
Operador operator Personal interno de IslaBox que opera el backoffice (recibe paquetes, KYC, conciliaciones)
Administrador admin Personal interno con permisos de configuración del sistema (tarifas, políticas, catálogos)
Sysadmin sysadmin Personal técnico con acceso a logs, métricas y operaciones destructivas
Agencia Aliada (sistema) agency API externa que recibe webhooks de IslaBox y consulta estado de envíos
Stripe (sistema) stripe Pasarela de pago que recibe webhooks de confirmación de cobro

Modelo de datos

El rol vive en users.role (enum) y los permisos granulares se derivan de un mapa estático en backend (core/permissions.py). Para el MVP no se requiere una tabla permissions + role_permissions; se valida en código. Si en el futuro se necesita mayor granularidad, se introduce el modelo RBAC completo.


Matriz de acciones

Leyenda: ✅ Permitido · ⚠️ Permitido con restricción · ❌ Prohibido · 🔵 Solo lectura

Autenticación y perfil

Acción user operator admin sysadmin agency stripe
Crear cuenta propia
Iniciar sesión
Editar perfil propio
Ver perfil de otro usuario ⚠️ (solo si es su usuario asignado)
Cambiar rol de un usuario
Desactivar cuenta

Casillero y dirección

Acción user operator admin sysadmin agency stripe
Ver su propia dirección del casillero ✅ (cualquiera)
Ver dirección de otro usuario ⚠️ (solo el user_id que les compete)
Modificar dirección del casillero

Prealerta (reporte de compra)

Acción user operator admin sysadmin agency stripe
Crear prealerta
Ver sus prealertas
Ver prealertas de todos
Editar prealerta propia ✅ (solo borrador, reportada_sin_tracking, requiere_correccion)
Cancelar prealerta propia
Adjuntar foto de la orden

Paquetes físicos (recepción en almacén)

Acción user operator admin sysadmin agency stripe
Ver paquete propio
Ver paquete cualquiera
Recibir paquete físico (peso, dimensiones, fotos)
Conciliar paquete sin identificar
Cambiar estado logístico manualmente ✅ (cualquiera)
Escanear código de barras/QR

KYC

Acción user operator admin sysadmin agency stripe
Cargar documentos KYC propios
Ver su propio estado KYC
Ver documentos KYC de cualquier usuario ⚠️ (datos enmascarados, solo para revisión)
Aprobar KYC
Rechazar KYC (con motivo)
Solicitar más información

Consolidación

Acción user operator admin sysadmin agency stripe
Crear consolidación ✅ (si KYC aprobado)
Consolidar manualmente (operador)
Ver sus consolidaciones
Ver cualquier consolidación
Cancelar consolidación propia ✅ (si borrador, cotizada, pendiente_pago)

Cotización y pago

Acción user operator admin sysadmin agency stripe
Generar cotización ❌ (la dispara el sistema al consolidar) ✅ (manual)
Ver cotización propia
Aprobar cotización
Pagar envío (MVP: registro manual) ✅ (registra el pago del usuario)
Pagar envío online (Stripe) ✅ (solo cuando esté integrado)
Registrar pago manual
Reembolsar
Webhook de Stripe confirma pago ✅ (es el único que puede confirmar)

Despacho y envío

Acción user operator admin sysadmin agency stripe
Ver su envío ⚠️ (solo los que la agencia transporta)
Confirmar despacho (marcar como despachado_desde_almacen) ⚠️ (vía webhook POST /webhooks/agency)
Actualizar estado de envío en tránsito ✅ (vía webhook)

Servicios adicionales

Acción user operator admin sysadmin agency stripe
Solicitar inspección / reempaque / devolución
Cancelar servicio propio (si no está en proceso)
Cargar evidencia (fotos, videos) del servicio
Aprobar costo de servicio adicional

Incidencias y reclamos

Acción user operator admin sysadmin agency stripe
Abrir incidencia sobre su paquete
Ver sus incidencias
Ver cualquier incidencia
Responder a incidencia (mensaje) ✅ (solo sobre las suyas)
Cambiar estado de incidencia
Cerrar incidencia con resolución
Iniciar reembolso por incidencia ⚠️ (escala a admin)

Notificaciones

Acción user operator admin sysadmin agency stripe
Ver sus notificaciones
Marcar notificación como leída
Configurar preferencias
Disparar notificación push al usuario ✅ (alertas operativas)

Administración y configuración

Acción user operator admin sysadmin agency stripe
Configurar días gratis y costo de almacenaje
Configurar tarifas de envío (barco/avión)
Configurar catálogo de categorías aduaneras
Ver logs de auditoría
Ejecutar operaciones destructivas (migraciones, reset)
Ver métricas y dashboards internos
Gestionar personal (alta/baja de operadores)

Reportes administrativos

Acción user operator admin sysadmin agency stripe
Reporte diario de paquetes recibidos
Reporte de ingresos por período
Reporte de incidencias abiertas/cerradas
Reporte de consolidados pendientes
Exportar reportes a CSV/PDF

Reglas derivadas de la matriz

Estas reglas se numeran con RN- y se referencian desde el código. Ver reglas-negocio.md para el catálogo completo.

ID Regla
RN-RBAC-001 Toda acción sobre un recurso que no es propio requiere scope admin o superior, salvo las acciones marcadas con ⚠️.
RN-RBAC-002 Los webhooks externos (agency, stripe) solo pueden usar los endpoints listados en stack/api-contract.md con el scope correspondiente.
RN-RBAC-003 Toda acción queda registrada en audit_logs con user_id, action, resource_type, resource_id, timestamp, ip, result (success/forbidden).
RN-RBAC-004 Los endpoints de admin (/api/v1/admin/*) rechazan requests sin scope admin o sysadmin.
RN-RBAC-005 El sysadmin es el único que puede ejecutar operaciones destructivas (DROP, TRUNCATE, FORCE_DELETE). Toda operación de sysadmin requiere segundo factor (TOTP).

Cómo aplicar esta matriz

Backend (Django + FastAPI)

# core/permissions.py
PERMISSIONS = {
    ("user", "package", "read", "own"): True,
    ("user", "package", "read", "any"): False,
    ("operator", "package", "read", "any"): True,
    ("operator", "package", "update", "any"): True,
    ("admin", "tariff", "update", "any"): True,
    # ...
}

def check_permission(role, resource, action, scope) -> bool:
    return PERMISSIONS.get((role, resource, action, scope), False)

Frontend (Android Kotlin)

// ui/permissions/Can.kt
@Composable
fun Can(action: String, resource: String) {
    val role = CurrentUser.role
    val visible = PermissionMap.get(role)?.get("$resource:$action") == true
    if (!visible) {
        // Ocultar botón o deshabilitar
    }
}

Contrato API

Ver api-contract.md — cada endpoint declara su permiso requerido, ej:

- path: /api/v1/admin/storage-policy
  method: PATCH
  permission: admin
  audit: true