Consola web y Web Push
La consola del navegador está en https://remote.ivjn.us/console/. Admite registro con verificación de correo, inicio de sesión con cuenta y contraseña o token de operador, dispositivos por espacio de trabajo, comandos con salida en directo, una PTY xterm, capturas/pulsaciones/navegación/entrada de texto de Android, métricas, registros de auditoría, creación y eliminación de dispositivos y notificaciones voluntarias. Las cuentas de solo lectura no pueden ejecutar comandos ni ver pantallas Android. Los dispositivos desconectados siguen visibles.
Los dispositivos que anuncian ubus muestran una pestaña ubus con objeto, método y parámetros de objeto JSON opcionales (vacío envía null). Las llamadas usan sesiones cifradas y requieren un dispositivo habilitado, en línea y permisos de operación. Cancelar termina la espera, pero no revierte métodos ya ejecutados. Cambiar de dispositivo o perder permisos borra las llamadas pendientes y los resultados.
El registro crea un espacio de trabajo independiente. Antes de iniciar sesión se debe verificar el correo con su código de ocho dígitos. La consola permite reenviar códigos y volver a la verificación tras recargar. Exchange necesita SMTP configurado: SMTP_HOST, SMTP_PORT, SMTP_FROM y los ajustes de autenticación y seguridad de .env.example. Sin un servicio de correo disponible, el registro muestra un error en lugar de omitir la verificación.
Las credenciales permanecen en la memoria de la página. Al recargar hay que iniciar sesión de nuevo. Cerrar sesión cierra las sesiones activas, intenta eliminar la suscripción push del navegador y revoca las sesiones de acceso por contraseña. Los tokens principales de operador conservan su duración habitual. Al pulsar una notificación, se enfoca una consola abierta sin recargar sus credenciales.
Compilar y servir
cd website/console
npm ci
npm test
npm run build
Copia dist/ al directorio console/ del sitio. Mantén website/assets/ disponible en /assets/ para las fuentes y la marca compartidas. Sirve index.html, sw.js y el manifiesto con revalidación/no-cache. Los recursos con hash pueden almacenarse con caché inmutable. No almacenes en caché /api/* ni /ws/*.
La consola utiliza /api/* y /ws/browser del mismo origen. Configura el proxy inverso hacia Exchange conservando Host y permitiendo la actualización a WebSocket. No elimines los prefijos /api ni /ws. El servidor de desarrollo Vite redirige API/WS a 127.0.0.1:18082. Rust Exchange permite por defecto acceso del navegador desde el mismo origen. Configure orígenes exactos con REMOTE_CORS_ORIGINS; solo un * explícito permite todos. Worker utiliza CORS_ORIGINS y sus propios valores predeterminados. La autenticación Bearer y los tickets WebSocket de un solo uso siguen siendo obligatorios; no se habilitan cookies entre orígenes.
La autenticación del navegador usa POST /api/ws-ticket con autorización Bearer, seguido de GET /ws/browser y una primera trama JSON {"ticket":"..."}. Los tickets caducan en 30 segundos, son de un solo uso y, al consumirse, vuelven a comprobar que el operador esté habilitado y sus credenciales sean válidas. Las credenciales duraderas nunca se incluyen en las URL de WebSocket. Los clientes nativos siguen usando /ws/operator.
Todas las operaciones de dispositivo utilizan sesiones WebSocket selladas nativas. HTTP ofrece autenticación, metadatos de dispositivos, directorios de claves y autorizaciones y administración de sesiones del servicio de retransmisión; consulte API HTTP para operaciones del agente.
Activar Web Push
Define ambas variables en el entorno de Exchange; omitir las dos desactiva push:
WEB_PUSH_VAPID_PRIVATE_KEY=<base64url-unpadded-32-byte-P256-private-key>
WEB_PUSH_VAPID_SUBJECT=https://remote.ivjn.us
Genera una clave privada con python scripts/generate-vapid-key.py. Guárdala fuera de Git en un archivo de entorno con acceso restringido, mantenla estable entre reinicios y realiza una copia de seguridad segura. La clave pública se deriva automáticamente. Si cambias la clave, los navegadores deben suscribirse de nuevo.
WEB_PUSH_ALLOWED_ORIGINS contiene de forma predeterminada los orígenes de confianza exactos https://fcm.googleapis.com,https://updates.push.services.mozilla.com,https://web.push.apple.com. Añade otro proveedor solo después de verificar su origen push HTTPS. Los endpoints proporcionados por clientes no pueden ampliar esta lista. Nunca se siguen redirecciones.
Rutas autenticadas:
| Método y ruta | Finalidad |
|---|---|
GET /api/webpush/config |
Estado de activación y clave pública del servidor de aplicaciones |
GET/POST /api/webpush/subscriptions |
Listar los metadatos propios o registrar/actualizar una suscripción |
DELETE /api/webpush/subscriptions/{id} |
Eliminar una suscripción propia |
POST /api/webpush/test |
Encolar una prueba visible para las suscripciones del solicitante |
POST /api/webpush/messages |
Enviar a su cuenta o, como administrador, a otra cuenta del mismo espacio |
POST /api/webpush/devices/{id}/messages |
Notificar a administradores suscritos que gestionan el dispositivo autenticado |
Las suscripciones utilizan PushSubscription.toJSON() del navegador, application_server_key y triggers. triggers admite como máximo un objeto online y otro offline. Cada objeto contiene kind, tick_count, con valor predeterminado 3 y rango 1–100, y device_ids opcional. offline notifica tras tick_count fallos consecutivos; online, tras tick_count éxitos consecutivos. device_ids puede ser un ID de dispositivo como cadena, una lista de IDs, o estar omitido/ser null para abarcar todo el espacio de trabajo. Un array triggers vacío suscribe el navegador sin avisos automáticos de conexión/desconexión. No se aceptan missed_count ni success_count. Los mensajes usan operator_id opcional y notification con title, body, y los campos opcionales url, una ruta relativa del mismo origen, y tag. /webpush/ es un cliente de referencia mínimo; la consola de producción utiliza su propio worker limitado a /console/.
La migración 0005_web_push.sql añade suscripciones y una bandeja de salida persistente. 0008_online_offline_triggers.sql traslada las notificaciones de dispositivos a triggers y elimina missed_count / success_count. 202 significa encolado, sin garantizar entrega ni visualización. Los trabajos caducan a los 15 minutos. Los errores de red y las respuestas 408, 429 y 5xx se reintentan hasta cinco veces; 404/410 eliminan la revisión correspondiente de la suscripción. Un arrendamiento de 90 segundos permite recuperar el trabajo pendiente tras un fallo del worker. La entrega es al menos una vez y la visualización depende del proveedor, los permisos y la política del sistema operativo. Bajo sobrecarga, los eventos de dispositivos previos al encolado persistente se procesan según disponibilidad; los ya encolados sobreviven a reinicios. Límites: 20 suscripciones por cuenta, 32 mensajes encolados por suscripción y 30 modificaciones por minuto y cuenta.
iOS/iPadOS puede exigir añadir la consola a la pantalla de inicio antes de activar las notificaciones. La accesibilidad del servicio Push del navegador es independiente de la conexión a Exchange.
Validación
Ejecuta cargo test --workspace, cargo clippy --workspace --all-targets -- -D warnings y las pruebas y compilación npm de la consola. Para la integración PostgreSQL/HTTPS, instala psycopg[binary], define WEB_PUSH_TEST_ADMIN_URL con una conexión PostgreSQL de prueba con permiso CREATE DATABASE y ejecuta python scripts/test-webpush.py. La prueba crea y elimina una base de datos desechable; no utilices un rol con privilegios que no quieras poner a su disposición.
Enviar desde todos los clientes
Web Console incluye un formulario en las notificaciones del navegador. Los ajustes de Console móvil ofrecen envío Web Push, pruebas y un enlace a Web Console. Los ajustes locales del Agent de escritorio, del Agent Android y de la extensión del navegador envían con las credenciales del dispositivo. Los Agents sin interfaz/OpenWrt utilizan el siguiente comando. Active las notificaciones en Web Console/PWA para recibirlas; no se añaden receptores nativos FCM/APNs.
remote-cli webpush status
remote-cli webpush subscriptions
remote-cli webpush test
remote-cli webpush send --title "Backup ready" --body "Completed"
remote-cli webpush send --operator-id ACCOUNT_UUID --title "Notice" --body "Hello"
remote-agent --config /path/to/config.json webpush --title "Device ready" --body "Completed"
{"notification":{"title":"Backup ready","body":"Completed","url":"/console/","device_id":"edge-1"}}
POST /api/webpush/messages utiliza autenticación Bearer del operador. Si se omite operator_id, se envía a su cuenta; otra cuenta requiere permisos de administrador y pertenecer al mismo espacio. El JSON anterior también funciona con remote-cli webpush send --json-file message.json. Los activadores de estado vacíos desactivan avisos automáticos de conexión/desconexión y mantienen los mensajes generales.
POST /api/webpush/devices/{id}/messages utiliza el token Bearer del dispositivo y acepta directamente un objeto de notificación (title, body, tag opcional). Solo reciben las suscripciones activas de administradores habilitados que gestionan ese dispositivo. El servidor fija device_id, event=device.message, occurred_at y /console/; el remitente no elige cuenta ni suplanta otro dispositivo. Los dispositivos comparten 30 solicitudes/minuto/espacio, con un máximo de 256 suscripciones por envío. Siguen vigentes los límites de cuentas y colas. Sin destinatarios activos se devuelve 202 {"queued":0}; queued cuenta suscripciones, no entregas.