diff --git a/.mike.yml b/.mike.yml index 85c23a41..99ff2814 100644 --- a/.mike.yml +++ b/.mike.yml @@ -2,6 +2,7 @@ version_selector: true title_switch: true versions_file: docs/versions/versions.json versions: + - 4.4.1 - 4.4.0 - 4.3.3 - 4.3.2 @@ -53,4 +54,4 @@ versions: - 0.1.0 - latest aliases: - latest: 4.4.0 + latest: 4.4.1 diff --git a/CHANGELOG.md b/CHANGELOG.md index 11b5730c..27cd41c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,24 @@ All notable changes to this project will be documented in this file. ___ +v4.4.1 (2026-10-16) +------------------- + +The CPU release: detection uses less CPU per request than 4.3.x and keeps the 4.4.0 event-loop responsiveness (v4.4.1) +---------------------------------------------------------------------------------------------------------------------- + +### Fixed + +- **The scan time budget charges CPU once per pass instead of once per pattern** (guard-core #172, #173). 4.4.0 read the thread CPU clock twice and entered a context manager for every pattern check, about 57,000 clock reads on a typical request, so a request cost about 1.4 times the CPU it cost on 4.3.1. The budget now takes one reading when a pass opens, charges at each 2 ms slice boundary and around every await that can suspend, and makes a final charge when the pass closes. Other requests' CPU is never charged to this one, and `detection_max_scan_seconds` still stops a long scan within about one slice. The fallback scan now charges its inline CPU too. +- **The event-loop yield slice spans the whole request** (guard-core #172, #173). The 2 ms slice restarted for every scanned value, so on short values it almost never fired and responsiveness came from per-pattern thread pool round trips instead. The slice now starts with the request budget, so the loop yields every 2 ms of scanning. +- **The performance monitor costs less per pattern check** (guard-core #172, #173). It no longer builds the sanitized anomaly copy when no callback is registered, and it computes the standard deviation in one C pass (`math.dist`). Results are identical to 6 decimals. + +### Changed + +- **Measured effect.** On a POST with a JSON body, browser headers and a bearer token, a request costs about 130 ms of CPU, against about 148 ms on 4.3.1 and about 209 ms on 4.4.0. Fifty concurrent requests finish in 6.7 s (4.3.1: 7.5 s, 4.4.0: 13.0 s) and the worst event-loop stall is 26 ms (4.3.1: 7.5 s, 4.4.0: 86 ms). Every verdict, category and score over the 738 production corpus cases is identical to 4.4.0. No configuration changes. + +___ + v4.4.0 (2026-10-15) ------------------- diff --git a/docs/release-notes.md b/docs/release-notes.md index e6feae46..15b3eeac 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -10,6 +10,24 @@ Release Notes ___ +v4.4.1 (2026-10-16) +------------------- + +The CPU release: detection uses less CPU per request than 4.3.x and keeps the 4.4.0 event-loop responsiveness (v4.4.1) +---------------------------------------------------------------------------------------------------------------------- + +### Fixed + +- **The scan time budget charges CPU once per pass instead of once per pattern** (guard-core #172, #173). 4.4.0 read the thread CPU clock twice and entered a context manager for every pattern check, about 57,000 clock reads on a typical request, so a request cost about 1.4 times the CPU it cost on 4.3.1. The budget now takes one reading when a pass opens, charges at each 2 ms slice boundary and around every await that can suspend, and makes a final charge when the pass closes. Other requests' CPU is never charged to this one, and `detection_max_scan_seconds` still stops a long scan within about one slice. The fallback scan now charges its inline CPU too. +- **The event-loop yield slice spans the whole request** (guard-core #172, #173). The 2 ms slice restarted for every scanned value, so on short values it almost never fired and responsiveness came from per-pattern thread pool round trips instead. The slice now starts with the request budget, so the loop yields every 2 ms of scanning. +- **The performance monitor costs less per pattern check** (guard-core #172, #173). It no longer builds the sanitized anomaly copy when no callback is registered, and it computes the standard deviation in one C pass (`math.dist`). Results are identical to 6 decimals. + +### Changed + +- **Measured effect.** On a POST with a JSON body, browser headers and a bearer token, a request costs about 130 ms of CPU, against about 148 ms on 4.3.1 and about 209 ms on 4.4.0. Fifty concurrent requests finish in 6.7 s (4.3.1: 7.5 s, 4.4.0: 13.0 s) and the worst event-loop stall is 26 ms (4.3.1: 7.5 s, 4.4.0: 86 ms). Every verdict, category and score over the 738 production corpus cases is identical to 4.4.0. No configuration changes. + +___ + v4.4.0 (2026-10-15) ------------------- diff --git a/docs/versions/versions.json b/docs/versions/versions.json index 7eb30c67..9f7604e7 100644 --- a/docs/versions/versions.json +++ b/docs/versions/versions.json @@ -1,4 +1,5 @@ { + "4.4.1": "4.4.1", "4.4.0": "4.4.0", "4.3.3": "4.3.3", "4.3.2": "4.3.2", @@ -49,5 +50,5 @@ "1.0.1": "1.0.1", "1.0.0": "1.0.0", "0.1.0": "0.1.0", - "latest": "4.4.0" + "latest": "4.4.1" } diff --git a/guard_core/.agents/skills/guard-core/SKILL.md b/guard_core/.agents/skills/guard-core/SKILL.md index 504e9503..8b014add 100644 --- a/guard_core/.agents/skills/guard-core/SKILL.md +++ b/guard_core/.agents/skills/guard-core/SKILL.md @@ -7,7 +7,7 @@ description: Guard Core best practices and conventions for the framework-agnosti Official guard-core skill to write code with best practices, keeping up to date with the real installed surface (introspect the package, do not rely on model memory of it). -Current as of guard-core 4.4.0. +Current as of guard-core 4.4.1. guard-core is the framework-agnostic security engine powering the Guard ecosystem. Framework adapters (fastapi-guard, flaskapi-guard, djapi-guard, tornadoapi-guard) implement three protocols and get the full pipeline, detection engine, Redis state, and telemetry for free. diff --git a/pyproject.toml b/pyproject.toml index 6a82b68c..2eed1966 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "guard-core" -version = "4.4.0" +version = "4.4.1" description = "Framework-agnostic security engine for the Guard ecosystem." authors = [ {name = "Renzo Franceschini", email = "rennf93@guard-core.com"}