docs(17-03): complete UI-Aufteilung Meine Quellen vs. Administration plan
Tessera CI/CD / Lint & Type Check (push) Successful in 46s
Tessera CI/CD / Tests (push) Successful in 53s
Tessera CI/CD / Build & Publish Images (push) Successful in 1m58s

This commit is contained in:
2026-08-12 12:06:31 +02:00
parent 809afbce13
commit 4453e86626
5 changed files with 265 additions and 16 deletions
+16 -1
View File
@@ -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).
+3 -3
View File
@@ -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.
+14 -9
View File
@@ -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
+29 -3
View File
@@ -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 <verification> 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
}
]
````
@@ -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-<verify>-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 `<RssFeedListForm />` 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*