Files
acaua/docs/pt-BR/arquitetura.md
T
Lucas RayanandClaude Sonnet 5 8a80504c45
Release / Plan (reuse the published image?) (push) Successful in 3s
CI / Docker image (build and smoke test) (push) Skipped
CI / Format and clippy (push) Successful in 4m32s
CI / Dependency audit (push) Successful in 11s
CI / Tests (Linux) (push) Successful in 9m15s
Release / ci (push) Successful in 9m18s
Release / Build image (arm64) (push) Failing after 7m7s
Release / Build image (amd64) (push) Failing after 13m53s
Release / Publish tags (push) Skipped
Release / Gitea release (push) Skipped
refactor: distribute Acaua as a Docker image instead of a desktop app
Acaua is a collective SOC daemon consuming only Zeek log files, not a
single-user tool needing local hardware like its siblings. Drop the
Tauri desktop shell, installers and self-update entirely; the server
and its web dashboard ship as a container, updated by pulling a new
image tag.

Link against the official prebuilt libduckdb instead of compiling it
from source via the bundled feature, cutting image build time from
15+ minutes to about 3. Fix a real bug found along the way: as PID 1
in a container, the daemon ignored SIGTERM and was always killed
after the stop timeout; it now shuts down gracefully.

Also corrects the Pillar 1 beaconing score: the period estimate had a
harmonic alias (a perfectly periodic 4h series resolved to 600s), and
the old score formula flagged pure random traffic as suspicious
(p95 = 0.839 on Poisson noise). The new formula was validated against
300 samples per scenario.

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

7.6 KiB
Raw Blame History

Arquitetura

English · Português

O Acauã é um produto único em Rust: um daemon/CLI, um núcleo compartilhado e um dashboard web embutido. 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 Motivo
Core, CLI e daemon Rust 2021 (MSRV 1.88) Toolchain única, segurança de memória, sem dependências externas de runtime
API HTTP Axum + Tokio + Tower HTTP Superfície assíncrona enxuta, fácil de embutir
Dashboard Web HTML/CSS/JS vanilla Sem etapa de build de frontend, assets embutidos no binário via rust-embed
Armazenamento analítico DuckDB + Parquet Armazenamento colunar embutido obrigatório, linkado à libduckdb.so oficial pré-compilada
Implantação Docker / docker-compose Daemon de SOC coletivo, usuário não-root sem privilégios, rootfs somente leitura
Validação científica Python apenas em research/ astropy/scipy/networkx para fixtures, nunca distribuído

O workspace possui dois crates: acaua-core e acaua-cli. Ambos utilizam version.workspace = true.

Componentes

Logs Zeek ──► acaua-core::zeek ──► eventos normalizados ──► storage
                                      │
                                      ├──► pillar1 (beaconing)
                                      ├──► pillar2 (sessões persistentes)
                                      ├──► pillar3 (anomalias de protocolo)
                                      └──► pillar4 (fusão) ──► alertas + evidência
                                                                    │
acaua-cli (serve) ──► API axum ──► dashboard web embutido ──────────┘
  • zeek: parser delimitado e confinamento de caminhos. Nunca segue symlink fora da raiz do dataset.
  • storage: motor DuckDB em memória sobre arquivos Parquet particionados por dia com TTL de sete dias.
  • pillar1–pillar4: funções puras sobre eventos normalizados. Retornam scores e evidência, nunca apenas um float.
  • fusion: combinação limitada em ordem fixa. Deve ser simétrica e reproduzível.
  • doctor: checagens do ambiente local; reporta linkagem da DuckDB pré-compilada e status do Zeek em container.
  • update: checa novas versões consultando a API de Releases do Gitea.

As seis correções

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

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

P(T) = (2 / N) * [ (sum cos(2*pi*t_i / T))^2 + (sum sin(2*pi*t_i / T))^2 ]

Lomb–Scargle generalizado fica reservado para a extensão futura que avaliará um atributo real de resposta (como tamanho de payload ou duração) contra o tempo.

2. Proteger o caso de dispersão zero no MADM

Um beacon sintético ou sem jitter produz intervalos perfeitamente iguais. O desvio absoluto mediano em relação à mediana (MADM) é então 0.0. Dividir por 0.0 ou tratá-lo como dado ausente é incorreto: dispersão zero é o resultado mais suspeito possível. A implementação protege esse caso com atribuição explícita de score (1.0) e sentinela documentado.

3. Substituir assimetria de Pearson por assimetria de Bowley

A assimetria amostral baseada no terceiro momento central é sensível a outliers individuais e pode divergir. A assimetria de Bowley utiliza quartis:

B = (Q3 + Q1 - 2*Q2) / (Q3 - Q1)

Ela é limitada em [-1.0, 1.0] por definição e resistente a outliers extremos. Quando Q3 == Q1 (dados concentrados), a implementação atribui 0.0 com flag sentinela.

4. Isolar o espaço de pesquisa Python

research/ tem seu próprio ambiente virtual e dependências. Ele é excluído do workspace Cargo, ignorado em builds Docker e releases de CI, e testado apenas quando scripts de validação de pesquisa forem invocados diretamente.

5. Modo degradado documentado para NetFlow/IPFIX

NetFlow v9 e IPFIX não carregam nomes de consulta DNS, SNI TLS, cadeias de certificados ou cabeçalhos HTTP. Qualquer análise que dependa de recursos de protocolo fica indisponível. O Acauã documenta isso como modo degradado e nunca alega paridade entre registros de fluxo e logs Zeek completos.

6. Fronteira única HTTP e RPC

O daemon expõe uma API Axum em loopback por padrão. A UI web embutida se comunica com o daemon exclusivamente por chamadas HTTP padrão.

API

A API HTTP é servida por acaua serve:

Método Caminho Significado
GET /api/health Liveness e versão
GET /api/status Uptime, diretório de dados, sumário do dataset
GET /api/alerts Alertas paginados com evidência
POST /api/analyze Ingestão e análise de diretório de dataset
GET /api/update Checagem de novas releases
GET /logo.png Asset de marca embutido
GET /* Fallback de UI embutida (rust-embed)

serve escuta em 127.0.0.1:8787 por padrão. Expô-lo em uma rede externa exige um proxy reverso com autenticação.

Armazenamento

DuckDB é uma dependência obrigatória linkada dinamicamente à libduckdb.so oficial pré-compilada (versão 1.5.6 fixada com SHA-256 em scripts/fetch-libduckdb.sh). Extensões Parquet, JSON e ICU já vêm compiladas estaticamente na biblioteca oficial. O esquema consiste em arquivos Parquet particionados por dia sob o diretório de dados configurado, com consultas DuckDB em memória e TTL de sete dias.

Atualizações

Atualizações do Acauã são distribuídas por imagens de container (docker compose pull && docker compose up -d). O comando acaua update consulta a API de Releases do Gitea para ciberfauna/acaua e notifica os operadores quando uma tag de versão mais nova estiver disponível. A sobrescrita binária em disco (update --apply) foi removida: em um daemon de SOC coletivo orquestrado via container, atualizações devem ser controladas por puxar imagens novas em vez de processos que alteram o próprio executável.

Alternativas rejeitadas

  1. Serviço Python com FastAPI/ClickHouse: Rejeitado. Um runtime Python introduziria imagens pesadas e fronteiras de memória desnecessárias; o ClickHouse adicionaria um servidor externo e custo operacional para datasets que cabem perfeitamente em um armazenamento colunar embutido. O produto é 100% Rust.
  2. Aplicativo desktop (Tauri / AppImage / NSIS): Rejeitado. Diferente do Guará (forense em disco bruto local) e do Sabiá (hardware Wi-Fi em modo monitor), o Acauã não tem dependência de hardware local: é um daemon de SOC multiusuário consumindo logs do Zeek. Um wrapper desktop traria manutenção e superfície de segurança sem ganho operacional.

Implantação

  • Docker Compose (Oficial): Imagem multi-arch (git.lucasrguerra.dev.br/ciberfauna/acaua), rodando com usuário não-privilegiado acaua (UID 10001), filesystem somente leitura e capabilities revogadas.
  • Compilação nativa: scripts/fetch-libduckdb.sh ~/.cache/acaua/duckdb seguido de cargo build --release -p acaua-cli.

Comportamento em falhas

Entradas malformadas são ignoradas com diagnóstico delimitado e contado. Um log ausente não é fatal. Um banco corrompido é reportado pelo doctor e nunca recriado silenciosamente sobre dados existentes.

Versionamento e compatibilidade

SemVer 2.0.0. O JSON de evidência carrega uma versão de esquema. Qualquer alteração em uma pontuação ou no formato de evidência é breaking change para versões minor 0.x e deve constar no changelog.