From 4453e866268ad86740d551b6ca35ecae8f38cf6d Mon Sep 17 00:00:00 2001 From: Schalli Date: Wed, 12 Aug 2026 12:06:31 +0200 Subject: [PATCH] docs(17-03): complete UI-Aufteilung Meine Quellen vs. Administration plan --- .planning/REQUIREMENTS.md | 17 +- .planning/ROADMAP.md | 6 +- .planning/STATE.md | 23 +- .planning/WINDOWS.md | 32 ++- .../17-03-SUMMARY.md | 203 ++++++++++++++++++ 5 files changed, 265 insertions(+), 16 deletions(-) create mode 100644 .planning/phases/17-eigene-ausschreibungs-quellen-je-nutzer/17-03-SUMMARY.md diff --git a/.planning/REQUIREMENTS.md b/.planning/REQUIREMENTS.md index 616de9b..0b22d72 100644 --- a/.planning/REQUIREMENTS.md +++ b/.planning/REQUIREMENTS.md @@ -55,6 +55,16 @@ - [x] **CONFIG-02**: Admin verwaltet Quellen-Poll-Konfiguration sowie das E-Mail-Ingestion-Postfach pro Mandant (Zugangsdaten verschlüsselt gespeichert). - [x] **CONFIG-03**: Die gesamte Modul-UI ist mehrsprachig (Deutsch + Englisch, i18n). +### SRC — Eigene Ausschreibungs-Quellen je Nutzer + +**Hinzugefügt 2026-08-12** — aus dem Backlog-Punkt `2026-08-11-tender-radar-einstellungen-mischen-rollen.md` und `.planning/phases/17-eigene-ausschreibungs-quellen-je-nutzer/17-CONTEXT.md` abgeleitet, neue modul-lokale Kategorie. + +- [x] **SRC-01**: Jeder Nutzer bindet sein eigenes Alert-Postfach an; ein Mandant kann mehrere Postfächer haben (D-01). +- [x] **SRC-02**: RSS-Feeds haben einen Besitzer; Feeds ohne Besitzer bleiben plattformweit und von der Administration gepflegt (D-02). +- [x] **SRC-03**: Der zeitgesteuerte Abruf holt weiterhin alle Quellen in einem Durchlauf; eine kaputte Quelle blockiert die anderen nicht. +- [x] **SRC-04**: Nutzereigene Einstellungen (Postfach, eigene Feeds, Digest-Intervall) liegen auf einer eigenen, für jeden Modulnutzer erreichbaren Seite (D-04). +- [x] **SRC-05**: Die verbleibenden Administrationseinstellungen sind für normale Nutzer nicht sichtbar; die Rollenprüfung greift in der Oberfläche wie in der API (D-03). + ## v1.2 Requirements **Milestone:** v1.2 Plattform-Berechtigungen — Modulzugriff nicht mehr nur pro Mandant, sondern zusätzlich pro Gruppe und pro Benutzer. @@ -121,6 +131,11 @@ | CONFIG-02 | Phase 14 | Complete | | CONFIG-03 | Phase 14 | Complete | | UI-06 | Phase 14 | Complete | +| SRC-01 | Phase 17 | Complete | +| SRC-02 | Phase 17 | Complete | +| SRC-03 | Phase 17 | Complete | +| SRC-04 | Phase 17 | Complete | +| SRC-05 | Phase 17 | Complete | | PERM-01 | Phase 15 | Complete | | PERM-02 | Phase 16 | Complete | @@ -130,4 +145,4 @@ | PERM-06 | Phase 15 | Pending | | PERM-07 | Phase 15 | Complete | -**Coverage:** 29/29 v1.1 requirements mapped — no orphans. 7/7 v1.2 requirements mapped: PERM-01/03/04/05/06/07 auf Phase 15, PERM-02 auf Phase 16 (umgehängt 2026-08-06). +**Coverage:** 34/34 v1.1 requirements mapped (29 aus Phase 10–14 + SRC-01..05 aus Phase 17, nachträglich am 2026-08-12 ergänzt — die Kategorie fehlte in dieser Datei, obwohl 17-01/17-02 sie bereits in ihren SUMMARY-Frontmattern als erledigt führten) — no orphans. 7/7 v1.2 requirements mapped: PERM-01/03/04/05/06/07 auf Phase 15, PERM-02 auf Phase 16 (umgehängt 2026-08-06). diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md index 37ae8b2..250919e 100644 --- a/.planning/ROADMAP.md +++ b/.planning/ROADMAP.md @@ -609,7 +609,7 @@ Phases execute in numeric order: 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 | 14. RSS, Email-Alert Ingestion & Module Rollout | 5/5 | In Progress| | | 15. Modul-Berechtigungen: Gruppen & User-Grants | 8/8 | Complete | 2026-08-04 (Bericht 15-04 am 2026-08-11 nachgezogen) | | 16. AD-Gruppen-Synchronisation | 5/5 | Complete | 2026-08-11 | -| 17. Eigene Ausschreibungs-Quellen je Nutzer | 2/3 | In Progress| | +| 17. Eigene Ausschreibungs-Quellen je Nutzer | 3/3 | In Progress| | ### Phase 17: Eigene Ausschreibungs-Quellen je Nutzer @@ -628,7 +628,7 @@ Phases execute in numeric order: 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 - **SRC-05**: Die verbleibenden Administrationseinstellungen sind fuer normale Nutzer nicht sichtbar; die Rollenpruefung greift in der Oberflaeche wie in der API (D-03). **Depends on:** Phase 16 -**Plans:** 2/3 plans executed +**Plans:** 3/3 plans executed **Success Criteria** (what must be TRUE): @@ -644,4 +644,4 @@ Plans (Wellenstruktur — streng nacheinander, alle drei fassen Schema, Controll - [x] 17-01-PLAN.md (Welle 1) — Alert-Postfach wechselt vom Mandanten zum Nutzer: Schema, handgeschriebene Migration mit Besitzer-Zuordnung, Dienst und Endpunkt, erste Fassung der Seite "Meine Quellen". Enthaelt den Entscheidungspunkt fuer beide Datenbank-Umbauten der Phase. - [x] 17-02-PLAN.md (Welle 2, nach 17-01) — RSS-Feeds bekommen einen Besitzer: Schema und Migration, Besitzerlogik, Schutz gegen fremdes Loeschen, Mengenbegrenzung, Herkunftsmarkierung im Abruf, angepasste Startbestueckung. -- [ ] 17-03-PLAN.md (Welle 3, nach 17-01 und 17-02) — Oberflaeche nach Zustaendigkeit trennen: "Meine Quellen" vollstaendig, Administrationsseite reduziert und rollengeprueft, Zahnrad umgehaengt, Beschriftungen in beiden Sprachen, Backlog-Punkt geschlossen. +- [x] 17-03-PLAN.md (Welle 3, nach 17-01 und 17-02) — Oberflaeche nach Zustaendigkeit trennen: "Meine Quellen" vollstaendig, Administrationsseite reduziert und rollengeprueft, Zahnrad umgehaengt, Beschriftungen in beiden Sprachen, Backlog-Punkt geschlossen. diff --git a/.planning/STATE.md b/.planning/STATE.md index b53fb72..4208563 100644 --- a/.planning/STATE.md +++ b/.planning/STATE.md @@ -4,16 +4,16 @@ milestone: v1.1 milestone_name: Ausschreibungs-Radar current_phase: 17 current_phase_name: eigene-ausschreibungs-quellen-je-nutzer -status: executing -stopped_at: "17-02 abgeschlossen: RSS-Feeds bekommen einen Besitzer (D-02), Migration lokal angewendet (alpha noch nicht ausgerollt), Loeschschutz+Obergrenze+D-06-Tagging getestet. Naechster Schritt: Plan 17-03 (UI-Aufteilung)." -last_updated: "2026-08-12T09:48:46.242Z" +status: verifying +stopped_at: "17-03 abgeschlossen: UI-Aufteilung Meine Quellen vs. Administration, Backlog-Punkt geschlossen. Phase 17 vollstaendig — bereit fuer /gsd-ship (Browser-Gegenprobe aller drei Plaene und Testserver-Rollout stehen als offene Punkte in WINDOWS.md)." +last_updated: "2026-08-12T10:06:09.773Z" last_activity: 2026-08-12 last_activity_desc: Phase 17 execution started progress: total_phases: 17 - completed_phases: 15 + completed_phases: 16 total_plans: 83 - completed_plans: 81 + completed_plans: 82 --- # Project State @@ -29,7 +29,7 @@ See: .planning/PROJECT.md (updated 2026-07-17) Phase: 17 (eigene-ausschreibungs-quellen-je-nutzer) — EXECUTING Plan: 3 of 3 -Status: Ready to execute +Status: Phase complete — ready for verification uebersprungen (kein AD-Schreibzugriff, Entscheidung des Users 2026-08-11). UAT-Test 2 hat einen kritischen Fehler in der Loescherkennung aufgedeckt, der beim ersten echten Sync alle AD-gebundenen Gruppen entfernt haette — behoben in @@ -37,7 +37,7 @@ beim ersten echten Sync alle AD-gebundenen Gruppen entfernt haette — behoben i dokumentiert in 16-VERIFICATION.md. Last activity: 2026-08-12 — Phase 17 execution started -Progress: [██████████] 98% +Progress: [██████████] 99% ## Performance Metrics @@ -119,6 +119,7 @@ Progress: [██████████] 98% | Phase 16 P05 | 6min | 2 tasks | 4 files | | Phase 17 P01 | 76min | 3 tasks | 12 files | | Phase 17 P02 | 58min | 3 tasks | 14 files | +| Phase 17 P03 | 62min | 3 tasks | 13 files | ## Accumulated Context @@ -288,6 +289,10 @@ Recent decisions affecting current work: - [Phase ?]: [17-02]: Startbestueckung (tenders.module.ts) vorgezogen aus Task 3 nach Task 1 (Rule 3) - find-then-create statt upsert-on-url, Prismas Compound-Unique-Typ verlangt userId als Pflicht-String - [Phase ?]: [17-02]: seedServiceBundRssFeed() aus TendersModule.onModuleInit extrahiert (tenders.seed.ts), damit die Bestueckungs-Idempotenz echten Produktivcode testet - [Phase ?]: [17-02]: DELETE /rss-feeds/:feedId von @Roles auf @UseModule umgestellt - Besitzpruefung im Dienst ersetzt die Rollenpruefung vollstaendig (T-17-07) +- [Phase ?]: [17-03]: RssFeedListForm scope-Prop (personal/platform) bedient beide Seiten; Berechtigung entscheidet der Server (T-17-08) +- [Phase ?]: [17-03]: createRssFeed-Antwort traegt kein isPlatformWide (nur GET mappt es) — Komponente leitet es lokal aus dem verwendeten scope ab (Rule 1) +- [Phase ?]: [17-03]: Anzeige-Rollenpruefung auf settings/page.tsx ueber useAuthStore (unbekannt/erlaubt/verweigert); verbindliche Pruefung bleibt serverseitig +- [Phase ?]: [17-03]: REQUIREMENTS.md SRC-01..05 nachtraeglich ergaenzt — Luecke aus 17-01/17-02, dort schon in SUMMARY-Frontmatter gefuehrt ### Pending Todos @@ -336,7 +341,7 @@ Items acknowledged and carried forward from previous milestone close: ## Session Continuity -Last session: 2026-08-12T09:48:46.207Z -Stopped at: 17-02 abgeschlossen: RSS-Feeds bekommen einen Besitzer (D-02), Migration lokal angewendet (alpha noch nicht ausgerollt), Loeschschutz+Obergrenze+D-06-Tagging getestet. Naechster Schritt: Plan 17-03 (UI-Aufteilung). +Last session: 2026-08-12T10:06:09.739Z +Stopped at: 17-03 abgeschlossen: UI-Aufteilung Meine Quellen vs. Administration, Backlog-Punkt geschlossen. Phase 17 vollstaendig — bereit fuer /gsd-ship (Browser-Gegenprobe aller drei Plaene und Testserver-Rollout stehen als offene Punkte in WINDOWS.md). Resume file: None Last activity: 2026-07-14 - Built LDAP per-user exclude/denylist filter (9d1323f), migration applied on live DB, verified via Playwright: sync deactivated 4 excluded service accounts (administrator/krbtgt/guest/dns-ldap), 2 real LDAP users stay active, 0 wrongly created diff --git a/.planning/WINDOWS.md b/.planning/WINDOWS.md index d24cd77..bdef505 100644 --- a/.planning/WINDOWS.md +++ b/.planning/WINDOWS.md @@ -1,10 +1,10 @@ --- schema_version: 1 -open_count: 7 +open_count: 9 waived_count: 0 fixed_count: 0 -total_count: 7 -last_updated: 2026-08-12T09:24:35.289Z +total_count: 9 +last_updated: 2026-08-12T10:02:49.291Z --- # Broken Windows Ledger @@ -22,6 +22,8 @@ last_updated: 2026-08-12T09:24:35.289Z | 5 | 16 | unrun-verify | .planning/phases/16-ad-gruppen-synchronisation/16-04-PLAN.md | | Manueller Browser-Durchklick aus dem Plan-Verification-Block (drei GroupFormModal-Zustaende: Anlegen mit Hinweis-Link, lokale Gruppe umbenennen, importierte Gruppe mit gesperrtem Namen + internem Namen speichern; Namensanzeige mit Tooltip in der Liste nach dem Speichern) nicht ausgefuehrt — kein Browser-Tool in dieser Session verfuegbar. | open | | 2026-08-06T14:31:14.336Z | | | 6 | 16 | unrun-verify | .planning/phases/16-ad-gruppen-synchronisation/16-05-PLAN.md | | 16-05 Manuell nachzuholen (Browser): Sync ausloesen und pruefen, dass alle drei Zahlenzeilen erscheinen; Lauf mit verschobener Standardmarkierung provozieren und Amber-Zeile pruefen; Freigabe-Matrix-Spaltensuche unter beiden Namen probieren - nicht ausgefuehrt, kein Browser-Tool in dieser Session verfuegbar. | open | | 2026-08-06T14:39:03.905Z | | | 7 | 17 | unrun-verify | .planning/phases/17-eigene-ausschreibungs-quellen-je-nutzer/17-01-PLAN.md | | 17-01 Task 2 human-check: Browser-Gegenprobe (normaler Nutzer oeffnet /modules/tender-radar/my-sources, speichert Postfach, zweites Konto desselben Mandanten sieht leeres Formular) nicht ausgefuehrt — kein Browser-Tool in dieser Session verfuegbar. Automatisierte Pruefungen (prisma validate/migrate status, Index-Liste, beide Typpruefungen, 335/335 src/tenders-Tests) sind gelaufen und gruen. | open | | 2026-08-12T09:24:35.289Z | | +| 8 | 17 | unrun-verify | apps/web/src/app/(portal)/modules/tender-radar/my-sources/page.tsx | | Browser-Gegenprobe Plan 17-03 Task 1 (Tracer-Feedback-Gate): Meine Quellen mit drei Abschnitten, neu angelegter eigener Feed sofort sichtbar, plattformweiter Feed ohne Entfernen-Knopf, Digest-Intervall speichert nach Reload — kein Browser-Tool in dieser Sitzung verfuegbar | open | | 2026-08-12T10:02:49.122Z | | +| 9 | 17 | unrun-verify | apps/web/src/app/(portal)/modules/tender-radar/settings/page.tsx | | Browser-Gegenprobe Plan 17-03 Task 2: USER-Konto sieht keine Bedienelemente auf /settings (nur Hinweis+Verweis), ADMIN-Konto sieht Abrufintervall+plattformweite Feeds ohne Postfach/Benachrichtigung, Zahnrad fuehrt in beiden Faellen nach Meine Quellen — kein Browser-Tool in dieser Sitzung verfuegbar | open | | 2026-08-12T10:02:49.291Z | | ````json [ @@ -108,6 +110,30 @@ last_updated: 2026-08-12T09:24:35.289Z "reason": "", "recorded_at": "2026-08-12T09:24:35.289Z", "resolved_at": null + }, + { + "id": 8, + "kind": "unrun-verify", + "phase": "17", + "file": "apps/web/src/app/(portal)/modules/tender-radar/my-sources/page.tsx", + "line": null, + "description": "Browser-Gegenprobe Plan 17-03 Task 1 (Tracer-Feedback-Gate): Meine Quellen mit drei Abschnitten, neu angelegter eigener Feed sofort sichtbar, plattformweiter Feed ohne Entfernen-Knopf, Digest-Intervall speichert nach Reload — kein Browser-Tool in dieser Sitzung verfuegbar", + "status": "open", + "reason": "", + "recorded_at": "2026-08-12T10:02:49.122Z", + "resolved_at": null + }, + { + "id": 9, + "kind": "unrun-verify", + "phase": "17", + "file": "apps/web/src/app/(portal)/modules/tender-radar/settings/page.tsx", + "line": null, + "description": "Browser-Gegenprobe Plan 17-03 Task 2: USER-Konto sieht keine Bedienelemente auf /settings (nur Hinweis+Verweis), ADMIN-Konto sieht Abrufintervall+plattformweite Feeds ohne Postfach/Benachrichtigung, Zahnrad fuehrt in beiden Faellen nach Meine Quellen — kein Browser-Tool in dieser Sitzung verfuegbar", + "status": "open", + "reason": "", + "recorded_at": "2026-08-12T10:02:49.291Z", + "resolved_at": null } ] ```` diff --git a/.planning/phases/17-eigene-ausschreibungs-quellen-je-nutzer/17-03-SUMMARY.md b/.planning/phases/17-eigene-ausschreibungs-quellen-je-nutzer/17-03-SUMMARY.md new file mode 100644 index 0000000..a2c6473 --- /dev/null +++ b/.planning/phases/17-eigene-ausschreibungs-quellen-je-nutzer/17-03-SUMMARY.md @@ -0,0 +1,203 @@ +--- +phase: 17-eigene-ausschreibungs-quellen-je-nutzer +plan: 03 +subsystem: ui +tags: [nextjs, next-intl, zustand, vitest, testing-library] + +# Dependency graph +requires: + - phase: 17-01 + provides: "TenderEmailConfig per-user, /modules/tender-radar/my-sources (Seite mit Postfach-Abschnitt)" + - phase: 17-02 + provides: "RssFeedSource.isPlatformWide-Vertrag (GET/POST /rss-feeds, scope-Wunsch, Besitz-basierter Loeschschutz)" +provides: + - "my-sources/page.tsx vollstaendig: Postfach + eigene Feeds + Digest-Intervall auf einer Seite" + - "RssFeedListForm mit scope-Prop (personal/platform) — eine Komponente fuer beide Seiten" + - "DigestIntervalForm als eigenstaendige Komponente (aus settings/page.tsx herausgeloest)" + - "settings/page.tsx auf reine Administration reduziert, Anzeige-Rollenpruefung ueber useAuthStore" + - "Zahnrad auf der Modulseite fuehrt zu /my-sources statt /settings" + - "REQUIREMENTS.md SRC-01..05 Sektion + Traceability (fehlte bisher trotz Nutzung in 17-01/17-02-SUMMARY)" +affects: [dkv-fleet-settings-restructuring, future-per-user-module-settings] + +# Actuals (#2632) +actuals: + tokens: 18180 + tasks: 3 + commits: 3 + +tech-stack: + added: [] + patterns: + - "Eine Formkomponente mit einem scope-Prop (personal/platform) statt zwei fast identischer Komponenten — der Server entscheidet ueber Berechtigung, das Prop entscheidet nur ueber Darstellung und den scope-Wunsch im Request" + - "Anzeige-Rollenpruefung ueber useAuthStore in der Seite selbst (drei Zustaende: unbekannt/Platzhalter, erlaubt/Inhalt, verweigert/Hinweis+Verweis) statt eines Guards oder Redirects — verbindliche Pruefung bleibt serverseitig" + - "Verhaltensunveraendertes Herausloesen einer Komponente aus einer Seite ohne neue i18n-Schluessel, wenn nur der Ort wechselt, nicht das Verhalten (DigestIntervalForm)" + +key-files: + created: + - "apps/web/src/app/(portal)/modules/tender-radar/settings/components/DigestIntervalForm.tsx" + - "apps/web/src/app/(portal)/modules/tender-radar/my-sources/my-sources.test.tsx" + - "apps/web/src/app/(portal)/modules/tender-radar/settings/settings-roles.test.tsx" + modified: + - apps/web/src/lib/tender-radar-api.ts + - "apps/web/src/app/(portal)/modules/tender-radar/settings/components/RssFeedListForm.tsx" + - "apps/web/src/app/(portal)/modules/tender-radar/settings/components/RssFeedListForm.test.tsx" + - "apps/web/src/app/(portal)/modules/tender-radar/my-sources/page.tsx" + - "apps/web/src/app/(portal)/modules/tender-radar/settings/page.tsx" + - "apps/web/src/app/(portal)/modules/tender-radar/page.tsx" + - apps/web/src/messages/de.json + - apps/web/src/messages/en.json + - .planning/REQUIREMENTS.md + +key-decisions: + - "[Rule 3] settings/page.tsx auf RssFeedListForm scope=\"platform\" vorgezogen bereits in Task 1, statt erst in Task 2 — Task 1s eigener Type-Check-Verify verlangt eine kompilierbare RssFeedListForm-Prop-Signatur ueber das ganze Projekt hinweg, gleiches Muster wie in 17-01/17-02" + - "[Rule 1] createRssFeed()-Antwort traegt kein isPlatformWide (nur GET /rss-feeds mappt es serverseitig, T-17-12) — RssFeedListForm setzt das Feld nach dem Anlegen lokal aus dem verwendeten scope, sonst waere ein frisch angelegter plattformweiter Feed bis zum naechsten Neuladen aus seiner eigenen Liste verschwunden" + - "page.settingsTitle bleibt bestehen und wird als Verweistext auf der Nutzerseite fuer Administratoren wiederverwendet (Task 1/2), statt eines separaten neuen Schluessels — neuer Schluessel page.mySourcesTitle nur fuer das umgehaengte Zahnrad" + - "REQUIREMENTS.md um die SRC-01..05-Sektion und Traceability-Zeilen ergaenzt — Luecke aus Plan 17-01/17-02 (dort bereits requirements-completed im SUMMARY-Frontmatter gefuehrt, aber nie in REQUIREMENTS.md selbst nachgezogen), gehoert inhaltlich zum Requirements-Traceability-Schritt dieses Plans" + +requirements-completed: [SRC-04, SRC-05] + +coverage: + - id: D1 + description: "\"Meine Quellen\" traegt alle drei nutzereigenen Abschnitte (Postfach, eigene Feeds, Benachrichtigung) auf einer Seite; ein neu angelegter eigener Feed erscheint sofort in der eigenen Liste; plattformweite Feeds erscheinen darunter als nicht bedienbare Aufzaehlung mit Administrations-Hinweis" + requirement: "SRC-04" + verification: + - kind: unit + ref: "apps/web/src/app/(portal)/modules/tender-radar/my-sources/my-sources.test.tsx (5 Tests)" + status: pass + - kind: unit + ref: "apps/web/src/app/(portal)/modules/tender-radar/settings/components/RssFeedListForm.test.tsx (scope=personal-Block, 6 Tests inkl. Mischliste mit/ohne Entfernen-Knopf)" + status: pass + human_judgment: false + - id: D2 + description: "Die Administrationsseite zeigt nur noch Abrufintervall und plattformweite Feeds; ein Konto ohne ADMIN/SUPER_ADMIN-Rolle sieht dort keine Bedienelemente mehr, sondern Hinweis + Verweis auf \"Meine Quellen\"; waehrend die Rolle noch unbekannt ist, erscheint weder das eine noch das andere" + requirement: "SRC-05" + verification: + - kind: unit + ref: "apps/web/src/app/(portal)/modules/tender-radar/settings/settings-roles.test.tsx (5 Tests: USER/ADMIN/SUPER_ADMIN/unbekannt/entfernte Ueberschriften)" + status: pass + - kind: unit + ref: "apps/web/src/app/(portal)/modules/tender-radar/settings/components/RssFeedListForm.test.tsx (scope=platform-Block, 2 Tests: eigene Feeds tauchen dort nicht auf, scope-Parameter im Request)" + status: pass + human_judgment: false + - id: D3 + description: "Das Zahnrad auf der Modulseite fuehrt jeden Nutzer nach /my-sources statt zur admin-only Administrationsseite; Administratoren erreichen die Administrationsseite von dort mit einem Klick" + requirement: "SRC-04" + verification: [] + human_judgment: true + rationale: "Browser-Gegenprobe (Klick auf das Zahnrad, Navigationsziel im echten Router pruefen) nicht ausgefuehrt — kein Browser-Tool in dieser Session verfuegbar (WINDOWS.md #8/#9). Der Link selbst ist per Testing-Library gegen den gerenderten href geprueft (my-sources.test.tsx, settings-roles.test.tsx), nicht aber die tatsaechliche Client-seitige Navigation im Next.js-Router." + - id: D4 + description: "Alle neuen Beschriftungen liegen in Deutsch und Englisch vor; keine mehr verwendete Beschriftung bleibt verwaist" + requirement: "SRC-04" + verification: + - kind: unit + ref: "Node-Skript-Schluesselvergleich beider Sprachdateien (in allen drei Task--Bloecken gelaufen)" + status: pass + human_judgment: false + +duration: 62min +completed: 2026-08-12 +status: complete +--- + +# Phase 17 Plan 03: UI-Aufteilung — "Meine Quellen" vs. Administration Summary + +**Ausschreibungs-Radar-Oberflaeche in zwei Seiten getrennt: "Meine Quellen" traegt jetzt Postfach, eigene RSS-Feeds und Digest-Intervall auf einer Seite fuer jeden Modulnutzer, die Administrationsseite schrumpft auf Abrufintervall und plattformweite Feeds mit einer Anzeige-Rollenpruefung — der urspruengliche Anlass des Backlog-Punkts ist damit geschlossen.** + +## Performance + +- **Duration:** 62 min +- **Started:** 2026-08-12T09:58:00Z +- **Completed:** 2026-08-12T11:00:00Z +- **Tasks:** 3 +- **Files modified:** 13 (3 neu, 10 geaendert) + Backlog-Punkt verschoben + REQUIREMENTS.md ergaenzt + +## Accomplishments + +- `RssFeedSource` bekommt das serverseitig gelieferte `isPlatformWide`-Kennzeichen, `createRssFeed` einen `scope`-Parameter (`personal`/`platform`, Vorgabe `personal`) — der Server entscheidet ueber Berechtigung (T-17-08), das Frontend nur ueber Darstellung +- `RssFeedListForm` bedient jetzt beide Seiten ueber ein `scope`-Prop: `scope="personal"` zeigt die eigenen Feeds editierbar und plattformweite darunter als schlichte, nicht bedienbare Liste mit Administrations-Hinweis; `scope="platform"` zeigt nur plattformweite Feeds editierbar, eigene Feeds tauchen dort gar nicht auf +- `DigestIntervalForm` unveraendert aus `settings/page.tsx` herausgeloest — dieselbe Logik, dieselben Beschriftungen, jetzt eine eigenstaendige Komponente, die beide Seiten nutzen +- `/modules/tender-radar/my-sources` traegt jetzt alle drei nutzereigenen Abschnitte (Postfach, eigene Feeds, Benachrichtigung) auf einer Seite; Administratoren sehen zusaetzlich einen Verweis auf die Administrationsseite +- `/modules/tender-radar/settings` zeigt nur noch Abrufintervall und plattformweite Feeds; eine Anzeige-Rollenpruefung ueber den vorhandenen Anmelde-Speicher blendet die Bedienelemente fuer Konten ohne ADMIN/SUPER_ADMIN-Rolle aus (Hinweis + Verweis auf "Meine Quellen" stattdessen) — die verbindliche Pruefung bleibt serverseitig unveraendert +- Das Zahnrad auf der Modulseite fuehrt jetzt zu "Meine Quellen" statt zur Administrationsseite +- Backlog-Punkt `2026-08-11-tender-radar-einstellungen-mischen-rollen.md` nach `todos/completed/` verschoben, mit Resolution-Abschnitt, der beide vom User im Gespraech getroffenen Entscheidungen (eigene Quellen je Nutzer, Trefferliste bleibt plattform-global) und die Antwort auf den offenen Punkt 4 (eigene nutzerseitige Modulseite als Vorbild fuer DKV-Fleet und kuenftige Module) dokumentiert +- `REQUIREMENTS.md` um die SRC-01..05-Sektion und Traceability-Zeilen ergaenzt (Luecke aus 17-01/17-02 geschlossen) + +## Task Commits + +Jede Aufgabe wurde einzeln committet: + +1. **Task 1: "Meine Quellen" wird vollstaendig — Postfach, eigene Feeds, Benachrichtigung** — `4100bb5` (feat) +2. **Task 2: Die Administrationsseite schrumpft auf das, was Administration ist** — `150046e` (feat) +3. **Task 3: Tests fuer beide Seiten und der Backlog-Punkt wird zugemacht** — `809afbc` (test) + +**Plan metadata:** wird mit diesem SUMMARY committet (docs) + +## Files Created/Modified + +- `apps/web/src/lib/tender-radar-api.ts` — `RssFeedSource.isPlatformWide`, `createRssFeed(payload, scope)` +- `apps/web/src/app/(portal)/modules/tender-radar/settings/components/RssFeedListForm.tsx` — `scope`-Prop, editierbare/nicht-editierbare Teillisten, lokale `isPlatformWide`-Ableitung nach dem Anlegen +- `apps/web/src/app/(portal)/modules/tender-radar/settings/components/RssFeedListForm.test.tsx` — auf `scope` umgestellt, Mischlisten-Faelle fuer beide Scopes ergaenzt +- `apps/web/src/app/(portal)/modules/tender-radar/settings/components/DigestIntervalForm.tsx` — neu, unveraendert aus `settings/page.tsx` herausgeloest +- `apps/web/src/app/(portal)/modules/tender-radar/my-sources/page.tsx` — Abschnitte "Meine Feeds" und "Benachrichtigung" ergaenzt, Verweis auf Administrationsseite fuer ADMIN/SUPER_ADMIN +- `apps/web/src/app/(portal)/modules/tender-radar/my-sources/my-sources.test.tsx` — neu, 5 Tests +- `apps/web/src/app/(portal)/modules/tender-radar/settings/page.tsx` — Postfach-/Benachrichtigungsabschnitt entfernt, Anzeige-Rollenpruefung ueber `useAuthStore` +- `apps/web/src/app/(portal)/modules/tender-radar/settings/settings-roles.test.tsx` — neu, 5 Tests +- `apps/web/src/app/(portal)/modules/tender-radar/page.tsx` — Zahnrad zeigt auf `/my-sources`, neue Beschriftung +- `apps/web/src/messages/de.json`, `apps/web/src/messages/en.json` — neue `mySources.*`/`settings.*`/`page.mySourcesTitle`-Schluessel, drei verwaiste `settings.*`-Schluessel entfernt +- `.planning/todos/completed/2026-08-11-tender-radar-einstellungen-mischen-rollen.md` — verschoben, mit Resolution-Abschnitt +- `.planning/REQUIREMENTS.md` — SRC-01..05-Sektion + Traceability ergaenzt + +## Decisions Made + +- `settings/page.tsx` bereits in Task 1 auf `RssFeedListForm scope="platform"` vorgezogen (Rule 3), volle Rollenpruefung + Abschnittsreduktion folgte in Task 2 +- `createRssFeed`s Antwort traegt kein `isPlatformWide` — Komponente leitet es lokal aus dem verwendeten `scope` ab (Rule 1, sonst verschwaende ein frisch angelegter plattformweiter Feed bis zum Neuladen) +- `page.settingsTitle` bleibt bestehen und dient jetzt als Verweistext auf der Nutzerseite; neuer Schluessel `page.mySourcesTitle` nur fuer das umgehaengte Zahnrad +- `REQUIREMENTS.md` um SRC-01..05 ergaenzt (gehoert zum Requirements-Traceability-Schritt dieses Plans, schliesst eine Luecke aus 17-01/17-02) + +## Deviations from Plan + +### Auto-fixed Issues + +**1. [Rule 3 - Blocking] `settings/page.tsx` auf `RssFeedListForm scope="platform"` vorgezogen aus Task 2 nach Task 1** +- **Found during:** Task 1 (Type-Check nach Aenderung der `RssFeedListForm`-Prop-Signatur) +- **Issue:** Task 1s eigener Verify verlangt einen fehlerfreien projektweiten Type-Check; `settings/page.tsx` (Task 2s Datei) rief `` noch ohne das neue Pflicht-Prop `scope` auf +- **Fix:** Minimale Ergaenzung `scope="platform"` an der bestehenden Aufrufstelle — die vollstaendige Umgestaltung der Seite (Rollenpruefung, Abschnittsreduktion) blieb Task 2 vorbehalten +- **Files modified:** apps/web/src/app/(portal)/modules/tender-radar/settings/page.tsx +- **Verification:** `pnpm --filter @tessera/web type-check` fehlerfrei ab Task 1 +- **Committed in:** 4100bb5 (Task 1 commit) + +**2. [Rule 1 - Bug] `RssFeedListForm` leitet `isPlatformWide` nach dem Anlegen lokal ab** +- **Found during:** Task 1 (beim Entwurf von `handleAdd` fuer beide Scopes) +- **Issue:** `POST /rss-feeds` mappt `isPlatformWide` nicht (nur `GET /rss-feeds` tut das serverseitig, T-17-12) — ein frisch angelegter Eintrag haette das Feld `undefined`, wodurch ein neu angelegter plattformweiter Feed (`scope="platform"`) faelschlich aus der eigenen editierbaren Liste gefallen waere, bis zum naechsten Neuladen +- **Fix:** Nach erfolgreichem `createRssFeed(...)` wird `isPlatformWide` clientseitig aus dem verwendeten `scope` gesetzt (`scope === 'platform'`), statt sich auf ein vom Server nicht geliefertes Feld zu verlassen +- **Files modified:** apps/web/src/app/(portal)/modules/tender-radar/settings/components/RssFeedListForm.tsx +- **Verification:** RssFeedListForm.test.tsx deckt beide Scopes explizit ab ("die neue Feed landet sofort in der editierbaren Liste, mit funktionierendem Entfernen-Knopf") +- **Committed in:** 4100bb5 (Task 1 commit) + +--- + +**Total deviations:** 2 auto-fixed (1× Rule 3 Kompilierfaehigkeit, 1× Rule 1 Bugfix) +**Impact on plan:** Beide Anpassungen waren fuer die Korrektheit der eigentlichen Plan-Aenderung zwingend notwendig. Kein Scope Creep — Deviation 1 ist eine minimale Vorziehung der ohnehin geplanten Aenderung, Deviation 2 behebt eine waehrend der Implementierung entdeckte Inkonsistenz zwischen POST- und GET-Antwortform derselben Ressource. + +## Issues Encountered + +- `REQUIREMENTS.md` enthielt keine SRC-Kategorie, obwohl 17-01/17-02-SUMMARY bereits `requirements-completed: [SRC-01, SRC-03]` bzw. `[SRC-02, SRC-03]` fuehrten — die Datei war seit dem Anlegen von Phase 17 nie nachgezogen worden (nur ROADMAP.md hatte die SRC-Beschreibungen). Ergaenzt als Teil des Requirements-Traceability-Schritts dieses Plans, keine separate Aenderung noetig. + +## User Setup Required + +None — keine externe Dienstkonfiguration erforderlich. + +## Next Phase Readiness + +- Phase 17 ist inhaltlich abgeschlossen: alle drei Plaene liefern D-01 bis D-05 vollstaendig, der Backlog-Punkt ist geschlossen, SRC-01..05 sind erledigt +- Web 205/205 Tests gruen, API `src/tenders` 362/362 gruen, beide Typpruefungen (API + Web) fehlerfrei +- Offen: die Browser-Gegenprobe aus den `human-check`-Schritten aller drei Plaene (17-01 bis 17-03) — kein Browser-Tool in den jeweiligen Sitzungen verfuegbar, festgehalten in WINDOWS.md (#7, #8, #9), vor `/gsd-ship` nachzuholen +- Offen: Rollout beider Migrationen (17-01, 17-02) auf dem Testserver (192.168.13.12) bleibt bewusst Nutzeraktion (Projektregel: kein `docker compose pull/up/rebuild` durch Claude auf dem Testserver) + +## Self-Check: PASSED + +Alle im SUMMARY genannten Dateien existieren auf der Festplatte; alle drei Task-Commit-Hashes (`4100bb5`, `150046e`, `809afbc`) sind im Git-Log auffindbar. + +--- +*Phase: 17-eigene-ausschreibungs-quellen-je-nutzer* +*Completed: 2026-08-12*