feat(13-04): NetServer-Adapter fuer tender24/lhs-vpbw/vergabe.landbw (INGEST-02)

- Package-Legitimacy-Checkpoint bestaetigt: cheerio (sauberer Gate-Pass,
  27M Downloads/Woche) statt node-html-parser installiert
- EIN config-getriebener NetServerAdapter bedient alle 3 AI-AG-Portale
  via PublicationSearchControllerServlet-Trefferliste, parst <table> mit
  cheerio zu RawTenderRecord[], sourcePortal je Zeile korrekt
- sourceNoticeId = data-oid (stabil, per Zeile eindeutig); sourceUrl =
  Such-URL als dokumentierter Best-Effort-Fallback (kein Deep-Link ohne
  JS-Ausfuehrung ermittelbar, Open Question 2)
- Fehlertoleranz: try/catch pro Zeile + pro Portal, []-Fallback bei
  Totalausfall, AbortController 15s-Timeout, hardcodierte Portal-URLs
  (SSRF-Guard T-13-04-01)
- Live-gecapturte Fixture (tender24.de, 2026-07-23) mit Umlaut-/&amp;-
  Buyer, gefuellter und leerer Deadline; 14 Spec-Tests gruen

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-23 09:13:01 +02:00
parent 2c28605397
commit 043ada9438
5 changed files with 651 additions and 21 deletions
@@ -0,0 +1,140 @@
<!DOCTYPE html>
<html lang="de">
<head><meta charset="utf-8"><title>Vergabe@Net - Suchergebnisse</title></head>
<body>
<!-- Live-gecapturte NetServer-Trefferliste (tender24.de, 2026-07-23), gekuerzt auf 6 Zeilen fuer die Test-Fixture. -->
<table class="table table-responsive table-striped table-hover tableHorizontalHeader">
<caption>Suchergebnisse</caption>
<thead>
<tr>
<th class="tabelleFirstLine background-blue">
<a href="PublicationSearchControllerServlet?function=SearchPublications&amp;OrderBy=Publishing&amp;Order=desc" title="Nach dem Erscheinungsdatum sortieren" class=" tableActive">Erschienen am</a>
</th>
<th class="tabelleFirstLine background-blue">
<a class="activeChange" href="PublicationSearchControllerServlet?function=SearchPublications&amp;OrderBy=TenderName&amp;Order=desc" title="Nach dem Namen der Veröffentlichung sortieren">Ausschreibung</a>
</th>
<th class="tabelleFirstLine background-blue">
<a class="activeChange" href="PublicationSearchControllerServlet?function=SearchPublications&amp;OrderBy=AuthorityName&amp;Order=desc" title="Nach dem Namen der ausschreibenden Stelle sortieren">Vergabestelle</a>
</th>
<th class="tabelleFirstLine background-blue">
<a class="activeChange" href="PublicationSearchControllerServlet?function=SearchPublications&amp;OrderBy=TenderKind&amp;Order=desc" title="Nach der Verfahrensart sortieren">Verfahrensart</a>
</th>
<th class="tabelleFirstLine background-blue">
<a class="activeChange" href="PublicationSearchControllerServlet?function=SearchPublications&amp;OrderBy=TenderLawCaption&amp;Order=desc" title="Nach dem Rechtsrahmen sortieren">Rechtsrahmen</a>
</th>
<th class="tabelleFirstLine background-blue">
<a class="activeChange" id="tableLastHeader" href="PublicationSearchControllerServlet?function=SearchPublications&amp;OrderBy=EndTime&amp;Order=desc" title="Nach der Abgabefrist sortieren">Abgabefrist</a>
</th>
</tr>
</thead>
<tr class="tableRow clickable-row publicationDetail" tabindex="0" style="cursor: pointer;" data-oid="54321-NetTender-19f800ce3b1-36b275763103203a" data-category="InvitationToTender">
<td >22.07.2026</td>
<td class="tender">
Wärmenetz Wunsiedel Planungs- und Koordinierungsleistungen (STKP-BY-2026-11)
</td>
<td class="tenderAuthority" >Sterr-Kölln &amp; Partner</td>
<td class="tenderType">Verhandlungsverfahren mit Teilnahmewettbewerb</td>
<td class="tenderType">VOL</td>
<td class="tenderDeadline">20.08.2026 24:00</td>
</tr>
<tr class="tableRow clickable-row publicationDetail" tabindex="0" style="cursor: pointer;" data-oid="54321-NetTender-19e21c643b8-4268f33140e63c36" data-category="ContractAward">
<td >22.07.2026</td>
<td class="tender">
POLY_BAU_2026_0003_000023 (Sanierung BT4) Stahlbauarbeiten (POLY_BAU_2026_0003)
</td>
<td class="tenderAuthority" >Max-Planck-Institut für Polymerforschung (IPF)</td>
<td class="tenderType">Freihändige Vergabe</td>
<td class="tenderType">VOB</td>
<td class="tenderDeadline"></td>
</tr>
<tr class="tableRow clickable-row publicationDetail" tabindex="0" style="cursor: pointer;" data-oid="54321-NetTender-19efec148b6-1a2bbf5ec4dade45" data-category="ContractAward">
<td >22.07.2026</td>
<td class="tender">
Zellanalyse- und Zellsortiersystem mit spektraler und bildbasierter Echtzeitanalyse (PFOR_2026_02)
</td>
<td class="tenderAuthority" >Max-Planck-Institut für Herz- und Lungenforschung (IHL)</td>
<td class="tenderType">Verhandlungsverfahren ohne Teilnahmewettbewerb</td>
<td class="tenderType">UVgO/VgV</td>
<td class="tenderDeadline"></td>
</tr>
<tr class="tableRow clickable-row publicationDetail" tabindex="0" style="cursor: pointer;" data-oid="54321-NetTender-19db46612b3-1a04aea066286c1" data-category="ContractAward">
<td >22.07.2026</td>
<td class="tender">
VE117_1 Malerarbeiten (VE117_1)
</td>
<td class="tenderAuthority" >Drees &amp; Sommer SE Smart Infrastructure</td>
<td class="tenderType">Offenes Verfahren</td>
<td class="tenderType">VOB</td>
<td class="tenderDeadline"></td>
</tr>
<tr class="tableRow clickable-row publicationDetail" tabindex="0" style="cursor: pointer;" data-oid="54321-NetTender-19eacb06976-633a2f5db089eb5c" data-category="ContractAward">
<td >22.07.2026</td>
<td class="tender">
ZV - Lautertal - Geschlossene Kanalsanierung (Schmutzwasserhauptkanal) Tiefenlauter (1200-0452-2026/000656)
</td>
<td class="tenderAuthority" >Stadt Coburg - Beschaffungsamt</td>
<td class="tenderType">Freihändige Vergabe</td>
<td class="tenderType">VOB</td>
<td class="tenderDeadline"></td>
</tr>
<tr class="tableRow clickable-row publicationDetail" tabindex="0" style="cursor: pointer;" data-oid="54321-NetTender-19cb85baaa1-34fafe93210c7594" data-category="ContractAward">
<td >22.07.2026</td>
<td class="tender">
Planungsleistungen Wärmenetz Obertürkheim (SWS-2026-0001)
</td>
<td class="tenderAuthority" >Stadtwerke Stuttgart GmbH</td>
<td class="tenderType">Verhandlungsverfahren mit Teilnahmewettbewerb</td>
<td class="tenderType">VOL</td>
<td class="tenderDeadline"></td>
</tr>
</table>
</body>
</html>