Appearance
Arquitectura de Respaldos, Gobernanza y Trazabilidad (Fase 4)
1. Almacenamiento y Ciclo de Vida de Respaldos Centrales (H4)
1.1 Estructura en Supabase
Los respaldos centrales de la plataforma se almacenan en la tabla dedicada central_backups en PostgreSQL / Supabase con la siguiente definición:
sql
CREATE TABLE IF NOT EXISTS central_backups (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
type TEXT NOT NULL CHECK (type IN ('manual', 'daily', 'auto')),
description TEXT,
condo_count INT NOT NULL DEFAULT 0,
data JSONB NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);- Almacenamiento JSONB: Todo el ecosistema (condominios registrados, unidades, gastos, alícuotas, adeudos, cobros, proveedores y configuración) queda consolidado en la columna
dataen formatoJSONB, lo que permite consultas atómicas y verificación de integridad sin desnormalizar la estructura. - Seguridad por RLS: La tabla cuenta con políticas de Row Level Security (RLS) que limitan la lectura (
SELECT), inserción (INSERT) y eliminación (DELETE) exclusivamente al rol Superadmin validado a través de la función de seguridad:sqlNingún administrador de condominio, miembro de directorio ni residente tiene visibilidad ni acceso sobreCREATE POLICY "Solo superadmin gestiona central_backups" ON central_backups FOR ALL USING ( EXISTS ( SELECT 1 FROM app_users WHERE email = auth.jwt() ->> 'email' AND role = 'admin' AND condo_id IS NULL ) );central_backups.
1.2 Formatos de Descarga (B3.1 ZIP Legible)
El panel de Superadmin (CentralBackupsModal.tsx) provee dos mecanismos de descarga:
- ZIP Multi-Condominio Legible (Recomendado):
- Utiliza la librería
jszipdirectamente en el navegador del cliente. - Desempaqueta el JSONB consolidado y crea archivos estructurados con nombres legibles y sanitizados:
_manifest.json: Metadatos completos del respaldo, fecha ISO, correo del operador/creador, versión de la plataforma y listado de condominios incluidos con su cantidad de unidades.condos/[nombre_sanitizado]_[id_corto].json: Archivo individual para cada condominio con su perfil institucional, viviendas, finanzas, cobros, egresos y configuración.
- Facilita la auditoría individual, apertura directa en editores de texto y la restauración selectiva de un único condominio sin alterar el resto del ecosistema.
- Utiliza la librería
- JSON Consolidado:
- Descarga directa del objeto completo para archivo frío o restauración técnica global.
1.3 Política de Retención y Purga Automática Integrada (B3.3)
Para garantizar la sostenibilidad del almacenamiento en Supabase sin intervención manual ni pérdida de copias históricas clave:
- Respaldos Manuales (
manual): Se conservan de forma permanente e inviolable. No son afectados por las rutinas de purga automática; solo el superadmin puede eliminarlos mediante el borrado selectivo. - Respaldos Diarios Automáticos (
daily_automated): Se retienen automáticamente hasta 30 respaldos diarios. - Purga Automática en Tiempo de Generación: La función
generateCentralBackupencentralBackupService.tsejecuta automáticamente la política de retención tras guardar exitosamente cualquier respaldo, eliminando los registros de tipodaily_automatedmás antiguos que excedan el límite de 30 copias.
1.4 Borrado Selectivo y Masivo de Respaldos (B3.2)
El modal CentralBackupsModal.tsx incorpora:
- Casillas de verificación para selección individual y masiva ("Seleccionar todos").
- Botón de eliminación en lote con modal de confirmación destructiva.
- Eliminación directa individual por fila.
- Validación de políticas RLS en Supabase para asegurar que solo el superadmin autenticado pueda ejecutar la eliminación.
2. Gobernanza y Auditoría Real en el Panel de Control (B2.1, B2.2, B2.3)
2.1 Aislamiento de Sesión del Superadmin (B2.1)
- Al ingresar al Panel de Control (Cockpit), ningún condominio aparece marcado como activo en sesión.
- El estado "Activo en sesión" aplica única y exclusivamente cuando el superadmin decide deliberadamente ingresar como operador a un condominio específico (
operatingCondoId). - Al regresar al Cockpit mediante el selector o botón de retorno, el estado de operador se reinicializa a
null, garantizando una vista neutral de supervisión. - Carga Garantizada: Los condominios se sincronizan desde Supabase antes de renderizar la tabla para evitar estados intermedios o cascarones vacíos.
2.2 Auditoría Real desde la Nube (B2.2)
La columna de actividad en el Cockpit consulta directamente las fuentes de verdad en la nube vía supabaseFetchCondosAudit():
- Fecha de Creación: Proviene de
condos.created_atregistrado en la base de datos de Supabase. - Último Acceso: Obtenido de
licenses.last_access_at(actualizado en cada inicio de sesión de los administradores) yapp_users.updated_at. - Trazabilidad de Acceso: Muestra la fecha, hora exacta y el correo electrónico del último usuario que ingresó al condominio.
- Se elimina cualquier dependencia de marcas temporales locales en
localStorage.
2.3 Gestión de Credenciales del Superadmin (B2.3)
- En la barra superior del Cockpit se provee acceso directo al cambio de contraseña del superadmin (
ChangePasswordModal), permitiendo actualizar las credenciales de la cuenta sin necesidad de ingresar al perfil de un condominio particular.
3. Arquitectura del Historial Local "Local-First" (G2)
2.1 Auditoría Inmutable
Cada operación crítica realizada por el superadmin queda registrada en el registro de auditoría (action_logs / supabaseAuditLog.ts):
- Creación de licencia y condominio: Registra el correo del operador, condominio destino, rol asignado y parámetros iniciales.
- Suspensión / Reactivación de licencia: Documenta el timestamp exacto, motivo y correo del administrador afectado.
- Desvinculación / Eliminación de condominio: Genera un evento crítico con detalle del conteo de dependencias eliminadas (cuentas de residentes/directorio) y licencias desvinculadas.
- Generación y Descarga de Respaldos: Deja constancia de la extracción de datos por parte del superadmin.
2.2 Principio de Menor Privilegio y Aislamiento Multitenant
- El superadmin tiene privilegios de plataforma (
condo_id IS NULL), lo que le permite operar el Cockpit y supervisar licencias sin estar acoplado a un condominio particular. - Cuando el superadmin ingresa a auditar o gestionar un condominio específico, lo hace en "Modo Operador", dejando constancia en auditoría de la sesión de soporte.
- Los administradores de condominio ordinarios tienen su licencia y permisos estrictamente acotados a su
condo_id, impidiendo cualquier visibilidad horizontal entre condominios.
3. Arquitectura del Historial Local "Local-First" (G2)
3.1 Justificación del Diseño Local-First
- El sistema de "Deshacer/Rehacer" y puntos de restauración rápidos dentro de un condominio opera de forma local-first en el navegador del usuario activo (
localStoragey memoria). - Prevención de Colisiones: En entornos multi-usuario donde un administrador y un asistente contable pudieran operar simultáneamente, un historial de deshacer sincronizado en tiempo real por websockets generaría colisiones destructivas (ej. el Administrador revierte una acción que el Asistente estaba editando en otro formulario).
- Acceso Rápido: Proporciona reversiones instantáneas con latencia cero ante equivocaciones de digitación o importaciones erróneas.
- Puntos Críticos: Para persistencia permanente y resguardo formal, el sistema utiliza la sincronización completa a Supabase y los Respaldos Centrales del Superadmin.
4. Reorganización de Configuración y Acceso a Módulos (B4.1)
4.1 Principio de Acceso de Referencia
- En
SettingsView.tsx, se implementó la sección "Herramientas Administrativas y Nube", complementada con un acceso rápido en la cuadrícula de módulos. - Acceso no duplicativo: Las herramientas administrativas disponibles en el cajón lateral derecho (Invitaciones, Despacho masivo de cobranza, Sincronización en la nube, Historial inmutable de auditoría y, para superadministradores, Licencias y Respaldos centrales) están ahora referenciadas directamente dentro de la vista de Configuración.
- Ambas rutas invocan exactamente los mismos controladores de estado y modales en
App.tsx, garantizando que el usuario tenga un punto focal claro en Configuración sin desmantelar la agilidad del acceso rápido desde el Navbar o panel lateral.
5. Hoja de Ruta Visual: Modo Oscuro (B5.1)
5.1 Registro de Mejora Visual Futura
- Estado Actual: La plataforma prioriza la estabilidad, exactitud contable, gobernanza y aislamiento de datos de acuerdo con los requerimientos prioritarios de la Fase 5-B.
- Planificación: La implementación del Modo Oscuro en todas las vistas operativas (Directorio, Egresos, Pagos, Presupuesto, Avisos de Cobro) queda formalmente registrada y clasificada como una mejora visual futura.
- Criterios de Implementación Futura:
- Respeto estricto a las directrices de diseño (contraste WCAG AA 4.5:1, tonalidades neutras sofisticadas sin saturaciones arbitrarias ni neones).
- Preservación de la legibilidad de documentos formales (los reportes imprimibles y avisos PDF deben mantenerse en fondos blancos de alta fidelidad independientemente del tema de la interfaz).
6. Regla de Identidad y Gobernanza: Los Superadmins son Intocables
6.1 Principio Fundamental de Intocabilidad del Superadmin
Los SUPERADMINS (los socios del producto designados de por vida, itecelecuador@gmail.com y zjuanf5@gmail.com, así como cualquier usuario en app_users con role = 'admin' y condo_id IS NULL) poseen un alcance global permanente e inviolable:
- (a) El Directorio NO genera contextos/licencias para superadmins: Las apariciones de un superadmin en viviendas o unidades residenciales (
housing_units, tanto enemailcomo encontacts[]) son SOLO contactos descriptivos (ej. si el socio es propietario o contacto de un departamento en un edificio del piloto). El sistema jamás compila contextos de condominio para ellos a partir del Directorio. - (b) El sistema de licencias JAMÁS crea licencias para superadmins: El módulo de licencias (
LicensesPanelModal.tsx,licenseService.ts) bloquea tajantemente la creación manual o aprobación rápida de licencias asignadas a correos de superadmin con rechazo explícito y mensaje informativo. - (c) El superadmin opera con SU alcance global — sin contextos de condominio: En
resolveUserRole()y en la función de base de datosget_user_contexts(), si el usuario es superadmin, se devuelve de inmediato su alcance global (role: 'admin',condoId: null,isSuperadmin: true,availableContexts: []). Su sesión jamás se pisa ni se reduce a un condominio individual, y nunca se le presenta el selector multi-contexto para su inicio de sesión global. - (d) Los 2 superadmins designados son de por vida: Representan a los socios del producto; su identidad y rol global están protegidos tanto en el cliente como en la base de datos de Supabase / PostgreSQL.
- (e) El sistema SÍ genera perfiles de residente o miembro del directorio para sus vistas residenciales: Las etiquetas y marcas en viviendas permiten emitir estados de cuenta y comunicaciones al superadmin en su calidad de contacto/propietario, pero la etiqueta de "Es Administrador" en el Directorio es meramente referencial y descriptiva.
6.2 Pregunta Abierta de Negocio (Gobernanza)
- Pregunta: ¿Debe permitirse a un superadmin alternar hacia contextos adicionales de condominio (por ejemplo, el socio actuando como superadmin global y a la vez como administrador activo o residente de SU edificio propio del piloto) mediante un conmutador de contexto explícito?
- Decisión Vigente: MUTUAMENTE EXCLUYENTES. Mientras la operación real no lo exija formalmente, el superadmin opera exclusivamente con su alcance global puro (
condo_id IS NULL), pudiendo supervisar o gestionar cualquier condominio mediante el "Modo Operador" desde el Cockpit. Sus apariciones en el Directorio son puramente descriptivas y no alteran su sesión global.
6.3 La Etiqueta "Es Administrador del Condominio" en Viviendas es Meramente Informativa
- Principio: La marcación "Es Administrador" (
isAdmin/is_admin) en una vivienda o contacto del Directorio tiene carácter ESTRICTAMENTE INFORMATIVO Y REFERENCIAL (para señalar en el listado físico del edificio quién funge de administrador). - Prohibición de rol de plataforma: Dicha marcación JAMÁS otorga el rol de plataforma
'admin'ni genera permisos administrativos ni mucho menos convierte al usuario en superadministrador. - Roles válidos desde el Directorio: Desde
housing_unitsel sistema ÚNICAMENTE confiere acceso con rol'committee'(si está marcado como miembro del directorio) o'resident'(rol residencial por defecto). - Origen exclusivo del rol
'admin': Los administradores de condominio se crean y habilitan EXCLUSIVAMENTE a través del sistema de Licencias (licenses/createLicense) oapp_usersoficiales, garantizando la regla 1 licencia = 1 condominio = 1 admin.