#1 _machinery_obligations: SET statement_timeout=4s + run_in_threadpool — auf
prod hing die maschinen-Query ~30s (langsame/unindizierte DB nach DB-Swap)
und blockierte den async-Worker. Jetzt: bei Langsamkeit graceful 'keine
Maschinen-Pflichten' statt Hang. (Fehlender prod-Index = Controls/DB-Session.)
#2 parse_grenzen_json: tolerant ggue. ```json-Fences / Prosa-umschlossenem JSON
(gehostete Modelle wie OVH ignorieren z.T. response_format) → Datenblatt-
Extraktion liefert auch ueber den OVH-Fallback Felder.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
1) createProject las proj.id, der Create-Response ist aber {project:{id}} →
'Projekt anlegen' war kaputt. Jetzt proj.project?.id. E2E verifiziert
(create→put limits_form→get→delete = 200).
2) MaschinenVO-Sicherheitspflichten wurden in die CRA-Cyber-Buckets
(Code/Prozess/Doku) gemischt → fehl-kategorisiert (Maschinen-Safety ≠
CRA-Annex-I-Cyber). Jetzt eigene Response-Liste machinery_guideline +
eigener Frontend-Abschnitt 'Maschinensicherheit (MaschinenVO 2023/1230)';
geklebtes 'MaschVO'-Badge entfaellt damit.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Hybrid-Extraktion Datenblatt → IACE Grenzen (ISO 12100): deterministischer
Detektor (Schnittstellen/Einheiten per Regex) + lokales 35B via llm_cascade
(Qwen-lokal-first) fuer die semantische Zuordnung auf die echten LimitsFormData-
Keys. Nichts erfinden: Feld nicht im Text → leer + Quellen-Zitat je Feld.
Essenzielle ISO-12100-Felder, die leer bleiben → gezielte Rückfragen
(foreseeable_misuses, person_groups, qualification, temporal_limits …).
Endpoint POST /api/v1/cra/extract-datasheet. 13 Tests gruen (reine Teile).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
3-Tier-MaschinenVO-Verdict (direkt / sicherheitsrelevant / nicht relevant) aus
Personengefährdungs-Signal: eine Komponente ist keine Maschine, aber wenn ihre
Funktion bei Fehler ODER Manipulation Personen gefaehrden kann (Bewegung, Laser/
Auge, Kraft, Temperatur, elektrisch), ist sie sicherheitsrelevant — Pflicht
trifft den Maschinenbauer, Zulieferer liefert Nachweise, und ein Cyber-Angriff
kann die Sicherheitsfunktion aushebeln (Cyber-Safety-Bruecke). OWIS-mit-Laser
landet so korrekt als 'sicherheitsrelevante Komponente'. Engine + /readiness
additiv; Frontend: Gefährdungs-Frage + -Typen, MaschinenVO-Ergebnisblock.
Presets aktualisiert (OWIS: Laser+Bewegung, Zwick: Bewegung). 22 Tests gruen.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Reine, deterministische Verdict-Schicht ueber der bestehenden Annex-III/IV-
Klassifikation (kein vierter Klassifizierer): trennt Rechtspflicht von Markt-
Druck. Kern: das Inverkehrbringen (ab 11.12.2027), nicht der Entwicklungs-
zeitpunkt, entscheidet — Bestandsprodukte, die nach der Frist weiter verkauft
werden, fallen unter CRA. Producer-Typen (component/end_device/machine_
integrator/software_app) steuern Default-Annahmen (Anlagenbauer: Vernetzung/OTA
vorausgesetzt) + Verdict-Betonung (Komponente => Markt-Druck). Plus Evidence-
Checkliste (SBOM/VDP/Patch/Lifecycle/Threat-Model/Logging/Auth/Incident) +
Reifegrad. /readiness additiv erweitert (verdict/maturity/digital_elements/
producer_type). 15 Tests gruen. Beispiele: OWIS PS90+, ZwickRoell roboTest.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Liest den Lebenszyklus jedes Befunds (status + tracker_issue_url) aus dem
Scanner zurück und rollt ihn zu einem Management-Bild auf: % erledigt,
4-Phasen (offen/in Arbeit/erledigt/ausgeschlossen), offenes Restrisiko nach
Schweregrad, Fortschritt je CRA-Anforderung und eine Aufgaben-/Ticket-Tabelle
mit Jira-Link. Neuer Endpoint GET/POST /api/v1/cra/progress (dünn → Service
cra_progress, rein deterministisch, kein /assess-Schema-Drift). Frontend:
ProgressView in Ebene 1 (CRACyberView), live je Scanner-Repo, sonst Demo-Status.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Jede Normreferenz einer Maßnahme wird lizenzklassifiziert (eu_law /
public_domain / open / paid_reference) — paid-reference-Normen werden nur als
Verweis geführt, nie im Text gespeichert (idea/expression). Kuratierte
Maßnahmen tragen Tier 'core', KI-/Fallback-Maßnahmen 'review' (indikativ).
Frontend zeigt Quellen-Badges + "indikativ"-Kennzeichnung. Methodik in
docs-src/development/mapping-methodology.md (Szenario C, Due-Diligence).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Ersetzt die ephemere Dropdown-Auswahl durch DB-Persistenz pro IACE-Projekt:
- Migration 156: compliance_cra_scanner_repo_map (tenant_id, iace_project_id PK,
scanner_repo_id). Additiv + idempotent.
- GET/PUT /v1/cra/scanner-repo-map/{iace_project_id} (Upsert/Clear).
- useCRA lädt das gespeicherte Repo beim Laden + persistiert bei Auswahl.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- GET /v1/cra/scanner-repos: distinct repo_ids (+counts) vom Scanner-MCP für den Picker.
- useCRA: scannerRepo-State; bei Auswahl POST /assess-from-scanner (echte Findings),
sonst by-iace/Demo wie bisher.
- ScannerRepoPicker im CRA/Cyber-Tab; leere Auswahl = Demo, Repo gewählt = echte Befunde.
Mapping repo_id↔Projekt aktuell UI-seitig (ephemeral); DB-Persistenz pro Projekt folgt.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Der harte relevant=true-Filter versteckte ~25% des Korpus (40.926 Atome),
~70% davon echte Pflichten (500er-Validierung). relevant wird zur Stufe:
- Service: tier-Param (core=Default schuetzt Agent/CRA; all=alles inkl. review),
ORDER BY relevant DESC; pro Control relevant/tier/source_type
(own_library bei license_rule=3, sonst derived) + source_regulation/article;
core_count/review_count. Pure Helper tier_label + source_type (+ Tests).
- Route: optionaler tier-Query (default core) — contract-safe (additiv).
- Frontend: Coverage-Drill-down /sdk/coverage/[useCase] — Kern-Pflichten vs.
"zur fachlichen Pruefung", je mit Herkunfts-Badge; Uebersicht zeigt Delta.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
(a) Labels: Module korrekt zugeordnet — Modul A = Selbstbewertung, Modul B+C =
benannte Stelle, EUCC = eigenes Zertifikat (nicht Modul H), "harmonisierte
Norm" ist kein Modul sondern Konformitätsvermutung. Für den CRA noch KEINE
harmonisierte Norm veröffentlicht → Kachel als "noch nicht verfügbar"
(erwartet ~2027), nicht wählbar, mit Hinweis. (page/path/documents-Labels.)
(b) Gating: wichtige Klasse II + kritische Produkte dürfen NICHT selbst bewerten;
harmonisierte Norm allein genügt dort nicht → ALLOWED_PATHS IMPORTANT_II/
CRITICAL = {eucc, notified_body}; DEFAULT_FOR II = notified_body. _PATH_HINT
entsprechend. Regressionstest test_cra_conformity_paths.py.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Migration 153 adds compliance_cra_projects.linked_iace_project_id (additive,
idempotent). New thin router cra_link_routes.py: POST /projects/{id}/link-iace
sets the reference; GET /by-iace/{iace_project_id} returns the linked CRA project
+ its latest assessment snapshot. The IACE "CRA / Cyber" tab now resolves the
linked CRA assessment first (real, from the snapshot) and only falls back to the
demo scenario when nothing is linked. One assessment, two views.
[migration-approved] — user approved the new column for the CRA<->IACE reference.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Follow-up to the machinery_reg_cyber.py removal: the readiness endpoint now pulls
Machinery Regulation 2023/1230 cyber-with-safety obligations from the shared
Controls-API (use_case=maschinen), tagged "Maschinen-VO", best-effort.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Machinery Regulation 2023/1230 cyber-with-safety obligations are already in the
shared Controls-API (use_case=maschinen, atom-grain, classified, license-clean) —
so remove the hand-authored machinery_reg_cyber.py spine. The readiness check now
fetches them from use_case=maschinen (sub_topics sicherheitsanforderungen ->
code, risikomanagement -> process, konformitaetsbewertung -> document), tagged
source "Maschinen-VO" alongside the CRA obligations. Same pattern as the security
cluster; no own formulation, no license question.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Machine/plant builders are hit by BOTH the CRA and the new Machinery Regulation.
New machinery_reg_cyber.py models its two well-corroborated Annex III cyber-with-
safety essential requirements (1.1.9 protection against corruption, 1.2.1 control-
system safety incl. foreseeable manipulation) in our own words; EU legal text is
freely reusable (Commission Decision 2011/833/EU, source acknowledged), harmonised
standards referenced by identifier only. The readiness check asks "is it
machinery?" and, if so, adds these obligations tagged "Maschinen-VO" alongside the
CRA ones — the combination is visible (regulations list + per-item source badge).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
For hardware CE projects (no repo) each networked component (controller/hmi/
gateway/drive/remote_access/sensor) yields typical ICS vulnerability CLASSES
(real CWE + "CISA-ICS — product-specific check" framing, NO fabricated CVEs);
they flow through the same CRA engine. /assess accepts components[]. MappedFinding
now echoes title/location/cwe so the response is self-contained for any finding
source. Live CISA-ICS/NVD per-product CVE lookup is the later enrichment.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Semantic breadth (2): each finding's CRA-AI is mapped to a network_security
sub_topic and enriched with atom-grain, framework-traceable obligations from the
shared Controls-API (compliance.atom_classification) — at the endpoint/view layer
(SessionLocal), NOT in the pure mapper. CRA-AI anchor + curated measure +
NIST/OWASP crosswalk stay the lead; this is breadth + source evidence. Only
network_security is queried (atom-grain), scoped by sub_topic + limit. Frontend
renders it under the collapsible best-practice depth (control_id · title · source).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Reads compliance.atom_classification (Haiku pass: relevant + sub_topic +
canonical_obligation) when present -> precise, sub-topic-organized controls per
topic; master-grain seed stays as fallback for unprocessed topics. New optional
sub_topic filter + subtopic_counts facet + granularity flag in the response.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Persist each CRA assessment as a versioned, auditable snapshot over the product
lifecycle. Reuses the existing compliance_cra_documents table (NO new schema,
frozen DB respected): doc_type='doc_risk_assessment', full assessment in
generation_context, requirements_coverage summary, auto-incrementing version,
prior version superseded. New endpoints: POST /projects/{id}/assess-snapshot,
GET /projects/{id}/assess-snapshots (history), GET /assess-snapshots/{id}.
Additive (no contract baseline change).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Deterministic bridge (cra_safety_bridge.py): a cyber finding's attack capability
(remote_actuation / code_tampering / integrity_loss / auth_bypass, derived from
its CRA category) is matched against what each CE safety function is vulnerable
to. A match re-opens the mitigated hazard, flags the finding safety_impact (which
floors it to P0), and produces the cross-link. Endpoint accepts safety_functions;
frontend passes the project's safety functions and renders the LIVE cross-links
(no more hardcode). Safety functions are demo input now; come from the CE risk
assessment in production.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Deterministic prioritisation on top of the mapper (cra_prioritizer.py): a
non-negotiable P0 floor (safety-function compromise / actively exploited /
CRITICAL — customer weights cannot demote) plus a discretionary tier ranked by
severity x the customer's weight (high/medium/low) for the 5 business objectives
(access/data/network_api/supply_updates/monitoring). Quick-win flag (high impact,
low effort) for a second view; each finding carries a short priority reason.
Endpoint accepts weights + per-finding safety_impact/exploited. Rough pre-sort
only (devs re-sort in Jira). No DB.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Live HTTP entry for the deterministic CRA assessment — repo-scanner findings
in, CRA Annex I mapping + risk + curated measures + NIST/OWASP golden-set
crosswalk out. Project-less (works for any customer, no CE-RA/FMEA required);
reuses the tested mapper, same logic the MCP server exposes. Additive endpoint
(no contract baseline change); no DB.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Read-only layer (service + thin route + tests) that returns the controls
mapped to a use-case/topic, ranked by a deterministic precision proxy
(is_primary + mapping confidence + registry keyword relevance) over the
existing mc_use_case_mappings seed. No schema change.
Shared handoff point: the document specialist agents AND the CRA
finding-mapper draw from this one controls index instead of separate
retrievals.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
User-Feedback umgesetzt: Cookie-Titel-Fix (rendern nicht mehr als nacktes
"Befund" — Titel aus cookie/type/vendor), Executive Summary oben, je Modul
Statistik (Counts + Severity-Balken + MCs) + nur Top-3 Befunde + Verweis auf
"N weitere" mit Frontend-Link (snapshot_id) + Zwischenfazit, Browser-Übersicht,
Gesamtanalyse, klarerer "Grenzen"-Satz, Report-Versionsnummer. 6 Tests grün.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- browser_cross_finding: deterministische Sicht ueber die Matrix (keine 2.
Engine, kein LLM). Findet Inkonsistenzen ZWISCHEN Browsern (Cookies vor
Consent / Ablehnen nicht universell respektiert / Banner-Links fehlend) und
ordnet ein: Safari-ITP / Brave-Shields / Firefox-ETP maskieren Verstoesse
clientseitig → strenge Engine "sauber" ist KEIN Compliance-Beleg, massgeblich
sind die nachgiebigen (Chrome/Edge). Coverage-Hinweis fuer nicht verfuegbare
Browser. Je Befund Titel/Detail/Severity/affected/Massnahme.
- snapshot_check_routes: cross_findings frisch in run + GET (nicht persistiert).
- BrowserBehaviorView: "Cross-Browser-Befunde"-Block ueber der Tabelle.
- Tests: test_browser_cross_finding (6).
Offen (Folge-Task): Borlabs-Consent-Historie-Live-Erkennung (braucht
consent-tester-Storage-Scan).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- check_snapshot: update_browser_matrix/load_browser_matrix — migrationsfrei
in banner_result.browser_matrix (JSONB jsonb_set, eigener scanned_at)
- snapshot_check_routes: POST /snapshots/{id}/browser-behavior/run laeuft
/scan-matrix LIVE (Re-Crawl je Engine, nur live messbar), persistiert das
Ergebnis; GET /snapshots/{id}/browser-behavior liefert die gespeicherte
Matrix ohne Re-Crawl. Profil-Set = 4 Default-Engines + Brave/Chrome/Edge.
- consent-tester multi_browser_scanner: Semaphore(2) gegen OOM (7 Browser
parallel sprengten das 2g-mem_limit)
- Pydantic-Modell mit Optional[List[...]] (nicht `| None`) → Py3.9-sicher
- Tests: _snapshot_scan_url + Request-Defaults (5)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Für die Library-getroffene Teilmesse (~32%) pro Cookie die Feld-
Abweichungen deklariert→Library (Kategorie/Laufzeit/Zweck) als Diff-Karte,
plus ehrlicher Funnel (gesamt → geprüft → abweichend) — nicht-getroffene
Cookies sind nicht prüfbar (kein Pass/Fail), passend zur Tonalität.
- analyze_cookies: 'expected'-Soll-Wert an tracker_as_necessary/
excessive_lifetime/missing_purpose (+ _CAT_LABEL_DE).
- neues cookie_declaration_diff.build_declaration_diff: reine Regroup-
Aggregation der Findings pro Cookie (single source = analyze_cookies),
Hinweis-Typen (third_country/eu_alternative) bewusst ausgeschlossen.
- cookie-check exponiert out['declaration_diff'].
- CookieDeclarationDiff.tsx oben im Cookie-Tab (vor Panel/ResultView).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
#3 Storage-Filter: cookie-check exponiert per-Cookie-Speichertyp
(storage_inventory.per_cookie); CookieResultView bekommt Filter-Chips
(Cookie/Local Storage/Framework …) + eine Speicher-Spalte, Anbieter ohne
passenden Treffer werden ausgeblendet, KPI zeigt gefilterte Zahl.
A-Routing: legal_notice ist jetzt ein kanonischer Doc-Type. Eigene
Discovery-Regel (legal-disclaimer/rechtlicher-hinweis) VOR impressum →
die Disclaimer-Seite wird nicht mehr als Impressum substituiert (Ursache,
dass die Cross-Doc-Reconciliation nie zündete). capture-only: als
doc_entry für B persistiert, aber nicht einzeln gescort (keine 0%-Noise,
da ohne eigene Checkliste). Im Scan-Form als Option auswählbar.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Cookies werden je Vendor nach Name dedupliziert (Consent-Phasen-Dubletten;
BMW 2196 → ~772) — in cookie-check + get_snapshot, behebt aufgeblähte
Kachel-/Finding-Zahlen.
- Impressum-Snapshot-Check überspringt den ~40s-LLM-Schritt (context skip_llm)
→ Tab lädt sofort statt leer zu bleiben.
- Vendor-Tabelle zeigt nur die Cookie-Zahl (kein 'Cookies'-Wort je Zeile).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Ein 'X fehlt'/'zu prüfen'-Finding wird unterdrückt, wenn die Pflicht in einem
ANDEREN Snapshot-Dokument erfüllt ist (z.B. § 36 VSBG / OS-Link stehen bei BMW
in AGB/'Rechtlicher Hinweis', nicht im Impressum → war False Positive).
Konservative Allowlist (impressum: verbraucher_streitbeilegung, odr_link) gegen
False-Reconciliation. Verdrahtet in _run_doc_agent (alle Doc-Checks). Frontend:
'In anderem Dokument abgedeckt'-Sektion. Greift voll nach Scan + Legal-Capture.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Linter: FORBIDDEN_OUTPUT_TERMS per Wortgrenze → 'Schutzgarantien'/'geeignete
Garantien' (Art. 46) passieren, 'garantiert'-Claims bleiben geblockt.
- DSE: L2-Detail wird übersprungen statt 'na', wenn die L1-Pflichtangabe fehlt
(kein irreführendes 'nicht anwendbar' für z.B. Transfermechanismus).
- DSE: Drittland → HIGH bei dokumentiertem Drittlandtransfer (scan_context via
AgentInput.context) — BMW (Konzern, US-Provider) ist kein weiches MEDIUM.
- DSE: Titel/Maßnahme kurz (treibt den Recommendation-Titel); ausführliche
Begründung als evidence — behebt 120-Zeichen-abgeschnittene Überschriften.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
DSEAgent wrappt die existierende ART13_CHECKLIST (33 kuratierte Pflichtangaben
L1 + Detailchecks L2) → strukturierter AgentOutput, NICHT der 90k-Library-
Firehose (eCall/Gesundheit/Telekom-Lärm). GET /snapshots/{id}/dse-check spiegelt
impressum-check; doc_input_from_snapshot generalisiert. Frontend: generischer
AgentModuleTab (lazy → AgentResultTab) für Impressum + DSE; DSE-Tab in der
Snapshot-Seite. Plus HRB-Pattern \d→\d+ (volle Registernummer als Beleg).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Snapshot-Detailseite wird zu Modul-Tabs (Cookies & Tracking | Impressum).
Backend GET /snapshots/{id}/impressum-check laeuft den v3 ImpressumAgent auf
dem gespeicherten Impressum-Text (kein Re-Crawl); Input-Erzeugung in
impressum_input_from_snapshot() ausgelagert (pure + getestet: Text/Scope/
company_name-Fallback/None-Pfad). Frontend laedt lazy beim Tab-Wechsel und
rendert mit dem bestehenden AgentResultTab (keine zweite Engine).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Cookie-Check-Endpoint liefert jetzt out["drift"] (audit_cookie_compliance):
deklariert (Cookie-Richtlinie-Text) vs. tatsaechlich geladen (Browser).
Frontend zeigt den Reality-Check-Strip oben im Panel: X dokumentiert ·
Y geladen · Z undokumentiert. Pinnt den Vertrag mit test_cookie_drift.py
(undokumentiert-geladen + beide Drift-Richtungen) + Vitest Drift-Strip.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>