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
This commit is contained in:
commit
1b974bb90d
95 files changed
+12016
No files matched your search
@@ -0,0 +1,177 @@
|
||||
# Architecture
|
||||
|
||||
**English** · [Português](pt-BR/arquitetura.md)
|
||||
|
||||
Acauã is a single Rust product: one daemon/CLI, one shared core, one embedded
|
||||
web UI and one Tauri shell. The shipped runtime has no Python and no external
|
||||
database. This document records the structural decisions and the six
|
||||
corrections applied to the original blueprint.
|
||||
|
||||
## Stack
|
||||
|
||||
| Layer | Choice | Why |
|
||||
|---|---|---|
|
||||
| Core, CLI and daemon | Rust 2021 | One toolchain, memory safety, no runtime dependency |
|
||||
| HTTP API | Axum + Tokio + Tower HTTP | Small async surface, easy to embed |
|
||||
| UI | Vanilla HTML/CSS/JS | No frontend build step, assets embedded in the binary |
|
||||
| Desktop | Tauri 2 | Native window over the same UI |
|
||||
| Analytical store | DuckDB + Parquet (optional `duckdb` feature) | Embedded, columnar, local-first |
|
||||
| Scientific validation | Python in `research/` only | astropy/scipy/networkx for fixtures, never shipped |
|
||||
|
||||
The workspace has two crates: `acaua-core` and `acaua-cli`. The GUI lives in
|
||||
`apps/gui`, **outside** the Cargo workspace, as in Guará and Sabiá. The spec
|
||||
mentioned `version.workspace = true` for the desktop manifest; keeping the GUI
|
||||
outside the workspace makes that impossible, so `check.sh` enforces SemVer
|
||||
equality across `Cargo.toml`, `acaua-cli/Cargo.toml`, the desktop manifest and
|
||||
`tauri.conf.json` instead. This is a deliberate deviation, not an oversight.
|
||||
|
||||
## Components
|
||||
|
||||
```
|
||||
Zeek logs ──► acaua-core::zeek ──► normalized events ──► storage
|
||||
│
|
||||
├──► pillar1 (beaconing)
|
||||
├──► pillar2 (persistent sessions)
|
||||
├──► pillar3 (protocol anomalies)
|
||||
└──► pillar4 (fusion) ──► alerts + evidence
|
||||
│
|
||||
acaua-cli ──► axum API ──► embedded UI ◄── Tauri shell ─────────────┘
|
||||
```
|
||||
|
||||
- `zeek`: bounded parser and path confinement. It must never follow a symlink
|
||||
outside the dataset root.
|
||||
- `storage`: DuckDB/Parquet writer with a seven-day TTL. Disabled by default so
|
||||
the skeleton does not require a C++ build.
|
||||
- `pillar1`–`pillar4`: pure functions over normalized events. They return
|
||||
scores plus evidence, never only a float.
|
||||
- `fusion`: fixed-order, bounded combination. It must be symmetric and
|
||||
reproducible.
|
||||
- `doctor`: local environment checks; no network calls except an explicit
|
||||
update check.
|
||||
- `update`: Gitea Releases client for the CLI only.
|
||||
|
||||
## The six corrections
|
||||
|
||||
### 1. Rayleigh/Schuster, not pure Lomb–Scargle
|
||||
|
||||
Event timestamps are a one-dimensional point process: there is no `y` value to
|
||||
fit. The primary periodogram is therefore Rayleigh/Schuster:
|
||||
|
||||
```text
|
||||
P(f) = |sum_k exp(2*pi*i*f*t_k)|^2 / N
|
||||
```
|
||||
|
||||
Generalized Lomb–Scargle is used only when a real `y` exists (for example bytes per bucket).
|
||||
This avoids inventing a dependent variable and keeps the null distribution
|
||||
honest.
|
||||
|
||||
### 2. Bowley skew with an explicit sentinel
|
||||
|
||||
The Bowley coefficient uses quartiles. When `Q3 == Q1`, the denominator is zero;
|
||||
the implementation returns a documented sentinel (`0.0` with an
|
||||
`degenerate_quartiles` evidence flag) instead of `NaN`, infinity or a panic. The
|
||||
sentinel is part of the alert record, not a silent fallback.
|
||||
|
||||
### 3. Jensen–Shannon, not raw KL
|
||||
|
||||
KL diverges when the reference distribution has a zero where the observed
|
||||
distribution does not. Fusion uses Jensen–Shannon, which is symmetric, bounded
|
||||
and defined for zero-probability bins with a small documented smoothing floor.
|
||||
This makes the score comparable across pillars and safe for sparse protocol
|
||||
histograms.
|
||||
|
||||
### 4. Persistent sessions get their own detector
|
||||
|
||||
A connection that stays open for hours never produces a short inter-arrival
|
||||
time, so a beaconing detector can miss it entirely. Pillar 2 scores duration,
|
||||
idle gaps and repeated long-lived flows directly. The two pillars may both fire;
|
||||
fusion treats that as separate evidence, not double counting of the same signal.
|
||||
|
||||
### 5. JA4 license caution
|
||||
|
||||
The client TLS JA4 fingerprint is usable. JA4S, JA4H, JA4X, JA4SSH and JA4L
|
||||
carry a non-OSI license and are **not** enabled by default. Any future use needs
|
||||
an explicit licensing decision and a documented opt-in. The default feature set
|
||||
must remain redistributable under MIT/Apache-2.0.
|
||||
|
||||
### 6. Determinism and per-alert JSON evidence
|
||||
|
||||
Every alert carries a JSON record: dataset hash, code version, pillar, inputs,
|
||||
intermediate values, sentinels, weights and final score. Reductions run in a
|
||||
fixed order; no hash-map iteration or thread scheduling may change a score.
|
||||
Given the same input and version, the evidence must be byte-identical.
|
||||
|
||||
## Data flow
|
||||
|
||||
1. `acaua analyze <dir>` validates the directory, reads supported logs and
|
||||
normalizes events. In this skeleton it validates and returns a stub report.
|
||||
2. Normalized events are written to the local store (when the `duckdb` feature
|
||||
is enabled) with a seven-day TTL.
|
||||
3. Each pillar runs over a deterministic window and returns candidate scores
|
||||
with evidence.
|
||||
4. Fusion combines candidates, applies thresholds and writes alerts.
|
||||
5. `serve` exposes the API and the embedded UI; the Tauri shell can open the same
|
||||
UI against a local or remote daemon.
|
||||
|
||||
## API
|
||||
|
||||
| Method | Path | Purpose |
|
||||
|---|---|---|
|
||||
| GET | `/api/health` | Liveness and version |
|
||||
| GET | `/api/status` | Uptime, data directory, pillar state |
|
||||
| GET | `/api/alerts` | Paginated alerts with evidence |
|
||||
| POST | `/api/analyze` | Analyze a dataset path |
|
||||
| POST | `/api/update` | Check for a CLI update |
|
||||
| GET | `/logo.png` | Embedded brand asset |
|
||||
| GET | `/*` | Embedded UI fallback |
|
||||
|
||||
`serve` binds to `127.0.0.1:8787` by default. There is no authentication layer in
|
||||
the skeleton; exposing it on a network interface requires an authenticating
|
||||
reverse proxy.
|
||||
|
||||
## Storage
|
||||
|
||||
DuckDB is an **optional** dependency (`features = ["duckdb"]`, `bundled`). The
|
||||
default skeleton does not compile the C++ backend. When enabled, the schema is
|
||||
append-only normalized events plus an alerts table, with Parquet export and a
|
||||
seven-day retention job. The database file lives under the configured data
|
||||
directory and never outside it.
|
||||
|
||||
## Updates
|
||||
|
||||
`update.rs` queries the Gitea Releases API for the `acaua` repository, selects
|
||||
the asset for the current platform, downloads over HTTPS with `curl`, verifies
|
||||
SHA-256 and replaces the CLI binary. It refuses to update a running GUI
|
||||
automatically; the desktop only reports that a new version exists. This mirrors
|
||||
the Sabiá updater and avoids a second update mechanism.
|
||||
|
||||
The Tauri updater plugin, its `latest.json` manifest, `updater.pubkey` and
|
||||
`createUpdaterArtifacts` are intentionally not used: they would add a second
|
||||
signing and distribution path, and the desktop must not self-update. The single
|
||||
CLI path is easier to audit and keeps release assets to tarballs plus SHA-256.
|
||||
|
||||
## Rejected alternatives
|
||||
|
||||
An earlier blueprint proposed a Python service with FastAPI and ClickHouse.
|
||||
Both are rejected. A Python service would add a second runtime, packaging burden
|
||||
and a network boundary inside a local-first tool; ClickHouse would add an
|
||||
external server and operational cost for datasets that fit an embedded columnar
|
||||
store. The product is 100% Rust, with Python confined to `research/`.
|
||||
|
||||
## Deployment
|
||||
|
||||
- **Native:** `cargo build --release -p acaua-cli`, then `acaua serve`.
|
||||
- **Desktop:** Tauri bundles for Linux and Windows, built in CI.
|
||||
- **Docker:** a slim runtime image for lab use; see [docker.md](docker.md).
|
||||
|
||||
## Failure behavior
|
||||
|
||||
Malformed input is skipped with a counted, bounded diagnostic. A missing log is
|
||||
not fatal. A corrupt store is reported by `doctor` and never silently recreated
|
||||
over existing data. A failed update leaves the current binary in place.
|
||||
|
||||
## Versioning and compatibility
|
||||
|
||||
SemVer 2.0.0. Evidence JSON carries a schema version. Any change to a score or
|
||||
to the evidence shape is a breaking change for `0.x` minor versions and must be
|
||||
recorded in the changelog.
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
# Terminal
|
||||
|
||||
**English** · [Português](pt-BR/cli.md)
|
||||
|
||||
The `acaua` binary is both the CLI and the daemon. This page describes the
|
||||
commands that exist in the `0.1.0` skeleton. Detection is not implemented yet;
|
||||
`analyze` validates input and returns a stub report.
|
||||
|
||||
```text
|
||||
acaua <command> [options]
|
||||
|
||||
Commands:
|
||||
serve Start the API and embedded UI
|
||||
analyze Analyze a Zeek log directory
|
||||
doctor Check the local environment
|
||||
update Check or apply a CLI update
|
||||
```
|
||||
|
||||
## `acaua serve`
|
||||
|
||||
Starts the HTTP API and the embedded UI.
|
||||
|
||||
```bash
|
||||
acaua serve --bind 127.0.0.1:8787 --data-dir .acaua
|
||||
```
|
||||
|
||||
| Option | Default | Meaning |
|
||||
|---|---|---|
|
||||
| `--bind` | `127.0.0.1:8787` | Listen address |
|
||||
| `--data-dir` | `.acaua` | Store and runtime files |
|
||||
|
||||
The default bind is loopback-only. Exposing the daemon on a network requires a
|
||||
reverse proxy with authentication. The API is documented in
|
||||
[architecture.md](architecture.md#api).
|
||||
|
||||
## `acaua analyze`
|
||||
|
||||
```bash
|
||||
acaua analyze /var/log/zeek/current
|
||||
acaua analyze /var/log/zeek/current --json
|
||||
```
|
||||
|
||||
The directory is validated and a report is printed. In this skeleton the parser
|
||||
does not read Zeek records yet: `logs seen` and `records` are placeholders, and
|
||||
`alerts` is empty. The command is still useful to check path handling and the
|
||||
JSON shape.
|
||||
|
||||
The future parser will support `conn.log`, `dns.log`, `ssl.log` and the protocol
|
||||
logs needed for identity and lateral-movement features. NetFlow/IPFIX is a
|
||||
degraded mode; it is not equivalent to full protocol logs.
|
||||
|
||||
## `acaua doctor`
|
||||
|
||||
```bash
|
||||
acaua doctor
|
||||
acaua doctor --json
|
||||
```
|
||||
|
||||
Prints checks for Zeek, `curl`, `tar`, the optional DuckDB feature and the
|
||||
isolation of `research/`, followed by the status (`skeleton` in `0.1.0`). A
|
||||
missing optional dependency is reported as `falha` but does not abort the
|
||||
command. It does not send telemetry.
|
||||
|
||||
## `acaua update`
|
||||
|
||||
```bash
|
||||
acaua update
|
||||
acaua update --apply
|
||||
```
|
||||
|
||||
`update` queries the latest Gitea Release, compares the tag with the running
|
||||
version and prints whether an update exists. `--apply` downloads the archive for
|
||||
the current platform, verifies its SHA-256, extracts it and replaces the
|
||||
`acaua` binary.
|
||||
|
||||
Requirements: `curl` and `tar` on `PATH`, and a writable binary location. The
|
||||
updater refuses to replace any executable whose name is not `acaua`; the desktop
|
||||
app must be updated through its installer. A failed checksum leaves the current
|
||||
binary untouched.
|
||||
|
||||
## Exit codes
|
||||
|
||||
| Code | Meaning |
|
||||
|---|---|
|
||||
| `0` | Success |
|
||||
| `1` | Runtime error (invalid path, failed update, I/O error) |
|
||||
| `2` | Invalid command-line usage (clap) |
|
||||
|
||||
## Environment
|
||||
|
||||
The skeleton has no required environment variable. `RUST_LOG` is reserved for
|
||||
the future tracing layer. The default data directory is relative to the current
|
||||
working directory; use an absolute path for a system service.
|
||||
|
||||
## Examples
|
||||
|
||||
```bash
|
||||
# Local lab
|
||||
acaua doctor
|
||||
acaua analyze ./fixtures/zeek --json
|
||||
acaua serve --bind 127.0.0.1:8787 --data-dir ./.acaua
|
||||
|
||||
# Container
|
||||
docker run --rm -p 127.0.0.1:8787:8787 -v "$PWD/zeek:/data:ro" acaua serve
|
||||
```
|
||||
|
||||
See [docker.md](docker.md) for the image and volume layout.
|
||||
@@ -0,0 +1,67 @@
|
||||
# Docker
|
||||
|
||||
**English** · [Português](pt-BR/docker.md)
|
||||
|
||||
The image is for lab and research use. It runs the same `acaua` binary as a
|
||||
native install, with the embedded UI. The skeleton does not enable the DuckDB
|
||||
feature in the image; the store remains reserved for a later release.
|
||||
|
||||
## Build
|
||||
|
||||
```bash
|
||||
docker build -t acaua .
|
||||
docker run --rm -p 127.0.0.1:8787:8787 -v "$PWD/data/acaua:/data/acaua" acaua
|
||||
```
|
||||
|
||||
The build stage uses `rust:1-slim-bookworm`; the runtime stage uses
|
||||
`debian:bookworm-slim` and installs only `ca-certificates`, `curl` and `tar`
|
||||
(the updater needs `curl` and `tar`).
|
||||
|
||||
## Compose
|
||||
|
||||
```bash
|
||||
cp .env.example .env # optional: set ZEEK_INTERFACE
|
||||
docker compose up --build
|
||||
```
|
||||
|
||||
The Compose file starts two services:
|
||||
|
||||
| Service | Purpose | Notes |
|
||||
|---|---|---|
|
||||
| `zeek` | Capture and write Zeek logs to `./data/zeek` | Host network and `NET_RAW`/`NET_ADMIN` |
|
||||
| `acaua` | Read logs and serve the UI/API | Host port bound to `127.0.0.1:8787` |
|
||||
|
||||
`acaua` mounts `./data/zeek` read-only at `/data/zeek` and `./data/acaua`
|
||||
read-write at `/data/acaua`. The daemon inside the container binds
|
||||
`0.0.0.0:8787`, but the published port is loopback-only on the host.
|
||||
|
||||
## Data layout
|
||||
|
||||
```text
|
||||
data/
|
||||
zeek/ # Zeek logs, written by the zeek service
|
||||
acaua/ # store, exports and runtime files
|
||||
```
|
||||
|
||||
Do not mount the host root or a directory containing unrelated sensitive files.
|
||||
The parser is expected to confine paths to the dataset root; the skeleton does
|
||||
not parse records yet.
|
||||
|
||||
## Security notes
|
||||
|
||||
- The `zeek` service needs packet capture privileges. Run it only on an
|
||||
interface and network you are authorized to monitor.
|
||||
- Do not change the host port mapping to `0.0.0.0:8787` without an
|
||||
authenticating reverse proxy.
|
||||
- The image has no telemetry and no outbound connection except an explicit
|
||||
`acaua update`.
|
||||
- The container is not a sandbox for hostile datasets. Treat a malformed capture
|
||||
as hostile input and keep the container unprivileged.
|
||||
|
||||
## Limitations
|
||||
|
||||
- No DuckDB build in the image; the analytical store is not active.
|
||||
- The UI is a shell and `analyze` returns a stub report.
|
||||
- The image does not include Zeek; the Compose file uses the upstream Zeek
|
||||
image.
|
||||
- There is no published image registry yet. Build locally.
|
||||
@@ -0,0 +1,67 @@
|
||||
# Interface
|
||||
|
||||
**English** · [Português](pt-BR/interface.md)
|
||||
|
||||
The interface is a vanilla HTML/CSS/JS app embedded in the `acaua` binary and
|
||||
loaded by the Tauri shell. There is no frontend build step and no React/Next.js
|
||||
runtime. This page describes the `0.1.0` shell; it is not a screenshot tour,
|
||||
because the detection views have nothing real to show yet.
|
||||
|
||||
## Layout
|
||||
|
||||
- **Sidebar:** brand, navigation, connection state, version and update check.
|
||||
- **Overview:** scope notice, authorized-use notice and the four pillar cards.
|
||||
- **Analysis:** dataset path field, analyze button, refresh and raw JSON output.
|
||||
- **Alerts:** empty state explaining that the detection engine will arrive in a
|
||||
later spec.
|
||||
- **Settings:** language and theme, stored locally.
|
||||
|
||||
## Language
|
||||
|
||||
The source text is Portuguese. `i18n.js` applies English strings from
|
||||
`i18n-en.js` at runtime and persists the choice in `localStorage`. `Auto`
|
||||
follows the browser/system language. The check `node scripts/check-ui-i18n.mjs`
|
||||
fails when a visible Portuguese string has no English pair.
|
||||
|
||||
## Theme
|
||||
|
||||
`Auto`, light and dark are supported. `Auto` follows `prefers-color-scheme`. The
|
||||
choice is stored locally; no preference leaves the machine.
|
||||
|
||||
## Connection state
|
||||
|
||||
The footer polls `/api/health` and shows one of:
|
||||
|
||||
- **Connecting:** the first request has not finished.
|
||||
- **Local service online:** `/api/health` answered.
|
||||
- **Service unavailable:** the request failed; the shell remains usable for settings.
|
||||
|
||||
The Tauri shell can point at a local daemon or a remote `serve` in a future
|
||||
version. In `0.1.0` it uses the local API.
|
||||
|
||||
## Analysis view
|
||||
|
||||
`Analyze` posts the path to `/api/analyze` and prints the JSON response. The
|
||||
skeleton validates the path and returns a stub report. It does not parse Zeek
|
||||
records and does not render scores. Failures are shown as text, never as a
|
||||
silent empty state.
|
||||
|
||||
## Alerts view
|
||||
|
||||
The list is intentionally empty. A future alert row will show the pillar, score,
|
||||
timestamp and a link to the evidence record. The evidence must include inputs,
|
||||
intermediate values, sentinels, weights and the code version; a score alone is
|
||||
not enough.
|
||||
|
||||
## Accessibility
|
||||
|
||||
- Navigation uses real buttons and an `aria-label`.
|
||||
- The settings dialog uses `<dialog>` with a labelled title.
|
||||
- Status changes use text, not color alone.
|
||||
|
||||
## Limitations
|
||||
|
||||
- No real screenshots: the views are shells.
|
||||
- No alert detail, no charts and no dataset browser yet.
|
||||
- No authentication: the UI assumes a loopback daemon.
|
||||
- The desktop app does not self-update; it only reports an available version.
|
||||
@@ -0,0 +1,177 @@
|
||||
# Arquitetura
|
||||
|
||||
[English](../architecture.md) · **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:
|
||||
|
||||
```text
|
||||
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](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.
|
||||
@@ -0,0 +1,106 @@
|
||||
# Terminal
|
||||
|
||||
[English](../cli.md) · **Português**
|
||||
|
||||
O binário `acaua` é ao mesmo tempo CLI e daemon. Esta página descreve os comandos
|
||||
que existem no esqueleto `0.1.0`. A detecção ainda não está implementada; o
|
||||
`analyze` valida a entrada e devolve um relatório stub.
|
||||
|
||||
```text
|
||||
acaua <comando> [opções]
|
||||
|
||||
Comandos:
|
||||
serve Sobe a API e a UI embutida
|
||||
analyze Analisa um diretório de logs Zeek
|
||||
doctor Checa o ambiente local
|
||||
update Checa ou aplica atualização da CLI
|
||||
```
|
||||
|
||||
## `acaua serve`
|
||||
|
||||
Sobe a API HTTP e a UI embutida.
|
||||
|
||||
```bash
|
||||
acaua serve --bind 127.0.0.1:8787 --data-dir .acaua
|
||||
```
|
||||
|
||||
| Opção | Padrão | Significado |
|
||||
|---|---|---|
|
||||
| `--bind` | `127.0.0.1:8787` | Endereço de escuta |
|
||||
| `--data-dir` | `.acaua` | Store e arquivos de runtime |
|
||||
|
||||
O bind padrão é só loopback. Expor o daemon na rede exige proxy reverso com
|
||||
autenticação. A API está documentada em
|
||||
[arquitetura.md](arquitetura.md#api).
|
||||
|
||||
## `acaua analyze`
|
||||
|
||||
```bash
|
||||
acaua analyze /var/log/zeek/current
|
||||
acaua analyze /var/log/zeek/current --json
|
||||
```
|
||||
|
||||
O diretório é validado e um relatório é impresso. Neste esqueleto o parser ainda
|
||||
não lê registros Zeek: `logs lidos` e `registros` são placeholders, e `alertas`
|
||||
vem vazio. O comando continua útil para conferir tratamento de caminho e o
|
||||
formato JSON.
|
||||
|
||||
O parser futuro vai suportar `conn.log`, `dns.log`, `ssl.log` e os logs de
|
||||
protocolo necessários para identidade e movimento lateral. NetFlow/IPFIX é modo
|
||||
degradado; não equivale a logs completos de protocolo.
|
||||
|
||||
## `acaua doctor`
|
||||
|
||||
```bash
|
||||
acaua doctor
|
||||
acaua doctor --json
|
||||
```
|
||||
|
||||
Imprime checagens de Zeek, `curl`, `tar`, da feature opcional DuckDB e do
|
||||
isolamento de `research/`, seguida do estado (`skeleton` em `0.1.0`). Dependência
|
||||
opcional ausente aparece como `falha`, mas não aborta o comando. Não envia
|
||||
telemetria.
|
||||
|
||||
## `acaua update`
|
||||
|
||||
```bash
|
||||
acaua update
|
||||
acaua update --apply
|
||||
```
|
||||
|
||||
O `update` consulta a última Release do Gitea, compara a tag com a versão em
|
||||
execução e informa se existe atualização. O `--apply` baixa o arquivo da
|
||||
plataforma atual, verifica o SHA-256, extrai e substitui o binário `acaua`.
|
||||
|
||||
Requisitos: `curl` e `tar` no `PATH`, e local de binário com permissão de escrita.
|
||||
O updater se recusa a substituir qualquer executável cujo nome não seja `acaua`;
|
||||
o app desktop deve ser atualizado pelo instalador. Checksum inválido mantém o
|
||||
binário atual intacto.
|
||||
|
||||
## Códigos de saída
|
||||
|
||||
| Código | Significado |
|
||||
|---|---|
|
||||
| `0` | Sucesso |
|
||||
| `1` | Erro de execução (caminho inválido, update falhou, erro de I/O) |
|
||||
| `2` | Uso inválido da linha de comando (clap) |
|
||||
|
||||
## Ambiente
|
||||
|
||||
O esqueleto não exige variável de ambiente. `RUST_LOG` está reservado para a
|
||||
camada de tracing futura. O diretório de dados padrão é relativo ao diretório de
|
||||
trabalho; use caminho absoluto em serviço de sistema.
|
||||
|
||||
## Exemplos
|
||||
|
||||
```bash
|
||||
# Laboratório local
|
||||
acaua doctor
|
||||
acaua analyze ./fixtures/zeek --json
|
||||
acaua serve --bind 127.0.0.1:8787 --data-dir ./.acaua
|
||||
|
||||
# Contêiner
|
||||
docker run --rm -p 127.0.0.1:8787:8787 -v "$PWD/zeek:/data:ro" acaua serve
|
||||
```
|
||||
|
||||
Veja [docker.md](docker.md) para a imagem e o layout de volumes.
|
||||
@@ -0,0 +1,66 @@
|
||||
# Docker
|
||||
|
||||
[English](../docker.md) · **Português**
|
||||
|
||||
A imagem é para laboratório e pesquisa. Ela roda o mesmo binário `acaua` de uma
|
||||
instalação nativa, com a UI embutida. O esqueleto não liga a feature DuckDB na
|
||||
imagem; o armazenamento continua reservado para uma release futura.
|
||||
|
||||
## Build
|
||||
|
||||
```bash
|
||||
docker build -t acaua .
|
||||
docker run --rm -p 127.0.0.1:8787:8787 -v "$PWD/data/acaua:/data/acaua" acaua
|
||||
```
|
||||
|
||||
O estágio de build usa `rust:1-slim-bookworm`; o de runtime usa
|
||||
`debian:bookworm-slim` e instala só `ca-certificates`, `curl` e `tar` (o updater
|
||||
precisa de `curl` e `tar`).
|
||||
|
||||
## Compose
|
||||
|
||||
```bash
|
||||
cp .env.example .env # opcional: defina ZEEK_INTERFACE
|
||||
docker compose up --build
|
||||
```
|
||||
|
||||
O Compose sobe dois serviços:
|
||||
|
||||
| Serviço | Função | Notas |
|
||||
|---|---|---|
|
||||
| `zeek` | Captura e grava logs Zeek em `./data/zeek` | Rede do host e `NET_RAW`/`NET_ADMIN` |
|
||||
| `acaua` | Lê logs e serve UI/API | Porta do host presa a `127.0.0.1:8787` |
|
||||
|
||||
O `acaua` monta `./data/zeek` somente leitura em `/data/zeek` e `./data/acaua`
|
||||
leitura-escrita em `/data/acaua`. O daemon dentro do contêiner escuta
|
||||
`0.0.0.0:8787`, mas a porta publicada é só loopback no host.
|
||||
|
||||
## Layout de dados
|
||||
|
||||
```text
|
||||
data/
|
||||
zeek/ # logs Zeek, escritos pelo serviço zeek
|
||||
acaua/ # store, exportações e arquivos de runtime
|
||||
```
|
||||
|
||||
Não monte a raiz do host nem um diretório com arquivos sensíveis sem relação. O
|
||||
parser deve confinar caminhos à raiz do dataset; o esqueleto ainda não lê
|
||||
registros.
|
||||
|
||||
## Notas de segurança
|
||||
|
||||
- O serviço `zeek` precisa de privilégio de captura. Rode só em interface e rede
|
||||
que você tem autorização para monitorar.
|
||||
- Não mude o mapeamento de porta do host para `0.0.0.0:8787` sem proxy reverso
|
||||
com autenticação.
|
||||
- A imagem não tem telemetria e não faz conexão de saída exceto um
|
||||
`acaua update` explícito.
|
||||
- O contêiner não é sandbox para dataset hostil. Trate captura malformada como
|
||||
entrada hostil e mantenha o contêiner sem privilégios.
|
||||
|
||||
## Limitações
|
||||
|
||||
- Sem build DuckDB na imagem; o armazenamento analítico não está ativo.
|
||||
- A UI é um shell e o `analyze` devolve relatório stub.
|
||||
- A imagem não inclui Zeek; o Compose usa a imagem upstream do Zeek.
|
||||
- Ainda não há imagem publicada em registry. Compile localmente.
|
||||
@@ -0,0 +1,72 @@
|
||||
# Interface
|
||||
|
||||
[English](../interface.md) · **Português**
|
||||
|
||||
A interface é um app HTML/CSS/JS vanilla embutido no binário `acaua` e carregado
|
||||
pelo shell Tauri. Não há etapa de build de frontend nem runtime React/Next.js.
|
||||
Esta página descreve o shell `0.1.0`; não é um tour de screenshots, porque as
|
||||
telas de detecção ainda não têm nada real para mostrar.
|
||||
|
||||
## Layout
|
||||
|
||||
- **Barra lateral:** marca, navegação, estado da conexão, versão e checagem de
|
||||
atualização.
|
||||
- **Visão geral:** aviso de escopo, aviso de uso autorizado e os quatro cards dos
|
||||
pilares.
|
||||
- **Análise:** campo de caminho do dataset, botão analisar, atualizar e saída
|
||||
JSON bruta.
|
||||
- **Alertas:** estado vazio explicando que o motor de detecção chega em spec
|
||||
futura.
|
||||
- **Configurações:** idioma e tema, guardados localmente.
|
||||
|
||||
## Idioma
|
||||
|
||||
O texto-fonte é em português. O `i18n.js` aplica as strings em inglês de
|
||||
`i18n-en.js` em tempo de execução e persiste a escolha no `localStorage`. `Auto`
|
||||
segue o idioma do navegador/sistema. A checagem
|
||||
`node scripts/check-ui-i18n.mjs` falha quando uma string visível em português não
|
||||
tem par em inglês.
|
||||
|
||||
## Tema
|
||||
|
||||
`Auto`, claro e escuro. `Auto` segue `prefers-color-scheme`. A escolha fica
|
||||
guardada localmente; nenhuma preferência sai da máquina.
|
||||
|
||||
## Estado da conexão
|
||||
|
||||
O rodapé consulta `/api/health` e mostra um de:
|
||||
|
||||
- **Conectando…:** a primeira requisição ainda não terminou.
|
||||
- **Serviço local ativo:** `/api/health` respondeu.
|
||||
- **Serviço indisponível:** a requisição falhou; o shell continua utilizável para
|
||||
configurações.
|
||||
|
||||
O shell Tauri poderá apontar para um daemon local ou um `serve` remoto em versão
|
||||
futura. Em `0.1.0` ele usa a API local.
|
||||
|
||||
## Tela de análise
|
||||
|
||||
`Analisar` envia o caminho para `/api/analyze` e imprime a resposta JSON. O
|
||||
esqueleto valida o caminho e devolve um relatório stub. Ele não lê registros Zeek
|
||||
e não renderiza pontuações. Falhas aparecem como texto, nunca como estado vazio
|
||||
silencioso.
|
||||
|
||||
## Tela de alertas
|
||||
|
||||
A lista está vazia de propósito. Uma linha futura de alerta vai mostrar pilar,
|
||||
pontuação, timestamp e link para o registro de evidência. A evidência precisa
|
||||
incluir entradas, valores intermediários, sentinelas, pesos e versão do código;
|
||||
pontuação sozinha não basta.
|
||||
|
||||
## Acessibilidade
|
||||
|
||||
- A navegação usa botões reais e `aria-label`.
|
||||
- O diálogo de configurações usa `<dialog>` com título rotulado.
|
||||
- Mudanças de estado usam texto, não só cor.
|
||||
|
||||
## Limitações
|
||||
|
||||
- Sem screenshots reais: as telas são shells.
|
||||
- Sem detalhe de alerta, gráficos ou navegador de dataset ainda.
|
||||
- Sem autenticação: a UI assume daemon em loopback.
|
||||
- O app desktop não se auto-atualiza; ele só informa a versão disponível.
|
||||
@@ -0,0 +1,47 @@
|
||||
# Suporte
|
||||
|
||||
[English](../support.md) · **Português**
|
||||
|
||||
O Acauã é pré-alfa. Não há contrato de suporte nem binário publicado ainda. O
|
||||
caminho mais rápido para obter ajuda é uma issue objetiva no repositório Gitea.
|
||||
|
||||
## Antes de abrir uma issue
|
||||
|
||||
1. Rode `acaua doctor --json` e guarde a saída.
|
||||
2. Confirme a versão com `acaua --version`.
|
||||
3. Tente a menor entrada que reproduz o problema.
|
||||
4. Leia os [limites conhecidos](../../README.pt-BR.md#limites-conhecidos) e a
|
||||
[arquitetura](arquitetura.md).
|
||||
|
||||
## O que incluir
|
||||
|
||||
- Sistema operacional, arquitetura e versão do Acauã.
|
||||
- O comando exato e a saída completa do terminal.
|
||||
- Se a entrada é diretório de logs Zeek, fixture sintética ou captura.
|
||||
- Para problema de UI: build de navegador ou desktop, idioma e tema.
|
||||
- Para problema de atualização: saída de `acaua update` e se `curl` e `tar` estão
|
||||
no `PATH`.
|
||||
|
||||
Não anexe capturas de produção nem credenciais. Redija endereços, hostnames e
|
||||
payloads antes de compartilhar.
|
||||
|
||||
## Problemas de segurança
|
||||
|
||||
Não inclua detalhes de exploração em issue pública. Siga o
|
||||
[SECURITY.pt-BR.md](../../SECURITY.pt-BR.md) e peça um canal privado primeiro.
|
||||
|
||||
## Situações comuns
|
||||
|
||||
| Sintoma | O que checar |
|
||||
|---|---|
|
||||
| `analyze` devolve zero registros | Esperado em `0.1.0`; o parser é stub |
|
||||
| `serve` inacessível de outra máquina | Ele escuta em loopback por padrão |
|
||||
| `update` falha | `curl`, `tar`, permissão de escrita e assets da release |
|
||||
| Build do desktop falha | Dependências de sistema do Tauri para a plataforma |
|
||||
| UI aparece em português | `Auto` segue o idioma do sistema; escolha English nas configurações |
|
||||
|
||||
## Escopo
|
||||
|
||||
O suporte cobre o código e a documentação do Acauã. Não cobre configuração de
|
||||
Zeek ou Suricata, legalidade de captura de rede ou pacotes de distribuição de
|
||||
terceiros. Use somente em redes próprias ou com autorização para monitorar.
|
||||
@@ -0,0 +1,47 @@
|
||||
# Support
|
||||
|
||||
**English** · [Português](pt-BR/suporte.md)
|
||||
|
||||
Acauã is pre-alpha. There is no support contract and no published binary yet.
|
||||
The fastest way to get help is a focused issue in the Gitea repository.
|
||||
|
||||
## Before opening an issue
|
||||
|
||||
1. Run `acaua doctor --json` and keep the output.
|
||||
2. Confirm the version with `acaua --version`.
|
||||
3. Try the smallest input that reproduces the problem.
|
||||
4. Read the [known limits](../README.md#known-limits) and
|
||||
[architecture](architecture.md).
|
||||
|
||||
## What to include
|
||||
|
||||
- Operating system, architecture and Acauã version.
|
||||
- The exact command and the full terminal output.
|
||||
- Whether the input is a Zeek log directory, a synthetic fixture or a capture.
|
||||
- For a UI problem: browser or desktop build, language and theme.
|
||||
- For an update problem: `acaua update` output and whether `curl` and `tar` are
|
||||
on `PATH`.
|
||||
|
||||
Do not attach production captures or credentials. Redact addresses, hostnames
|
||||
and payloads before sharing.
|
||||
|
||||
## Security issues
|
||||
|
||||
Do not include exploit details in a public issue. Follow
|
||||
[SECURITY.md](../SECURITY.md) and ask for a private channel first.
|
||||
|
||||
## Common situations
|
||||
|
||||
| Symptom | What to check |
|
||||
|---|---|
|
||||
| `analyze` returns zero records | Expected in `0.1.0`; the parser is a stub |
|
||||
| `serve` is unreachable from another machine | It binds to loopback by default |
|
||||
| `update` fails | `curl`, `tar`, write permission and release assets |
|
||||
| Desktop build fails | Tauri system dependencies for the platform |
|
||||
| UI shows Portuguese | `Auto` follows the system language; choose English in settings |
|
||||
|
||||
## Scope
|
||||
|
||||
Support covers the Acauã code and documentation. It does not cover Zeek or
|
||||
Suricata configuration, network capture legality, or third-party distribution
|
||||
packages. Use only on networks you own or are authorized to monitor.
|
||||
Reference in new issue
Block a user