Records the user's choice between the two candidate link targets (the notice page on oeffentlichevergabe.de, not the awarding portal's own page), what was checked before touching the adapter, and the trap in verifying it: the target is a single-page app that answers 200 with an identical shell for any id, so only rendered content proves the link works. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2.9 KiB
quick_id, slug, date, status, relates_to, closes_todo, commits
| quick_id | slug | date | status | relates_to | closes_todo | commits | |||
|---|---|---|---|---|---|---|---|---|---|
| 260811-j04 | doe-tender-links-point-to-the-api-instea | 2026-08-11 | complete | tender-radar | 2026-08-05-ausschreibungsportal-falsche-url |
|
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.urianderswo 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 (sourceNoticeId25671684, 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.