--- schema_version: 1 open_count: 5 waived_count: 0 fixed_count: 7 total_count: 12 last_updated: 2026-09-07T08:09:04.406Z --- # Broken Windows Ledger > Cross-phase defect register. With `workflow.windows_enforce` enabled, `/gsd-ship` blocks while `open_count > 0`. > Waive with `gsd-tools windows waive ""` (reason required). > Mark fixed with `gsd-tools windows fixed `. | id | phase | kind | file | line | description | status | reason | recorded_at | resolved_at | |----|-------|------|------|------|-------------|--------|--------|-------------|-------------| | 1 | 15 | unrun-verify | .planning/phases/15-modul-berechtigungen-gruppen-user-grants/15-06-PLAN.md | | 15-06 : manueller Browser-Durchklick (Anlegen/Umbenennen/Standardmarkierung/AD-Bindung/Mitglieder/Loeschdialog + Fehlerpfade bei abgeschalteter API) nicht ausgefuehrt — kein Browser-Tool in dieser Session verfuegbar | fixed | | 2026-08-04T17:05:42.026Z | 2026-09-07T08:03:50.832Z | | 2 | 15 | unrun-verify | .planning/phases/15-modul-berechtigungen-gruppen-user-grants/15-07-PLAN.md | | Manueller Browser-Durchklick aus dem Plan-Verification-Block (Matrix-Freigabe setzen/entziehen, Aktivierungsdialog beide Wege, Direkt-Grant neben Gruppen-Grant, Fehlerfall bei gestoppter API, lange Namen) nicht ausgefuehrt -- kein Browser-Tool in dieser Session (15-07-SUMMARY.md D4) | fixed | | 2026-08-04T17:27:42.267Z | 2026-09-07T08:03:51.067Z | | 3 | 15 | unrun-verify | .planning/phases/15-modul-berechtigungen-gruppen-user-grants/15-08-PLAN.md | | Manueller Browser-Durchklick aus dem Plan-Verification-Block (USER ohne Freigabe: Sidebar/403-Seite/Marketplace-Badge+Toast/API-403 identisch; ADMIN: alle vier Ebenen zugaenglich) nicht ausgefuehrt - kein Browser-Tool in dieser Session verfuegbar. | fixed | | 2026-08-04T17:50:13.320Z | 2026-09-07T08:03:51.288Z | | 4 | 16 | unrun-verify | .planning/phases/16-ad-gruppen-synchronisation/16-03-PLAN.md | | 16-03 Task 2 human-check: RESEARCH.md Annahmen A1 (objectGUID uebersteht AD-Umbenennung) und A2 (byteweise Hex-Filter-Syntax) sind gegen kein echtes Active Directory geprueft — kein erreichbares AD in dieser Sandbox. Negatives Ergebnis bei A1 oder A2 ist Stopp-Grund fuer die Loeschsemantik (D-05). | open | | 2026-08-06T14:21:59.987Z | | | 5 | 16 | unrun-verify | .planning/phases/16-ad-gruppen-synchronisation/16-04-PLAN.md | | Manueller Browser-Durchklick aus dem Plan-Verification-Block (drei GroupFormModal-Zustaende: Anlegen mit Hinweis-Link, lokale Gruppe umbenennen, importierte Gruppe mit gesperrtem Namen + internem Namen speichern; Namensanzeige mit Tooltip in der Liste nach dem Speichern) nicht ausgefuehrt — kein Browser-Tool in dieser Session verfuegbar. | fixed | | 2026-08-06T14:31:14.336Z | 2026-09-07T08:03:51.517Z | | 6 | 16 | unrun-verify | .planning/phases/16-ad-gruppen-synchronisation/16-05-PLAN.md | | 16-05 Manuell nachzuholen (Browser): Sync ausloesen und pruefen, dass alle drei Zahlenzeilen erscheinen; Lauf mit verschobener Standardmarkierung provozieren und Amber-Zeile pruefen; Freigabe-Matrix-Spaltensuche unter beiden Namen probieren - nicht ausgefuehrt, kein Browser-Tool in dieser Session verfuegbar. | open | | 2026-08-06T14:39:03.905Z | | | 7 | 17 | unrun-verify | .planning/phases/17-eigene-ausschreibungs-quellen-je-nutzer/17-01-PLAN.md | | 17-01 Task 2 human-check: Browser-Gegenprobe (normaler Nutzer oeffnet /modules/tender-radar/my-sources, speichert Postfach, zweites Konto desselben Mandanten sieht leeres Formular) nicht ausgefuehrt — kein Browser-Tool in dieser Session verfuegbar. Automatisierte Pruefungen (prisma validate/migrate status, Index-Liste, beide Typpruefungen, 335/335 src/tenders-Tests) sind gelaufen und gruen. | fixed | | 2026-08-12T09:24:35.289Z | 2026-09-07T07:50:56.468Z | | 8 | 17 | unrun-verify | apps/web/src/app/(portal)/modules/tender-radar/my-sources/page.tsx | | Browser-Gegenprobe Plan 17-03 Task 1 (Tracer-Feedback-Gate): Meine Quellen mit drei Abschnitten, neu angelegter eigener Feed sofort sichtbar, plattformweiter Feed ohne Entfernen-Knopf, Digest-Intervall speichert nach Reload — kein Browser-Tool in dieser Sitzung verfuegbar | fixed | | 2026-08-12T10:02:49.122Z | 2026-09-07T07:50:56.693Z | | 9 | 17 | unrun-verify | apps/web/src/app/(portal)/modules/tender-radar/settings/page.tsx | | Browser-Gegenprobe Plan 17-03 Task 2: USER-Konto sieht keine Bedienelemente auf /settings (nur Hinweis+Verweis), ADMIN-Konto sieht Abrufintervall+plattformweite Feeds ohne Postfach/Benachrichtigung, Zahnrad fuehrt in beiden Faellen nach Meine Quellen — kein Browser-Tool in dieser Sitzung verfuegbar | fixed | | 2026-08-12T10:02:49.291Z | 2026-09-07T07:50:56.910Z | | 10 | 15 | unmet-truth | apps/web/src/app/(portal)/modules/tender-radar/page.tsx | | PERM-04 greift nicht auf modul-eigenen Routen: der Zugriffs-Guard sitzt nur in modules/[category]/[moduleSlug]/page.tsx. Die vier fest verdrahteten Modulrouten (tender-radar, dkv-fleet, cert-manager, domaincheck) samt Unterseiten (z.B. tender-radar/my-sources) laufen daran vorbei und rendern fuer einen USER OHNE Modulfreigabe vollstaendig, inklusive bedienbarer Knoepfe. Im Browser gemessen am 2026-09-07 mit nutzer2 (keine Freigabe): /modules/procurement/tender-radar zeigt korrekt die 403-Seite, /modules/tender-radar und /modules/tender-radar/my-sources und /modules/dkv-fleet zeigen die volle Seite. Keine Datenpreisgabe - die API antwortet auf allen Endpunkten mit 403 - aber der Nutzer sieht Bedienelemente, die er nicht benutzen darf, und bekommt rohe englische Techniktexte statt einer verstaendlichen Meldung. Beleg: .planning/phases/17-eigene-ausschreibungs-quellen-je-nutzer/uat-2026-09-07/befund-modul-eigene-route-ohne-freigabe.png | open | | 2026-09-07T08:03:45.978Z | | | 11 | 13 | unmet-truth | apps/api/src/tenders/tender-fingerprint.ts | | Cross-Source-Dedup kollabiert die Mehrzahl echter Duplikate nicht: tenderFingerprint() haengt [buyerName, title, cpvDivisionKey, deadlineKey, valueBucket] zu einem String und hasht ihn. Die Scraper-Adapter liefern cpvDivisions immer leer, DOE dagegen meist gefuellt - dieselbe Ausschreibung ergibt aus beiden Quellen verschiedene Fingerabdruecke, die Fingerprint-Stufe greift also gerade dort nicht, wo sie greifen soll. Steht als offener Rest in 13-VERIFICATION.md (status gaps_found, 3/4 Wahrheiten), war aber bisher nicht im Ledger und damit unsichtbar. Die frueher vermutete Ursache (Normalizer-Defaults) ist mit 9881005 geschlossen und nicht gemeint. | open | | 2026-09-07T08:09:04.188Z | | | 12 | 14 | unrun-verify | .planning/phases/14-rss-email-alert-ingestion-module-rollout/14-03-PLAN.md | | 14-03 Task 4 (checkpoint human-verify, gate blocking): echtes Portal-Alert-Postfach ueber den Exchange/EWS-Weg anbinden und eine echte Alarm-Mail ingestieren. Zu belegen sind (a) die Mail erzeugt eine mandantenprivate Ausschreibung, (b) ein anderer Mandant sieht sie nicht, (c) der EWS-Body-Abruf liefert nicht-leeren, nicht-verstuemmelten Inhalt gegen einen echten Exchange-Server. Der handgeschriebene NTLM/SOAP-Weg ist nur gegen gemocktes httpntlm.post geprueft, nie gegen einen echten Server. Braucht ein echtes Postfach - vom User am 2026-07-24 bewusst zurueckgestellt. Stand bisher nur in 14-VERIFICATION.md (status human_needed), nicht im Ledger. | open | | 2026-09-07T08:09:04.406Z | | ````json [ { "id": 1, "kind": "unrun-verify", "phase": "15", "file": ".planning/phases/15-modul-berechtigungen-gruppen-user-grants/15-06-PLAN.md", "line": null, "description": "15-06 : manueller Browser-Durchklick (Anlegen/Umbenennen/Standardmarkierung/AD-Bindung/Mitglieder/Loeschdialog + Fehlerpfade bei abgeschalteter API) nicht ausgefuehrt — kein Browser-Tool in dieser Session verfuegbar", "status": "fixed", "reason": "", "recorded_at": "2026-08-04T17:05:42.026Z", "resolved_at": "2026-09-07T08:03:50.832Z" }, { "id": 2, "kind": "unrun-verify", "phase": "15", "file": ".planning/phases/15-modul-berechtigungen-gruppen-user-grants/15-07-PLAN.md", "line": null, "description": "Manueller Browser-Durchklick aus dem Plan-Verification-Block (Matrix-Freigabe setzen/entziehen, Aktivierungsdialog beide Wege, Direkt-Grant neben Gruppen-Grant, Fehlerfall bei gestoppter API, lange Namen) nicht ausgefuehrt -- kein Browser-Tool in dieser Session (15-07-SUMMARY.md D4)", "status": "fixed", "reason": "", "recorded_at": "2026-08-04T17:27:42.267Z", "resolved_at": "2026-09-07T08:03:51.067Z" }, { "id": 3, "kind": "unrun-verify", "phase": "15", "file": ".planning/phases/15-modul-berechtigungen-gruppen-user-grants/15-08-PLAN.md", "line": null, "description": "Manueller Browser-Durchklick aus dem Plan-Verification-Block (USER ohne Freigabe: Sidebar/403-Seite/Marketplace-Badge+Toast/API-403 identisch; ADMIN: alle vier Ebenen zugaenglich) nicht ausgefuehrt - kein Browser-Tool in dieser Session verfuegbar.", "status": "fixed", "reason": "", "recorded_at": "2026-08-04T17:50:13.320Z", "resolved_at": "2026-09-07T08:03:51.288Z" }, { "id": 4, "kind": "unrun-verify", "phase": "16", "file": ".planning/phases/16-ad-gruppen-synchronisation/16-03-PLAN.md", "line": null, "description": "16-03 Task 2 human-check: RESEARCH.md Annahmen A1 (objectGUID uebersteht AD-Umbenennung) und A2 (byteweise Hex-Filter-Syntax) sind gegen kein echtes Active Directory geprueft — kein erreichbares AD in dieser Sandbox. Negatives Ergebnis bei A1 oder A2 ist Stopp-Grund fuer die Loeschsemantik (D-05).", "status": "open", "reason": "", "recorded_at": "2026-08-06T14:21:59.987Z", "resolved_at": null }, { "id": 5, "kind": "unrun-verify", "phase": "16", "file": ".planning/phases/16-ad-gruppen-synchronisation/16-04-PLAN.md", "line": null, "description": "Manueller Browser-Durchklick aus dem Plan-Verification-Block (drei GroupFormModal-Zustaende: Anlegen mit Hinweis-Link, lokale Gruppe umbenennen, importierte Gruppe mit gesperrtem Namen + internem Namen speichern; Namensanzeige mit Tooltip in der Liste nach dem Speichern) nicht ausgefuehrt — kein Browser-Tool in dieser Session verfuegbar.", "status": "fixed", "reason": "", "recorded_at": "2026-08-06T14:31:14.336Z", "resolved_at": "2026-09-07T08:03:51.517Z" }, { "id": 6, "kind": "unrun-verify", "phase": "16", "file": ".planning/phases/16-ad-gruppen-synchronisation/16-05-PLAN.md", "line": null, "description": "16-05 Manuell nachzuholen (Browser): Sync ausloesen und pruefen, dass alle drei Zahlenzeilen erscheinen; Lauf mit verschobener Standardmarkierung provozieren und Amber-Zeile pruefen; Freigabe-Matrix-Spaltensuche unter beiden Namen probieren - nicht ausgefuehrt, kein Browser-Tool in dieser Session verfuegbar.", "status": "open", "reason": "", "recorded_at": "2026-08-06T14:39:03.905Z", "resolved_at": null }, { "id": 7, "kind": "unrun-verify", "phase": "17", "file": ".planning/phases/17-eigene-ausschreibungs-quellen-je-nutzer/17-01-PLAN.md", "line": null, "description": "17-01 Task 2 human-check: Browser-Gegenprobe (normaler Nutzer oeffnet /modules/tender-radar/my-sources, speichert Postfach, zweites Konto desselben Mandanten sieht leeres Formular) nicht ausgefuehrt — kein Browser-Tool in dieser Session verfuegbar. Automatisierte Pruefungen (prisma validate/migrate status, Index-Liste, beide Typpruefungen, 335/335 src/tenders-Tests) sind gelaufen und gruen.", "status": "fixed", "reason": "", "recorded_at": "2026-08-12T09:24:35.289Z", "resolved_at": "2026-09-07T07:50:56.468Z" }, { "id": 8, "kind": "unrun-verify", "phase": "17", "file": "apps/web/src/app/(portal)/modules/tender-radar/my-sources/page.tsx", "line": null, "description": "Browser-Gegenprobe Plan 17-03 Task 1 (Tracer-Feedback-Gate): Meine Quellen mit drei Abschnitten, neu angelegter eigener Feed sofort sichtbar, plattformweiter Feed ohne Entfernen-Knopf, Digest-Intervall speichert nach Reload — kein Browser-Tool in dieser Sitzung verfuegbar", "status": "fixed", "reason": "", "recorded_at": "2026-08-12T10:02:49.122Z", "resolved_at": "2026-09-07T07:50:56.693Z" }, { "id": 9, "kind": "unrun-verify", "phase": "17", "file": "apps/web/src/app/(portal)/modules/tender-radar/settings/page.tsx", "line": null, "description": "Browser-Gegenprobe Plan 17-03 Task 2: USER-Konto sieht keine Bedienelemente auf /settings (nur Hinweis+Verweis), ADMIN-Konto sieht Abrufintervall+plattformweite Feeds ohne Postfach/Benachrichtigung, Zahnrad fuehrt in beiden Faellen nach Meine Quellen — kein Browser-Tool in dieser Sitzung verfuegbar", "status": "fixed", "reason": "", "recorded_at": "2026-08-12T10:02:49.291Z", "resolved_at": "2026-09-07T07:50:56.910Z" }, { "id": 10, "kind": "unmet-truth", "phase": "15", "file": "apps/web/src/app/(portal)/modules/tender-radar/page.tsx", "line": null, "description": "PERM-04 greift nicht auf modul-eigenen Routen: der Zugriffs-Guard sitzt nur in modules/[category]/[moduleSlug]/page.tsx. Die vier fest verdrahteten Modulrouten (tender-radar, dkv-fleet, cert-manager, domaincheck) samt Unterseiten (z.B. tender-radar/my-sources) laufen daran vorbei und rendern fuer einen USER OHNE Modulfreigabe vollstaendig, inklusive bedienbarer Knoepfe. Im Browser gemessen am 2026-09-07 mit nutzer2 (keine Freigabe): /modules/procurement/tender-radar zeigt korrekt die 403-Seite, /modules/tender-radar und /modules/tender-radar/my-sources und /modules/dkv-fleet zeigen die volle Seite. Keine Datenpreisgabe - die API antwortet auf allen Endpunkten mit 403 - aber der Nutzer sieht Bedienelemente, die er nicht benutzen darf, und bekommt rohe englische Techniktexte statt einer verstaendlichen Meldung. Beleg: .planning/phases/17-eigene-ausschreibungs-quellen-je-nutzer/uat-2026-09-07/befund-modul-eigene-route-ohne-freigabe.png", "status": "open", "reason": "", "recorded_at": "2026-09-07T08:03:45.978Z", "resolved_at": null }, { "id": 11, "kind": "unmet-truth", "phase": "13", "file": "apps/api/src/tenders/tender-fingerprint.ts", "line": null, "description": "Cross-Source-Dedup kollabiert die Mehrzahl echter Duplikate nicht: tenderFingerprint() haengt [buyerName, title, cpvDivisionKey, deadlineKey, valueBucket] zu einem String und hasht ihn. Die Scraper-Adapter liefern cpvDivisions immer leer, DOE dagegen meist gefuellt - dieselbe Ausschreibung ergibt aus beiden Quellen verschiedene Fingerabdruecke, die Fingerprint-Stufe greift also gerade dort nicht, wo sie greifen soll. Steht als offener Rest in 13-VERIFICATION.md (status gaps_found, 3/4 Wahrheiten), war aber bisher nicht im Ledger und damit unsichtbar. Die frueher vermutete Ursache (Normalizer-Defaults) ist mit 9881005 geschlossen und nicht gemeint.", "status": "open", "reason": "", "recorded_at": "2026-09-07T08:09:04.188Z", "resolved_at": null }, { "id": 12, "kind": "unrun-verify", "phase": "14", "file": ".planning/phases/14-rss-email-alert-ingestion-module-rollout/14-03-PLAN.md", "line": null, "description": "14-03 Task 4 (checkpoint human-verify, gate blocking): echtes Portal-Alert-Postfach ueber den Exchange/EWS-Weg anbinden und eine echte Alarm-Mail ingestieren. Zu belegen sind (a) die Mail erzeugt eine mandantenprivate Ausschreibung, (b) ein anderer Mandant sieht sie nicht, (c) der EWS-Body-Abruf liefert nicht-leeren, nicht-verstuemmelten Inhalt gegen einen echten Exchange-Server. Der handgeschriebene NTLM/SOAP-Weg ist nur gegen gemocktes httpntlm.post geprueft, nie gegen einen echten Server. Braucht ein echtes Postfach - vom User am 2026-07-24 bewusst zurueckgestellt. Stand bisher nur in 14-VERIFICATION.md (status human_needed), nicht im Ledger.", "status": "open", "reason": "", "recorded_at": "2026-09-07T08:09:04.406Z", "resolved_at": null } ] ````