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

-4314
View File
File diff suppressed because it is too large. Load diff
-24
View File
@@ -1,24 +0,0 @@
[package]
name = "acaua-gui"
description = "Acauã: graphical network threat hunting interface"
version = "0.1.0"
edition = "2021"
license = "MIT OR Apache-2.0"
authors = ["Acauã contributors"]
repository = "https://git.lucasrguerra.dev.br/ciberfauna/acaua"
rust-version = "1.80"
[workspace]
[build-dependencies]
tauri-build = { version = "2", features = [] }
[dependencies]
acaua-core = { path = "../../../crates/acaua-core" }
serde_json = "1"
tauri = { version = "2", features = [] }
[profile.release]
lto = "thin"
codegen-units = 1
strip = true
-5
View File
@@ -1,5 +0,0 @@
fn main() {
println!("cargo:rerun-if-changed=../../../logo.png");
let _ = std::fs::copy("../../../logo.png", "../ui/logo.png");
tauri_build::build();
}
@@ -1,7 +0,0 @@
{
"$schema": "../gen/schemas/desktop-schema.json",
"identifier": "default",
"description": "Main window permissions",
"windows": ["main"],
"permissions": ["core:default", "core:window:allow-destroy", "core:window:allow-close"]
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 155 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 452 KiB

-62
View File
@@ -1,62 +0,0 @@
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
use acaua_core::{doctor, update, zeek};
#[tauri::command]
fn app_info() -> serde_json::Value {
serde_json::json!({
"version": env!("CARGO_PKG_VERSION"),
"mode": "desktop",
"status": "skeleton"
})
}
#[tauri::command]
fn doctor_report() -> Result<serde_json::Value, String> {
serde_json::to_value(doctor::run()).map_err(|error| error.to_string())
}
#[tauri::command]
fn analyze_dataset(path: String) -> Result<serde_json::Value, String> {
let report = zeek::analyze_dir(&path).map_err(|error| error.to_string())?;
serde_json::to_value(report).map_err(|error| error.to_string())
}
#[tauri::command]
fn list_alerts() -> serde_json::Value {
serde_json::json!([])
}
#[tauri::command]
fn update_check() -> Result<serde_json::Value, String> {
let status = update::check(env!("CARGO_PKG_VERSION")).map_err(|error| error.to_string())?;
serde_json::to_value(status).map_err(|error| error.to_string())
}
#[tauri::command]
fn update_apply(app: tauri::AppHandle) -> Result<String, String> {
use tauri::Emitter;
let exe = std::env::var_os("APPIMAGE")
.map(std::path::PathBuf::from)
.filter(|p| p.is_file())
.or_else(|| std::env::current_exe().ok())
.unwrap_or_else(|| std::path::PathBuf::from("acaua-gui"));
update::apply_desktop_with_progress(&exe, move |phase| {
let _ = app.emit("update-progress", serde_json::json!({ "phase": phase }));
})
.map_err(|error| error.to_string())
}
fn main() {
tauri::Builder::default()
.invoke_handler(tauri::generate_handler![
app_info,
doctor_report,
analyze_dataset,
list_alerts,
update_check,
update_apply
])
.run(tauri::generate_context!())
.expect("failed to run Acauã");
}
-39
View File
@@ -1,39 +0,0 @@
{
"$schema": "https://schema.tauri.app/config/2",
"productName": "Acauã",
"version": "0.1.0",
"identifier": "dev.acaua.app",
"build": {
"frontendDist": "../ui"
},
"app": {
"withGlobalTauri": true,
"windows": [
{
"title": "Acauã",
"width": 1280,
"height": 820,
"minWidth": 460,
"minHeight": 600,
"resizable": true
}
],
"security": {
"csp": "default-src 'self'; img-src 'self' data:; connect-src 'self' ipc: http://ipc.localhost; style-src 'self' 'unsafe-inline'; script-src 'self'; object-src 'none'"
}
},
"bundle": {
"active": true,
"targets": "all",
"category": "Utility",
"shortDescription": "Caça a ameaças em rede",
"longDescription": "Acauã é uma ferramenta de caça a ameaças em rede com evidência determinística, processamento local e sem IA opaca.",
"icon": [
"icons/32x32.png",
"icons/128x128.png",
"icons/128x128@2x.png",
"icons/icon.icns",
"icons/icon.ico"
]
}
}
-2
View File
@@ -1,7 +1,6 @@
import { setLang, tr } from './i18n.js';
const $ = (selector) => document.querySelector(selector);
const tauriInvoke = window.__TAURI__?.core?.invoke;
const connection = $('#connection');
const connectionText = $('#connectionText');
@@ -30,7 +29,6 @@ async function fetchJson(path, options = {}) {
}
async function call(command, args = {}) {
if (tauriInvoke) return tauriInvoke(command, args);
switch (command) {
case 'app_info':
return fetchJson('/api/status');