diff --git a/.planning/STATE.md b/.planning/STATE.md index 98d5eee..1a4f669 100644 --- a/.planning/STATE.md +++ b/.planning/STATE.md @@ -8,7 +8,7 @@ status: complete stopped_at: Phase 16 abgeschlossen — UAT durchgefuehrt, kritischer Sweep-Fehler gefunden und behoben (260811-f9i), Rest-Annahme A1 bewusst als offen akzeptiert last_updated: "2026-08-11T09:25:00.000Z" last_activity: 2026-08-11 -last_activity_desc: Phase 16 UAT abgeschlossen; objectGUID-Existenzpruefung repariert +last_activity_desc: DOE-Bekanntmachungslinks repariert (260811-j04) progress: total_phases: 16 completed_phases: 15 @@ -309,6 +309,7 @@ None yet. | 260728-lih | LDAP: Sync strikt selektiv (leere Auswahl = No-Op statt Voll-Import) + Auto-Sync-Default aus (syncIntervalMin 60→0) | 2026-07-28 | c54e424,57bc7f9,63a07ab | [260728-lih-ldap-sync-selektiv-und-auto-sync-default](.planning/quick/260728-lih-ldap-sync-selektiv-und-auto-sync-default/) | | 260729-d3k | LDAP: Multi-Base-DN und Base-DN als Sync-Scope (statt leerer Gruppenfilter = No-Op) | 2026-07-29 | 5cbd530,96be7e1 | [260729-d3k-ldap-multi-base-dn-und-base-dn-als-scope](.planning/quick/260729-d3k-ldap-multi-base-dn-und-base-dn-als-scope/) | | 260805-d0r | Benutzer-Detail zeigte Gruppenmitgliedschaften aus Freigaben statt aus Mitgliedschaften — GET /module-grants/users/:userId liefert jetzt { groups, modules }, Chips mit Herkunfts-Badge; im Browser gegengeprüft: Mitgliedschaft bleibt sichtbar, auch wenn die Gruppe kein Modul freigibt | 2026-08-05 | ecadf69,f8ff74b,8ce3748 | [260805-d0r-benutzer-detail-zeigt-gruppenmitgliedsch](.planning/quick/260805-d0r-benutzer-detail-zeigt-gruppenmitgliedsch/) | +| 260811-j04 | DOE-Ausschreibungen verlinkten auf die API (rohes JSON) statt auf die Bekanntmachung — betraf Trefferliste, Detailansicht und Alarm-Mails. Adapter baut die URL jetzt aus der Bekanntmachungsnummer, Migration schreibt 2846 bestehende Zeilen in Tender und TenderSource um. Zielseite im Browser fuer beide Kennungsformen verifiziert (numerisch und UUID) — ein HTTP-Statuscheck taugt dort nicht, die Seite antwortet auf jede Kennung mit 200 | 2026-08-11 | ecf7872 | [260811-j04-doe-tender-links-point-to-the-api-instea](.planning/quick/260811-j04-doe-tender-links-point-to-the-api-instea/) | | 260811-f9i | KRITISCH: objectGUID-Existenzpruefung fand nie etwas — der Filter wurde als `\xx`-escapter String gebaut, ldapts wandelt das nicht in Rohbytes; beide Suchen (Base-DNs und WR-03-Fallback) teilten ihn, also haette der erste echte Sync JEDE AD-gebundene Gruppe samt Mitgliedschaften und Modulfreigaben geloescht. Jetzt EqualityFilter ueber den rohen Buffer, `escapeLdapFilterBuffer()` entfernt. Read-only am echten AD gemessen (escapter String 0 Treffer, EqualityFilter 1 korrekter Treffer); Regressionstests gegengeprueft (alter Code = 8 rote Tests) | 2026-08-11 | d2019dc | [260811-f9i-fix-objectguid-existence-sweep-to-use-eq](.planning/quick/260811-f9i-fix-objectguid-existence-sweep-to-use-eq/) | | 260805-fok | Standardgruppe bei Mandanten-Anlage + Startup-Reparatur — GroupsService.ensureDefaultGroup(tenantId) mit D-13-Waechter (null Gruppen, nicht fehlende Markierung), verdrahtet in TenantService.create und AdminSeedService.ensureDefaultGroupsForAllTenants; schliesst die Migrations-Backfill-Luecke auf frischen Installationen (Testserver: tenants=1 users=4 groups=0) | 2026-08-05 | 9d1254c,0d7d8a5 | [260805-fok-standardgruppe-bei-mandanten-anlage-und-](.planning/quick/260805-fok-standardgruppe-bei-mandanten-anlage-und-/) | diff --git a/.planning/quick/260811-j04-doe-tender-links-point-to-the-api-instea/SUMMARY.md b/.planning/quick/260811-j04-doe-tender-links-point-to-the-api-instea/SUMMARY.md new file mode 100644 index 0000000..4f8748f --- /dev/null +++ b/.planning/quick/260811-j04-doe-tender-links-point-to-the-api-instea/SUMMARY.md @@ -0,0 +1,64 @@ +--- +quick_id: 260811-j04 +slug: doe-tender-links-point-to-the-api-instea +date: 2026-08-11 +status: complete +relates_to: tender-radar +closes_todo: 2026-08-05-ausschreibungsportal-falsche-url +commits: + - ecf7872 fix(tenders): link DOE notices to the notice page, not the API +--- + +# Summary: DÖE-Ausschreibungen verlinken auf die Bekanntmachungsseite + +## Entscheidung des Users + +Von den beiden möglichen Zielen — Bekanntmachungsseite auf oeffentlichevergabe.de +oder Link auf das ausschreibende Portal selbst (`tender.documents[0].url`) — hat +der User am 2026-08-11 die **Bekanntmachungsseite** gewählt. + +## Was gemacht wurde + +`doe-opendata.adapter.ts` baut `sourceUrl` jetzt über die neue Funktion +`buildDoeNoticeUrl()` aus der Bekanntmachungsnummer, statt `ocdsDocument.uri` +durchzureichen. Die Nummer liegt ohnehin schon als `sourceNoticeId` im Datensatz, +es braucht also keinen zweiten Abruf. + +Dazu die Migration `20260811120000_doe_notice_url_backfill`, die die bereits +importierten Zeilen umschreibt — in `Tender` und in `TenderSource`, weil die +Detailansicht die Quell-Links zusammengeführter Ausschreibungen einzeln auflistet. + +## Was vorher geprüft wurde + +- **Ist `ocdsDocument.uri` anderswo als Kennung in Gebrauch?** Nein — die einzige + Verwendung im gesamten Code war genau diese eine Zeile. +- **Ist die Nummer in der API-URL dieselbe wie `releases[0].id`?** Ja, live gegen + den Feed geprüft. Der eine auffällige Datensatz in der Datenbank + (`sourceNoticeId` 25671684, URL auf 25671680) stammt nicht aus einer + Feld-Verwechslung, sondern aus der Dedup-Zusammenführung zweier echter, + gleichnamiger Bekanntmachungen ("Bauleistungen"). Nach dem Backfill folgt die + URL der Kennung der Zeile und ist damit in sich stimmig. +- **Funktioniert die Zielseite für beide Kennungsformen?** Ja, im Browser + verifiziert: numerisch (25673764 → "Feuerwehr-Gerätehaus Miehlen + Fliesenarbeiten") und als UUID (7085ba12-… → "Holzfassade"). +- **Reicht ein HTTP-Statuscheck?** Nein, und das ist die Falle an dieser Stelle: + die Zielseite ist eine Single-Page-App und antwortet auf JEDE Kennung mit 200 + und identischen 1309 Bytes, auch auf `NONSENSE123`. Nur der gerenderte Inhalt + beweist etwas. +- **Wie viele Zeilen betrifft der Nachlauf?** Read-only auf alpha gezählt: 2846 + DÖE-Zeilen betroffen, 0 fallen durch die Kennungsprüfung. + +## Verifikation + +- `pnpm --filter @tessera/api test` — 575 Tests grün (41 Dateien) +- `npx tsc --noEmit` — sauber +- Neue Tests: der Adapter setzt für jeden Datensatz die Bekanntmachungs-URL und + nie mehr `/api/notices/`; `buildDoeNoticeUrl()` escapet die Kennung; das + Migrations-SQL fasst beide Tabellen an, ist idempotent und rührt andere Portale + nicht an. + +## Offen + +Der Nachlauf läuft erst beim nächsten Deploy an, weil Migrationen beim +Containerstart ausgeführt werden. Danach im Browser gegenprüfen, dass ein +Treffer aus der Liste auf der Bekanntmachung landet. diff --git a/.planning/todos/pending/2026-08-05-ausschreibungsportal-falsche-url.md b/.planning/todos/completed/2026-08-05-ausschreibungsportal-falsche-url.md similarity index 87% rename from .planning/todos/pending/2026-08-05-ausschreibungsportal-falsche-url.md rename to .planning/todos/completed/2026-08-05-ausschreibungsportal-falsche-url.md index 9fbb6de..be2ad73 100644 --- a/.planning/todos/pending/2026-08-05-ausschreibungsportal-falsche-url.md +++ b/.planning/todos/completed/2026-08-05-ausschreibungsportal-falsche-url.md @@ -1,5 +1,11 @@ --- created: 2026-08-05 +resolved: 2026-08-11 +resolution: | + Behoben in Quick-Task 260811-j04, Commit ecf7872. Der User hat sich fuer die + Bekanntmachungsseite entschieden (nicht fuer den Link auf das ausschreibende + Portal). Adapter baut die URL jetzt aus der Bekanntmachungsnummer, Migration + 20260811120000_doe_notice_url_backfill schreibt die 2846 bestehenden Zeilen um. title: DÖE-Ausschreibungen verlinken auf die API statt auf die Bekanntmachungsseite area: tender-radar severity: major