"""Pin the CRA-AI -> network_security sub_topic map (DB enrichment verified live).""" from compliance.services import cra_use_case_controls from compliance.services.cra_use_case_controls import ( enrich_findings_with_breadth, subtopic_for, ) from compliance.api.cra_annex_i_data import ANNEX_I_REQUIREMENTS # Exact atom-grain sub_topic keys (verified against the live atom_classification). _VALID = { "access_control", "authentication", "cryptography", "network_segmentation", "logging_monitoring", "supply_chain_security", "vulnerability_management", "incident_response", "secure_development", "data_protection", } def test_every_requirement_maps_to_a_valid_subtopic(): for req in ANNEX_I_REQUIREMENTS: st = subtopic_for(req["req_id"]) assert st in _VALID, "{} -> {}".format(req["req_id"], st) class _FakeControlsService: """Stands in for UseCaseControlsService: returns one atom control per (use_case, sub_topic) pair, carrying the legal anchor (source_article) the real batched atom query now selects.""" def __init__(self, db): pass def breadth_controls_batch(self, pairs, per=3): return { (uc, st): [{ "control_id": "AI-{}-{}".format(uc, st), "title": "Test obligation", "source_regulation": "Cyber Resilience Act (CRA)", "source_article": "Artikel 13", "severity": "high", "use_case": uc, }] for uc, st in pairs } def test_breadth_carries_source_article(monkeypatch): cra_use_case_controls._BREADTH_CACHE.clear() # process cache — isolate the test monkeypatch.setattr( cra_use_case_controls, "UseCaseControlsService", _FakeControlsService, ) mapped = [{"primary_requirement": "CRA-AI-8"}] # -> authentication sub_topic enrich_findings_with_breadth(mapped, db=None) breadth = mapped[0]["regulatory_breadth"] assert breadth, "expected breadth controls" assert all("source_article" in c for c in breadth) assert any(c["source_article"] == "Artikel 13" for c in breadth)