Skip to content
KitploitKITPLOIT
FerramentasExploitsBlog
Log in
Enviar
FerramentasExploitsBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

FeedsContatoPrivacidade© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
Seal — Chat peer-to-peer com criptografia de ponta a ponta. Sem caixa de entrada. Sem conta para recuperar. Ninguém está ouvindo — nem mesmo nós. | Kitploit
Ferramentas/GitHubGitHub/emn4tor/seal
Ferramentas de Criptografia/DescriptografiaCriptografiaPrivacidade
GitHubemn4tor/seal

Seal

Chat peer-to-peer com criptografia de ponta a ponta. Sem caixa de entrada. Sem conta para recuperar. Ninguém está ouvindo — nem mesmo nós.

Ver Repositório
944há 2 mesesAinda não revisado

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
Compartilhar
<div align="center">
  <a href="https://github.com/Emn4tor/Seal">
    <img src="https://assets.kitploit.com/production/public/readmes/49626/0d175b4ba9dd08a1b35a94415f701b49b89aac52b6f5c25731822653ea386e6f.png" width="112" height="112" alt="Logotipo do Seal" />
  </a>

  <h1>Seal</h1>

  <p><em>Chat peer-to-peer com criptografia de ponta a ponta.<br />Sem caixa de entrada. Sem conta para recuperar. Ninguém está ouvindo — nem nós.</em></p>

  <p><a href="https://github.com/Emn4tor/Seal">github.com/Emn4tor/Seal</a></p>

  <p>
    <img src="https://img.shields.io/badge/rust-1.97+-c9a15c?style=flat-square&amp;labelColor=0e1116&amp;logo=rust&amp;logoColor=e8e3d8" alt="Rust: 1.97+" />
    <img src="https://img.shields.io/badge/tauri-2.11.5-4f8f86?style=flat-square&amp;labelColor=0e1116&amp;logo=tauri&amp;logoColor=e8e3d8" alt="Tauri: 2.11.5" />
    <img src="https://img.shields.io/badge/react-19.2-c9a15c?style=flat-square&amp;labelColor=0e1116&amp;logo=react&amp;logoColor=e8e3d8" alt="React: 19.2" />
    <img src="https://img.shields.io/badge/platforms-macOS%20%7C%20Linux%20%7C%20Windows-4f8f86?style=flat-square&amp;labelColor=0e1116" alt="Plataformas: macOS, Linux, Windows" />
    <img src="https://img.shields.io/badge/encryption-Olm%20/%20Megolm-c9a15c?style=flat-square&amp;labelColor=0e1116" alt="Criptografia: Olm / Megolm" />
    <img src="https://img.shields.io/badge/server%20storage-none-4f8f86?style=flat-square&amp;labelColor=0e1116" alt="Armazenamento de mensagens no servidor: nenhum" />
  </p>
  <p>
    <a href="https://github.com/Emn4tor/Seal/stargazers"><img src="https://img.shields.io/github/stars/Emn4tor/Seal?style=flat-square&amp;color=c9a15c&amp;labelColor=0e1116" alt="Estrelas do GitHub" /></a>
    <a href="https://github.com/Emn4tor/Seal/network/members"><img src="https://img.shields.io/github/forks/Emn4tor/Seal?style=flat-square&amp;color=4f8f86&amp;labelColor=0e1116" alt="Forks do GitHub" /></a>
    <a href="https://github.com/Emn4tor/Seal/issues"><img src="https://img.shields.io/github/issues/Emn4tor/Seal?style=flat-square&amp;color=c9a15c&amp;labelColor=0e1116" alt="Issues do GitHub" /></a>
    <a href="https://github.com/Emn4tor/Seal/commits"><img src="https://img.shields.io/github/last-commit/Emn4tor/Seal?style=flat-square&amp;color=4f8f86&amp;labelColor=0e1116" alt="Último commit do GitHub" /></a>
    <a href="https://github.com/Emn4tor/Seal"><img src="https://img.shields.io/github/repo-size/Emn4tor/Seal?style=flat-square&amp;color=c9a15c&amp;labelColor=0e1116" alt="Tamanho do repositório no GitHub" /></a>
  </p>
  <p>
    <a href="https://github.com/Emn4tor/Seal/graphs/contributors"><img src="https://img.shields.io/github/contributors/Emn4tor/Seal?style=for-the-badge&amp;color=c9a15c&amp;labelColor=0e1116" alt="Contribuidores" /></a>
    <a href="https://github.com/Emn4tor/Seal/commits"><img src="https://img.shields.io/github/commit-activity/t/Emn4tor/Seal?style=for-the-badge&amp;color=4f8f86&amp;labelColor=0e1116" alt="Total de commits" /></a>
  </p>
</div>

As mensagens viajam diretamente entre pares pela libp2p e são criptografadas com os
protocolos Olm/Megolm no estilo Signal (via
[vodozemac](https://github.com/matrix-org/vodozemac)) antes de saírem
do seu dispositivo. O único servidor envolvido é um pequeno diretório que ajuda os pares
a encontrarem o endereço atual uns dos outros. Ele nunca vê o conteúdo das mensagens e pode ser
apagado com um único comando.

Consulte [`docs/THREAT_MODEL.md`](https://github.com/emn4tor/seal/blob/main/docs/THREAT_MODEL.md) e
[`docs/SECURITY.md`](https://github.com/emn4tor/seal/blob/main/docs/SECURITY.md) para saber o que é realmente protegido
e como.

## Conteúdo

- [Capturas de tela](#screenshots)
- [Recursos](#features)
- [Como funciona](#how-it-works)
- [Estrutura do projeto](#project-layout)
- [1. Pré-requisitos](#1-prerequisites)
- [2. Compilação](#2-building)
- [3. Executando em modo de desenvolvimento](#3-running-it-in-dev-mode)
- [4. Testes](#4-testing)
- [5. Configuração do backend (servidor de diretório)](#5-backend-directory-server-setup)
- [6. Usando o aplicativo](#6-using-the-app)

---

## Capturas de tela

<div align="center">

**Primeira execução** — escolha um nome; nada mais para configurar.

<img src="https://assets.kitploit.com/production/public/readmes/49626/c45dd83972e6760574f3a07186a511aa3c9b5d544d22aa7f4dd370d38038eb4d.png" width="820" alt="Tela de primeira execução do Seal: uma explicação do modelo de criptografia ao lado de um formulário de nome de exibição, com um alternador de iniciar no login" />

<br /><br />

**Conversas** — a barra de grupos, a lista de contatos e um painel de chat com criptografia de ponta a ponta.

<img src="https://assets.kitploit.com/production/public/readmes/49626/fd29b87e22a02fc9a44097d9dc62b9ef74b73fd53d4762bc54ebb165b4ef84e8.png" width="820" alt="Uma conversa de mensagem direta no Seal, mostrando a barra de grupos, a lista de contatos e o painel de chat com criptografia de ponta a ponta" />

<br /><br />

**Configurações** — sensibilidade do microfone, push-to-talk, iniciar no login, alcance de rede.

<img src="https://assets.kitploit.com/production/public/readmes/49626/425c46d395741ed088ac2c50c178e1e41eeb457487cfbc2c0fa6ab61515f648f.png" width="820" alt="Painel de configurações do Seal: sensibilidade do microfone, push-to-talk, iniciar no login e alcance de rede" />

</div>

## Recursos

- **Criptografia de ponta a ponta, sempre** — toda mensagem é lacrada com Olm (1:1)
  ou Megolm (grupos) antes de sair do seu dispositivo, usando
  o esquema estilo Double Ratchet do [vodozemac](https://github.com/matrix-org/vodozemac):
  cada mensagem tem sua própria chave.
- **Sem caixa de entrada, nunca** — as mensagens viajam por uma conexão direta ponto a ponto
  ([libp2p](https://libp2p.io): QUIC/TCP + Noise, com relay e
  hole punching para NATs). Se o destinatário estiver offline, a mensagem aguarda
  localmente e tenta novamente — ela nunca é enfileirada na infraestrutura de terceiros.
- **Um diretório, não um banco de dados** — o único servidor envolvido
  (`crates/directory-server`) mapeia um ID de usuário para um endereço de rede atual
  e nada mais. Ele é estruturalmente incapaz de ler o conteúdo das mensagens:
  seu `Cargo.toml` nem sequer depende das crates que saberiam como fazer.
- **Várias contas, um dispositivo** — identidades totalmente separadas (chaves,
  contatos, mensagens) entre as quais você pode alternar sem reiniciar.
- **Grupos com mudanças reais de membros** — canais de texto e voz por
  grupo; remover alguém rotaciona a chave do grupo para que essa pessoa não consiga ler
  nada enviado depois.
- **Voz, integrada** — push-to-talk com um atalho global do sistema (funciona em
  qualquer aplicativo, não apenas no Seal), sensibilidade de microfone ajustável e um
  alterador de voz opcional.
- **Anexos sem os metadados** — os dados EXIF (localização GPS,
  informações de câmera/dispositivo) são removidos das imagens antes de serem enviados, ativado por
  padrão.
- **Um botão de pânico de verdade** — Configurações → Dados e Privacidade exclui instantânea e
  irreversivelmente todas as chaves, contatos e mensagens deste dispositivo, com
  zero efeito sobre qualquer pessoa com quem você conversou.
- **Iniciar no login, se você quiser** — ativado por padrão, a um interruptor de distância nas
  Configurações.
- **Uma base de código, três plataformas** — janelas nativas em macOS, Windows e
  Linux, via [Tauri](https://tauri.app).

## Como funciona

Há dois tipos de identidade neste aplicativo, e eles são mantidos deliberadamente
separados:

- **Sua identidade de chat** é um par de chaves Ed25519/Curve25519 gerado localmente
  pelo [vodozemac](https://github.com/matrix-org/vodozemac) na primeira vez que você
  abre o aplicativo (`identity::Identity`). Seu "ID de usuário" público é apenas a
  impressão digital (fingerprint) dessa chave (`wire_proto::user_id_from_ed25519`). Ele não pode ser
  emitido ou revogado por nenhum servidor, porque nenhum servidor participa da sua criação.
- **Sua identidade de rede** é um par de chaves libp2p separado (`PeerId`), usado
  apenas na camada de transporte. Ela pode mudar entre reinicializações sem
  afetar em nada sua identidade de chat; as duas estão ligadas apenas por um
  registro de presença que você mesmo assina.

Encontrar alguém e de fato conversar com essa pessoa são duas etapas diferentes:```
                     ┌────────────────────────┐
                     │     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 procura Bob no diretório pelo ID de usuário dele. Isso retorna as
   chaves públicas dele e o último endereço de rede anunciado. Isso é tudo
   o que o diretório contém: chaves públicas, nomes de exibição, listas de
   associação a grupos e anúncios de endereço de curta duração
   (`crates/directory-server`).
2. Alice conecta-se diretamente a Bob via libp2p (QUIC ou TCP+Noise, com relay +
   hole-punching para peers atrás de NATs; veja `crates/net`). O diretório fica
   completamente fora de cena a partir daqui.
3. A mensagem em si é criptografada com **Olm** para um chat 1:1, ou
   **Megolm** para um grupo (`crates/crypto-session`), um esquema no estilo
   Double-Ratchet em que cada mensagem recebe sua própria chave, antes de ser
   colocada nessa conexão libp2p. Não existe caixa de entrada no servidor: se Bob
   estiver offline, a mensagem aguarda localmente e é tentada novamente, não
   sendo armazenada na infraestrutura de ninguém.

Tudo o que está acima é orquestrado pelo `AppService` de `crates/core`, que é
o que o backend Rust do aplicativo Tauri (`apps/desktop/src-tauri`) realmente
chama; a UI nunca fala diretamente com a rede.

## Estrutura do projeto```
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. Pré-requisitos

Você precisa de **Rust** e **Node.js** em todas as plataformas, além de uma
toolchain específica da plataforma que o Tauri requer para compilar uma janela
nativa. `storage` e `directory-server` também compilam o SQLite a partir do
código-fonte, o que requer um compilador C simples (nenhuma OpenSSL ou outra
biblioteca criptográfica nativa é necessária em qualquer lugar deste projeto).

Comum a todas as plataformas:

- [Rust](https://rustup.rs) (canal estável; instale via `rustup`, não pelo gerenciador de pacotes do seu sistema operacional)
- [Node.js](https://nodejs.org) 20+ e npm

<details>
<summary><strong>macOS</strong></summary>```sh
xcode-select --install
```
É só isso. As Xcode Command Line Tools fornecem tanto o compilador C quanto os
frameworks de que o backend macOS do Tauri (baseado em WKWebView) precisa.

</details>

<details>
<summary><strong>Linux</strong></summary>

Instale um compilador C, `pkg-config` e os pacotes de desenvolvimento
WebKitGTK/AppIndicator com os quais o backend Linux do Tauri faz link.

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"
```
Arch:```sh
sudo pacman -S --needed webkit2gtk-4.1 base-devel curl wget file openssl \
  appmenu-gtk-module libappindicator-gtk3 librsvg pkgconf
```
(Os nomes dos pacotes mudam entre versões do Tauri: se uma compilação falhar procurando por um arquivo `.pc` ausente, consulte os
[pré-requisitos atuais do Tauri para Linux](https://v2.tauri.app/start/prerequisites/)
para a sua distribuição.)

</details>

<details>
<summary><strong>Windows</strong></summary>

1. Instale as **Ferramentas de Build do Microsoft C++** (Visual Studio Installer →
   carga de trabalho "Desenvolvimento para desktop com C++"), necessárias tanto para o shell nativo do Tauri
   quanto para compilar o SQLite embutido.
2. Instale a toolchain Rust **MSVC**: `rustup default stable-msvc`.
3. **WebView2**: já está presente no Windows 11 e na maioria das instalações atualizadas do Windows
   10; se não estiver, o build do Tauri solicitará que você instale o
   runtime Evergreen.

</details>

---

## 2. Compilação

Na raiz do repositório:```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` gera um instalador nativo da plataforma em
`target/release/bundle/` na raiz do repositório (este é um workspace do Cargo, então todos
os crates, incluindo o app Tauri, compartilham um diretório `target/` de nível superior).
A compilação cruzada (por exemplo, gerar o instalador do Windows a partir do macOS) não está
configurada: compile em cada plataforma de destino ou use o fluxo de trabalho do GitHub Actions do Tauri
se você quiser releases compilados por CI.

### Ou use os scripts

`scripts/` tem um script de build por plataforma/saída, cada um independentemente
executável e cada um verificado para realmente produzir um artefato funcional:

| Script | Produz |
|---|---|
| `scripts/build-mac-dmg.sh` | instalador `.dmg` do macOS |
| `scripts/build-mac-app.sh` | pacote `.app` bruto do macOS, sem instalador |
| `scripts/build-linux.sh` | Linux `.AppImage` + `.deb` |
| `scripts/build-windows.ps1` | Windows `.msi` + `.exe` (NSIS) |

Cada um apenas encapsula `npm run tauri build --bundles <...>` com as flags corretas
e verificação de plataforma; execute você mesmo o comando direto se quiser uma
combinação de bundle diferente (`npx tauri build --help` a partir de `apps/desktop`).

`scripts/release.sh vX.Y.Z` atualiza a versão em todos os lugares necessários
e marca o commit — veja [`docs/RELEASING.md`](https://github.com/emn4tor/seal/blob/main/docs/RELEASING.md). É executado em
macOS e Linux; não faz commit nem push.

### Incorporando sua própria rede "Seal"

A tela de escolha do servidor (§3) sempre mostra três opções: **Seal** (sua
própria rede oficial), **Servidor personalizado** e um pequeno **Servidor de teste local**
link na parte inferior. "Seal" fica desabilitado (esmaecido, com "Ainda não configurado
neste build") até você incorporar uma URL no momento do *build*:```sh
SEAL_DEFAULT_DIRECTORY_URL=https://directory.example.com npm run tauri build
```
Depois de subir seu próprio servidor (§5) e apontar um domínio real para
ele, configure isso e recompile: toda cópia que você distribuir a partir de então mostra
"Seal" como uma opção real e selecionável usando essa URL, sem tocar em nenhum
outro código. Deixe sem configurar para builds comuns/de desenvolvimento: não há um servidor
oficial hospedado por este repositório, então "Seal" permanece desabilitado e as pessoas recorrem a
um servidor personalizado ou ao local, em vez de o aplicativo apontar silenciosamente para
um domínio placeholder que não está realmente executando nada.

---

## 3. Executando em modo de desenvolvimento```sh
cd apps/desktop
npm install
npm run tauri dev
```
Isto inicia o servidor de desenvolvimento Vite, compila o backend Rust em modo de depuração e
abre uma janela nativa com hot-reload no frontend. A primeira compilação compila
toda a árvore de dependências e leva alguns minutos; as execuções seguintes são rápidas.

### Escolhendo um servidor (primeira execução)

Na primeira vez que você iniciar, o Seal pergunta qual servidor de diretório usar, nesta
ordem:

- **Seal**: a rede oficial, se esta compilação tiver uma incorporada (ver
  §2). Desabilitada até que tenha; este repositório não vem apontando para um
  domínio provisório.
- **Servidor personalizado**: o de qualquer pessoa, incluindo o seu (§5).
- **Servidor de teste local**: um link pequeno e deliberadamente menos destacado na
  parte inferior. Inicia o **servidor embutido** do próprio aplicativo (vincula
  `127.0.0.1:47100`/`47101`, dados no diretório de dados de aplicativos do seu sistema
  operacional), adequado para experimentar o Seal ou testar instâncias em uma única máquina, não uma
  implantação real. Se uma segunda instância descobrir que essas portas já estão ocupadas, ela apenas
  reutiliza o servidor da primeira instância em vez de iniciar outro,
  que é o que permite que duas instâncias na mesma máquina se encontrem. Isto é o
  que é selecionado automaticamente se "Seal" não estiver configurado e você não escolher
  mais nada.

A escolha é salva (`server.json` ao lado dos outros dados locais do aplicativo) e
reutilizada silenciosamente em todos os lançamentos posteriores; altere-a em Configurações → Servidor de
diretório, que terá efeito na próxima vez que você iniciar o aplicativo, em vez de
tentar trocar a quente uma conexão em execução. Para uso com scripts/desenvolvimento, uma
variável de ambiente ignora o prompt completamente:```sh
P2P_CHAT_DIRECTORY_URL=https://directory.example.com npm run tauri dev
```
### Executando duas instâncias localmente (para realmente testar mensagens)

Cada instância precisa de sua própria identidade. O Seal suporta múltiplas contas
nativamente (Configurações → Contas neste dispositivo), mas para dois *processos
separados* na mesma máquina, `P2P_CHAT_PROFILE` é o caminho mais rápido: ele
cria automaticamente (primeira vez) ou retoma automaticamente (todas as vezes depois) uma conta
com esse nome, de forma não interativa, pulando completamente o seletor de contas:```sh
# terminal 1
P2P_CHAT_PROFILE=alice npm run tauri dev

# terminal 2
P2P_CHAT_PROFILE=bob npm run tauri dev
```
A escolha do servidor (`server.json`) e a lista de contas (`accounts.json`)
são compartilhadas entre os processos em uma mesma máquina, não por perfil. A
primeira instância que você iniciar escolhe o servidor, e todos os perfis seguintes
(incluindo `bob` aqui) o reutilizam silenciosamente. Ambas as janelas terminam no
mesmo servidor de diretório incorporado, então vocês podem adicionar um ao outro como contatos por ID
e trocar mensagens entre elas.

O servidor de desenvolvimento do Vite precisa de uma porta real e fixa para o webview do Tauri apontar,
o que normalmente significa que apenas um `npm run tauri dev` pode ser executado por vez — a
segunda instância encontraria a porta 1420 já ocupada e falharia imediatamente.
`npm run tauri` é, na verdade, um pequeno wrapper (`apps/desktop/scripts/tauri.mjs`)
que escolhe a próxima porta livre (1421, 1422, …) para cada instância após a
primeira e a conecta automaticamente, então executar os dois comandos acima
em dois terminais simplesmente funciona; você não precisa fazer nada de diferente. Ele
só altera o comportamento para `dev` — `npm run tauri build` e todo o resto
passa direto para a CLI real.

### Testando contra uma build real (não modo dev)```sh
./scripts/run-two-mac-instances.sh          # profiles: alice, bob
./scripts/run-two-mac-instances.sh carol dave
```
Mesma ideia de acima, mas inicia o aplicativo realmente compilado (saída de `build-mac-app.sh` /
`build-mac-dmg.sh`, ou uma cópia instalada em `/Applications`) duas vezes
com diferentes `P2P_CHAT_PROFILE`s em vez de `npm run tauri dev`, mais próximo
do que um usuário real executa. Mostra os PIDs e como interromper ambos.

### Depuração

- **Logs Rust**: defina `RUST_LOG` antes de iniciar, ex.:
  `RUST_LOG=debug npm run tauri dev` (ou `RUST_LOG=p2p_core=debug,net=debug`
  para restringir). Os campos registrados são limitados a metadados (IDs de
  peer/grupo/usuário, tipos de erro); veja [`docs/SECURITY.md`](https://github.com/emn4tor/seal/blob/main/docs/SECURITY.md) para saber por que
  é seguro deixá-los detalhados.
- **Frontend**: a janela de desenvolvimento é um webview real; clique com o botão direito → Inspecionar
  Elemento (ou abra as ferramentas de desenvolvedor) funciona como um navegador normal.
- **Crates de backend isoladamente**: cada crate tem sua própria suíte de testes que você pode
  executar e iterar sem tocar na interface; veja §4.
- **Um servidor de diretório autônomo**, em vez do embutido: veja §5.

---

## 4. Testes```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. Configuração do backend (servidor de diretório)

Recapitulando o que isso realmente é, já que é fácil imaginar demais: um axum
processo, um arquivo SQLite, três tipos de registro (chaves públicas,
anúncios de presença de curta duração, listas de grupo), todas as escritas assinadas pela
própria chave de identidade do chamador. Ele nunca está no caminho de uma mensagem. Veja
[`docs/THREAT_MODEL.md`](https://github.com/emn4tor/seal/blob/main/docs/THREAT_MODEL.md) para entender por que isso é verdade
estruturalmente, não apenas por política: o `Cargo.toml` do `directory-server` não
depende nem mesmo dos crates que sabem ler o conteúdo das mensagens.

### Caminho mais rápido: o script de configuração```sh
sudo ./scripts/setup-backend.sh
```
Interativo, apenas Linux + systemd (veja o cabeçalho do script para saber o porquê). Ele
pergunta em qual família de distro você está (Debian/Ubuntu, Fedora/RHEL/Rocky/Alma,
Arch/Manjaro ou openSUSE, pré-preenchida com uma suposição de `/etc/os-release`,
então normalmente é só uma tecla para confirmar) e instala os pré-requisitos
de compilação dessa distro com uma função dedicada por família, oferece instalar o Rust
via `rustup` se estiver faltando, compila o binário de release, cria um usuário
de sistema dedicado, gera um token de administrador, pergunta se você quer que ele
configure um domínio com HTTPS automático via [Caddy](https://caddyserver.com)
(instalando o próprio Caddy, por distro, recorrendo ao binário estático oficial
do Caddy se o pacote da distro não estiver disponível), ou apenas fazer bind
em loopback/HTTP simples se você preferir expô-lo você mesmo, depois grava e
ativa o serviço systemd. Seguro para reexecutar.
Tudo abaixo é o que ele realmente faz, se você preferir fazer manualmente
ou entender antes de executá-lo.

### macOS: um servidor de teste rápido na LAN```sh
./scripts/run-mac-test-server.sh
```
Não é para hospedagem real: para testar o aplicativo em dois dispositivos na mesma
rede (ex.: seu Mac + outra máquina, ou duas pessoas no mesmo Wi-Fi)
sem configurar domínio, TLS ou systemd (que não existe no macOS
de qualquer forma). Ele compila o binário de release, gera um token de administrador (reutilizado em
execuções posteriores), vincula a API pública a todas as interfaces e imprime a URL a
usar: o IP LAN real do seu Mac (via `ipconfig getifaddr`), não apenas
`127.0.0.1`, para que outros dispositivos também possam alcançá-lo. A porta de administração permanece em
somente loopback. Executa em primeiro plano; `Ctrl-C` interrompe. Os dados ficam em
`~/.seal-test-server`.

### Execução 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
```
| Variável | Obrigatório | Significado |
|---|---|---|
| `DIRECTORY_DB_PATH` | não (padrão `directory.sqlite3`, diretório de trabalho atual) | Onde o arquivo SQLite único fica. O diretório pai deve existir. |
| `DIRECTORY_PUBLIC_ADDR` | não (padrão `0.0.0.0:8080`) | A API de rendezvous com a qual os apps falam. Pode ser exposta publicamente. |
| `DIRECTORY_ADMIN_ADDR` | não (padrão `127.0.0.1:8090`) | O endpoint de purga. Mantenha-o fora da internet pública; veja abaixo. |
| `DIRECTORY_ADMIN_TOKEN` | **sim** | Token Bearer para a API de administração. O processo se recusa a iniciar sem um. Gere com `openssl rand -hex 32` ou similar; não o reutilize em nenhum outro lugar. |

O processo registra em log quais endereços ele vinculou na inicialização e avisa alto se
`DIRECTORY_ADMIN_ADDR` não for loopback.

### Apontando o aplicativo para ele

Três maneiras, na ordem em que você normalmente as usaria:

1. **Tela da primeira execução**: escolha "Custom server" e digite a URL. Veja §3.
2. **Configurações → Directory server**: altere depois; tem efeito no próximo
   reinício.
3. **`P2P_CHAT_DIRECTORY_URL`**, definida antes de iniciar: pula a pergunta
   completamente e substitui o que foi salvo, útil para execuções de desenvolvimento/script:   ```sh
   P2P_CHAT_DIRECTORY_URL=https://directory.example.com npm run tauri dev
   ```
Todos os que querem encontrar-se uns aos outros precisam de apontar para a *mesma*
instância de diretório; é assim que se procuram uns aos outros em primeiro lugar.

### Executá-lo como um serviço real (systemd)

<details>
<summary>Mostrar a unit do systemd + notas</summary>```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** aqui de propósito; coloque um
  proxy reverso na frente para TLS (abaixo) em vez de expor o axum diretamente
  à internet.
- Crie o usuário/grupo de sistema `seal-directory` e
  `/var/lib/seal-directory` primeiro (`useradd --system --no-create-home
  seal-directory && install -d -o seal-directory -g seal-directory
  /var/lib/seal-directory`) e copie o binário `directory-server` compilado
  (de `target/release/`) para `/usr/local/bin/`.
- Coloque o token de administrador em um `EnvironmentFile` legível apenas por root, não diretamente
  no arquivo de unidade (arquivos de unidade geralmente são legíveis por todos).

</details>

### TLS através de um proxy reverso

<details>
<summary>Mostrar a configuração do Caddy / nginx</summary>

[Caddy](https://caddyserver.com) fornece HTTPS automático com o mínimo de
configuração:```
# /etc/caddy/Caddyfile
directory.example.com {
    reverse_proxy 127.0.0.1:8080
}
```
`caddy run` (ou `systemctl enable --now caddy`) trata da emissão/renovação de certificados por conta própria. Se preferir usar o nginx, finalize o TLS nele e use `proxy_pass http://127.0.0.1:8080;`, já que o aplicativo só precisa de HTTP simples do ponto de vista do proxy.

Em relação ao firewall: apenas a porta pública precisa estar acessível de fora (`8080` nos exemplos acima, atrás da 443 via proxy). A porta administrativa nunca deve estar acessível de fora; acesse-a via encaminhamento de porta SSH (`ssh -L 8090:127.0.0.1:8090 seu-servidor`) quando precisar executar uma purga remotamente.

</details>

### Purgando```sh
cargo run --release -p directory-server --bin directory-admin -- \
  --admin-url http://127.0.0.1:8090 --token "$DIRECTORY_ADMIN_TOKEN" purge
```
Isto elimina o ficheiro SQLite e recria um esquema vazio: não há instruções
`DELETE`, nem estado parcial. É seguro executar sem avisar ninguém primeiro:
cada registo nele é um cache de dados que cada cliente já possui localmente
(o seu próprio registo, presença e quaisquer listas de grupos de que seja
membro), pelo que os clientes apenas o voltam a preencher momentos após a
sua próxima ação. Não há deliberadamente nenhuma política de cópias de
segurança para esta base de dados; consulte
[`docs/SECURITY.md`](https://github.com/emn4tor/seal/blob/main/docs/SECURITY.md) para saber por que razão manter uma
comprometeria todo o propósito.

---

## 6. Usar a aplicação

1. **Primeiro arranque, primeira pergunta**: qual servidor de diretório usar (§3).
   O padrão é o que estiver incorporado na compilação que você está a executar (um servidor
   de teste local, a menos que quem o compilou tenha configurado um oficial); escolha
   "Servidor personalizado" para apontar para um que você ou alguém em quem confie hospede.
2. **Escolha um nome de exibição.** Isto gera um par de chaves privadas no seu dispositivo
   (nada para lembrar e nada recuperável se perdido: isso é deliberado) e orienta-o através
   de uma breve explicação na aplicação sobre como a encriptação realmente funciona. Pode
   repeti-la em qualquer altura a partir das Definições. Cada arranque posterior volta a
   entrar diretamente, sem qualquer pedido; isto só acontece uma vez por conta. Adicione
   mais contas (identidades totalmente separadas) a partir de Definições → Contas neste
   dispositivo e alterne entre elas sem reiniciar.
3. **Adicionar alguém**: clique em **+** ao lado de "Mensagens diretas" e introduza o ID da pessoa
   (encontrado nas Definições → A Minha Identidade). Não há diretório para navegar, de propósito;
   a ligação é feita da mesma forma que se partilharia um número de telefone.
4. **Envie-lhes uma mensagem**: escolha o nome da pessoa na lista e escreva. A primeira
   mensagem para alguém estabelece automaticamente uma sessão encriptada.
5. **Iniciar um grupo**: clique em **+** na barra de ícones, dê-lhe um nome e convide pessoas
   pelo ID da mesma forma. Remover alguém roda a chave do grupo para que essa pessoa não
   consiga ler nada enviado posteriormente.
6. **Eliminar tudo**: Definições → Dados e Privacidade. Isto é instantâneo, apenas local e irreversível:
   destrói as suas chaves, contactos e historial *neste dispositivo* e não tem qualquer efeito nas pessoas
   com quem falou.
Baixar ferramenta