v0.1.0: logo, i18n pt/en, CI com caches, testes e documentação

- Logo oficial (sabia.png) e conjunto de ícones do app desktop.
- Interface em português e inglês: tradutor por observação do DOM, seletor
  de idioma e checagem de cobertura de tradução no CI.
- CI/CD com caches (rust-cache, .deb do Tauri em cache) e pipeline de release
  multiplataforma (CLI em 5 alvos + app desktop via tauri-action), templates
  de issue/PR.
- Suíte de testes de integração do sabia-core (scan e2e, handshake/crack
  4-way e PMKID, pcap, trilha de auditoria) — 46 testes verdes.
- Documentação completa pt/en: README, ROADMAP, SECURITY, CONTRIBUTING,
  CHANGELOG e docs/ (cli, interface, arquitetura), com enquadramento de uso
  autorizado.
- Correções de clippy (-D warnings) e formatação em toda a árvore.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Lucas RayanandClaude Opus 5.5 committed 2026-10-23 12:46:19 -03:00
1 parent df27974359
commit 791538c9d9
112 files changed
+15620 -494

No files matched your search

+87
View File
@@ -0,0 +1,87 @@
//! Integração: beacon + probe + handshake completo passando pelo caminho
//! público de agregação (`ScanTable`), verificando que AP, cliente e
//! handshake são detectados de ponta a ponta.
mod common;
use sabia_core::scan::ScanTable;
#[test]
fn detects_ap_client_and_handshake_end_to_end() {
let mut table = ScanTable::new();
// RSN com AKM PSK (2) para que a rede apareça como WPA2-PSK.
let beacon = common::beacon_frame(common::ap(), "RedeTeste", 6, &[2]);
table.ingest(&common::radiotap_wrap(&beacon, 2437, -35));
let probe = common::probe_request(common::sta(), "RedeTeste");
table.ingest(&common::radiotap_wrap(&probe, 2437, -50));
let (f1, f2) = common::handshake_radiotap_frames("RedeTeste", "senha-correta", 2, false);
let ev1 = table.ingest_at(&f1, 10);
assert!(ev1.eapol, "quadro msg1 deveria ser reconhecido como EAPOL");
let ev2 = table.ingest_at(&f2, 11);
assert!(ev2.eapol, "quadro msg2 deveria ser reconhecido como EAPOL");
assert!(
ev2.handshake_updated,
"msg2 deveria completar/atualizar o handshake"
);
let aps = table.access_points();
assert_eq!(aps.len(), 1);
let ap = &aps[0];
assert_eq!(ap.bssid, sabia_core::dot11::mac_to_string(&common::ap()));
assert_eq!(ap.ssid.as_deref(), Some("RedeTeste"));
assert_eq!(ap.channel, Some(6));
assert_eq!(ap.security.as_deref(), Some("WPA2"));
let clients = table.clients();
assert!(clients
.iter()
.any(|c| c.mac == sabia_core::dot11::mac_to_string(&common::sta())));
let handshakes = table.handshakes();
assert_eq!(handshakes.len(), 1);
let hs = &handshakes[0];
assert_eq!(hs.ssid.as_deref(), Some("RedeTeste"));
assert!(hs.complete, "handshake deveria estar completo (msg1+msg2)");
assert!(hs.crackable, "handshake deveria ser quebrável");
let stats = table.stats();
assert_eq!(stats.aps, 1);
assert_eq!(stats.clients, 1);
assert_eq!(stats.handshakes, 1);
assert!(stats.eapol_frames >= 2);
}
#[test]
fn hidden_ssid_beacon_is_marked_hidden() {
let mut table = ScanTable::new();
// SSID vazio = rede oculta.
let beacon = common::beacon_frame(common::ap(), "", 11, &[2]);
table.ingest(&common::radiotap_wrap(&beacon, 2462, -60));
let aps = table.access_points();
assert_eq!(aps.len(), 1);
assert!(aps[0].hidden);
}
#[test]
fn pmkid_only_handshake_is_detected_and_crackable() {
let mut table = ScanTable::new();
// Beacon com SSID visível, para que o handshake herde o SSID via hint.
let beacon = common::beacon_frame(common::ap(), "RedePmkid", 11, &[2]);
table.ingest_at(&common::radiotap_wrap(&beacon, 2462, -60), 1);
// Handshake via PMKID (só msg1, sem msg2/snonce).
let (m1, _m2) = common::handshake_frames("RedePmkid", "outra-senha", 2, true);
let f1 = common::frame_with_eapol(true, common::ap(), common::sta(), common::sta(), &m1);
let ev = table.ingest_at(&common::radiotap_wrap(&f1, 2462, -55), 20);
assert!(ev.eapol);
let handshakes = table.handshakes();
assert_eq!(handshakes.len(), 1);
assert!(handshakes[0].crackable, "PMKID isolado já é quebrável");
}