docs(14): capture phase context
This commit is contained in:
@@ -0,0 +1,149 @@
|
|||||||
|
# Phase 14: RSS, Email-Alert Ingestion & Module Rollout - Context
|
||||||
|
|
||||||
|
**Gathered:** 2026-07-23
|
||||||
|
**Status:** Ready for planning
|
||||||
|
|
||||||
|
<domain>
|
||||||
|
## Phase Boundary
|
||||||
|
|
||||||
|
Phase 14 rundet die Ausschreibungs-Abdeckung im Unterschwellenbereich ab und macht das Modul auslieferungsreif. Vier Fähigkeiten:
|
||||||
|
|
||||||
|
1. **RSS-Ingestion** — öffentliche Feeds (subreport-elvis, service.bund.de) werden automatisch als zusätzliche Ausschreibungsquelle eingelesen (INGEST-04).
|
||||||
|
2. **E-Mail-Alert-Ingestion** — Tessera liest ein pro Mandant konfiguriertes Postfach aus, in das Vergabeportale ihre Benachrichtigungsmails schicken (eingehend, nicht ausgehend), und macht daraus Ausschreibungs-Einträge. Baut auf einem geteilten `inbox/`-Modul, das als einmaliger Prerequisite-Refactor aus DKV herausgelöst wird (INGEST-05).
|
||||||
|
3. **Admin-Konfiguration** — pro Mandant Quellen-Poll- und Postfach-Konfiguration, Zugangsdaten AES-256-GCM-verschlüsselt (CONFIG-02, CONFIG-03).
|
||||||
|
4. **Denylist-Transparenz** — vergabe24 und aumass werden im UI als „manuell beobachten" mit Direktlink gezeigt statt als stille Lücke (UI-06).
|
||||||
|
5. **i18n** — das gesamte Modul-UI liegt in Deutsch und Englisch vor (Teil von UI-06/Modul-Rollout).
|
||||||
|
|
||||||
|
**Wichtige Klarstellung (aus Diskussion):** Kriterium 2 ist *eingehende* E-Mail (Tessera liest ein Postfach), nicht *ausgehende* (das Versenden von Nutzer-Benachrichtigungen ist bereits in Phase 12 gebaut, via SMTP). Das Ausschreibungs-Postfach ist ein **separates** Postfach mit eigener Adresse und eigenen Zugangsdaten — NICHT dasselbe, an das DKV-Rechnungen gehen.
|
||||||
|
|
||||||
|
</domain>
|
||||||
|
|
||||||
|
<decisions>
|
||||||
|
## Implementation Decisions
|
||||||
|
|
||||||
|
### Inbox-Modul-Extraktion (INGEST-05, Refactor)
|
||||||
|
- **D-01:** Additiver Refactor, DKV bleibt verhaltensgleich. Die bestehenden IMAP-/Exchange-Provider (`ImapProvider`, `ExchangeInboxProvider`) und das `InboxProvider`-Interface werden aus `apps/api/src/dkv/providers/` in ein geteiltes `apps/api/src/inbox/`-Modul gehoben. Geteilt wird ausschließlich die **Verbindungsmechanik** (IMAP/Exchange-Anmeldung, TLS, NTLM via httpntlm, Timeouts, Mail-Abruf).
|
||||||
|
- **D-02:** Die bestehende PDF-Anhang-Methode (`fetchPdfAttachments`) bleibt unverändert erhalten. Für die Ausschreibungs-Ingestion wird eine **zusätzliche** Methode ergänzt, die den Mail-Body (HTML/Text) und ganze Nachrichten liefert. DKV wird NICHT auf die neue Methode umgestellt — nur der Import-Pfad wechselt auf `inbox/`. Grund: DKV läuft produktiv, der Exchange/NTLM-Pfad ist bekannt fragil (siehe [[project_calendar_ews_fix]]); Regressionsrisiko im Fleet-Modul muss null bleiben.
|
||||||
|
- **D-03:** Jedes Modul behält seine **eigene, unabhängige** Postfach-Konfiguration (eigene Adresse, eigene Credentials). Geteilt ist nur der Code, nicht die Config.
|
||||||
|
|
||||||
|
### E-Mail-Alert-Parsing (INGEST-05)
|
||||||
|
- **D-04:** Generische Auswertung statt portalspezifischer Parser. Aus jeder Alert-Mail werden die enthaltenen Links (auf die Ausschreibungs-Detailseite) plus Betreff/erste Textzeile als Titel extrahiert. Grund: Es sind keine konkreten Alert-Portale bekannt (User kennt aktuelle Praxis nicht), daher wären portalspezifische Parser Raterei. Feldarmut (kein CPV/Buyer/Frist) wird bewusst und offen dokumentiert — analog zur NetServer-Deep-Link-Beschränkung (D-01 in Phase 13).
|
||||||
|
- **D-05:** Konsequenz für Cross-Source-Dedup: E-Mail-/RSS-Records haben dünne Felder (leeres CPV) und erben damit dieselbe Fingerprint-Asymmetrie wie die Scraper aus Phase 13 (siehe [[project_resume_2026-07-22]], residual_gap_decision = Option C, dormant). Kein neuer Dedup-Mechanismus in Phase 14; das Thema bleibt bis zur Live-Aktivierung einer zweiten Quelle vertagt.
|
||||||
|
|
||||||
|
### Config-Modell + Admin-UI (CONFIG-02, CONFIG-03)
|
||||||
|
- **D-06:** Postfach-Konfiguration ist **pro Mandant** (tenantId-scoped), Muster wie `DkvModuleConfig` (`schema.prisma:180`: `tenantId @unique` + verschlüsselte Creds). Neues Prisma-Modell, kein Ausbau des globalen `TenderSourcePollConfig`-Singletons.
|
||||||
|
- **D-07:** Zugangsdaten werden mit `CalendarCryptoService` (AES-256-GCM, Format `iv:authTag:ciphertext`, Key aus env) verschlüsselt — dasselbe Verfahren, das DKV und der SMTP-Versand bereits nutzen. Verschlüsselte Felder werden aus GET-Responses ausgeschlossen (Safe-Select-Muster, T-07-12).
|
||||||
|
- **D-08:** RSS-Feeds sind öffentlich und für alle gleich → globale Plattform-Konfiguration (bestehendes Singleton-Muster), nicht pro Mandant.
|
||||||
|
- **D-09:** Die bestehende Admin-Seite (`apps/web/.../tender-radar/settings/`) wird **erweitert**, nicht neu gebaut: ein Abschnitt „E-Mail-Alerts" (pro Mandant, durch Mandanten-Admin konfigurierbar) und einer „RSS-Feeds" (global). Rollen-Trennung über bestehendes `@Roles(ADMIN, SUPER_ADMIN)`.
|
||||||
|
|
||||||
|
### i18n (UI-06)
|
||||||
|
- **D-10:** „Zweisprachig" = alle Modul-Texte liegen in Deutsch UND Englisch vor. Ein neuer `tenderRadar`-Namensraum wird in `apps/web/src/messages/de.json` und `en.json` angelegt; alle hartcodierten deutschen Strings der tender-radar-Komponenten werden in `useTranslations`-Keys überführt (ResultsList, FilterPanel, SavedSearchBar, TenderDetail, CoverageBanner, Settings-Seite, SourceConfigForm).
|
||||||
|
- **D-11:** KEIN sichtbarer Sprachumschalter. Die Sprachwahl folgt dem bestehenden next-intl-Mechanismus. Ein app-weiter Language-Switcher ist ausdrücklich NICHT Teil dieser Phase (siehe Deferred Ideas).
|
||||||
|
|
||||||
|
### Denylist-Transparenz (UI-06)
|
||||||
|
- **D-12:** vergabe24 und aumass werden im UI als „manuell beobachten" mit Direktlink dargestellt (statt stiller Lücke). Vorhandene `CoverageBanner.tsx`-Komponente ist der natürliche Ort. Denylist-Quelle bleibt der code-level Gate `DENYLISTED_PORTALS` (`source-registry.ts:12`).
|
||||||
|
|
||||||
|
### Claude's Discretion
|
||||||
|
- Wahl der RSS-Parsing-Bibliothek und das genaue Feld-Mapping der RSS-Items auf `NormalizedTenderFields` (generische Bag, analog zu Scraper-Adaptern).
|
||||||
|
- Genaue Struktur des neuen `inbox/`-Modul-Interfaces und der zusätzlichen Message-Methode.
|
||||||
|
- Scheduler-Anbindung der neuen Quellen (RSS-Adapter, E-Mail-Adapter) über das bestehende `SourceRegistry` + `pollDueSources`-Muster.
|
||||||
|
- EN-Übersetzungen erstellt Claude selbst (Fachbegriffe der Vergabe-Domäne konsistent halten).
|
||||||
|
|
||||||
|
</decisions>
|
||||||
|
|
||||||
|
<canonical_refs>
|
||||||
|
## Canonical References
|
||||||
|
|
||||||
|
**Downstream agents MUST read these before planning or implementing.**
|
||||||
|
|
||||||
|
### Inbox-Refactor (INGEST-05)
|
||||||
|
- `apps/api/src/dkv/providers/inbox-provider.interface.ts` — bestehendes `InboxProvider`-Interface (`fetchPdfAttachments`, `testConnection`); Basis der Extraktion.
|
||||||
|
- `apps/api/src/dkv/providers/imap.provider.ts` — `ImapProvider` (IMAP-Verbindung).
|
||||||
|
- `apps/api/src/dkv/providers/exchange-inbox.provider.ts` — `ExchangeInboxProvider` (EWS/NTLM via httpntlm).
|
||||||
|
- `apps/api/src/dkv/dkv.types.ts` §47/§69/§78 — `InboxConfig`, `InboxAttachment`, `InboxEmail`.
|
||||||
|
- `apps/api/src/dkv/dkv.service.ts` §82-83/§117-118 — aktuelle Injektion + Nutzung; Import-Pfad wechselt hier auf `inbox/`.
|
||||||
|
- `apps/api/src/dkv/dkv.module.ts` §52-53 — Provider-Registrierung.
|
||||||
|
|
||||||
|
### Verschlüsselung (CONFIG-03)
|
||||||
|
- `apps/api/src/calendar/crypto.service.ts` §18 — `CalendarCryptoService.encrypt/decrypt`, AES-256-GCM, Key aus env.
|
||||||
|
- `apps/api/prisma/schema.prisma` §180/§194 — `DkvModuleConfig` (per-tenant Vorlage) mit `encryptedInboxCreds`.
|
||||||
|
- `apps/api/src/settings/settings.service.ts` §30 — SMTP-Wiederverwendung desselben Krypto-Musters (Safe-Select).
|
||||||
|
|
||||||
|
### Quellen-Ingestion + Registry (INGEST-04/05)
|
||||||
|
- `apps/api/src/tenders/adapters/tender-source-adapter.interface.ts` §15 — Adapter-Vertrag (`sourceType`, `portals[]`, `fetchTenders(dayCursor)`); Docstring nennt RSS+E-Mail als Zukunfts-Adapter.
|
||||||
|
- `apps/api/src/tenders/source-registry.ts` §12/§35 — `SourceRegistry`, Denylist-Gate `DENYLISTED_PORTALS`.
|
||||||
|
- `apps/api/src/tenders/tenders.module.ts` §100-115/§129-138/§162-213 — Provider-Registrierung, `onModuleInit`-Registrierung, Poll-Config-Seeds (Plug-in-Punkt neuer Adapter).
|
||||||
|
- `apps/api/src/tenders/tender-ingestion.service.ts` §75/§98/§118/§144 — `pollDueSources`-Fan-out über Poll-Configs.
|
||||||
|
- `apps/api/src/tenders/tender-scheduler.service.ts` §49/§115 — globaler Cron.
|
||||||
|
- `apps/api/src/tenders/tender.types.ts` — `RawTenderRecord`, `NormalizedTenderFields`, `SourceType`-Union (um RSS/E-Mail-Typen erweitern).
|
||||||
|
- `apps/api/src/tenders/tender-normalizer.service.ts` — `normalizeBag()`-Pfad (Quick 260723-e7i) ist die Vorlage für generische Bag-Normalisierung von RSS/E-Mail-Records.
|
||||||
|
|
||||||
|
### Poll-Config + Admin-UI (CONFIG-02)
|
||||||
|
- `apps/api/prisma/schema.prisma` §416 — `TenderSourcePollConfig` (globales Singleton, kein tenantId).
|
||||||
|
- `apps/api/src/tenders/tenders.controller.ts` §147/§383 — bestehende `GET/PUT /source-config`, `@Roles(ADMIN, SUPER_ADMIN)`.
|
||||||
|
- `apps/web/src/app/(portal)/modules/tender-radar/settings/page.tsx` + `settings/components/SourceConfigForm.tsx` §29 — zu erweiternde Admin-Seite.
|
||||||
|
- `apps/web/src/lib/tender-radar-api.ts` — API-Client.
|
||||||
|
|
||||||
|
### Multi-Tenancy
|
||||||
|
- `apps/api/src/prisma/prisma-tenant.extension.ts` §9 — `forTenant()` (RLS via `set_config('app.current_tenant', …)`).
|
||||||
|
- `apps/api/src/tenders/tender-mail.service.ts` §62/§153 — per-Tenant SMTP-Auflösung (`getDecryptedSmtpConfig(tenantId)`), Muster für per-Tenant Mailbox-Auflösung.
|
||||||
|
|
||||||
|
### i18n (UI-06)
|
||||||
|
- `apps/web/src/messages/de.json`, `apps/web/src/messages/en.json` — Message-Dateien (575 Zeilen, parallel); neuer `tenderRadar`-Key fehlt bisher.
|
||||||
|
- `apps/web/src/app/layout.tsx` — next-intl-Provider (Sprachquelle heute).
|
||||||
|
- `apps/web/src/middleware.ts` — JWT-only, KEIN Locale-Routing.
|
||||||
|
- tender-radar-Komponenten (alle hartcodiert Deutsch): `apps/web/src/app/(portal)/modules/tender-radar/components/{ResultsList,FilterPanel,SavedSearchBar,TenderDetail,CoverageBanner}.tsx`, `.../page.tsx`, `.../settings/page.tsx`, `.../settings/components/SourceConfigForm.tsx`.
|
||||||
|
|
||||||
|
### Phase-Fahrplan
|
||||||
|
- `.planning/ROADMAP.md` §453 — Phase-14-Ziel + 5 Success Criteria.
|
||||||
|
- `.planning/REQUIREMENTS.md` — INGEST-04, INGEST-05, CONFIG-02, CONFIG-03, UI-06.
|
||||||
|
|
||||||
|
</canonical_refs>
|
||||||
|
|
||||||
|
<code_context>
|
||||||
|
## Existing Code Insights
|
||||||
|
|
||||||
|
### Reusable Assets
|
||||||
|
- `CalendarCryptoService` (AES-256-GCM) — direkt wiederverwendbar für Mailbox-Credentials; von DKV + SMTP bereits genutzt.
|
||||||
|
- `ImapProvider` / `ExchangeInboxProvider` — Verbindungsmechanik wiederverwendbar; werden nach `inbox/` gehoben.
|
||||||
|
- `SourceRegistry` + `pollDueSources` + Adapter-Interface — RSS- und E-Mail-Adapter plugen sich exakt wie NetServer/cosinex ein (Interface implementieren → Provider + register in `tenders.module.ts` → Poll-Config-Zeile seeden).
|
||||||
|
- `normalizeBag()` in `tender-normalizer.service.ts` — Vorlage für die generische Normalisierung dünn gefüllter RSS/E-Mail-Records.
|
||||||
|
- `DkvModuleConfig` (per-tenant, `tenantId @unique`, verschlüsselte Creds) — Struktur-Vorlage für das neue Mailbox-Config-Modell.
|
||||||
|
- `CoverageBanner.tsx` — vorhandener Ort für die Denylist-Transparenz.
|
||||||
|
- next-intl ist app-weit eingerichtet; `de.json`/`en.json` existieren mit paralleler Struktur.
|
||||||
|
|
||||||
|
### Established Patterns
|
||||||
|
- Safe-Select: verschlüsselte Credential-Felder werden aus GET-Responses ausgeschlossen (T-07-12).
|
||||||
|
- Per-Tenant-Config: `tenantId @unique`-Modell + Auflösung im Service pro Anfrage (wie SMTP in `tender-mail.service.ts`).
|
||||||
|
- Generische Bag-Normalisierung: Adapter legen dünne Felder in `ocdsPayload`, `normalizeBag()` mappt per `sourceType`.
|
||||||
|
|
||||||
|
### Integration Points
|
||||||
|
- Neuer RSS-Adapter + neuer E-Mail-Adapter → registriert in `tenders.module.ts onModuleInit`.
|
||||||
|
- Neues `inbox/`-Modul → importiert von DKV (Pfadwechsel) und vom neuen E-Mail-Adapter.
|
||||||
|
- Neues Mailbox-Config-Modell → `schema.prisma` (Migration), verschlüsselt via `CalendarCryptoService`.
|
||||||
|
- Admin-UI → Erweiterung der bestehenden tender-radar-Settings-Seite.
|
||||||
|
- `tenderRadar`-i18n-Namensraum → `de.json`/`en.json` + `useTranslations` in allen tender-radar-Komponenten.
|
||||||
|
|
||||||
|
</code_context>
|
||||||
|
|
||||||
|
<specifics>
|
||||||
|
## Specific Ideas
|
||||||
|
|
||||||
|
- Das Ausschreibungs-Postfach ist ausdrücklich ein anderes Postfach als das DKV-Rechnungs-Postfach (User-Klarstellung). Adresse + Zugangsdaten werden in den Modul-Einstellungen hinterlegt.
|
||||||
|
- „Zweisprachig" bedeutet: übersetzte Strings genügen; kein Umschalt-Knopf für den Endnutzer.
|
||||||
|
|
||||||
|
</specifics>
|
||||||
|
|
||||||
|
<deferred>
|
||||||
|
## Deferred Ideas
|
||||||
|
|
||||||
|
- **App-weiter Sprachumschalter** — ein sichtbares UI-Element, mit dem ein Benutzer aktiv zwischen DE und EN wechselt (inkl. Persistenz in User-Präferenz/Cookie und ggf. Locale-Routing). Betrifft die gesamte Anwendung, nicht nur tender-radar → eigene Plattform-Phase, nicht Teil von Phase 14.
|
||||||
|
- **Portalspezifische E-Mail-Parser** — präzise Parser pro Alert-Portal (bessere Feldqualität als die generische Extraktion) → sinnvoll erst, wenn konkrete Alert-Portale und echte Mail-Samples bekannt sind.
|
||||||
|
- **Cross-Source-Fingerprint für dünne Quellen** — CPV-loser Zweit-Fingerprint (Option A aus Phase-13-Entscheidung), damit RSS/E-Mail-/Scraper-Records mit DÖE deduplizieren → erst bei Live-Aktivierung einer zweiten Quelle.
|
||||||
|
|
||||||
|
</deferred>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Phase: 14-rss-email-alert-ingestion-module-rollout*
|
||||||
|
*Context gathered: 2026-07-23*
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
# Phase 14: RSS, Email-Alert Ingestion & Module Rollout - Discussion Log
|
||||||
|
|
||||||
|
> **Audit trail only.** Do not use as input to planning, research, or execution agents.
|
||||||
|
> Decisions are captured in CONTEXT.md — this log preserves the alternatives considered.
|
||||||
|
|
||||||
|
**Date:** 2026-07-23
|
||||||
|
**Phase:** 14-rss-email-alert-ingestion-module-rollout
|
||||||
|
**Areas discussed:** Inbox-Modul-Extraktion, E-Mail-Alert-Parsing, Config-Modell + Admin-UI, i18n + Sprachumschaltung
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Klarstellung des Phasenziels (Ausgangspunkt der Diskussion)
|
||||||
|
|
||||||
|
Der User war zunächst verwirrt, was das DKV-Modul mit dem Ausschreibungsportal zu tun hat, und nahm an, das Ausschreibungs-Modul „solle nur Mails versenden". Kernklärung:
|
||||||
|
|
||||||
|
- **Ausgehend (Phase 12, bereits gebaut):** Tessera *versendet* Benachrichtigungs-Mails an Nutzer via SMTP.
|
||||||
|
- **Eingehend (Phase 14, Kriterium 2):** Tessera *liest* ein pro Mandant konfiguriertes Postfach aus, in das Vergabeportale ihre Alert-Mails schicken, und macht daraus Ausschreibungs-Einträge.
|
||||||
|
|
||||||
|
Der Bezug zu DKV: DKV verbindet sich technisch bereits per IMAP/Exchange mit einem Postfach und verarbeitet dessen Inhalt (PDF-Anhänge). Geteilt wird nur diese Verbindungsmechanik, nicht die Postfach-Konfiguration. Der User bestätigte das Verständnis und stellte klar: Das Ausschreibungs-Postfach ist ein **separates** Postfach, nicht das DKV-Rechnungs-Postfach.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Inbox-Modul-Extraktion
|
||||||
|
|
||||||
|
| Option | Description | Selected |
|
||||||
|
|--------|-------------|----------|
|
||||||
|
| A — Interface generalisieren, DKV mitziehen | `fetchMessages()` ergänzen, IMAP/Exchange aufbohren, DKV auf neue Methode umstellen. Sauberste Architektur, aber Regressionsrisiko im produktiven DKV/NTLM-Pfad. | |
|
||||||
|
| B — Additiv, DKV unangetastet | Provider + Interface nach `inbox/` heben, PDF-Methode unverändert lassen, zusätzliche Message-Methode einführen, DKV wechselt nur Import-Pfad. | ✓ |
|
||||||
|
|
||||||
|
**User's choice:** B (folgte Claudes Empfehlung, bestätigt durch die Klarstellung getrennter Postfächer)
|
||||||
|
**Notes:** Getrennte Postfächer bedeuten, dass ohnehin nur die Verbindungslogik geteilt wird, nicht die Config — das deckt sich exakt mit dem additiven Weg. DKV läuft produktiv, Exchange-Pfad nutzt fragiles NTLM via httpntlm → Regressionsrisiko muss null bleiben.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## E-Mail-Alert-Parsing
|
||||||
|
|
||||||
|
| Option | Description | Selected |
|
||||||
|
|--------|-------------|----------|
|
||||||
|
| Pro-Portal-Parser | Ein Parser je bekanntem Portal. Präzise Felder, aber wartungsintensiv und spröde. | |
|
||||||
|
| Generische Extraktion | Ein Parser für alle: Links + Betreff/erste Zeile. Robust, aber dünne Feldqualität. | ✓ |
|
||||||
|
|
||||||
|
**User's choice:** Generische Extraktion (implizit, da User keine konkreten Alert-Portale nennen kann)
|
||||||
|
**Notes:** User kennt die aktuelle Praxis nicht und kann keine konkreten Alert-Portale benennen → portalspezifische Parser wären Raterei. Fähigkeit wird generisch gebaut; jeder Mandant entscheidet durch Einrichten/Leerlassen seines Postfachs, ob und was eingespeist wird. Feldarmut wird offen dokumentiert.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Config-Modell + Admin-UI
|
||||||
|
|
||||||
|
| Option | Description | Selected |
|
||||||
|
|--------|-------------|----------|
|
||||||
|
| Global (Singleton wie TenderSourcePollConfig) | Eine Config für alle Mandanten. | teilweise (nur RSS) |
|
||||||
|
| Per-Tenant (wie DkvModuleConfig) | tenantId-scoped Config mit verschlüsselten Creds. | ✓ (Mailbox) |
|
||||||
|
|
||||||
|
**User's choice:** Gemischt — Postfach pro Mandant in den Modul-Einstellungen; RSS-Feeds global. Bestehende Admin-Seite erweitern.
|
||||||
|
**Notes:** User bestätigte aktiv, dass die Mailadresse in den Modul-Einstellungen hinterlegt wird und getrennt vom DKV-Postfach ist. Damit ist das per-Tenant-Modell für die Mailbox gesetzt (Vorlage DkvModuleConfig), Credentials via CalendarCryptoService verschlüsselt. Offene Detailfrage (wer genau konfiguriert) via bestehende Rollen ADMIN/SUPER_ADMIN aufgelöst.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## i18n + Sprachumschaltung
|
||||||
|
|
||||||
|
| Option | Description | Selected |
|
||||||
|
|--------|-------------|----------|
|
||||||
|
| Eng — nur übersetzte Strings | tender-radar-Strings in DE/EN-Keys überführen; Sprachwahl über bestehenden Mechanismus. | ✓ |
|
||||||
|
| Weit — plus Language-Switcher | Zusätzlich sichtbarer Umschalter (app-weite Infrastruktur). | |
|
||||||
|
|
||||||
|
**User's choice:** „Übersetzte Strings reichen, kein Umschalter nötig"
|
||||||
|
**Notes:** Es existiert bisher kein Language-Switcher/Locale-Routing in der App. Ein app-weiter Umschalter wäre eigene Infrastruktur → als Deferred Idea vermerkt.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Claude's Discretion
|
||||||
|
|
||||||
|
- RSS-Parsing-Bibliothek + Feld-Mapping der RSS-Items (generische Bag, analog Scraper-Adapter).
|
||||||
|
- Genaue Struktur des `inbox/`-Modul-Interfaces und der zusätzlichen Message-Methode.
|
||||||
|
- Scheduler-Anbindung neuer Quellen über bestehendes SourceRegistry/pollDueSources-Muster.
|
||||||
|
- EN-Übersetzungen (Vergabe-Fachbegriffe konsistent).
|
||||||
|
|
||||||
|
## Deferred Ideas
|
||||||
|
|
||||||
|
- App-weiter Sprachumschalter (eigene Plattform-Phase).
|
||||||
|
- Portalspezifische E-Mail-Parser (erst bei bekannten Alert-Portalen + echten Mail-Samples).
|
||||||
|
- CPV-loser Zweit-Fingerprint für Cross-Source-Dedup dünner Quellen (Option A aus Phase-13-Entscheidung; erst bei Live-Aktivierung einer zweiten Quelle).
|
||||||
Reference in New Issue
Block a user