refactor: distribute Acaua as a Docker image instead of a desktop app
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

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
This commit is contained in:
Lucas RayanandClaude Sonnet 5 committed 2026-10-31 19:54:45 -03:00
1 parent 1b974bb90d
commit 8a80504c45
72 files changed
+2524 -6384

No files matched your search

+75 -90
View File
@@ -2,8 +2,8 @@
**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
Acauã is a single Rust product: one daemon/CLI, one shared core, and one
embedded web dashboard. 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.
@@ -11,19 +11,14 @@ corrections applied to the original blueprint.
| Layer | Choice | Why |
|---|---|---|
| Core, CLI and daemon | Rust 2021 | One toolchain, memory safety, no runtime dependency |
| Core, CLI and daemon | Rust 2021 (MSRV 1.88) | 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 |
| Web Dashboard | Vanilla HTML/CSS/JS | No frontend build step, assets embedded in the binary via `rust-embed` |
| Analytical store | DuckDB + Parquet | Mandatory embedded columnar store, linked to official prebuilt `libduckdb.so` |
| Deployment | Docker / docker-compose | Collective SOC daemon, unprivileged non-root user, read-only rootfs |
| 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.
The workspace has two crates: `acaua-core` and `acaua-cli`. Both use `version.workspace = true`.
## Components
@@ -35,20 +30,20 @@ Zeek logs ──► acaua-core::zeek ──► normalized events ──► stora
├──► pillar3 (protocol anomalies)
└──► pillar4 (fusion) ──► alerts + evidence
│
acaua-cli ──► axum API ──► embedded UI ◄── Tauri shell ─────────────┘
acaua-cli (serve) ──► axum API ──► embedded web dashboard ──────────┘
```
- `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.
- `storage`: DuckDB in-memory engine over daily partitioned Parquet files with a
seven-day TTL.
- `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.
- `doctor`: local environment checks; reports prebuilt DuckDB linkage and
containerized Zeek status.
- `update`: checks for updates against the Gitea Releases API.
## The six corrections
@@ -58,117 +53,107 @@ 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
P(T) = (2 / N) * [ (sum cos(2*pi*t_i / T))^2 + (sum sin(2*pi*t_i / T))^2 ]
```
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.
Generalized Lomb–Scargle is reserved for the future extension that evaluates a
real response attribute (such as payload size or duration) against time.
### 2. Bowley skew with an explicit sentinel
### 2. Guard the zero-dispersion case in MADM
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.
A synthetic or unjittered beacon produces equal intervals. The median absolute
deviation from the median (MADM) is then `0.0`. Dividing by `0.0` or treating it
as a missing value is wrong: zero dispersion is the most suspicious outcome. The
implementation guards this case with an explicit score assignment (`1.0`) and a
documented sentinel.
### 3. Jensen–Shannon, not raw KL
### 3. Replace Pearson skewness with Bowley skewness
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.
Sample skewness based on the third central moment is sensitive to single
outliers and can diverge. Bowley skewness uses quartiles:
### 4. Persistent sessions get their own detector
```text
B = (Q3 + Q1 - 2*Q2) / (Q3 - Q1)
```
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.
It is bounded in `[-1.0, 1.0]` by definition and resistant to extreme outliers.
When `Q3 == Q1` (concentrated data), the implementation assigns `0.0` with a
sentinel flag.
### 5. JA4 license caution
### 4. Isolate the Python research workspace
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.
`research/` has its own virtual environment and dependencies. It is excluded
from the Cargo workspace, ignored by Docker builds and CI releases, and tested
only when research validation scripts are invoked directly.
### 6. Determinism and per-alert JSON evidence
### 5. Documented degraded mode for NetFlow/IPFIX
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.
NetFlow v9 and IPFIX do not carry DNS query names, TLS SNI, certificate chains
or HTTP headers. Any analysis that depends on protocol features is unavailable.
Acauã documents this as a degraded mode and never claims parity between flow
records and full Zeek logs.
## Data flow
### 6. Single HTTP and RPC boundary
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.
The daemon exposes an Axum API on loopback by default. The embedded web UI
communicates with the daemon exclusively via standard HTTP calls.
## API
| Method | Path | Purpose |
The HTTP API is served by `acaua serve`:
| Method | Path | Meaning |
|---|---|---|
| GET | `/api/health` | Liveness and version |
| GET | `/api/status` | Uptime, data directory, pillar state |
| GET | `/api/status` | Uptime, data directory, dataset summary |
| GET | `/api/alerts` | Paginated alerts with evidence |
| POST | `/api/analyze` | Analyze a dataset path |
| POST | `/api/update` | Check for a CLI update |
| POST | `/api/analyze` | Ingest and analyze a dataset directory |
| GET | `/api/update` | Check for newer releases |
| GET | `/logo.png` | Embedded brand asset |
| GET | `/*` | Embedded UI fallback |
| GET | `/*` | Embedded UI fallback (`rust-embed`) |
`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.
`serve` binds to `127.0.0.1:8787` by default. Exposing it on an external network
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.
DuckDB is a mandatory dependency linked dynamically to the official prebuilt
`libduckdb.so` (version 1.5.6 pinned with SHA-256 in `scripts/fetch-libduckdb.sh`).
Parquet, JSON and ICU extensions are statically built into the official library.
The schema consists of daily partitioned Parquet files under the configured
data directory, with in-memory DuckDB querying and a seven-day TTL.
## 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.
Updates for Acauã are delivered via container images (`docker compose pull && docker compose up -d`).
The `acaua update` command queries the Gitea Releases API for `ciberfauna/acaua` and
notifies operators when a newer version tag is available. Binary self-overwrite
(`update --apply`) is removed: in a collective SOC daemon running under container
orchestration, updates must be controlled by image pulls rather than self-mutating
processes.
## 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/`.
1. **Python service with FastAPI/ClickHouse:** Rejected. A Python runtime introduces
heavy container footprints and unnecessary memory boundaries; ClickHouse adds an
external server operational burden for datasets that fit an embedded columnar store.
The product is 100% Rust.
2. **Desktop application (Tauri / AppImage / NSIS):** Rejected. Unlike Guará (local
raw disk forensics) and Sabiá (Wi-Fi monitor-mode hardware), Acauã has no local
hardware dependencies: it is a multi-user SOC daemon consuming Zeek logs. A desktop
wrapper adds maintenance and security surface without operational benefits.
## 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).
- **Docker Compose (Official):** Multi-arch container image (`git.lucasrguerra.dev.br/ciberfauna/acaua`),
running as unprivileged user `acaua` (UID 10001), read-only root filesystem, dropped capabilities.
- **Native compilation:** `scripts/fetch-libduckdb.sh ~/.cache/acaua/duckdb` followed by `cargo build --release -p acaua-cli`.
## 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.
over existing data.
## Versioning and compatibility
+21 -46
View File
@@ -2,23 +2,22 @@
**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.
The `acaua` binary serves both as the CLI command runner and the background daemon.
This page describes the commands available in the engine.
```text
acaua <command> [options]
Commands:
serve Start the API and embedded UI
serve Start the API and embedded web dashboard
analyze Analyze a Zeek log directory
doctor Check the local environment
update Check or apply a CLI update
update Check for available releases
```
## `acaua serve`
Starts the HTTP API and the embedded UI.
Starts the HTTP API and the embedded web dashboard.
```bash
acaua serve --bind 127.0.0.1:8787 --data-dir .acaua
@@ -40,14 +39,8 @@ 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.
Validates the target directory, ingests `conn.log` traffic into Parquet partitions,
and runs threat detection algorithms.
## `acaua doctor`
@@ -56,52 +49,34 @@ 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.
Runs environment checks:
- `zeek`: verifies `zeek --version` or detects containerized execution (`ACAUA_RUNTIME=container`).
- `curl`: confirms HTTP download availability.
- `duckdb`: confirms dynamic linkage against `libduckdb.so` in runtime.
- `research`: verifies that the research workspace remains isolated.
## `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.
Queries the Gitea Releases API, compares the latest tag against the running
version, and prints upgrade instructions (`docker compose pull && docker compose up -d`
when running inside a container).
## Exit codes
| Code | Meaning |
|---|---|
| `0` | Success |
| `1` | Runtime error (invalid path, failed update, I/O error) |
| `1` | Runtime error (invalid path, query error, 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.
| Variable | Meaning |
|---|---|
| `ACAUA_RUNTIME` | Set to `container` inside Docker images to adapt service checks |
| `DUCKDB_LIB_DIR` | Path to directory containing `libduckdb.so` when compiling natively |
| `LD_LIBRARY_PATH` | Shared library load path for `libduckdb.so` outside standard paths |
+57 -45
View File
@@ -2,66 +2,78 @@
**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.
Acauã is distributed as an official container image:
`git.lucasrguerra.dev.br/ciberfauna/acaua`.
## Build
Available image tags:
- `latest`: Most recent stable release.
- `X.Y.Z` / `X.Y`: Pinned semantic versions.
- `edge`: Built automatically from the `main` branch.
The container runs as an unprivileged system user (`acaua`, UID 10001), with a
read-only root filesystem (`read_only: true`), all capabilities dropped
(`cap_drop: [ALL]`), and security hardening (`no-new-privileges:true`).
## Compose deployment
The recommended production and lab deployment uses Docker Compose:
```bash
docker build -t acaua .
docker run --rm -p 127.0.0.1:8787:8787 -v "$PWD/data/acaua:/data/acaua" acaua
cp .env.example .env # configure ZEEK_INTERFACE (authorized networks only)
docker compose pull && docker compose up -d
```
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
To build and run locally from source:
```bash
cp .env.example .env # optional: set ZEEK_INTERFACE
docker compose up --build
docker compose up -d --build
```
The Compose file starts two services:
The stack coordinates 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` |
| Service | Image | Purpose | Security profile |
|---|---|---|---|
| `zeek` | `zeek/zeek:9.0.1` | Network packet capture and hourly log rotation | Host network, `NET_RAW` and `NET_ADMIN` capabilities |
| `acaua` | `git.lucasrguerra.dev.br/ciberfauna/acaua` | Analytical processing, API and web dashboard | Unprivileged (UID 10001), read-only rootfs, no capabilities |
`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.
## Volumes and data layout
## Data layout
The stack uses named volumes to manage ownership and permissions cleanly:
```text
data/
zeek/ # Zeek logs, written by the zeek service
acaua/ # store, exports and runtime files
- `zeek-logs`: Shared volume mounted at `/logs` in the Zeek service and mounted
**read-only** at `/data/zeek:ro` in the Acauã service.
- `acaua-data`: Dedicated read-write volume mounted at `/data/acaua` for DuckDB
analytical store, Parquet partitions and runtime files.
To inspect or extract data on the host:
```bash
docker compose cp acaua:/data/acaua ./local-acaua-backup
```
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.
Or run a one-off inspection container:
```bash
docker run --rm -v acaua_acaua-data:/data:ro debian:trixie-slim ls -la /data
```
## Updating
Because Acauã runs as a multi-user collective SOC daemon, updates are performed
by pulling the latest verified image:
```bash
docker compose pull && docker compose up -d
```
The running daemon shuts down cleanly on `SIGTERM` within sub-second intervals,
ensuring Parquet writes and DuckDB transactions are committed properly.
## 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.
- The `zeek` service requires packet capture privileges (`NET_RAW`, `NET_ADMIN`).
Run it only on interfaces and networks you are explicitly authorized to monitor.
- The default dashboard binding is loopback-only (`ACAUA_PUBLISH=127.0.0.1:8787`).
Do not expose the service on external interfaces without an authenticating reverse proxy.
- The image contains no telemetry. Outbound traffic is restricted to operator-initiated
update checks against the Gitea Releases API.
+20 -47
View File
@@ -2,66 +2,39 @@
**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.
The interface is a vanilla HTML/CSS/JS dashboard embedded directly into the
`acaua` binary via `rust-embed` and served by `acaua serve`. There is no
frontend build step and no heavy framework runtime.
## 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.
- **Sidebar:** brand logo, navigation, daemon connection indicator, version and update check.
- **Overview:** monitoring scope notice, authorized-use warning and four detection pillar cards.
- **Analysis:** dataset path entry, analyze button, refresh and raw JSON output inspection.
- **Alerts:** list of alerts with deterministic evidence metadata.
- **Settings:** language and theme preferences, stored in browser local storage.
## 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.
The source text is Portuguese. `i18n.js` applies English translations from
`i18n-en.js` at runtime and persists the selection in `localStorage`. `Auto`
detects the browser language. The automated test `node scripts/check-ui-i18n.mjs`
guarantees that every visible Portuguese string has an exact English pair.
## Theme
`Auto`, light and dark are supported. `Auto` follows `prefers-color-scheme`. The
choice is stored locally; no preference leaves the machine.
Light, dark and `Auto` modes are supported. `Auto` reacts to system
`prefers-color-scheme`. Preferences stay local; no telemetry is sent.
## Connection state
The footer polls `/api/health` and shows one of:
The interface communicates with `/api/health` and displays:
- **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.
- **Connecting:** initial connection in progress.
- **Local service online:** daemon is responding.
- **Service unavailable:** connection to daemon failed; interface remains accessible for offline settings.
## 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.
Posting a directory path to `/api/analyze` triggers the Zeek ingestion and
analytical detection pipeline.
+100 -115
View File
@@ -2,176 +2,161 @@
[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.
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 | Por quê |
| Camada | Escolha | Motivo |
|---|---|---|
| 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 |
| 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 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.
O workspace possui dois crates: `acaua-core` e `acaua-cli`. Ambos utilizam `version.workspace = true`.
## 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 ────────────┘
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 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.
- `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 existe um `y`
Timestamps de eventos são um processo pontual unidimensional: não há valor `y`
para ajustar. O periodograma primário é, portanto, Rayleigh/Schuster:
```text
P(f) = |sum_k exp(2*pi*i*f*t_k)|^2 / N
P(T) = (2 / N) * [ (sum cos(2*pi*t_i / T))^2 + (sum sin(2*pi*t_i / T))^2 ]
```
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.
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. Bowley com sentinela explícito
### 2. Proteger o caso de dispersão zero no MADM
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.
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. Jensen–Shannon, não KL puro
### 3. Substituir assimetria de Pearson por assimetria de Bowley
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.
A assimetria amostral baseada no terceiro momento central é sensível a outliers
individuais e pode divergir. A assimetria de Bowley utiliza quartis:
### 4. Sessões persistentes têm detector próprio
```text
B = (Q3 + Q1 - 2*Q2) / (Q3 - Q1)
```
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.
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.
### 5. Cautela com a licença JA4
### 4. Isolar o espaço de pesquisa Python
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.
`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.
### 6. Determinismo e evidência JSON por alerta
### 5. Modo degradado documentado para NetFlow/IPFIX
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.
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.
## Fluxo de dados
### 6. Fronteira única HTTP e RPC
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.
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
| Método | Caminho | Finalidade |
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, estado dos pilares |
| GET | `/api/status` | Uptime, diretório de dados, sumário do dataset |
| GET | `/api/alerts` | Alertas paginados com evidência |
| POST | `/api/analyze` | Analisar um caminho de dataset |
| POST | `/api/update` | Checar atualização da CLI |
| 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 da UI embutida |
| GET | `/*` | Fallback de UI embutida (`rust-embed`) |
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.
`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 é 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.
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
`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.
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
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/`.
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
- **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).
- **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 falha
## Comportamento em falhas
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.
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 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.
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.
+28 -52
View File
@@ -2,23 +2,22 @@
[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.
O binário `acaua` atua tanto como utilitário de linha de comando quanto como daemon de segundo plano.
Esta página descreve os comandos disponíveis no motor.
```text
acaua <comando> [opções]
acaua <command> [options]
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
serve Inicia a API e o dashboard web embutido
analyze Analisa um diretório de logs do Zeek
doctor Verifica o ambiente local
update Checa por releases disponíveis
```
## `acaua serve`
Sobe a API HTTP e a UI embutida.
Inicia a API HTTP e o dashboard web embutido.
```bash
acaua serve --bind 127.0.0.1:8787 --data-dir .acaua
@@ -27,10 +26,10 @@ 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 |
| `--data-dir` | `.acaua` | Diretório de dados e arquivos de execução |
O bind padrão é só loopback. Expor o daemon na rede exige proxy reverso com
autenticação. A API está documentada em
O bind padrão restringe-se a loopback. Expô-lo em uma rede exige um proxy
reverso com autenticação. A API está documentada em
[arquitetura.md](arquitetura.md#api).
## `acaua analyze`
@@ -40,14 +39,8 @@ 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.
Valida o diretório alvo, ingere tráfego do `conn.log` em partições Parquet e
executa os algoritmos de detecção de ameaças.
## `acaua doctor`
@@ -56,51 +49,34 @@ 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.
Executa checagens de ambiente:
- `zeek`: verifica `zeek --version` ou detecta execução em container (`ACAUA_RUNTIME=container`).
- `curl`: confirma disponibilidade de download HTTP.
- `duckdb`: confirma linkagem dinâmica contra a `libduckdb.so` em tempo de execução.
- `research`: valida o isolamento do workspace de pesquisa.
## `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.
Consulta a API de Releases do Gitea, compara a última tag com a versão em
execução e imprime instruções de atualização (`docker compose pull && docker compose up -d`
quando em container).
## 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) |
| `1` | Erro em tempo de execução (caminho inválido, erro de consulta, I/O) |
| `2` | Uso inválido de 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.
| Variável | Significado |
|---|---|
| `ACAUA_RUNTIME` | Definida como `container` em imagens Docker para adaptar checagens |
| `DUCKDB_LIB_DIR` | Caminho do diretório contendo `libduckdb.so` em compilação nativa |
| `LD_LIBRARY_PATH` | Caminho de busca de bibliotecas compartilhadas para `libduckdb.so` |
+58 -44
View File
@@ -2,65 +2,79 @@
[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.
O Acauã é distribuído como uma imagem de container oficial:
`git.lucasrguerra.dev.br/ciberfauna/acaua`.
## Build
Tags de imagem disponíveis:
- `latest`: Release estável mais recente.
- `X.Y.Z` / `X.Y`: Versões semânticas fixadas.
- `edge`: Gerada automaticamente a partir do branch `main`.
O container executa como usuário de sistema não privilegiado (`acaua`, UID 10001),
com filesystem raiz somente leitura (`read_only: true`), todas as capabilities revogadas
(`cap_drop: [ALL]`), e endurecimento de segurança (`no-new-privileges:true`).
## Implantação com Compose
A implantação recomendada para produção e laboratório utiliza Docker Compose:
```bash
docker build -t acaua .
docker run --rm -p 127.0.0.1:8787:8787 -v "$PWD/data/acaua:/data/acaua" acaua
cp .env.example .env # configure ZEEK_INTERFACE (apenas redes autorizadas)
docker compose pull && docker compose up -d
```
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
Para compilar e rodar localmente a partir do código:
```bash
cp .env.example .env # opcional: defina ZEEK_INTERFACE
docker compose up --build
docker compose up -d --build
```
O Compose sobe dois serviços:
A stack coordena 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` |
| Serviço | Imagem | Finalidade | Perfil de segurança |
|---|---|---|---|
| `zeek` | `zeek/zeek:9.0.1` | Captura de pacotes de rede e rotação horária de logs | Rede host, capabilities `NET_RAW` e `NET_ADMIN` |
| `acaua` | `git.lucasrguerra.dev.br/ciberfauna/acaua` | Processamento analítico, API e dashboard web | Não privilegiado (UID 10001), rootfs read-only, sem capabilities |
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.
## Volumes e organização de dados
## Layout de dados
A stack utiliza volumes nomeados para isolamento limpo de permissões e propriedade:
```text
data/
zeek/ # logs Zeek, escritos pelo serviço zeek
acaua/ # store, exportações e arquivos de runtime
- `zeek-logs`: Volume compartilhado montado em `/logs` no serviço Zeek e montado
como **somente leitura** em `/data/zeek:ro` no serviço Acauã.
- `acaua-data`: Volume dedicado de leitura e escrita montado em `/data/acaua` para o
armazenamento DuckDB, partições Parquet e arquivos de execução.
Para inspecionar ou extrair dados no host:
```bash
docker compose cp acaua:/data/acaua ./local-acaua-backup
```
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.
Ou executar um container efêmero de inspeção:
```bash
docker run --rm -v acaua_acaua-data:/data:ro debian:trixie-slim ls -la /data
```
## Atualização
Por rodar como um daemon de SOC de uso coletivo, atualizações são realizadas
puxando a imagem verificada mais recente:
```bash
docker compose pull && docker compose up -d
```
O daemon em execução finaliza de forma limpa em resposta ao `SIGTERM` em tempo
sub-segundo, garantindo que gravações Parquet e transações DuckDB sejam concluídas
sem corrupção.
## 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.
- O serviço `zeek` requer privilégios de captura de pacotes (`NET_RAW`, `NET_ADMIN`).
Execute-o apenas em interfaces e redes que você tem autorização explícita para monitorar.
- A publicação padrão do dashboard é restrita a loopback (`ACAUA_PUBLISH=127.0.0.1:8787`).
Não exponha o serviço em interfaces externas sem um proxy reverso com autenticação.
- A imagem não possui telemetria. Tráfego de saída restringe-se a checagens de
versão iniciadas pelo operador contra a API de Releases do Gitea.
+22 -54
View File
@@ -2,71 +2,39 @@
[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.
A interface é um dashboard vanilla em HTML/CSS/JS embutido diretamente no binário
`acaua` via `rust-embed` e servido por `acaua serve`. Não há etapa de build de
frontend nem frameworks pesados em runtime.
## Layout
## Estrutura
- **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.
- **Barra lateral:** logo da marca, navegação, indicador de conexão ao daemon, versão e checagem de atualizações.
- **Visão geral:** aviso de escopo de monitoramento, alerta de uso autorizado e cartões dos quatro pilares de detecção.
- **Análise:** campo de caminho de dataset, botão de análise, atualização e inspeção de saída JSON.
- **Alertas:** listagem de alertas com metadados de evidência determinística.
- **Configurações:** preferências de idioma e tema, salvas no armazenamento local do navegador.
## 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.
O texto original é em português. `i18n.js` aplica as traduções em inglês de
`i18n-en.js` em tempo de execução e salva a escolha no `localStorage`. `Auto`
detecta o idioma do navegador. O teste automatizado `node scripts/check-ui-i18n.mjs`
garante que toda string visível em português tenha seu par exato 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.
Modos claro, escuro e `Auto` são suportados. `Auto` responde ao `prefers-color-scheme`
do sistema operacional. Preferências ficam no host; nenhuma telemetria é emitida.
## Estado da conexão
## Estado de conexão
O rodapé consulta `/api/health` e mostra um de:
A interface comunica-se com `/api/health` e exibe:
- **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.
- **Conectando:** conexão inicial em andamento.
- **Serviço local ativo:** o daemon está respondendo.
- **Serviço indisponível:** falha na conexão com o daemon; a interface continua acessível para ajustes locais.
## 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.
Enviar um caminho de diretório para `/api/analyze` dispara a ingestão do Zeek e o
pipeline analítico de detecção.
+19 -29
View File
@@ -2,46 +2,36 @@
[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.
O Acauã é distribuído como um motor de NDR containerizado. A forma mais rápida de
obter assistência é abrir uma issue no repositório do Gitea.
## Antes de abrir uma issue
1. Rode `acaua doctor --json` e guarde a saída.
1. Execute `acaua doctor --json` dentro do container (`docker exec acaua acaua doctor --json`) ou no host.
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).
3. Tente reproduzir o problema com a menor captura de logs Zeek possível.
4. Revise 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`.
- Sistema operacional do host, arquitetura (`uname -m`) e versão/tag do Acauã.
- O comando exato ou definição do Docker Compose.
- Logs completos do container (`docker compose logs acaua`).
- Amostras anonimizadas de logs Zeek que demonstrem a falha.
Não anexe capturas de produção nem credenciais. Redija endereços, hostnames e
payloads antes de compartilhar.
Não anexe capturas de tráfego de produção nem credenciais. Anonimize endereços IP,
hostnames e payloads sensíveis antes de compartilhar.
## Problemas de segurança
## Questões 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.
Não inclua detalhes de exploração em uma issue pública. Siga a política em
[SECURITY.pt-BR.md](../../SECURITY.pt-BR.md) e solicite um canal privado de comunicação.
## Situações comuns
| Sintoma | O que checar |
| Sintoma | O que verificar |
|---|---|
| `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.
| Container não sobe | Confirme linkagem de `libduckdb.so` via `docker logs` e verifique permissões nos volumes nomeados |
| `serve` inacessível a partir de outro host | O serviço escuta em loopback (`127.0.0.1:8787`) por padrão; verifique o proxy reverso |
| `update` falha | Verifique conectividade de rede com a API de Releases do Gitea ou permissões de pull do registry |
| UI web exibe português | `Auto` segue o idioma do navegador; escolha inglês nas configurações |
+16 -26
View File
@@ -2,46 +2,36 @@
**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.
Acauã is distributed as a containerized NDR engine. The fastest way to get help
is opening an issue in the Gitea repository.
## Before opening an issue
1. Run `acaua doctor --json` and keep the output.
1. Run `acaua doctor --json` inside the container (`docker exec acaua acaua doctor --json`) or host.
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).
3. Try reproducing with the smallest possible Zeek log capture.
4. Review 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`.
- Host operating system, architecture (`uname -m`) and Acauã version/tag.
- The exact command or Docker Compose definition.
- Full container logs (`docker compose logs acaua`).
- Redacted Zeek log samples demonstrating the issue.
Do not attach production captures or credentials. Redact addresses, hostnames
and payloads before sharing.
Do not attach production captures or credentials. Redact IP addresses, hostnames
and sensitive 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.
[SECURITY.md](../SECURITY.md) and request a private communication channel.
## 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.
| Container fails to start | Confirm `libduckdb.so` linkage via `docker logs` and verify permissions on named volumes |
| `serve` is unreachable from another host | Service binds to loopback (`127.0.0.1:8787`) by default; verify reverse proxy configuration |
| `update` fails | Check network connectivity to Gitea Releases API or verify registry pull permissions |
| Web UI shows Portuguese | `Auto` follows the browser language; select English in settings |