# v1.1 Ausschreibungs-Radar — Milestone Audit **Milestone:** v1.1 (Phasen 10–14) **Audited:** 2026-07-24 **Verdict:** GAPS — 1 neuer Blocker, 1 Warnung, 2 akzeptierte Deferrals ## Phasen-Verifikationen (aggregiert) | Phase | Status | Score | |-------|--------|-------| | 10 Foundation & DÖE | passed | 5/5 | | 11 Filter/UI/Saved Searches | passed | 5/5 | | 12 Notifications | passed | 4/4 | | 13 Scraping-Adapter + Dedup | gaps_found | 3/4 (Truth 3 Dedup dormant, Option C) | | 14 RSS/E-Mail/Rollout | human_needed | 4/5 (EWS-Live-Test offen) | Alle 24 Requirements sind in REQUIREMENTS.md als `[x]` markiert. Der Integrations-Checker bestätigt: die Ingestion-Pipeline aller 5 Quellen ist verdrahtet (Registry → pollDueSources → Normalizer → Tender), Filter/UI/Notifications/Denylist/i18n sind end-to-end verbunden. ABER: ## BLOCKER — NetServer/cosinex-Adapter haben keinen Aktivierungspfad **Betroffene REQ-IDs: INGEST-02, INGEST-03, CONFIG-02 (teilweise)** - `ai-netserver` und `cosinex-dtvp` `TenderSourcePollConfig`-Zeilen werden mit `isActive: false` geseedet, Kommentar „activation deferred to Phase 14 UI". - Aber Phase 14 hat diese UI nie geliefert: `SourceConfigDto` (`dto/source-config.dto.ts`) hat KEIN `sourceType`-Feld; `GET/PUT /modules/tender-radar/source-config` (`tenders.controller.ts:43,190-215`) ist auf `DOE_SOURCE_TYPE = 'doe-opendata'` hartverdrahtet. `SourceConfigForm.tsx` spricht denselben Single-Source-Endpoint an. - Es existiert KEINE Route/Service-Methode/UI, die `isActive` für `ai-netserver`/`cosinex-dtvp` umschalten kann. - Netto: Die in Phase 13 gebauten, getesteten, registrierten Adapter (INGEST-02/03) sind produktiv unerreichbar — sie bleiben für immer `isActive:false` (außer manuellem DB-Write). Widerspricht Phase-13-Kriterien 1/2 und CONFIG-02 („Admin verwaltet Quellen-Poll-Konfiguration"). **Fix (klein):** `SourceConfigDto`/Endpoint auf beliebigen `sourceType` generalisieren (nicht nur DÖE) + `SourceConfigForm` alle pollbaren Quellen auflisten und togglebar machen. Denylist-Gate bleibt (vergabe24/aumass werden ohnehin nicht registriert). ## WARNUNG — Scheduler-Cron hängt allein am DÖE-Config `TenderSchedulerService.onApplicationBootstrap()` (`tender-scheduler.service.ts:73-89`) registriert den einen globalen Cron NUR, wenn `doe-opendata` aktiv ist; die admin `source-config` PUT-Route ruft `stopJob()`, wenn DÖE deaktiviert wird. Da dieser eine Cron via `pollDueSources()` ALLE aktiven Quellen fächert, würde ein Deaktivieren von DÖE still auch RSS + E-Mail-Ingestion abschalten. Architektur-Schuld (Phase-13/14-Fan-out auf Phase-10-Single-Source-Scheduler gesetzt, ohne die Bootstrap/Stop-Bedingung auf „irgendeine aktive Quelle" umzustellen). Nicht user-facing im Normalfall (DÖE ist active-by-default, kein Toggle für die anderen exponiert) → WARNUNG, nicht Blocker. ## Akzeptierte Deferrals (keine neuen Findings) 1. **SCHEMA-03 Cross-Source-Fingerprint-Dedup dormant** — `dedupActive = activePortalCount >= 2`; Fingerprint-CPV-Asymmetrie (Option C, 13-VERIFICATION.md). Hinweis: durch den Blocker oben verschärft — mit inaktiven NetServer/cosinex sind praktisch nur DÖE+RSS aktiv, echte Cross-Source-Overlaps bleiben unwahrscheinlich. 2. **14-03 EWS/Exchange-Live-Test** — braucht echtes Postfach, vom User bewusst vertagt. ## Empfehlung Den Blocker (Quellen-Aktivierungs-UI) vor dem formalen v1.1-Abschluss schließen — er ist klein und macht INGEST-02/03 + CONFIG-02 erst wirklich wahr. Die Scheduler-Warnung optional gleich mitnehmen. EWS-Test + Dedup-dormant bleiben legitime „braucht-Live-Daten"-Deferrals nach v1.2.