From 7cd4ffdaab1cbb013f60655e4447c9ed09ead6eb Mon Sep 17 00:00:00 2001 From: Sharang Parnerkar <30073382+mighty840@users.noreply.github.com> Date: Tue, 21 Jul 2026 14:50:50 +0200 Subject: [PATCH] =?UTF-8?q?feat(controls):=20B3=20=E2=80=94=20categorize?= =?UTF-8?q?=20the=20rest=20of=20needs=5Ftooling=20(architectural=20+=20RBA?= =?UTF-8?q?C)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes out B's coverage of the 16 needs_tooling CRA controls: - cra-ai-2,3,4,5 (minimal attack surface, secure architecture, least-privilege, tamper protection) are design properties, not local code patterns -> marked not_code_checkable (out of static-scan scope) with reviewer notes. - cra-ai-12 (RBAC) is surface-checkable (authorization points) -> added to the grounded surface pass; note points to the gated grounded mechanism. Final CRA coverage: covered 13 | needs_tooling 8 (all grounded-covered, gated) | not_code_checkable 19. The 16 needs_tooling now fully categorized: 4 custom-semgrep (B1) + 8 grounded surface (B2/B3, gated) + 4 architectural (B3). Co-Authored-By: Claude Fable 5 --- compliance-agent/src/controls/surface.rs | 14 +++++++++++++- control-map/data/cra_control_map.json | 18 +++++++++--------- control-map/src/lib.rs | 21 +++++++++++++++++++++ 3 files changed, 43 insertions(+), 10 deletions(-) diff --git a/compliance-agent/src/controls/surface.rs b/compliance-agent/src/controls/surface.rs index ade5bc1..0e37932 100644 --- a/compliance-agent/src/controls/surface.rs +++ b/compliance-agent/src/controls/surface.rs @@ -47,6 +47,17 @@ pub const SURFACES: &[Surface] = &[ "ratelimit", ], }, + Surface { + control_id: "cra-ai-12", // Rollenbasierte Autorisierung (RBAC) + terms: &[ + "authorize", + "permission", + "role", + "rbac", + "require_role", + "has_role", + ], + }, Surface { control_id: "cra-ai-24", // Security-Logging terms: &["login", "authorize", "permission", "role", "admin", "audit"], @@ -196,10 +207,11 @@ mod tests { #[test] fn surfaces_cover_the_absence_based_controls() { - assert_eq!(SURFACES.len(), 7); + assert_eq!(SURFACES.len(), 8); for id in [ "cra-ai-6", "cra-ai-11", + "cra-ai-12", "cra-ai-24", "cra-ai-27", "cra-ai-28", diff --git a/control-map/data/cra_control_map.json b/control-map/data/cra_control_map.json index 9705e63..f445025 100644 --- a/control-map/data/cra_control_map.json +++ b/control-map/data/cra_control_map.json @@ -25,29 +25,29 @@ "control": "cra-ai-2", "title": "Minimale Angriffsflaeche", "scans": [], - "note": "code-checkable but no off-the-shelf tool digs it out — author a detector (custom semgrep rule / check)", - "status": "needs_tooling" + "note": "design property (minimal attack surface) — not derivable from local code patterns; architecture/threat-model review", + "status": "not_code_checkable" }, { "control": "cra-ai-3", "title": "Sichere Systemarchitektur", "scans": [], - "note": "code-checkable but no off-the-shelf tool digs it out — author a detector (custom semgrep rule / check)", - "status": "needs_tooling" + "note": "design property (secure system architecture) — architecture review, not statically code-checkable", + "status": "not_code_checkable" }, { "control": "cra-ai-4", "title": "Least-Privilege-Prinzip", "scans": [], - "note": "code-checkable but no off-the-shelf tool digs it out — author a detector (custom semgrep rule / check)", - "status": "needs_tooling" + "note": "design property (least-privilege) — deployment/IAM & architecture review, not a local code pattern", + "status": "not_code_checkable" }, { "control": "cra-ai-5", "title": "Manipulationsschutz", "scans": [], - "note": "code-checkable but no off-the-shelf tool digs it out — author a detector (custom semgrep rule / check)", - "status": "needs_tooling" + "note": "design property (tamper protection) — hardware/runtime & operational control, not statically code-checkable", + "status": "not_code_checkable" }, { "control": "cra-ai-6", @@ -146,7 +146,7 @@ "control": "cra-ai-12", "title": "Rollenbasierte Autorisierung", "scans": [], - "note": "code-checkable but no off-the-shelf tool digs it out — author a detector (custom semgrep rule / check)", + "note": "absence-based — no syntactic pattern; covered by the grounded surface check (retrieve surface + LLM judge), gated (BREAKPILOT_GROUNDED_CHECKS) pending live tuning", "status": "needs_tooling" }, { diff --git a/control-map/src/lib.rs b/control-map/src/lib.rs index 8db0ede..63107a8 100644 --- a/control-map/src/lib.rs +++ b/control-map/src/lib.rs @@ -214,6 +214,27 @@ mod tests { assert!(hits.iter().any(|c| c.control == "cra-ai-1")); } + #[test] + fn coverage_reflects_the_b_track_split() { + let s = ControlMap::cra().unwrap().summary(); + // 9 already tool-covered + B1's 4 custom-semgrep controls. + assert_eq!(s.covered, 13); + // The 8 grounded surface controls stay needs_tooling until live-tuned. + assert_eq!(s.needs_tooling, 8); + // B3 marked the 4 pure-architectural controls not code-checkable. + assert_eq!(s.not_code_checkable, 19); + } + + #[test] + fn architectural_controls_are_not_code_checkable() { + let map = ControlMap::cra().unwrap(); + for id in ["cra-ai-2", "cra-ai-3", "cra-ai-4", "cra-ai-5"] { + let c = map.coverage(id).unwrap(); + assert_eq!(c.status, Coverage::NotCodeCheckable, "{id}"); + assert!(c.scans.is_empty(), "{id} should carry no scan bindings"); + } + } + #[test] fn custom_rule_controls_do_not_bind_by_broad_cwe() { let map = ControlMap::cra().unwrap();