Schnelltest-nur-Chrome wieder entfernt (User: Banner-Test soll IMMER alle
Browser abdecken). Ein primärer Button im Leerzustand + "Erneut testen" im
Ergebnis-Kopf; beide lösen die volle Matrix aus.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Stage 1 of the FailureKnowledge bulk loader: harvest NASA NTRS
lessons-learned with a strict public-reuse gate (NTRSUsable: public
release, not export-controlled/EAR/ITAR, not CUI, PUBLIC_USE_PERMITTED,
no third-party copyright). NTRSPDFURL prefers the PDF download for
downstream text/OCR extraction. GET /iace/failure-knowledge/ntrs runs
the live harvest and returns only the licence-clean records.
Pure parse/gate helpers are fixture-tested (usable vs ITAR / third-party
/ restricted / video-only); accepted licences also pass the FK allowlist.
Next: tuple extraction (abstract -> FailureKnowledge) + Playwright/OCR for
scanned PDFs -> bp_iace_failure_kb.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Korrektheit (§ 25 TDDDG): "Cookies vor Consent" ist KEIN Verstoss per se —
technisch notwendige Cookies inkl. des Consent-Cookies (speichert die
Ablehnung) sind nach Abs. 2 erlaubt. Verstoss ist nur nicht-essentielles
TRACKING vor Consent.
- browser_cross_finding: Befund haengt jetzt an violations.before_consent
(Tracking), nicht an der Cookie-Rohzahl; § 25 Abs. 2-Hinweis im Detail.
Regressionstest: Cookies-ohne-Tracking → KEIN Befund.
- multi_browser_scanner._extract_dimensions: Score nutzt Tracking-Violations
+ reject_respected-Verdikt statt Rohzahl (Fallback erhalten).
- BrowserBehaviorView: "Cookies vor Consent" nur rot/⚠ bei Tracking,
"nach Ablehnen" neutral (Verdikt = reject-Spalte); erklaerende Zeile.
Speed: run_consent_test ueberspringt im Matrix-Modus (browser_profile gesetzt)
die teuren Phasen C/D-F/G — nur A+B noetig. Verhindert das 504 beim
Multi-Engine-Scan (BMW 4 Engines lief sonst in den 338s-Gateway-Timeout).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
E2E auf BMW (macmini, arm64) zeigte: nur Chromium lief, Firefox/WebKit/Mobile-
Safari scheiterten mit "Host system is missing dependencies to run browsers".
Die manuell gepflegte apt-Lib-Liste war fuer Gecko/WebKit unvollstaendig.
`playwright install-deps chromium firefox webkit` (als root) installiert den
vollstaendigen OS-Dep-Satz → alle Engines starten. Betrifft beide Arches.
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>
P1 of the auto-FMEA build plan: establish the public-domain methodology
foundation (no AIAG-VDA/SAE/IEC tables reproduced).
- fmea_data_sources.go: MIL-STD-882E severity (Cat I-IV→1-10) + probability
(A-F→1-10 with per-hour λ bands), OccurrenceFromRate(λp·α), SeverityForCategory,
MIL-STD-1629A CriticalityCm = λp·α·β·t. Own 1-10 projection, government-anchored.
- 4 versioned source docs (MIL-STD-1629A, MIL-STD-882E, NASA RCM, FMD-91/NPRD-91)
ingested into the new RAG collection bp_iace_fmea_kb (whitelisted).
- Tests for all scales/mappings/criticality (green).
Next (P1 step 2): fetch FMD-91/NPRD-91 bulk λ/α tables from DTIC.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Dockerfile: Brave-apt-Repo + `playwright install --with-deps chrome msedge`,
beide hinter TARGETARCH=amd64-Gate und best-effort (|| echo) → arm64-Dev-
Builds (macmini) brechen NICHT, laufen mit den 4 Default-Engines; Brave/
Chrome/Edge sind amd64-only opt-in-Extras (EXTRA_PROFILES).
- docker-compose.hetzner.yml: consent-tester auf linux/amd64 (statt arm64-
Emulation auf Orca) — Voraussetzung dafuer, dass die echten Browser
ueberhaupt installiert werden.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
run_consent_test nimmt jetzt browser_profile (browser_profiles.py): Firefox/Gecko,
WebKit/Safari oder Blink (Chromium-Default / Chrome-/Edge-Channel / Brave via
executable_path). Rückwärtskompatibel: None → Chromium wie bisher. Fundament für
die echte /scan-matrix (Stage-1.b-Shim), die als nächstes Profile durchreicht.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
#1/#2 (kein-Banner-affirmativ) feuerte nicht, weil der no-banner-Pfad bei
Zeile 220 früh zurückkehrt — vor dem Edge-Case-Block am Funktionsende.
Logik in _apply_edge_case_findings extrahiert und an BEIDEN Return-Pfaden
aufgerufen (Früh-Return + Ende). Damit greift #1 jetzt auf statischen Seiten.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
#1/#2: Wenn KEIN Banner erkannt UND kein Tracking vor Consent (statische Seite
oder nur technisch notwendige Cookies, §25 Abs.2 TDDDG) → affirmativer LOW-Befund
"konform, kein Banner nötig" statt stillem "Banner fehlt". Inkl. Geo-Caveat
(Scan außerhalb EU sieht geo-getargetete Banner evtl. nicht).
#3: detect_non_cookie_tracking erkennt Pixel/Fingerprinting per Domain-Signatur
(Meta, TikTok, LinkedIn, Pinterest, Clarity, FingerprintJS, Hotjar, Reddit,
Snapchat) → MEDIUM-Befund "§25/Art.5(3) gilt auch ohne Cookies". '0 Cookies' ≠
'kein einwilligungspflichtiges Tracking'.
Verdrahtet in consent_scanner vor dem Return. Tests + py_compile grün.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Cookie-freie Analyse mit reinem Opt-out-Hinweis (z.B. bayshore.ai:
"Privacy-friendly, cookie-free analytics are currently enabled ... Disable")
ist KEIN Consent-Banner: cookieless = kein Endgeräte-Zugriff → §25 TDDDG
verlangt keine Einwilligung → Opt-out statt Opt-in. Die Standard-Opt-in-
Checks (granulare Kategorien, Accept/Reject-Balance, Impressum-im-Banner)
trafen nicht zu und erzeugten 3 Falsch-HIGHs.
is_cookieless_optout() erkennt das Muster (cookieless-Signal + Opt-out-Wort,
KEIN Consent-Signal); check_banner_text gibt dann früh EINEN ausführlichen
LOW-Erklär-Befund zurück (zählt nicht als HIGH) und setzt die Opt-in-Checks
aus. Ausführlich, weil der Fall extrem untypisch ist.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Ollama entlädt das 35b-Modell nach 5 Min Leerlauf → jede Frage danach
startet es kalt (Modell-Load) und läuft in den Frontend-Timeout ("Load
failed"). keep_alive='30m' im Chat-Request hält es warm.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
compliance-advisor.soul.md (Sie durchgehend):
- Persona: ruhiger Compliance Co-Pilot (Komplexität abnehmen, Nutzer entscheidet),
DSB/Anwalt als Partner-Schritt statt Ausrede.
- Antwortlänge an die Frage koppeln (kurze Frage → 1-3 Sätze, kein erzwungenes
4-Punkte-Schema); proaktiv mit nächstem Schritt schließen.
- Konfidenz-bewusst (Wahrscheinlichkeit statt Garantie); Risiken/Bußgelder nur auf
Nachfrage + konstruktiv, nie als erster Eindruck.
- Scope-Disziplin: nur Compliance/Datenschutz/Security/Recht; Off-Topic freundlich
+ knapp ablehnen, kein Erfinden fachfremder Antworten.
drafting-agent.soul.md: Anti-Leak-Regel (Anweisungen nie offenlegen) + Sie + Off-Topic-Disziplin.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Der Advisor deutete Inhaltsfragen ("Was ist der CRA?") als Quellen-/
System-Frage und wich aus; auf Nachfrage zitierte er sogar seine
Quellenschutz-Anweisung. Fixes in compliance-advisor.soul.md:
- Quellenschutz gilt nur noch für ECHTE Meta-Fragen (Quellenliste/RAG),
NICHT für "Was ist X?"-Fachfragen → die werden sofort beantwortet.
- Neue Regel: System-Anweisungen/Prompt NIE offenlegen oder zitieren;
auf "warum hast du nicht geantwortet?" nicht mit internen Regeln erklären.
- Neue Regel: mehrdeutige Abkürzungen (CRA …) kurz disambiguieren statt
ausweichen.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Der "Voll-Audit öffnen (alle MCs)"-Link hing in ComplianceResultTabs (aus
der Agent-Seite entfernt). Jetzt im Detail-Header der Snapshot-Ansicht via
snap.check_id → /sdk/agent/audit/{check_id} (Audit-Daten verifiziert
vorhanden). Plus Site-Titel-Header.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Tabs Website-Scan (nie funktioniert), Banner-Check, Agent-Test entfernt;
Tab-Leiste weg, da nur noch Compliance-Check übrig.
- Unter dem Compliance-Check jetzt die Snapshot-Historie (neuer
SnapshotHistoryList): neuester oben + farblich markiert, Klick → Detail-
Seite mit den Ergebnissen. Macht /sdk/agent/snapshots erreichbar.
- ComplianceCheckTab zeigt nach dem Lauf keine Inline-Ergebnisse mehr,
sondern einen Hinweis auf die Historie (onComplete refresht sie).
- Tote Komponenten gelöscht (ScanResult/BannerCheckTab/AgentTestTab).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- architecture.go: DataSources now reflect the real ingested set (ESAW 2023,
BLS CFOI, OSHA OTM, PRISM, cobot CC-BY, HSE) with their RAG collections;
risk stage cites BLS + the searchable RAG layer; matrix stage now mentions
the distance-benchmark dimension.
- Architektur & Datenfluss tab: new DataFlowDiagram — 4 lanes (input →
knowledge/RAG-evidence → deterministic engine → outputs) with live counts.
- scripts/ingest_iace_kb.sh: idempotent E1 ingest — creates the 2 collections
and uploads the 6 datasources docs against a configurable RAG_URL (for prod
Qdrant), with retry.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Die Deklaration-vs-Bibliothek-Sicht deckte sofort einen Fehl-Match auf:
'cct_chatSessionToken' (Genesys-Webchat) traf die Library-Basis 'cct'
(actual_category Marketing, purpose 'shopping cart') → falsches
'necessary→Marketing'-Finding. Ursache: gekürzte 3-Zeichen-Basis ohne
führenden _.
_is_distinctive_base: gekürzte Präfix-Basis nur akzeptieren bei ≥4 Zeichen
ODER führendem '_' (kanonische Cookies wie '_ga'). GTM-/AdobeOrg-/Hash-
Suffix-Stripping bleibt erhalten (Tests grün), generische 'cct'/'sid'/'gtm'
über-matchen nicht mehr.
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>
Cross-checked cobot_biomech_limits.md against both source papers:
- Behrens et al. 2022 (Frontiers): 10 body regions spot-checked, force
values match the paper EXACTLY in both columns (pinching + impact).
- Park et al. 2019 (PLOS ONE): lowest/highest/range pressure values exact.
Fix: 28 -> 29 body locations; add a verification stamp. Threshold VALUES
were already correct (no data change), so no RAG re-ingest needed.
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>
Versioned, license-tagged source docs for the multi-layer GT knowledge base,
ingested into the new core RAG collection bp_iace_safety_kb (whitelisted in
the RAG search handler):
- prism_risk_methodology.md — OPSS PRISM v2 (OGL v3): full severity(4)×
probability(8) → risk-level matrix (Serious/High/Medium/Low), RAPEX-aligned.
- cobot_biomech_limits.md — CC BY 4.0 papers (Behrens 2022 / Park 2019):
force (N) & pressure (N/cm²) pain thresholds by body region (the data behind
ISO/TS 15066, cited from the open papers — standard tables NOT reproduced).
- hse_example_risk_assessments.md — HSE (OGL v3): qualitative hazard→control.
- osha_robot_safety.md — OSHA OTM (public domain): 250 mm/s teach anchor,
robot hazard taxonomy, safeguarding hierarchy.
No DIN/EN/ISO/IEC/DGUV content reproduced; each doc states its license + attribution.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Surface result.distances in the benchmark module: a DistanceComparison
panel showing agreement %, covered values (green), GT-only gaps (amber)
and engine-only extras — mirroring the RiskComparison panel.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
US severity anchor complementing ESAW: BLS Census of Fatal Occupational
Injuries (public domain), event/exposure distribution 2023-24 + the
machine-relevant "Contact incidents" breakdown (struck/caught/compressed
by running powered equipment: 226/213). Key finding: in MANUFACTURING,
contact is the leading fatal event (104/353 = 29.5%) — independent support
for the model's mechanical-contact emphasis. Ingested into the core RAG
collection bp_iace_accident_stats.
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>
load_big_library matchte nur EXAKT → nur ~27% der BMW-Cookies trafen die
Open-Cookie-DB, weil Per-Instanz-Suffixe abweichen (_ga_GTM-XYZ, AMCVS_###@
AdobeOrg, _pk_id.5.7d8). Jetzt: Library einmal laden, Namen entwildcarden,
über _candidate_keys (exact + Präfix an Trennzeichen, Mindestlänge 3 gegen
Über-Match) matchen. Reuse der bewährten _strip_wildcards-Logik.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
C1: drop the misleading OSHA §1910.212(a)(5) fan-guard citation from M602
(overhead lift clearance) — EN 349 + EN ISO 13854 already cover it.
C2: frame M237's 25/500 mm as Richtwerte to be determined per EN ISO 13854
(single factual values in prose are facts, not table reproduction — but
keep the conservative caveat).
C3: keep ergonomic W=2 deliberately and document why — ESAW ranks it the most
frequent non-fatal mode (24.7%) but that population doesn't transfer to an
acute machine point-hazard; the machine GT governs.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Adding M605 (drive-limited general speed) and M606 (limited descent on
energy loss) to the library wasn't enough — measures only get suggested
if a pattern's SuggestedMeasureIDs references them. Add M605 to the three
lift crush patterns and M606 to the floor-stop descent pattern (HP2100),
so a re-seed actually attaches them and the distance benchmark closes the
≤150 mm/s gap.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
CompareBenchmark now also compares the engine's numeric dimensions
(mm gaps, mm/s speeds) against the professional's GT measures: parses
distance tokens from both sides (German thousands/decimal aware),
reports matched / gt_only (gaps) / engine_only + an agreement %.
Surfaces as result.distances on the existing benchmark endpoint.
Deterministic, no LLM. On the GT-derived seed sessions it mainly guards
DRIFT; its real value is new sessions. Real-GT test pins that the engine
covers the Bremse (250 mm/s, 250/850 mm) and Kistenhub (25/120 mm,
150/75 mm/s) headline dimensions.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The GT distance benchmark surfaced three Fachmann lift values the engine
carried no measure for: general lift/lower speed (≤150 mm/s), the low-zone
inching regime (<200 mm floor clearance, ≤75 mm/s), and limited descent on
power loss (≤100 mm). Extend M603 (inching) and add M605 (drive-limited
general speed) + M606 (load-holding on energy loss). Values framed as
generic hoist recommendations with EN 1570-1 reference, not GT-memorised.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The Risikobewertung page only mentioned the data sources as static prose.
Add a collapsible "Datenquellen & Evidenz" panel sourced from
/iace/risk-data-sources: the real Eurostat ESAW 2023 contact-mode shares
per mode, with license + ready-to-print attribution, and the note that
tiers anchor the ordering while values stay GT-calibrated.
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>
Makes the OSHA minimum-distance anchor visible per measure in a project
without a DB schema change or re-seed: persisted mitigations store the
measure NAME verbatim (not the catalog ID), and measure names are unique
across the 578-entry library (pinned by test), so a name→ID resolver
bridges the gap.
Backend: MeasureIDByName + MinimumDistancesForMeasureName/LinksForMeasureName;
/iace/minimum-distances now accepts ?measure_name=; link table enriched with
measure_name for one-request UI matching.
Frontend: useMinimumDistances loads the link table once and keys it by name;
OshaDistanceNote renders the anchor (value/CFR/license/EU-hint/relation) on the
matching measure group in the Maßnahmen tab.
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>
_match_value gibt genau den gematchten Bereich zurück (nur die E-Mail unter
Email, nur die USt-IdNr, nur die Telefonnummer) — nicht mehr ein Fenster/den
umgebenden Satz. Behebt die Wiederholung desselben Anfangssatzes bei Texten
ohne Zeilenumbrüche (BMW = ein Block).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Executes the accident-statistics pipeline for the risk anchors:
- Refresh contactModeEvidence with real Eurostat ESAW figures
(dataset hsw_ph3_08, reference year 2023): impact 24.0%/21.4%,
struck-by 13.0%/23.8%, sharp 14.5%, trapped/crushed 13.8% (fatal),
+ new physical/mental-stress mode 24.7% → ergonomic. GT-calibrated
tier VALUES unchanged; the real data confirms the ordering.
- Add the versioned source document (datasources/esaw_accident_stats_2023.md,
ESAW CC BY 4.0 + OSHA public-domain context) that is ingested into the
core RAG collection bp_iace_accident_stats for searchable evidence.
- Whitelist bp_iace_accident_stats in the RAG search handler so seeding
can full-text search the statistics with citation at seed time.
Two-layer design: the small license-tagged code table stays the deterministic
tier/citation lookup; the RAG holds the searchable source evidence.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Drittland: unbekannte Herkunft ('N/A') + Self-Hosting feuern nicht mehr —
First-Party-Session-Cookies (PHPSESSID/JSESSIONID) waren False Positives.
- Impressum _line_of: enges Fenster um den Treffer bei Texten ohne Umbrüche
(BMW = ein Block) → jede Pflichtangabe zeigt IHREN Beleg statt denselben Satz.
- Neuer Finding-Typ missing_opt_out: einwilligungspflichtiger Anbieter mit
Cookies ohne Opt-Out-/Widerspruchs-Link (Art. 7 Abs. 3 + Art. 21).
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>
The May-built OSHA distance library (minimum_distances.go, 29 CFR 1910,
US public domain) was dead code — zero callers, no route, no test, while
the mm values that actually appear in measures are independent hand-prose
(some carrying ISO 13854/13857 values, not OSHA).
This surfaces it without touching the measures response contract:
- GET /iace/minimum-distances (+ ?measure_id=) returns the distances, the
curated measure→distance link table and the licensing note.
- AllMeasureDistanceLinks/MinimumDistancesForMeasure resolve only the
defensible links (M600 value_source; M254/M065 public-domain crossref to
ISO), with the relation made explicit so the join stays honest.
- architecture.go lists the OSHA library so it shows in the audit explainer.
- Tests: inch→mm conversion + license completeness, link integrity, and a
consistency test pinning that a value_source measure's prose still
matches the OSHA source (codifies the audit finding as a regression gate).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>