Sealer y Organizer
Envío sellado (con sus límites reales) y organización con IA.
En esta página
Sealer: envío sellado#
El envío sellado permite mandar un mensaje que se cifra en el navegador del remitente; el servidor solo guarda un sobre cifrado. El destinatario no necesita cuenta: recibe un enlace /secure/<id> y descifra en su navegador. Está activo (la extensión core-sealer está active), pero el cifrado no lo hace la extensión (su server.js solo describe el protocolo): vive en la aplicación (src/lib/sealed/*, /api/secure-message, /secure/[id] y la opción "Enviar sellado" del editor).
Cómo funciona#
- El navegador genera una clave aleatoria de 256 bits (
K) y cifra{asunto, html}con AES-256-GCM (IV de 96 bits, tag de 128 bits; máx. 700 000 bytes de texto plano). - Opcional: contraseña (8–256 caracteres). La clave de contenido pasa a
HKDF-SHA256(K ‖ P)conPderivada con PBKDF2-SHA256 (600 000 iteraciones por defecto, sal de 16 bytes). Hacen falta ambos secretos: el fragmento y la contraseña. El AAD (bloomx-sealed:v1:nopwo…:pw:<iter>) impide ataques de degradación. - El navegador sube el sobre
{v, alg, iv, ct, pw, …}aPOST /api/secure-message(con sesión; 30/h por correo) conmaxViews(1–100 o sin límite). El servidor devuelve{id, viewUrl, expiresAt}y guardasecure/<id>.sealed, envuelto además con la clave de datos del servidor (defensa en profundidad). - El correo saliente lleva solo el enlace con la clave en el fragmento
#k=…, que el navegador nunca envía al servidor. - El destinatario abre
/secure/<id>; si hay límite de vistas se muestra una pantalla previa antes de gastar una.GET /api/secure-message/<id>da metadatos sin contar vista;POST(con cabeceraX-Sealed-Reveal: 1) consume una vista de forma atómica y devuelve el sobre; el navegador descifra.
https://mail.tu-dominio.com/secure/<uuid>#k=<43 caracteres base64url>
└── el fragmento (#…) NO se envía nunca al servidor- TTL:
min(ttlDays pedido, SECURE_MESSAGE_TTL_DAYS)(30 por defecto). La interfaz no exponettlDays, así que siempre se usa el máximo configurado. Al caducar o agotar las vistas se borra el objeto. Un id inexistente, caducado o agotado responde igual (404). SECURE_MESSAGE_ENABLED=falsedesactiva el módulo (403 al crear).- Rate limit: abrir 120/min por IP y 240/h por id; consumir 60/min por IP y 120/h por id.
- El editor ofrece la casilla "Enviar sellado", panel de contraseña/vistas, y "copiar enlace" (cifra y sube sin enviar correo). Funciona con envío programado.
Límites reales#
La clave viaja en el enlace
Quien pueda leer el correo (o el enlace completo) obtiene la clave. Sin contraseña, el sellado protege el contenido en el servidor y en tránsito hacia BloomX, pero no frente a alguien con acceso al buzón del destinatario. Para proteger de verdad, define una contraseña y compártela por otro canal. Sin contraseña el editor pide confirmación.
- Un envío sellado no admite adjuntos.
- El contenido sellado evade el DLP: el hook
EMAIL_PRE_SENDsolo ve el correo exterior con el enlace, no el contenido cifrado. - No oculta metadatos: quién envía a quién y cuándo sigue siendo visible, y el destinatario ve el correo exterior.
- El conteo de vistas es atómico en la tabla
SecureMessageMeta; si la tabla no existe (npm run db:ensure), cae a un conteo con bloqueo en memoria y, con varias instancias, podría exceder el límite en 1. - La frase de contraseña la valida el cliente (8–256); el servidor no la ve. Cualquier fallo de descifrado da el mismo error genérico.
- Los enlaces con
.msgantiguos (texto plano guardado en el servidor) siguen legibles; el formato antiguo concontentse rechaza al crear.
Organizer: organización con IA#
El Organizer clasifica el correo de la bandeja en categorías y aplica etiquetas automáticamente (o las propone). Es una extensión (core-organizer, active); el frontend solo aporta el puente de datos (/api/internal/mail) y la interfaz de propuestas.
Requisitos
Necesita services.mail: llamada firmada (tu dominio en modo firmado, con BLOOMX_DOMAIN_PRIVATE_KEY); el backend no necesita ninguna clave. Si no, falla con ORGANIZER_MAIL_SERVICE_UNAVAILABLE y el hook EMAIL_RECEIVED se omite en silencio. La IA usa la configuración de la instancia en /admin/ai (IA); sin IA degrada a heurística.
Cómo decide#
- Candidatos: solo
inbox, sin etiquetas y sin decisión previa del organizer. Cada correo se evalúa una sola vez. "Organize" procesa hasta 50 recientes (máx. 100, antigüedad 30 días); el hookEMAIL_RECEIVEDlo hace al llegar. - Tus reglas primero: si una regla habilitada ya etiqueta o mueve el correo, el organizer se abstiene.
- Heurística (regex sobre asunto, extracto y remitente; confianza 0.72–0.9). Con confianza ≥ 0.85 no gasta IA.
- IA para lo dudoso, en lotes de 25 con ids anónimos (
e1…eN); el texto del correo se trata como dato no confiable y la respuesta debe ser JSON. Confianza tope 0.95; una categoría fuera de lista se descarta. - Sin IA, con fallo o respuesta inválida, degrada a la heurística; lo no clasificable queda como
none(examinado).
| Categoría | Etiqueta creada | Color |
|---|---|---|
work | Work | #2563eb |
personal | Personal | #16a34a |
newsletter | Newsletters | #9333ea |
notification | Notifications | #64748b |
finance | Finance | #ca8a04 |
social | Social | #db2777 |
spam | (ninguna: solo se propone) | — |
- Confianza: piso 0.5; umbral
minConfidence(por defecto 0.7, configurable 0.5–0.99 por dominio). ≥ umbral: aplica la etiqueta; entre 0.5 y el umbral: propone; < 0.5: examinado sin acción. - Propuestas:
GET /api/organizer/proposalsyPOST /api/organizer/proposals/<emailId>con{action: "accept" | "dismiss"}. La interfaz está en Ajustes → Etiquetas (solo aparece si hay propuestas), con asunto, remitente, categoría y porcentaje. - Undo: el botón "Undo organize" deshace la última corrida (o un
runId): solo desconecta las etiquetas que esa corrida añadió; es idempotente. Las propuestas no se deshacen (no hay nada aplicado). - Los nombres internos de etiqueta son en inglés (se muestran traducidos);
settings.useAi === falsedesactiva la IA.