From 8281dc2b1203754cd6c812a0c7bd86205d07674e Mon Sep 17 00:00:00 2001 From: RoyLin Date: Wed, 24 Jun 2026 12:19:28 +0800 Subject: [PATCH 1/2] test: cover all 14 SNI provider mappings + no-SNI case Classifier (the LLM-detection core) only tested 6/14 providers; add Gemini/Cohere/XAi/Groq/ Together/Perplexity/Fireworks/OpenRouter + the None-SNI path. traits.rs classify fully covered; lib total 78->79.6%. --- src/traits.rs | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/traits.rs b/src/traits.rs index 5aeb15b..8ce1b37 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -276,6 +276,33 @@ mod tests { c.classify(Some("bedrock-runtime.us-east-1.amazonaws.com"), ip), Some(Provider::Bedrock) ); + assert_eq!( + c.classify(Some("generativelanguage.googleapis.com"), ip), + Some(Provider::Gemini) + ); + assert_eq!( + c.classify(Some("api.cohere.ai"), ip), + Some(Provider::Cohere) + ); + assert_eq!(c.classify(Some("api.x.ai"), ip), Some(Provider::XAi)); + assert_eq!(c.classify(Some("api.groq.com"), ip), Some(Provider::Groq)); + assert_eq!( + c.classify(Some("api.together.xyz"), ip), + Some(Provider::Together) + ); + assert_eq!( + c.classify(Some("api.perplexity.ai"), ip), + Some(Provider::Perplexity) + ); + assert_eq!( + c.classify(Some("api.fireworks.ai"), ip), + Some(Provider::Fireworks) + ); + assert_eq!( + c.classify(Some("openrouter.ai"), ip), + Some(Provider::OpenRouter) + ); + assert_eq!(c.classify(None, ip), None); // no SNI → unclassified assert_eq!(c.classify(Some("example.com"), ip), None); } From d1b1e6571ae5c163e7e37c17791a36edb59d9e69 Mon Sep 17 00:00:00 2001 From: RoyLin Date: Wed, 24 Jun 2026 13:02:23 +0800 Subject: [PATCH 2/2] =?UTF-8?q?release:=20v0.9.3=20=E2=80=94=20soak=20vali?= =?UTF-8?q?dation=20+=20test=20coverage;=20add=20README=20Tested=20section?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 0.9.2 -> 0.9.3 (test/docs only, no runtime change). CHANGELOG records the 15-case soak suite (observe + intervene) and the 72->79.6% lib coverage; README gains a Tested section. --- CHANGELOG.md | 12 ++++++++++++ Cargo.lock | 8 ++++---- Cargo.toml | 2 +- README.md | 13 +++++++++++++ a3s-observer-collector/Cargo.toml | 2 +- a3s-observer-common/Cargo.toml | 2 +- a3s-observer-ebpf/Cargo.toml | 2 +- 7 files changed, 33 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ca1c54..5dd9964 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,18 @@ All notable changes to a3s-observer will be documented in this file. +## [0.9.3] — soak validation + test coverage (no runtime change) + +### Tested + +- Full-stack soak validation — 15 cases, leak-free and correct under load on a prod host + an + isolated VM. Observe: steady 20 min, edge-input, a real a3s-code agent, throughput (110k ev/60s), + memory-bound (256 Mi), restart ×8, idle + heartbeat, SIGTERM, concurrent collectors, + backpressure, connection-churn. Intervene: egress, file/exec, and SSL-content guards — plus all + three running alongside the collector. +- Lib line coverage 72% → **79.6%** (`cargo llvm-cov`): adversarial SNI/DNS parser tests, the + cgroup→pod parser, the full 14-provider SNI classifier, and the v0.9.2 writer-thread path. + ## [0.9.2] — fix: output backpressure no longer stalls the event loop ### Fixed diff --git a/Cargo.lock b/Cargo.lock index 7d346fa..ba44fbe 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,7 +4,7 @@ version = 4 [[package]] name = "a3s-observer" -version = "0.9.2" +version = "0.9.3" dependencies = [ "serde", "serde_json", @@ -13,7 +13,7 @@ dependencies = [ [[package]] name = "a3s-observer-collector" -version = "0.9.2" +version = "0.9.3" dependencies = [ "a3s-observer", "a3s-observer-common", @@ -28,11 +28,11 @@ dependencies = [ [[package]] name = "a3s-observer-common" -version = "0.9.2" +version = "0.9.3" [[package]] name = "a3s-observer-ebpf" -version = "0.9.2" +version = "0.9.3" dependencies = [ "a3s-observer-common", "aya-ebpf", diff --git a/Cargo.toml b/Cargo.toml index 7de287d..6bf77a8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "a3s-observer" -version = "0.9.2" +version = "0.9.3" edition = "2021" license = "MIT" description = "General-purpose, language-agnostic eBPF observability for AI agents (LLM calls, tools, files, network egress)." diff --git a/README.md b/README.md index 05db340..fef6411 100644 --- a/README.md +++ b/README.md @@ -194,6 +194,19 @@ a3s-observer → NDJSON → OTel Collector (filelog → OTLP) → your bac Rust + [Aya](https://aya-rs.dev). Validated on Linux 6.8. +## Tested + +Soak-tested under sustained load — observe on a production host, intervene in an isolated VM: + +| path | cases (all leak-free + correct under load) | +|---|---| +| **observe** | steady 20 min · edge-input · **a real a3s-code agent** · throughput 110k ev/60s · memory-bound (256 Mi) · restart ×8 · idle + heartbeat · SIGTERM · concurrent collectors · backpressure · connection-churn | +| **intervene** | egress · file/exec · SSL-content guards — and all three running alongside the collector | + +Two robustness bugs surfaced and were fixed this way: NDJSON stdout pollution (v0.9.1) and an +output-backpressure event-loop stall (v0.9.2). Lib line coverage **79.6%** (`cargo llvm-cov`) — +the untrusted SNI / DNS / cgroup parsers and the full 14-provider classifier are unit-tested. + ## Security Privileged component — see [SECURITY.md](SECURITY.md) for the disclosure policy and how to diff --git a/a3s-observer-collector/Cargo.toml b/a3s-observer-collector/Cargo.toml index 8fbb10b..fcf78d6 100644 --- a/a3s-observer-collector/Cargo.toml +++ b/a3s-observer-collector/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "a3s-observer-collector" -version = "0.9.2" +version = "0.9.3" edition = "2021" license = "MIT" description = "a3s-observer collector: loads the eBPF probes and exports enriched events." diff --git a/a3s-observer-common/Cargo.toml b/a3s-observer-common/Cargo.toml index 0ac04a2..68474f8 100644 --- a/a3s-observer-common/Cargo.toml +++ b/a3s-observer-common/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "a3s-observer-common" -version = "0.9.2" +version = "0.9.3" edition = "2021" license = "MIT" description = "Shared no_std types crossing the eBPF <-> userspace boundary for a3s-observer." diff --git a/a3s-observer-ebpf/Cargo.toml b/a3s-observer-ebpf/Cargo.toml index c08c441..40113e8 100644 --- a/a3s-observer-ebpf/Cargo.toml +++ b/a3s-observer-ebpf/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "a3s-observer-ebpf" -version = "0.9.2" +version = "0.9.3" edition = "2021" license = "MIT" publish = false