Skip to content

0052. Operator pasa de solo-lectura a operador de soporte

Estado

Aceptada

Contexto

El rol de sistema de plataforma Operator era, desde su creación (ADR-0048), solo-lectura en los 6 módulos del catálogo de plataforma (ver uniforme). En la práctica, un operador de soporte necesita poder actuar sobre un tenant (corregir datos de una organización, dar de alta o editar usuarios de esa organización) sin tener que pedirle ese trabajo a un Owner. Decisión de producto tomada el 2026-07-23.

Decisión

Matriz explícita por módulo en vez del ['ver'] uniforme (PLATFORM_DEFAULT_ROLE_PERMISSIONS.Operator, platform-rbac.constants.ts):

MóduloAccionesPor qué
organizacionesver, editarcorregir/activar-desactivar datos de una org
usuarios-tenantver, crear, editaraltas/ediciones de usuarios de un tenant
roles-tenantversolo lectura de roles de tenant
usuarios-plataformaversin escritura — no crea superadmins
roles-plataformaversin escritura — no amplía roles de plataforma, ni el propio
metricasverdashboard

(a) usuarios-plataforma/roles-plataforma quedan en solo ver — cierre explícito del vector de escalada

Es la parte no negociable de la decisión: si Operator pudiera crear usuarios de plataforma o editar la matriz de cualquier rol de plataforma (incluido el suyo propio), podría fabricarse permisos de Owner. Cubierto por test/platform-operator-role.e2e-spec.ts (403 en las 5 combinaciones de escritura sobre esos dos módulos).

(b) Backfill por migración explícita, no por el onModuleInit existente

PlatformPermissionsService.backfillDefaultPermissions() (el mecanismo que ya otorga defaults a los roles de sistema al agregar un módulo nuevo) es conservador a propósito: solo agrega los defaults de un módulo a un rol si ese rol no tiene aún ningún permiso de ese módulo — para no re-otorgar algo que un Owner haya quitado deliberadamente en un módulo ya conocido. Como los Operator ya sembrados tienen ver en organizaciones y usuarios-tenant desde que esos módulos existen, ese backfill de arranque saltearía por completo las acciones nuevas (editar, crear) — no las agregaría nunca.

Por eso el backfill de las bases ya sembradas va por una migración SQL dedicada (prisma/migrations/20260723180000_operator_soporte_permisos_backfill/), no por generalizar el mecanismo de arranque: es explícita, corre una sola vez, es idempotente (ON CONFLICT DO NOTHING sobre el índice único (roleId, moduleId, actionId)), solo agrega filas nuevas (no borra nada, no toca Owner ni roles custom) y no cambia el comportamiento conservador existente del onModuleInit para el resto de los módulos. Verificada con un test que baja manualmente un Operator a su perfil viejo (solo ver), corre el SQL de la migración dos veces (idempotencia) y confirma que converge al perfil nuevo.

Consecuencias

  • platform-rbac.constants.ts: PLATFORM_DEFAULT_ROLE_PERMISSIONS.Operator pasa de PLATFORM_MODULES.map(() => ['ver']) a la lista explícita por módulo de la tabla arriba.
  • Migración nueva 20260723180000_operator_soporte_permisos_backfill — solo INSERT condicional, sin cambios de schema.
  • Tests e2e nuevos: test/platform-operator-role.e2e-spec.ts (perfil exacto, invariante anti-escalada, idempotencia de la migración). Se ajustaron además dos tests preexistentes que usaban Operator como stand-in genérico de "rol sin el permiso X" (platform-organizations.e2e-spec.ts, dos casos de organizaciones:editar) — ya no es válido usar Operator para esos casos porque ahora sí tiene ese permiso; se reemplazó por un rol custom sin permisos. Y un test en platform-tenant-admin.e2e-spec.ts que documentaba el perfil viejo de Operator se actualizó al perfil nuevo.
  • camaroneras_platform/camaroneras_admin/camaroneras_mobile: sin cambios — la UI de plataforma renderiza el catálogo/matriz que devuelve el backend, no hardcodea el perfil de Operator.

Referencias

  • Tarea operator-permisos-soporte (2026-07-23).
  • ADR-0048 — RBAC de plataforma, define el mecanismo de backfill de onModuleInit cuyo límite motiva esta decisión.
  • ADR-0051 — introdujo los módulos usuarios-tenant/roles-tenant sobre los que ahora Operator gana escritura acotada.
  • camaroneras_backend/src/modules/platform/platform-rbac.constants.ts, platform-permissions.service.ts.
  • camaroneras_backend/prisma/migrations/20260723180000_operator_soporte_permisos_backfill/.
  • camaroneras_backend/test/platform-operator-role.e2e-spec.ts.
  • camaroneras_docs/plataforma/superadmin-flow.md (matriz documentada en la sección RBAC de plataforma).