Files
acaua/docs/pt-BR/arquitetura.md
T
Lucas RayanandClaude Sonnet 5 1b974bb90d chore: initial project skeleton
Acauã: Network Detection & Threat Hunting, heuristic analysis over a
rolling 7-day window using deterministic math (time series, graph
theory, information theory) instead of opaque ML models. Third
product in the Ciberfauna ecosystem, alongside Guará and Sabiá.

Follows the ecosystem's established conventions: OpenWolf project
memory, bilingual PT-BR/EN docs and UI, Gitea Actions CI/CD on the
same self-hosted runners, Conventional Commits, SemVer, logo and
productName handling, MIT OR Apache-2.0 licensing.

Architecture decision (made with the project owner after a dedicated
consultation, not the original blueprint's suggested stack): Rust
throughout, not Python/FastAPI/React. Most of the statistics (Bowley
skew, MADM, Shannon entropy, PCR, Z-score, novel-edge detection,
pivot chains) reduces to SQL over an embedded DuckDB/Parquet store;
only the spectral analysis and graph centrality need host-language
code, and both have workable Rust crates. Documented in full, including
six corrections to the original blueprint's math (Rayleigh/Schuster
instead of a degenerate Lomb-Scargle over bare timestamps, an explicit
sentinel for Bowley skew's Q3=Q1 case, Jensen-Shannon instead of
unbounded KL, a dedicated long-connection detector, JA4 vs. JA4+
licensing caution, deterministic per-alert evidence), in
docs/architecture.md.

Skeleton only: crates/acaua-core has the four detection pillars,
fusion, storage, zeek log parsing and the updater as typed stubs that
compile and return a clear "skeleton" status rather than real
detection logic — that is separate, future work. crates/acaua-cli has
serve/analyze/doctor/update. apps/gui is a minimal Tauri shell. Also
already includes the one-click desktop self-update mechanism shared
with Guará and Sabiá (AppImage/.deb/Windows installer), even with no
release published yet, for consistency across the ecosystem.

No Gitea repository exists for this project yet; this is a local-only
commit.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VAyr8d7HuAdUGB6aA5xmDD
2026-10-31 10:20:03 -03:00

8.2 KiB
Raw Blame History

Arquitetura

English · Português

O Acauã é um único produto Rust: um daemon/CLI, um núcleo compartilhado, uma UI web embutida e um shell Tauri. O runtime distribuído não tem Python nem banco externo. Este documento registra as decisões estruturais e as seis correções aplicadas ao blueprint original.

Stack

Camada Escolha Por quê
Núcleo, CLI e daemon Rust 2021 Uma toolchain, segurança de memória, sem dependência de runtime
API HTTP Axum + Tokio + Tower HTTP Superfície async pequena e fácil de embutir
UI HTML/CSS/JS vanilla Sem etapa de build de frontend, assets embutidos no binário
Desktop Tauri 2 Janela nativa sobre a mesma UI
Armazenamento analítico DuckDB + Parquet (feature opcional duckdb) Embutido, colunar, local-first
Validação científica Python só em research/ astropy/scipy/networkx para fixtures, nunca distribuído

O workspace tem dois crates: acaua-core e acaua-cli. A GUI fica em apps/gui, fora do workspace Cargo, como no Guará e no Sabiá. A spec citou version.workspace = true para o manifesto do desktop; manter a GUI fora do workspace torna isso impossível, então o check.sh impõe igualdade de SemVer entre Cargo.toml, acaua-cli/Cargo.toml, o manifesto do desktop e tauri.conf.json. É um desvio deliberado, não um esquecimento.

Componentes

Logs Zeek ──► acaua-core::zeek ──► eventos normalizados ──► armazenamento
                                        │
                                        ├──► pilar1 (beaconing)
                                        ├──► pilar2 (sessões persistentes)
                                        ├──► pilar3 (anomalias de protocolo)
                                        └──► pilar4 (fusão) ──► alertas + evidência
                                                                  │
acaua-cli ──► API axum ──► UI embutida ◄── shell Tauri ────────────┘
  • zeek: parser limitado e confinamento de caminho. Nunca segue link simbólico para fora da raiz do dataset.
  • storage: escritor DuckDB/Parquet com TTL de sete dias. Desligado por padrão para o esqueleto não exigir build C++.
  • pillar1–pillar4: funções puras sobre eventos normalizados. Devolvem pontuação e evidência, nunca só um float.
  • fusion: combinação limitada e em ordem fixa. Precisa ser simétrica e reproduzível.
  • doctor: checagens do ambiente local; sem chamadas de rede exceto a checagem explícita de atualização.
  • update: cliente de Gitea Releases só para a CLI.

As seis correções

1. Rayleigh/Schuster, não Lomb–Scargle puro

Timestamps de eventos são um processo pontual unidimensional: não existe um y para ajustar. O periodograma primário é, portanto, Rayleigh/Schuster:

P(f) = |sum_k exp(2*pi*i*f*t_k)|^2 / N

O Lomb–Scargle generalizado só é usado quando existe um y real (por exemplo, bytes por bucket). Isso evita inventar uma variável dependente e mantém a distribuição nula honesta.

2. Bowley com sentinela explícito

O coeficiente de Bowley usa quartis. Quando Q3 == Q1, o denominador é zero; a implementação devolve um sentinela documentado (0.0 com a flag de evidência degenerate_quartiles) em vez de NaN, infinito ou panic. O sentinela faz parte do registro do alerta, não é fallback silencioso.

3. Jensen–Shannon, não KL puro

KL diverge quando a distribuição de referência tem zero onde a observada não tem. A fusão usa Jensen–Shannon, que é simétrica, limitada e definida para bins com probabilidade zero com um piso de suavização documentado. Isso torna a pontuação comparável entre pilares e segura para histogramas esparsos.

4. Sessões persistentes têm detector próprio

Uma conexão aberta por horas nunca produz um intervalo curto, então um detector de beaconing pode ignorá-la. O pilar 2 pontua duração, lacunas ociosas e fluxos longos repetidos diretamente. Os dois pilares podem disparar; a fusão trata isso como evidências separadas, não como contagem dupla do mesmo sinal.

5. Cautela com a licença JA4

A impressão digital JA4 de cliente TLS pode ser usada. JA4S, JA4H, JA4X, JA4SSH e JA4L têm licença não-OSI e não são habilitadas por padrão. Qualquer uso futuro exige decisão explícita de licenciamento e opt-in documentado. O conjunto padrão precisa continuar redistribuível sob MIT/Apache-2.0.

6. Determinismo e evidência JSON por alerta

Todo alerta carrega um registro JSON: hash do dataset, versão do código, pilar, entradas, valores intermediários, sentinelas, pesos e pontuação final. As reduções rodam em ordem fixa; iteração de hash map ou agendamento de threads não pode mudar uma pontuação. Com a mesma entrada e versão, a evidência precisa ser byte a byte idêntica.

Fluxo de dados

  1. acaua analyze <dir> valida o diretório, lê logs suportados e normaliza eventos. Neste esqueleto ele valida e devolve um relatório stub.
  2. Eventos normalizados vão para o armazenamento local (quando a feature duckdb está ligada) com TTL de sete dias.
  3. Cada pilar roda sobre uma janela determinística e devolve candidatos com evidência.
  4. A fusão combina candidatos, aplica limiares e grava alertas.
  5. serve expõe a API e a UI embutida; o shell Tauri abre a mesma UI contra um daemon local ou remoto.

API

Método Caminho Finalidade
GET /api/health Liveness e versão
GET /api/status Uptime, diretório de dados, estado dos pilares
GET /api/alerts Alertas paginados com evidência
POST /api/analyze Analisar um caminho de dataset
POST /api/update Checar atualização da CLI
GET /logo.png Asset de marca embutido
GET /* Fallback da UI embutida

O serve escuta em 127.0.0.1:8787 por padrão. Não há camada de autenticação no esqueleto; expor em interface de rede exige proxy reverso com autenticação.

Armazenamento

DuckDB é dependência opcional (features = ["duckdb"], bundled). O esqueleto padrão não compila o backend C++. Quando ligado, o schema é de eventos normalizados append-only mais uma tabela de alertas, com exportação Parquet e retenção de sete dias. O arquivo do banco fica sob o diretório de dados configurado e nunca fora dele.

Atualizações

update.rs consulta a API de Gitea Releases do repositório acaua, escolhe o asset da plataforma atual, baixa por HTTPS com curl, verifica SHA-256 e substitui o binário da CLI. Ele se recusa a atualizar automaticamente uma GUI em execução; o desktop só informa que existe versão nova. Isso espelha o updater do Sabiá e evita um segundo mecanismo de atualização.

O plugin updater do Tauri e seu fluxo de manifesto e assinatura não são usados de propósito: adicionariam um segundo caminho de assinatura e distribuição, e o desktop não deve se auto-atualizar. O caminho único da CLI é mais fácil de auditar e mantém os assets de release em tarballs mais SHA-256.

Alternativas rejeitadas

Um blueprint anterior propunha um serviço Python e um banco colunar externo. Os dois são rejeitados. Um serviço Python adicionaria um segundo runtime, custo de empacotamento e uma fronteira de rede dentro de uma ferramenta local-first; um banco externo adicionaria servidor e custo operacional para datasets que cabem em um armazenamento colunar embutido. O produto é 100% Rust, com Python confinado a research/.

Implantação

  • Nativa: cargo build --release -p acaua-cli, depois acaua serve.
  • Desktop: bundles Tauri para Linux e Windows, construídos no CI.
  • Docker: imagem enxuta de runtime para laboratório; veja docker.md.

Comportamento em falha

Entrada malformada é ignorada com diagnóstico contado e limitado. Log ausente não é fatal. Store corrompido é reportado pelo doctor e nunca recriado por cima de dados existentes. Atualização falha mantém o binário atual.

Versionamento e compatibilidade

SemVer 2.0.0. O JSON de evidência carrega versão de schema. Qualquer mudança em pontuação ou no formato da evidência é quebra para versões menores 0.x e precisa constar no changelog.