
Seal v0.2.3
Peer-to-peer, chat cifrado de extremo a extremo. Sin bandeja de entrada. Sin cuenta que recuperar. Nadie está escuchando, ni siquiera nosotros.
Seal
Chat cifrado de extremo a extremo entre pares.
Sin bandeja de entrada. Sin cuenta que recuperar. Nadie escucha — ni siquiera nosotros.
Los mensajes viajan directamente entre pares a través de libp2p y se cifran con los protocolos Olm/Megolm estilo Signal (mediante vodozemac) antes de salir jamás de tu dispositivo. El único servidor implicado es un pequeño directorio que ayuda a los pares a encontrar la dirección actual de los demás. Nunca ve el contenido de los mensajes y se puede purgar con un solo comando.
Consulta docs/THREAT_MODEL.md y
docs/SECURITY.md para saber qué se protege realmente y cómo.
Contenido
- Capturas de pantalla
- Características
- Cómo funciona
- Estructura del proyecto
- 1. Requisitos previos
- 2. Compilación
- 3. Ejecutarlo en modo de desarrollo
- 4. Pruebas
- 5. Configuración del backend (servidor de directorio)
- 6. Uso de la aplicación
Capturas de pantalla
Primera ejecución — elige un nombre; no hay nada más que configurar.
Conversaciones — la barra de grupos, la lista de contactos y un panel de chat cifrado de extremo a extremo.
Ajustes — sensibilidad del micrófono, pulsar para hablar, inicio de sesión al arrancar y accesibilidad de red.
Características
- Cifrado de extremo a extremo, siempre — cada mensaje se sella con Olm (1:1) o Megolm (grupos) antes de salir jamás de tu dispositivo, usando el esquema de estilo Double Ratchet de vodozemac: cada mensaje tiene su propia clave.
- Sin bandeja de entrada, nunca — los mensajes viajan a través de una conexión directa entre pares (libp2p: QUIC/TCP + Noise, con retransmisión y perforación de NAT). Si el destinatario está sin conexión, el mensaje espera localmente y reintenta; nunca se pone en cola en la infraestructura de nadie más.
- Un directorio, no una base de datos — el único servidor implicado
(
crates/directory-server) asigna un ID de usuario a una dirección de red actual y nada más. Es estructuralmente incapaz de leer el contenido de los mensajes: suCargo.tomlni siquiera depende de los crates que saben hacerlo. - Varias cuentas, un dispositivo — identidades totalmente separadas (claves, contactos, mensajes) entre las que puedes cambiar sin reiniciar.
- Grupos con cambios reales de membresía — canales de texto y voz por grupo; eliminar a alguien rota la clave del grupo para que no pueda leer nada de lo que se envíe después.
- Voz integrada — pulsar para hablar con un atajo global del sistema (funciona desde cualquier aplicación, no solo Seal), sensibilidad de micrófono ajustable y un cambiador de voz opcional.
- Archivos adjuntos sin los metadatos — los datos EXIF (ubicación GPS, información de cámara/dispositivo) se eliminan de las imágenes antes de enviarlas, activado por defecto.
- Un botón de pánico de verdad — Ajustes → Datos y privacidad elimina al instante y de forma irreversible todas las claves, contactos y mensajes de este dispositivo, sin ningún efecto sobre las personas con las que has hablado.
- Iniciar sesión al arrancar, si lo quieres — activado por defecto, a un interruptor de distancia en Ajustes.
- Una base de código, tres plataformas — ventanas nativas en macOS, Windows y Linux, mediante Tauri.
Cómo funciona
Hay dos tipos de identidad en esta aplicación, y se mantienen deliberadamente separados:
- Tu identidad de chat es un par de claves Ed25519/Curve25519 generado localmente
por vodozemac la primera vez que
abres la aplicación (
identity::Identity). Tu «ID de usuario» pública es simplemente la huella de esa clave (wire_proto::user_id_from_ed25519). Ningún servidor puede emitirla ni revocarla, porque no hay ningún servidor implicado en su creación. - Tu identidad de red es un par de claves libp2p independiente (
PeerId), utilizado solo para la capa de transporte. Puede cambiar entre reinicios sin afectar en absoluto a tu identidad de chat; ambas están vinculadas únicamente por un registro de presencia que firmas tú mismo.
Encontrar a alguien y hablar realmente con esa persona son dos pasos distintos:``` ┌────────────────────────┐ │ directory server │ │ (axum + one SQLite │ │ file: users, │ │ presence, group │ │ rosters. Never │ │ message content.) │ └─────────┬───────────────┘ 1. "where is bob │ 2. "here's my current right now?" │ address" (signed, │ expires in minutes) ┌─────────┴───────────────┐ ▼ ▼ ┌───────┐ 3. direct libp2p ┌───────┐ │ alice │◄──── connection ────►│ bob │ └───────┘ (Noise + Olm/ └───────┘ Megolm encrypted)
1. Alice busca a Bob en el directorio por su ID de usuario. Esto devuelve sus
claves públicas y su última dirección de red anunciada. Eso es todo
lo que contiene el directorio: claves públicas, nombres para mostrar, listas
de membresía de grupos y anuncios de dirección de corta duración
(`crates/directory-server`).
2. Alice se comunica directamente con Bob a través de libp2p (QUIC o TCP+Noise, con relay +
hole-punching para pares detrás de NAT; ver `crates/net`). El directorio queda
completamente fuera de escena a partir de aquí.
3. El mensaje real se cifra con **Olm** para un chat 1:1, o con
**Megolm** para un grupo (`crates/crypto-session`), un esquema de estilo Double-Ratchet
en el que cada mensaje tiene su propia clave, antes de que se coloque en
esa conexión libp2p. No hay bandeja de entrada del lado del servidor: si Bob está
desconectado, el mensaje espera localmente y se reintenta, no se almacena en
la infraestructura de nadie más.
Todo lo anterior está orquestado por `AppService` de `crates/core`, que es
lo que el backend Rust de la aplicación Tauri (`apps/desktop/src-tauri`) realmente
invoca; la UI nunca habla directamente con la red.
## Estructura del proyecto```
crates/
wire-proto shared signed-request types for the directory API
identity vodozemac identity, OS-keychain key management
storage local encrypted store (contacts, messages, groups)
net libp2p transport + directory HTTP client
crypto-session Olm (1:1) / Megolm (group) session management
core orchestrates the above into `AppService` / `ChatNode`
directory-server the one server component (axum + SQLite)
apps/desktop the Tauri + React app
scripts/ build + backend-deployment scripts (§2, §5)
1. Requisitos previos
Necesitas Rust y Node.js en todas las plataformas, además de una cadena de
herramientas específica de la plataforma que Tauri necesita para crear una ventana nativa. storage y directory-server
también compilan y empaquetan SQLite desde el código fuente, lo que requiere un compilador de C estándar (no
se requiere OpenSSL ni ninguna otra biblioteca criptográfica nativa en ningún lugar de este proyecto).
Común a todas las plataformas:
- Rust (canal estable; instálalo con
rustup, no con el gestor de paquetes de tu sistema operativo) - Node.js 20+ y npm
macOS
```sh xcode-select --install ``` Eso es todo. Xcode Command Line Tools proporcionan tanto el compilador de C como los frameworks que necesita el backend de macOS de Tauri (basado en WKWebView).Linux
Instala un compilador de C, pkg-config, y los paquetes de desarrollo
WebKitGTK/AppIndicator con los que enlaza el backend de Linux de Tauri.
Debian/Ubuntu:```sh
sudo apt update
sudo apt install libwebkit2gtk-4.1-dev build-essential curl wget file
libxdo-dev libssl-dev libayatana-appindicator3-dev librsvg2-dev pkg-config
Fedora:```sh
sudo dnf install webkit2gtk4.1-devel openssl-devel curl wget file \
libappindicator-gtk3-devel librsvg2-devel pkgconf-pkg-config
sudo dnf group install "C Development Tools and Libraries"
Arquitectura:```sh
sudo pacman -S --needed webkit2gtk-4.1 base-devel curl wget file openssl
appmenu-gtk-module libappindicator-gtk3 librsvg pkgconf
(Los nombres de los paquetes cambian entre versiones de Tauri: si una compilación falla al buscar un archivo `.pc` que falta, consulta los
[requisitos actuales de Tauri para Linux](https://v2.tauri.app/start/prerequisites/)
para tu distribución.)
</details>
<details>
<summary><strong>Windows</strong></summary>
1. Instala las **Microsoft C++ Build Tools** (carga de trabajo "Desarrollo de escritorio con C++" en el Instalador de Visual Studio), necesarias tanto para el shell nativo de Tauri como para compilar el SQLite incluido.
2. Instala la cadena de herramientas de Rust **MSVC**: `rustup default stable-msvc`.
3. **WebView2**: ya está presente en Windows 11 y en la mayoría de instalaciones actualizadas de Windows 10; si no es así, la compilación de Tauri te pedirá que instales el runtime Evergreen.
</details>
---
## 2. Compilación
Desde la raíz del repositorio:```sh
# Rust workspace (backend crates + the directory server)
cargo build --workspace --release
# Frontend + the actual desktop app bundle (installer/.app/.exe)
cd apps/desktop
npm install
npm run tauri build
npm run tauri build produce un instalador nativo de plataforma en
target/release/bundle/ en la raíz del repositorio (este es un workspace de Cargo, por lo que todos los crates, incluida la app de Tauri, comparten un único directorio target/ de nivel superior).
La compilación cruzada (p. ej., generar el instalador de Windows desde macOS) no está configurada: compila en cada plataforma de destino o usa el flujo de trabajo de GitHub Actions de Tauri si quieres lanzamientos compilados por CI.
O usa los scripts
scripts/ tiene un script de compilación por plataforma/salida, cada uno ejecutable de forma independiente y verificado para producir realmente un artefacto funcional:
| Script | Produce |
|---|---|
scripts/build-mac-dmg.sh | instalador .dmg de macOS |
scripts/build-mac-app.sh | Paquete .app de macOS sin procesar, sin instalador |
scripts/build-linux.sh | Linux .AppImage + .deb |
scripts/build-windows.ps1 | Windows .msi + .exe (NSIS) |
Cada uno solo envuelve npm run tauri build --bundles <...> con las opciones adecuadas y la comprobación de plataforma; ejecuta tú mismo el comando directo si quieres una combinación de bundles distinta (npx tauri build --help desde apps/desktop).
scripts/release.sh vX.Y.Z actualiza la versión en todos los sitios donde debe estar y etiqueta el commit — consulta docs/RELEASING.md. Se ejecuta en macOS y Linux; no hace commit ni push.
Integrar tu propia red "Seal"
La pantalla de selección de servidor (§3) siempre muestra tres opciones: Seal (tu propia red oficial), Servidor personalizado, y un pequeño enlace Servidor de prueba local en la parte inferior. "Seal" está deshabilitado (atenuado, con "Aún no configurado en esta compilación") hasta que incorpores una URL en el momento de la compilación:```sh SEAL_DEFAULT_DIRECTORY_URL=https://directory.example.com npm run tauri build
Una vez que hayas puesto en marcha tu propio servidor (§5) y tengas un dominio real apuntando a
él, configura esto y recompila: cada copia que distribuyas a partir de entonces mostrará
"Seal" como una opción real y seleccionable usando esa URL, sin tocar ningún
otro código. Déjalo sin configurar para compilaciones ordinarias/de desarrollo: no hay un servidor oficial
alojado por este repositorio, así que "Seal" permanece deshabilitado y la gente recurre a
un servidor personalizado o al local, en lugar de que la aplicación apunte silenciosamente a
un dominio de marcador de posición que en realidad no ejecuta nada.
---
## 3. Ejecutarlo en modo de desarrollo```sh
cd apps/desktop
npm install
npm run tauri dev
Esto inicia el servidor de desarrollo de Vite, compila el backend de Rust en modo depuración y abre una ventana nativa con recarga en caliente en el frontend. La primera compilación compila todo el árbol de dependencias y tarda unos minutos; las ejecuciones posteriores son rápidas.
Elegir un servidor (primera ejecución)
La primera vez que lo lanzas, Seal pregunta qué servidor de directorio usar, en este orden:
- Seal: la red oficial, si esta compilación tiene una integrada (ver §2). Deshabilitado hasta que la tenga; este repositorio no viene apuntando a un dominio de marcador de posición.
- Servidor personalizado: el de cualquiera, incluido el tuyo (§5).
- Servidor de prueba local: un enlace pequeño, deliberadamente poco destacado en la
parte inferior. Inicia el servidor integrado de la propia aplicación (se vincula a
127.0.0.1:47100/47101, datos bajo el directorio de datos de aplicación de tu SO), adecuado para probar Seal o probar instancias en una sola máquina, no un despliegue real. Si una segunda instancia encuentra que esos puertos ya están ocupados, simplemente reutiliza el servidor de la primera instancia en lugar de iniciar otro, lo que permite que dos instancias en una misma máquina se encuentren entre sí. Esto es lo que se selecciona automáticamente si "Seal" no está configurado y no eliges nada más.
La elección se guarda (server.json junto a los otros datos locales de la aplicación) y
se reutiliza silenciosamente en cada lanzamiento posterior; cámbiala desde Ajustes → Servidor de
directorio, que surte efecto la próxima vez que inicies la aplicación en lugar de
intentar intercambiar en caliente una conexión en ejecución. Para uso mediante scripts/desarrollo, una
variable de entorno omite el aviso por completo:```sh
P2P_CHAT_DIRECTORY_URL=https://directory.example.com npm run tauri dev
### Ejecutar dos instancias localmente (para probar realmente la mensajería)
Cada instancia necesita su propia identidad. Seal admite múltiples cuentas
de forma nativa (Configuración → Cuentas en este dispositivo), pero para dos *procesos
separados* en una misma máquina, `P2P_CHAT_PROFILE` es la vía más rápida:
crea automáticamente (la primera vez) o reanuda automáticamente (cada vez después) una cuenta
con ese nombre, de forma no interactiva, omitiendo por completo el selector de cuentas:```sh
# terminal 1
P2P_CHAT_PROFILE=alice npm run tauri dev
# terminal 2
P2P_CHAT_PROFILE=bob npm run tauri dev
La elección del servidor (server.json) y la lista de cuentas (accounts.json) se comparten entre procesos en una misma máquina, no por perfil. La primera instancia que lanzas elige el servidor, y todos los perfiles posteriores (incluido bob aquí) lo reutilizan silenciosamente. Ambas ventanas terminan en el mismo servidor de directorio integrado, por lo que pueden agregarse mutuamente como contactos por ID y enviarse mensajes entre ellas.
El servidor de desarrollo de Vite necesita un puerto real y fijo al que apunte la webview de Tauri, lo que normalmente significa que solo un npm run tauri dev puede ejecutarse a la vez — el segundo encontraría el puerto 1420 ya ocupado y fallaría directamente. npm run tauri es en realidad un pequeño envoltorio (apps/desktop/scripts/tauri.mjs) que elige el siguiente puerto libre (1421, 1422, …) para cada instancia posterior a la primera y lo conecta automáticamente, así que ejecutar los dos comandos anteriores en dos terminales simplemente funciona; no necesitas hacer nada diferente. Solo cambia el comportamiento para dev — npm run tauri build y todo lo demás pasan directamente al CLI real.
Probar contra una compilación real (no modo dev)```sh
./scripts/run-two-mac-instances.sh # profiles: alice, bob ./scripts/run-two-mac-instances.sh carol dave
Misma idea que arriba, pero inicia la aplicación compilada real (la salida de `build-mac-app.sh` / `build-mac-dmg.sh`, o una copia instalada en `/Applications`) dos veces con diferentes `P2P_CHAT_PROFILE`s en lugar de `npm run tauri dev`, más parecido a lo que ejecuta un usuario real. Muestra los PIDs y cómo detener ambos.
### Depuración
- **Registros de Rust**: establece `RUST_LOG` antes de iniciar, p. ej. `RUST_LOG=debug npm run tauri dev` (o `RUST_LOG=p2p_core=debug,net=debug` para acotarlo). Los campos registrados se limitan a metadatos (IDs de par/grupo/usuario, tipos de error); consulta [`docs/SECURITY.md`](https://github.com/emn4tor/seal/blob/HEAD/docs/SECURITY.md) para ver por qué es seguro dejarlo en modo verboso.
- **Frontend**: la ventana de desarrollo es un webview real; clic derecho → Inspeccionar elemento (o abrir las herramientas de desarrollo) funciona como en un navegador normal.
- **Crates del backend de forma aislada**: cada crate tiene su propio conjunto de pruebas que puedes ejecutar e iterar sin tocar la interfaz en absoluto; ver §4.
- **Un servidor de directorio independiente**, en lugar del integrado: ver §5.
---
## 4. Pruebas```sh
# everything
cargo test --workspace
# one crate, e.g. the full backend-to-backend flow a Tauri command would trigger
cargo test -p p2p-core --test app_service
# lint + format check (what CI runs)
cargo fmt --all -- --check
cargo clippy --workspace --all-targets -- -D warnings
# dependency vulnerability scan
cargo install cargo-audit --locked # once
cargo audit
# frontend type-check + build
cd apps/desktop && npm run build
5. Configuración del backend (servidor de directorio)
Recapitulación de lo que esto es en realidad, ya que es fácil imaginarse de más: un proceso axum,
un archivo SQLite, tres tipos de registros (claves públicas, anuncios de presencia
de corta duración, listas de grupos), todas las escrituras firmadas por la clave de
identidad del propio llamante. Nunca está en la ruta de un mensaje. Consulta
docs/THREAT_MODEL.md para saber por qué esto es cierto
estructuralmente, y no solo por política: el Cargo.toml de directory-server no
depende ni siquiera de las crates que saben leer el contenido de los mensajes.
Ruta más rápida: el script de configuración```sh
sudo ./scripts/setup-backend.sh
Interactivo, solo Linux + systemd (consulta el encabezado del script para saber por qué). Pregunta sobre qué familia de distribución estás usando (Debian/Ubuntu, Fedora/RHEL/Rocky/Alma, Arch/Manjaro u openSUSE, pre-rellenada con una suposición de `/etc/os-release`, por lo que normalmente es una confirmación con una sola tecla) e instala los requisitos previos de compilación de esa distribución con una función dedicada por familia, ofrece instalar Rust mediante `rustup` si falta, compila el binario de lanzamiento, crea un usuario de sistema dedicado, genera un token de administrador, pregunta si quieres que configure un dominio con HTTPS automático mediante [Caddy](https://caddyserver.com) (instalando el propio Caddy, por distribución, recurriendo al binario estático oficial de Caddy si el paquete de una distribución no está disponible), o que simplemente enlace loopback/HTTP plano si prefieres ponerlo tú mismo al frente, luego escribe y habilita el servicio systemd. Es seguro volver a ejecutarlo.
Todo lo siguiente es lo que realmente hace, si prefieres hacerlo a mano
o entenderlo antes de ejecutarlo.
### macOS: un servidor de prueba LAN rápido```sh
./scripts/run-mac-test-server.sh
No es para alojamiento real: es para probar la aplicación en dos dispositivos en la misma
red (p. ej., tu Mac y otra máquina, o dos personas en el mismo Wi-Fi)
sin configurar un dominio, TLS ni systemd (que no existe en macOS
de todos modos). Compila el binario de lanzamiento, genera un token de administrador (reutilizado en
ejecuciones posteriores), vincula la API pública a todas las interfaces e imprime la URL a
usar: la IP LAN real de tu Mac (mediante ipconfig getifaddr), no solo
127.0.0.1, para que otros dispositivos también puedan acceder a ella. El puerto de administración permanece
solo en loopback. Se ejecuta en primer plano; Ctrl-C lo detiene. Los datos se guardan en
~/.seal-test-server.
Ejecución local rápida```sh
DIRECTORY_DB_PATH=/var/lib/seal-directory/directory.sqlite3
DIRECTORY_PUBLIC_ADDR=0.0.0.0:8080
DIRECTORY_ADMIN_ADDR=127.0.0.1:8090
DIRECTORY_ADMIN_TOKEN=$(openssl rand -hex 32)
cargo run --release -p directory-server --bin directory-server
| Variable | Requerido | Significado |
|---|---|---|
| `DIRECTORY_DB_PATH` | no (por defecto `directory.sqlite3`, cwd) | Dónde reside el único archivo SQLite. El directorio padre debe existir. |
| `DIRECTORY_PUBLIC_ADDR` | no (por defecto `0.0.0.0:8080`) | La API de rendezvous con la que hablan las aplicaciones. Es seguro exponerla públicamente. |
| `DIRECTORY_ADMIN_ADDR` | no (por defecto `127.0.0.1:8090`) | El endpoint de purga. Mantenlo fuera de la internet pública; ver más abajo. |
| `DIRECTORY_ADMIN_TOKEN` | **sí** | Token Bearer para la API de administración. El proceso se niega a iniciar sin uno. Genéralo con `openssl rand -hex 32` o similar; no lo reutilices en ningún otro lugar. |
El proceso registra en los logs las direcciones a las que se vinculó al iniciar y advierte enérgicamente si `DIRECTORY_ADMIN_ADDR` no es loopback.
### Apuntar la aplicación al directorio
Tres maneras, en el orden en que normalmente acudirías a ellas:
1. **Pantalla de primer inicio**: elige "Custom server" e introduce la URL. Ver §3.
2. **Settings → Directory server**: cámbialo más tarde; surte efecto en el
siguiente reinicio.
3. **`P2P_CHAT_DIRECTORY_URL`**, establecida antes de iniciar: omite la pregunta
por completo y sobrescribe lo que se haya guardado, útil para ejecuciones de desarrollo o mediante scripts: ```sh
P2P_CHAT_DIRECTORY_URL=https://directory.example.com npm run tauri dev
Todos los que quieren encontrarse necesitan apuntar a la misma instancia de directorio; así es como se buscan entre sí en primer lugar.
Ejecutándolo como un servicio real (systemd)
Mostrar la unidad de systemd + notas
```ini # /etc/systemd/system/seal-directory.service [Unit] Description=Seal directory server After=network.target[Service] Type=simple User=seal-directory Group=seal-directory Environment=DIRECTORY_DB_PATH=/var/lib/seal-directory/directory.sqlite3 Environment=DIRECTORY_PUBLIC_ADDR=127.0.0.1:8080 Environment=DIRECTORY_ADMIN_ADDR=127.0.0.1:8090 EnvironmentFile=/etc/seal-directory/admin-token.env ; DIRECTORY_ADMIN_TOKEN=... ExecStart=/usr/local/bin/directory-server Restart=on-failure
Sandboxing: this process needs almost nothing
ProtectSystem=strict ProtectHome=true PrivateTmp=true NoNewPrivileges=true ReadWritePaths=/var/lib/seal-directory
[Install] WantedBy=multi-user.target
Notas:
- `DIRECTORY_PUBLIC_ADDR` está vinculado a **loopback** aquí a propósito; pon
un proxy inverso delante para TLS (abajo) en lugar de exponer axum
directamente a internet.
- Crea primero el usuario/grupo de sistema `seal-directory` y
`/var/lib/seal-directory` (`useradd --system --no-create-home
seal-directory && install -d -o seal-directory -g seal-directory
/var/lib/seal-directory`), y copia el binario `directory-server` compilado
(desde `target/release/`) a `/usr/local/bin/`.
- Pon el token de administrador en un `EnvironmentFile` legible solo por root,
no directamente en el archivo de unidad (los archivos de unidad suelen ser
legibles por todos).
</details>
### TLS mediante un proxy inverso
<details>
<summary>Mostrar la configuración de Caddy / nginx</summary>
[Caddy](https://caddyserver.com) te proporciona HTTPS automático con la menor
configuración:```
# /etc/caddy/Caddyfile
directory.example.com {
reverse_proxy 127.0.0.1:8080
}
caddy run (o systemctl enable --now caddy) se encarga de la
emisión/renovación de certificados por sí solo. Si prefieres usar nginx, termina TLS ahí
y proxy_pass http://127.0.0.1:8080;, ya que la aplicación solo necesita HTTP sin cifrar
desde la perspectiva del proxy.
En cuanto al firewall: solo el puerto público tiene que ser accesible desde fuera
(8080 en los ejemplos anteriores, con el 443 al frente mediante el proxy). El puerto de administración
nunca debe ser accesible desde fuera; accede a él mediante el reenvío de puertos SSH
(ssh -L 8090:127.0.0.1:8090 your-server) cuando necesites ejecutar una purga
de forma remota.
Purgarlo```sh
cargo run --release -p directory-server --bin directory-admin --
--admin-url http://127.0.0.1:8090 --token "$DIRECTORY_ADMIN_TOKEN" purge
Esto elimina el archivo SQLite y recrea un esquema vacío: no hay sentencias `DELETE`
ni estado parcial. Es seguro ejecutarlo sin avisar a nadie primero:
cada registro en él es una caché de datos que cada cliente ya tiene localmente
(su propio registro, presencia y cualquier lista de miembros de grupo de la que
formen parte), por lo que los clientes simplemente lo vuelven a poblar en cuestión de momentos tras su siguiente acción.
Deliberadamente no hay política de copia de seguridad para esta base de datos; consulta
[`docs/SECURITY.md`](https://github.com/emn4tor/seal/blob/HEAD/docs/SECURITY.md) para saber por qué mantener una socavaría
todo el propósito.
---
## 6. Uso de la aplicación
1. **Primer lanzamiento, primera pregunta**: qué servidor de directorio usar (§3).
El valor predeterminado es el que esté integrado en la compilación que estés ejecutando (un servidor
de pruebas local, a menos que quien lo haya compilado haya configurado uno oficial); elige
"Servidor personalizado" para apuntar a uno que tú o alguien de confianza aloje.
2. **Elige un nombre para mostrar.** Esto genera un par de claves privadas en tu
dispositivo (nada que recordar, y nada recuperable si se pierde: eso es
deliberado) y te guía a través de una breve explicación dentro de la aplicación de cómo
el cifrado realmente funciona. Puedes reproducirla cuando quieras desde Ajustes. Cada
lanzamiento posterior te lleva directamente de vuelta sin aviso; esto solo ocurre una vez por
cuenta. Añade más cuentas (identidades completamente separadas) desde Ajustes →
Cuentas en este dispositivo, y cambia entre ellas sin reiniciar.
3. **Añade a alguien**: haz clic en **+** junto a "Mensajes directos" e introduce su
ID (que se encuentra en *sus* Ajustes → Mi identidad). No hay un directorio para
navegar por diseño; te conectas de la misma manera en que compartirías un número de teléfono.
4. **Envíales un mensaje**: elige su nombre de la lista y escribe. El primer
mensaje a alguien establece una sesión cifrada automáticamente.
5. **Crea un grupo**: haz clic en **+** en la barra de iconos, ponle nombre y luego invita
a personas por ID de la misma manera. Eliminar a alguien rota la clave del grupo para que
no puedan leer nada enviado después.
6. **Bórralo todo**: Ajustes → Datos y privacidad. Esto es instantáneo,
solo local e irreversible: destruye tus claves, contactos e
historial en *este dispositivo* y no tiene ningún efecto en las personas con las que has hablado.