611 lines
36 KiB
Markdown
611 lines
36 KiB
Markdown
# Roadmap: Tessera
|
|
|
|
## Overview
|
|
|
|
Tessera delivers a modular portal platform where tenants activate workflow modules from a marketplace, interact through a configurable dashboard, and optionally use a desktop wrapper. The roadmap builds foundation-first (Docker + DB + shell), layers in authentication and multi-tenancy, establishes the module system with a proof-of-concept module, adds marketplace and portal navigation, delivers the dashboard experience, and wraps up with desktop client and CI/CD integration. The v1.1 Ausschreibungs-Radar milestone (Phases 10-14) adds a new module that aggregates German public tenders from DÖE OpenData plus AI-AG NetServer, cosinex, RSS, and email-alert sources into one normalized, filterable, notifiable catalog -- shipped DÖE-first as a legally-clean, demoable MVP, then layered with scraping adapters and finally the long-tail RSS/email sources.
|
|
|
|
## Milestones
|
|
|
|
- ✅ **v1.0 MVP** - Phases 1-9 (shipped 2026-07-02)
|
|
- 🚧 **v1.1 Ausschreibungs-Radar** - Phases 10-14 (in progress)
|
|
- 🚧 **v1.2 Plattform-Berechtigungen** - Phase 15+ (in progress)
|
|
|
|
## Phases
|
|
|
|
**Phase Numbering:**
|
|
|
|
- Integer phases (1, 2, 3): Planned milestone work
|
|
- Decimal phases (2.1, 2.2): Urgent insertions (marked with INSERTED)
|
|
|
|
Decimal phases appear between their surrounding integers in numeric order.
|
|
|
|
- [x] **Phase 1: Foundation & Portal Shell** - Docker infrastructure, database with RLS, frontend shell with i18n and theming (completed 2026-06-18)
|
|
- [~] **Phase 2: Authentication & Multi-Tenancy** - User accounts, sessions, RBAC, tenant isolation per request (4/5 plans; 02-05 visual verification never run)
|
|
- [x] **Phase 3: Module System & Domaincheck** - Module SDK, registry, lazy loading, and first proof-of-concept module (completed 2026-06-20)
|
|
- [x] **Phase 4: Marketplace & Portal Navigation** - Module catalog, licensing, activation, and sidebar integration (completed 2026-06-23)
|
|
- [x] **Phase 5: Dashboard & Calendar** - Configurable widget grid with drag-and-drop, core widgets, and calendar integration (completed 2026-06-24)
|
|
- [x] **Phase 6: Desktop Client & CI/CD** - Tauri wrapper for Windows/Linux and automated Gitea integration (completed 2026-06-25)
|
|
- [x] **Phase 7: DKV Fleet Module** - Automated DKV invoice processing via email monitoring, PDF parsing, and Excel export with driver mapping (completed 2026-06-27)
|
|
- [x] **Phase 8: Dashboard Widgets Vollimplementierung** - Calculator, Favorites, and Stopwatch widgets plus unified grid constraints across all dashboard widgets (completed 2026-07-01)
|
|
- [x] **Phase 9: Cert Manager Module** - Server-side certificate toolkit: upload/paste, inspect, split chains, merge/bundle, convert formats, password-protected PFX support (completed 2026-07-02)
|
|
- [x] **Phase 10: Ausschreibungs-Radar Foundation & DÖE Ingestion** - Normalized DÖE tender ingestion on a multi-tenant-safe shared schedule, module activatable from the marketplace (completed 2026-07-21)
|
|
- [ ] **Phase 11: Filter Engine, Results UI & Saved Searches** - Searchable/filterable tender results, personal saved search profiles, per-user read/favourite triage
|
|
- [ ] **Phase 12: Tender Notifications** - Configurable digest and instant email alerts without duplicate sends or backfill floods
|
|
- [ ] **Phase 13: Scraping Adapters & Cross-Source Deduplication** - AI-AG NetServer + cosinex adapters with fuzzy cross-source dedup and a hard denylist for banned portals
|
|
- [ ] **Phase 14: RSS, Email-Alert Ingestion & Module Rollout** - RSS + email-alert long tail, admin source/mailbox config, excluded-portal transparency, i18n
|
|
- [ ] **Phase 15: Modul-Berechtigungen: Gruppen & User-Grants** - Modulzugriff pro Gruppe und pro Benutzer zusätzlich zur Mandanten-Aktivierung, Gruppen mit optionaler AD-Bindung
|
|
- [ ] **Phase 16: AD-Gruppen-Synchronisation** - Ausgewählte AD-Gruppen werden als Tessera-Gruppen übernommen und in Name, Bestand und Mitgliedschaft nachgeführt
|
|
|
|
## Phase Details
|
|
|
|
### Phase 1: Foundation & Portal Shell
|
|
|
|
**Goal:** Users can access a running portal application with responsive layout, theme switching, and bilingual interface -- the structural frame into which all features will be placed.
|
|
**Mode:** mvp
|
|
**Depends on**: Nothing (first phase)
|
|
**Requirements**: INFRA-01, INFRA-02, INFRA-03, PRTAL-01, PRTAL-04, UI-01, UI-02, UI-03
|
|
**Success Criteria** (what must be TRUE):
|
|
|
|
1. User can access the portal in a browser served from a Docker Compose stack with PostgreSQL
|
|
2. User sees a responsive layout with header (branding area) and sidebar frame that adapts to screen size
|
|
3. User can toggle between light and dark theme and the preference persists
|
|
4. User can switch between German and English interface language
|
|
5. All UI strings are rendered through the i18n framework (no hardcoded text)
|
|
|
|
**Plans**: 3 plans
|
|
**Wave 1**
|
|
|
|
- [x] 01-01-PLAN.md -- Walking Skeleton: Monorepo + Docker Compose stack with NestJS, Next.js, PostgreSQL, Traefik
|
|
|
|
**Wave 2** *(blocked on Wave 1 completion)*
|
|
|
|
- [x] 01-02-PLAN.md -- Portal Shell: Design tokens, i18n (DE/EN), theme switching, responsive layout with header + sidebar
|
|
|
|
**Wave 3** *(blocked on Wave 2 completion)*
|
|
|
|
- [x] 01-03-PLAN.md -- Visual Verification: Human confirms portal appearance and interactions
|
|
|
|
**UI hint**: yes
|
|
|
|
### Phase 2: Authentication & Multi-Tenancy
|
|
|
|
**Goal:** Users can securely log in, manage accounts, and operate within isolated tenant boundaries -- every request is scoped to the correct tenant with data fully separated at the database level.
|
|
**Mode:** mvp
|
|
**Depends on**: Phase 1
|
|
**Requirements**: AUTH-01, AUTH-02, AUTH-03, AUTH-04, AUTH-05, AUTH-06, TNNT-01, TNNT-02, TNNT-03
|
|
**Success Criteria** (what must be TRUE):
|
|
|
|
1. Initial admin account is created automatically from Docker environment variables on first startup
|
|
2. Admin can create, edit, and delete user accounts with role assignment (Admin/User)
|
|
3. User can log in and log out, with session surviving browser refresh
|
|
4. Admin can create and manage tenants, and each user's data is isolated per tenant via RLS
|
|
5. Users can be imported from an LDAP/AD directory
|
|
|
|
**Plans**: 5 plans
|
|
|
|
**Wave 1**
|
|
|
|
- [x] 02-01-PLAN.md -- Backend Auth Foundation: Prisma schema, RLS migration, JWT Passport auth, admin seed, tenant middleware
|
|
|
|
**Wave 2** *(blocked on Wave 1 completion)*
|
|
|
|
- [x] 02-02-PLAN.md -- Frontend Auth & CRUD: Login page, Next.js middleware, user/tenant management UI, auth-wired portal
|
|
- [x] 02-03-PLAN.md -- Password Reset & Mail: SUS package verification, MailModule, password reset flow, force-change interceptor
|
|
|
|
**Wave 3** *(blocked on Wave 2 completion)*
|
|
|
|
- [x] 02-04-PLAN.md -- LDAP Integration: LDAP sync service, per-tenant config, field mapping, admin UI
|
|
|
|
**Wave 4** *(blocked on Wave 3 completion)*
|
|
|
|
- [ ] 02-05-PLAN.md -- Visual Verification: Human confirms complete auth and multi-tenancy flow (never executed — no summary)
|
|
|
|
**UI hint**: yes
|
|
|
|
### Phase 3: Module System & Domaincheck
|
|
|
|
**Goal:** The platform can discover, register, and load modules dynamically -- validated end-to-end by a working Domaincheck module that users can interact with.
|
|
**Mode:** mvp
|
|
**Depends on**: Phase 2
|
|
**Requirements**: MOD-01, MOD-02, MOD-03, MOD-04, DCHK-01, DCHK-02, DCHK-03
|
|
**Success Criteria** (what must be TRUE):
|
|
|
|
1. Modules are registered in a database-driven registry with a versioned SDK interface
|
|
2. An admin can activate and deactivate a module without restarting the application
|
|
3. Module UIs load on demand (lazy loading) -- no bundle bloat from inactive modules
|
|
4. User can open the Domaincheck module, enter a domain, and see whether it is registered or available
|
|
|
|
**Plans**: 4 plans
|
|
|
|
**Wave 1**
|
|
|
|
- [x] 03-01-PLAN.md -- Module SDK, Prisma Registry, Activation API
|
|
|
|
**Wave 2** *(blocked on Wave 1 completion)*
|
|
|
|
- [x] 03-02-PLAN.md -- Domaincheck Module: Backend DNS + Frontend UI
|
|
- [x] 03-03-PLAN.md -- Lazy Loading, Category Pages, Expanded Module View
|
|
|
|
**Wave 3** *(blocked on Wave 2 completion)*
|
|
|
|
- [x] 03-04-PLAN.md -- Visual Verification: Human confirms module system
|
|
|
|
**UI hint**: yes
|
|
|
|
### Phase 4: Marketplace & Portal Navigation
|
|
|
|
**Goal:** Users can browse available modules in a categorized marketplace, admins can activate modules per tenant, and activated modules appear in the sidebar for navigation.
|
|
**Mode:** mvp
|
|
**Depends on**: Phase 3
|
|
**Requirements**: MRKT-01, MRKT-02, MRKT-03, MRKT-04, PRTAL-02, PRTAL-03, PRTAL-05
|
|
**Success Criteria** (what must be TRUE):
|
|
|
|
1. User can browse a marketplace view showing all available modules with descriptions and categories
|
|
2. Admin can activate or deactivate modules for their tenant from the marketplace
|
|
3. Only activated modules appear in the left sidebar, grouped by category
|
|
4. User can select a module from the sidebar and it opens in the main content area
|
|
5. User can search and filter modules in the sidebar
|
|
|
|
**Plans**: 4 plans
|
|
|
|
**Wave 1**
|
|
|
|
- [x] 04-01-PLAN.md -- Test infra (Vitest) + marketplace i18n + Marketplace page slice: card grid browse + activate (MRKT-01/02/04)
|
|
|
|
**Wave 2** *(blocked on Wave 1 completion)*
|
|
|
|
- [x] 04-02-PLAN.md -- Marketplace refinements: search/category/status filters, deactivation dialog, toast, Super-Admin tenant context, module detail page
|
|
- [x] 04-03-PLAN.md -- Sidebar enhancement: Next.js Link + usePathname active state, per-module links, sidebar search, live refresh (PRTAL-02/03/05, MRKT-03)
|
|
|
|
**Wave 3** *(blocked on Wave 2 completion)*
|
|
|
|
- [x] 04-04-PLAN.md -- Visual Verification: Human confirms marketplace, activation, tenant context, and sidebar navigation
|
|
|
|
**UI hint**: yes
|
|
|
|
### Phase 5: Dashboard & Calendar
|
|
|
|
**Goal:** Users have a personal, configurable start page with freely arrangeable widgets -- including clock, search, notes, and calendar with external calendar source integration.
|
|
**Mode:** mvp
|
|
**Depends on**: Phase 4
|
|
**Requirements**: DASH-01, DASH-02, DASH-03, DASH-04, DASH-05, DASH-06, DASH-07, CAL-01, CAL-02, CAL-03
|
|
**Success Criteria** (what must be TRUE):
|
|
|
|
1. User sees a configurable dashboard as their start page with a drag-and-drop grid
|
|
2. User can add, reposition, and resize widgets (clock, search bar, calendar, notes)
|
|
3. Dashboard layout is saved per user and restored on next login
|
|
4. User can configure external calendar sources (WebDAV, Exchange, ICS) in settings
|
|
5. Calendar widget shows upcoming events from selected calendar sources
|
|
|
|
**Plans**: 5 plans
|
|
|
|
**Wave 1**
|
|
|
|
- [x] 05-01-PLAN.md -- Dashboard foundation: Prisma models, CRUD API, grid, edit-mode, clock widget, settings shell, header link, i18n (DASH-01/02/03/07)
|
|
|
|
**Wave 2** *(blocked on Wave 1 completion)*
|
|
|
|
- [x] 05-02-PLAN.md -- Search + Notes widgets, widget settings panel, SearchProvider backend (DASH-04/06)
|
|
|
|
**Wave 3** *(blocked on Wave 2 completion)*
|
|
|
|
- [x] 05-03-PLAN.md -- Calendar backend: Prisma model, AES-256-GCM crypto, source CRUD, CalDAV/ICS/Exchange providers, DB push (CAL-01/02/03, DASH-05)
|
|
|
|
**Wave 4** *(blocked on Wave 3 completion)*
|
|
|
|
- [x] 05-04-PLAN.md -- Calendar frontend: calendar widget, calendar settings page, API client (CAL-01/02/03, DASH-05)
|
|
|
|
**Wave 5** *(blocked on Wave 4 completion)*
|
|
|
|
- [x] 05-05-PLAN.md -- Visual Verification: Human confirms dashboard, widgets, calendar, settings
|
|
|
|
**UI hint**: yes
|
|
|
|
### Phase 6: Desktop Client & CI/CD
|
|
|
|
**Goal:** Users can install and run Tessera as a native desktop application, and the development workflow includes automated version control via Gitea.
|
|
**Mode:** mvp
|
|
**Depends on**: Phase 5
|
|
**Requirements**: DESK-01, DESK-02, INFRA-04
|
|
**Success Criteria** (what must be TRUE):
|
|
|
|
1. User can install a Tauri-based desktop app on Windows or Linux
|
|
2. Desktop app connects to the existing web backend (no standalone server)
|
|
3. Code changes are automatically committed and pushed to Gitea with minimal manual intervention
|
|
|
|
**Plans**: 3 plans
|
|
|
|
**Wave 1** *(parallel — disjoint files)*
|
|
|
|
- [x] 06-01-PLAN.md -- Desktop foundation: Tauri toolchain, apps/desktop scaffold, URL-loading WebView + first-run server URL setup (DESK-01/02)
|
|
- [x] 06-03-PLAN.md -- CI/CD: Gitea remote, act_runner, multi-stage Gitea Actions pipeline (lint+type-check -> tests -> docker build+deploy) (INFRA-04)
|
|
|
|
**Wave 2** *(blocked on 06-01)*
|
|
|
|
- [x] 06-02-PLAN.md -- Desktop native: tray + close-to-tray, window-state, autostart, notifications + version check, branded icon, AppImage+NSIS bundles, /health/version API (DESK-01/02)
|
|
|
|
### Phase 7: DKV Fleet Module
|
|
|
|
**Goal:** Administrators can automatically process DKV fuel card invoices by monitoring an email inbox, parsing PDF attachments, mapping license plates to drivers, and exporting structured Excel reports via SMTP.
|
|
**Mode:** mvp
|
|
**Depends on**: Phase 6
|
|
**Requirements**: DKV-01, DKV-02, DKV-03, DKV-04, DKV-05
|
|
**Success Criteria** (what must be TRUE):
|
|
|
|
1. System automatically detects DKV invoice PDFs from a configured email inbox (IMAP or Exchange)
|
|
2. All transactions are parsed per vehicle with: date, service station, km reading, product, quantity, unit, net/gross amounts
|
|
3. License plate → driver mapping is importable as CSV and manually editable in the UI
|
|
4. Processed data is exported as Excel file and sent to a configurable recipient via SMTP
|
|
5. SMTP settings are configurable in general settings (shared with other modules)
|
|
6. Module configuration (inbox, sender filter, folder, recipient) is editable in the module settings UI
|
|
|
|
**Plans**: 6 plans
|
|
|
|
**Wave 0**
|
|
|
|
- [x] 07-01-PLAN.md -- Backend foundation: deps install, Prisma models, ScheduleModule, crypto export, validated DKV PDF parser (DKV-02)
|
|
|
|
**Wave 1** *(blocked on Wave 0 completion)*
|
|
|
|
- [x] 07-02-PLAN.md -- Inbox-access layer: InboxProvider interface, IMAP + Exchange providers, config/vehicle/history DTOs (DKV-01)
|
|
- [x] 07-03-PLAN.md -- Export + delivery + SMTP backend: SettingsModule (SMTP CRUD + test), DkvExportService (xlsx + prune), DkvMailService, MailModule DB-SMTP migration (DKV-04/05, D-06)
|
|
|
|
**Wave 2** *(blocked on Wave 1 completion)*
|
|
|
|
- [x] 07-04-PLAN.md -- Pipeline integration: DkvService orchestration, dynamic scheduler, DkvController REST, module registry seed, i18n keys (DKV-01/03/04/05)
|
|
- [x] 07-05-PLAN.md -- Module frontend: dkv-api client, main page (history + export download + "Jetzt prüfen"), inbox settings form, vehicle CRUD + CSV import (DKV-01/03/04)
|
|
- [x] 07-06-PLAN.md -- SMTP settings frontend: settings-api client, SMTP config form + connection test, settings-sidebar "Allgemein" category (DKV-05)
|
|
|
|
**UI hint**: yes
|
|
|
|
### Phase 8: Dashboard Widgets Vollimplementierung
|
|
|
|
**Goal:** Users have a complete dashboard widget set — Calculator, Favorites (with backend persistence), and Stopwatch added alongside existing widgets. All widgets share unified grid constraints for a consistent layout experience.
|
|
**Mode:** mvp
|
|
**Depends on**: Phase 5
|
|
**Requirements**: DASH-08, DASH-09, DASH-10, DASH-11
|
|
**Success Criteria** (what must be TRUE):
|
|
|
|
1. User can open a Calculator widget and perform basic arithmetic operations with keyboard support
|
|
2. User can manage favorite links (add, edit, delete) in the Favorites widget; links persist across sessions via a backend DB table (FavoriteLink)
|
|
3. User can start, stop, and reset a Stopwatch widget with lap time recording
|
|
4. All dashboard widgets share the same minW, minH, defaultW, defaultH grid constraint values
|
|
5. Existing widgets (Clock, Search, Calendar, Notes) remain fully functional after constraint normalization
|
|
|
|
**Plans**: 4/4 plans complete
|
|
|
|
**Wave 1**
|
|
|
|
- [x] 08-01-PLAN.md — Foundation + Calculator slice: registry constraints for all 4 new types, catalog, DTO, i18n; working Calculator widget (DASH-08, DASH-11)
|
|
|
|
**Wave 2** *(blocked on Wave 1 completion)*
|
|
|
|
- [x] 08-02-PLAN.md — Stopwatch widget: start/stop/reset/lap with config persistence + reload reconstruction (DASH-10)
|
|
|
|
**Wave 3** *(blocked on Wave 2 completion)*
|
|
|
|
- [x] 08-03-PLAN.md — Favorites slice: FavoriteLink schema + FavoritesModule (SSRF icon discovery) + FavoritesWidget list/grid + inline CRUD (DASH-09)
|
|
|
|
**Wave 4** *(blocked on Wave 3 completion)*
|
|
|
|
- [x] 08-04-PLAN.md — Link widget: single-link tile reusing favorites backend, row/tile views (DASH-09 / D-06)
|
|
|
|
**UI hint**: yes
|
|
|
|
### Phase 9: Cert Manager Module
|
|
|
|
**Goal:** Users can upload or paste certificates in any common format, inspect their details, split fullchain/P7B bundles into individual certificates, merge certs into chains or PFX bundles, and convert between formats — all processed server-side with no database persistence.
|
|
**Mode:** mvp
|
|
**Depends on**: Phase 3
|
|
**Requirements**: CERT-01, CERT-02, CERT-03, CERT-04, CERT-05, CERT-06
|
|
**Success Criteria** (what must be TRUE):
|
|
|
|
1. User can upload a cert file (PEM, DER, PFX/P12, CRT, CER, P7B) or paste PEM/CRT text and see parsed details (subject, issuer, validity, SANs, fingerprint)
|
|
2. User can split a fullchain.pem or P7B bundle into individual certificate files (downloadable)
|
|
3. User can merge multiple cert files into a PEM chain or a PFX bundle (with password)
|
|
4. User can convert between PEM, DER, PFX/P12, P7B, CRT/CER formats
|
|
5. Password-protected PFX/PKCS12 files can be opened (password prompt) and created (password input)
|
|
6. Module appears in the module registry with slug `cert-manager`
|
|
|
|
**Plans**: 6/6 plans complete
|
|
|
|
Plans:
|
|
**Wave 1**
|
|
|
|
- [x] 09-01-PLAN.md — API foundation: install node-forge + Vitest runner, scaffold module, seed registry (CERT-06), shared node-forge helpers
|
|
- [x] 09-02-PLAN.md — Frontend shell: tab page, DropZone, conditional password field, download helpers, certManager i18n (de/en)
|
|
|
|
**Wave 2** *(blocked on Wave 1 completion)*
|
|
|
|
- [x] 09-03-PLAN.md — Inspect slice: parseCert (PEM/DER/PFX/P7B) + POST /parse + Inspect tab (CERT-01, CERT-05 read)
|
|
|
|
**Wave 3** *(blocked on Wave 2 completion)*
|
|
|
|
- [x] 09-04-PLAN.md — Split slice: splitCerts (fullchain/P7B) + POST /split + Split tab download list (CERT-02)
|
|
|
|
**Wave 4** *(blocked on Wave 3 completion)*
|
|
|
|
- [x] 09-05-PLAN.md — Convert slice: convertCert (PEM/DER/P7B round-trips) + POST /convert + Convert tab (CERT-04)
|
|
|
|
**Wave 5** *(blocked on Wave 4 completion)*
|
|
|
|
- [x] 09-06-PLAN.md — Merge/PFX slice: mergeCerts (PEM chain + password PFX) + POST /merge + Merge tab + PFX convert option (CERT-03, CERT-05 write)
|
|
|
|
**UI hint**: yes
|
|
|
|
### Phase 10: Ausschreibungs-Radar Foundation & DÖE Ingestion
|
|
|
|
**Goal:** The platform ingests German public tenders from the DÖE OpenData API on a shared, multi-tenant-safe schedule into a normalized, platform-global schema, and the module can be activated per tenant from the marketplace.
|
|
**Mode:** mvp
|
|
**Depends on**: Phase 9 (existing platform infrastructure: module registry, multi-tenancy, mail/SMTP)
|
|
**Requirements**: CONFIG-01, INGEST-01, INGEST-06, SCHEMA-01, SCHEMA-02
|
|
**Success Criteria** (what must be TRUE):
|
|
|
|
1. Admin can find "Ausschreibungs-Radar" in the marketplace and activate it for a tenant, same as the DKV-Fleet/Cert-Manager modules
|
|
2. New DÖE OpenData tenders appear as normalized records (title, buyer, CPV codes, region/PLZ, deadline, estimated value, procedure type, source URL) after a poll cycle -- tender data is platform-global, not tied to any one tenant
|
|
3. A DÖE tender that changes on the source side (e.g. deadline extension, cancellation) updates the existing record via content-hash change detection instead of creating a duplicate
|
|
4. DÖE is polled once on a shared, admin-configurable interval regardless of how many tenants have the module active -- never once per tenant (poll-once-fan-out-many, not the DKV single-tenant `findFirst()` pattern)
|
|
5. Activating the module for a second tenant does not duplicate ingestion, re-trigger a redundant DÖE poll, or interfere with the first tenant's data
|
|
|
|
**Plans**: 6/6 plans complete
|
|
|
|
**Wave 1**
|
|
|
|
- [x] 10-01-PLAN.md — Foundation: install fast-xml-parser/adm-zip/csv-parse (adm-zip supply-chain checkpoint), add global Tender + TenderSourcePollConfig models, [BLOCKING] migration (SCHEMA-01)
|
|
|
|
**Wave 2** *(blocked on Wave 1 completion)*
|
|
|
|
- [x] 10-02-PLAN.md — Marketplace registration slice: self-seed tender-radar module, module-loader whitelist entry, placeholder page, singleton doe-opendata poll config (CONFIG-01)
|
|
|
|
**Wave 3** *(blocked on Wave 2 completion)*
|
|
|
|
- [x] 10-03-PLAN.md — DÖE adapter + normalizer (TDD): fetch/extract/parse day-export ZIP, D-02 open-tender filter, eForms-primary normalize with dedupKey + contentHash (INGEST-01, SCHEMA-01)
|
|
|
|
**Wave 4** *(blocked on Wave 3 completion)*
|
|
|
|
- [x] 10-04-PLAN.md — Ingestion + shared scheduler: day-cursor gate, upsert change-detection, single global cron (poll-once-fan-out-many), 90-day retention, two-tenant safety test (SCHEMA-02, INGEST-06)
|
|
|
|
**Wave 5** *(blocked on Wave 4 completion)*
|
|
|
|
- [x] 10-05-PLAN.md — Controller + admin source-config: global ModuleGuard-gated read, admin-configurable poll interval applied live to scheduler (INGEST-06)
|
|
|
|
**Wave 6** *(blocked on Wave 5 completion)*
|
|
|
|
- [x] 10-06-PLAN.md — Admin config UI: tender-radar-api client + settings page SourceConfigForm reading/writing GET/PUT source-config, mirroring DKV InboxConfigForm (INGEST-06 admin-UI)
|
|
|
|
**UI hint**: yes (admin source-config settings form; results UI is Phase 11)
|
|
|
|
### Phase 11: Filter Engine, Results UI & Saved Searches
|
|
|
|
**Goal:** Users can search, filter, and personally triage DÖE tender results, and save reusable filter combinations as personal search profiles, with the UI transparently communicating data coverage.
|
|
**Mode:** mvp
|
|
**Depends on**: Phase 10
|
|
**Requirements**: FILTER-01, FILTER-02, FILTER-03, FILTER-04, FILTER-05, FILTER-06, UI-01, UI-02, UI-03, UI-04, UI-05
|
|
**Success Criteria** (what must be TRUE):
|
|
|
|
1. User sees a searchable, sortable results list (by deadline, value, publish date) and can filter by keyword, region/PLZ/Bundesland, CPV code (hierarchical, with autocomplete), deadline, and estimated value -- tenders with no value stated are handled gracefully, not excluded or errored
|
|
2. User can open a detail view for any tender showing the source link and any document URLs present in the notice (no local mirroring of Vergabeunterlagen)
|
|
3. User can save a combination of filter criteria as a named search profile and later edit or delete it -- profiles are personal (per user) and scoped to their own tenant
|
|
4. User can mark a tender as read/unread and as favourite, and filter the results list to only favourites -- both states are per-user, not shared across the tenant
|
|
5. The UI clearly indicates data coverage (Oberschwelle vs. Unterschwelle) so an empty or thin result set isn't mistaken for a bug
|
|
|
|
**Plans**: 6/6 plans executed
|
|
|
|
- [x] 11-01-PLAN.md — Trefferliste + Freitext + Sortierung + Coverage-Banner (FILTER-01/04/05, UI-01/05)
|
|
- [x] 11-02-PLAN.md — Bundesland-Ableitung (NUTS + Backfill) + Region/PLZ/Bundesland-Filter (FILTER-02)
|
|
- [x] 11-03-PLAN.md — CPV-Filter (Katalog + Divisionen) + Wert-Filter-UI (FILTER-03/05)
|
|
- [x] 11-04-PLAN.md — Detailansicht via ?tender=<id> + Quell-Link (UI-02)
|
|
- [x] 11-05-PLAN.md — Triage: gelesen/ungelesen + Favorit + Merklisten-Filter (UI-03/04)
|
|
- [x] 11-06-PLAN.md — Suchprofile speichern/bearbeiten/löschen (FILTER-06)
|
|
|
|
**UI hint**: yes
|
|
|
|
### Phase 12: Tender Notifications
|
|
|
|
**Goal:** Users are proactively notified by email about new matching tenders, via a configurable digest and/or instant alert, without duplicate sends or backfill floods, using the tenant's own SMTP configuration.
|
|
**Mode:** mvp
|
|
**Depends on**: Phase 11
|
|
**Requirements**: NOTIFY-01, NOTIFY-02, NOTIFY-03, NOTIFY-04
|
|
**Success Criteria** (what must be TRUE):
|
|
|
|
1. User receives a periodic email digest of new matches for their active search profiles, with the interval configurable in the web interface
|
|
2. User can enable an instant email alert per search profile and receives a single email shortly after a new match against that profile
|
|
3. Activating a new search profile with many pre-existing historical matches does not flood the user with individual emails -- backfill is suppressed/batched on first activation, and a match already notified once (digest or instant) is never notified again for the same tender+profile pair (explicit matched-vs-notified state)
|
|
4. Notification emails are sent through the tenant's own SMTP configuration (reusing the DKV mail pattern), not a shared/global system mailer
|
|
|
|
**Plans**: 4/4 plans executed
|
|
**UI hint**: yes
|
|
|
|
**Wave 1**
|
|
|
|
- [x] 12-01-PLAN.md — Schema (TenderMatch/NotificationPref/instantAlert) + delta-only Matching in den Poll-Tick (NOTIFY-03)
|
|
|
|
**Wave 2** *(blocked on Wave 1)*
|
|
|
|
- [x] 12-02-PLAN.md — TenderMailService (mandanten-SMTP) + globaler Digest-Cron (NOTIFY-01/04)
|
|
|
|
**Wave 3** *(blocked on Wave 2)*
|
|
|
|
- [x] 12-03-PLAN.md — Sofort-Alerts am Poll-Tick + Ein-Mail-Garantie über beide Kanäle (NOTIFY-02/03)
|
|
- [x] 12-04-PLAN.md — Web-UI: Digest-Intervall + Sofort-Alert-Toggle, Pref-Backend (NOTIFY-01/02)
|
|
|
|
### Phase 13: Scraping Adapters & Cross-Source Deduplication
|
|
|
|
**Goal:** The platform expands tender coverage with AI-AG NetServer and cosinex portal adapters and collapses tenders seen on multiple sources into a single entry, while structurally refusing to ever scrape the AGB-prohibited portals.
|
|
**Mode:** mvp
|
|
**Depends on**: Phase 12
|
|
**Requirements**: INGEST-02, INGEST-03, INGEST-07, SCHEMA-03
|
|
**Success Criteria** (what must be TRUE):
|
|
|
|
1. Tenders from AI-AG NetServer portals (lhs-vpbw, tender24, vergabe.landbw) appear as additional, correctly normalized results via one config-driven adapter
|
|
2. Tenders from the cosinex Vergabemarktplatz (DTVP) appear as additional, correctly normalized results via a separate config-driven adapter
|
|
3. A tender that appears via both DÖE and a scraping adapter shows up once in the results list (fuzzy fingerprint dedup on buyer+title+CPV+deadline+value), with links to all of its source portals -- dedup logic only activates once a second source is live
|
|
4. Attempting to register vergabe24 or aumass as a poll source is refused by the system itself (adapter registry denylist enforced in code), not just documented as forbidden
|
|
|
|
**Plans**: 6/6 plans executed
|
|
|
|
Plans:
|
|
|
|
- [x] 13-01-PLAN.md — TenderSource-Schema + Backfill + NULL-tolerante Fingerprint-Fn + SourceType-Union (SCHEMA-03 Datenschicht)
|
|
- [x] 13-02-PLAN.md — SourceRegistry + harte Denylist-Gate (vergabe24/aumass) + Adapter-Interface-Generalisierung (INGEST-07)
|
|
- [x] 13-03-PLAN.md — 3-Stufen-Dedup-Resolver + pollDueSources Fan-out (catch-per-source) + Modul-Wiring (SCHEMA-03)
|
|
- [x] 13-04-PLAN.md — NetServer-Adapter (config-getrieben, 3 Portale) + Package-Legitimacy-Checkpoint (INGEST-02)
|
|
- [x] 13-05-PLAN.md — cosinex/DTVP-Adapter (separat, best-effort) (INGEST-03)
|
|
- [x] 13-06-PLAN.md — Read-Endpoint include sources[] + TenderDetail Multi-Source-Links (SCHEMA-03 Anzeige)
|
|
|
|
### Phase 14: RSS, Email-Alert Ingestion & Module Rollout
|
|
|
|
**Goal:** The platform rounds out Unterschwelle long-tail coverage via RSS feeds and per-tenant email-alert mailboxes (reusing a shared inbox module extracted from DKV), admins can manage source and mailbox configuration per tenant, excluded portals are shown transparently, and the whole module is bilingual.
|
|
**Mode:** mvp
|
|
**Depends on**: Phase 13
|
|
**Requirements**: INGEST-04, INGEST-05, CONFIG-02, CONFIG-03, UI-06
|
|
**Success Criteria** (what must be TRUE):
|
|
|
|
1. Tenders from the RSS feeds subreport-elvis and service.bund.de appear automatically in the results list
|
|
2. Tenders parsed from a configured mailbox's portal-alert emails appear automatically in the results list -- built on a shared `inbox/` module, extracted as a one-time prerequisite refactor from DKV's `ImapProvider`/`ExchangeInboxProvider` (previously living inside `dkv/`)
|
|
3. Admin can manage per-tenant source poll configuration and the email-alert ingestion mailbox, with credentials stored encrypted (same AES-256-GCM pattern as `DkvModuleConfig`)
|
|
4. vergabe24 and aumass are shown in the UI as "manually monitor" with a direct link, instead of appearing as a silent coverage gap
|
|
5. The entire module UI (results list, filters, saved searches, settings) is fully usable in both German and English
|
|
|
|
**Plans**: 5/5 plans executed
|
|
|
|
**Wave 1** *(parallel — disjoint files)*
|
|
|
|
- [x] 14-01-PLAN.md — Inbox-Modul-Extraktion (ImapProvider/ExchangeInboxProvider → apps/api/src/inbox/) + additive fetchMessages() (INGEST-05 prerequisite)
|
|
- [x] 14-02-PLAN.md — RSS-Ingestion-Slice: RssAdapter + globale Feed-Liste-CRUD (Denylist/SSRF-Guard) + pollGranularity-Tick-Gate + Admin-UI (INGEST-04, CONFIG-02)
|
|
|
|
**Wave 2** *(blocked on 14-01 + 14-02)*
|
|
|
|
- [x] 14-03-PLAN.md — E-Mail-Alert-Slice: TenderEmailConfig (pro Mandant, verschlüsselt) + EmailAlertAdapter + per-Mandant Tender-Sichtbarkeit (D-13) + EWS-Human-Verify (INGEST-05, CONFIG-02)
|
|
|
|
**Wave 3** *(blocked on 14-03)*
|
|
|
|
- [x] 14-04-PLAN.md — Denylist-Transparenz: denylisted-portals-Endpoint + CoverageBanner „manuell beobachten"-Block (UI-06)
|
|
|
|
**Wave 4** *(blocked on 14-02 + 14-03 + 14-04)*
|
|
|
|
- [x] 14-05-PLAN.md — i18n-Rollout: tenderRadar-Namensraum (DE/EN) + Komponenten auf useTranslations + Key-Parity-Test (CONFIG-03)
|
|
|
|
**UI hint**: yes
|
|
|
|
### Phase 15: Modul-Berechtigungen: Gruppen & User-Grants
|
|
|
|
**Goal:** Modulzugriff wird zweistufig: die bestehende Mandanten-Aktivierung bleibt Voraussetzung, darüber hinaus entscheiden Freigaben pro Gruppe und pro einzelnem Benutzer, wer ein Modul sieht und dessen API nutzen darf. Admins verwalten Gruppen (optional an eine AD-Gruppe gebunden) und eine Freigabe-Matrix pro Modul im Admin-UI.
|
|
**Depends on**: Phase 14
|
|
**Requirements**: PERM-01, PERM-02, PERM-03, PERM-04, PERM-05, PERM-06, PERM-07
|
|
**Success Criteria** (what must be TRUE):
|
|
|
|
1. Ein Admin kann im Admin-UI Gruppen anlegen, umbenennen und löschen sowie Benutzer manuell zuweisen und entfernen
|
|
2. Eine Gruppe kann optional an einen AD-Gruppen-DN gebunden werden; der LDAP-Sync trägt die Mitglieder aus `memberOf` ein und entfernt dabei keine manuell gesetzten Mitglieder
|
|
3. Ein Admin kann ein mandantenweit aktives Modul gezielt für Gruppen und/oder einzelne Benutzer freigeben und die Freigabe wieder entziehen
|
|
4. Ohne Freigabe hat ein USER keinen Zugriff: das Modul fehlt in der Sidebar, die Modulseite ist gesperrt und die Modul-API antwortet mit 403 — Sidebar und API nutzen dieselbe Zugriffsauflösung
|
|
5. ADMIN und SUPER_ADMIN sehen und nutzen innerhalb ihres Mandanten alle aktiven Module ohne Freigabe
|
|
6. Nach der Migration hat kein bestehender Benutzer Zugriff verloren: pro Mandant existiert eine als Standardgruppe markierte Gruppe „Alle Benutzer" mit allen Bestandsbenutzern und Freigaben für alle zum Migrationszeitpunkt aktiven Module
|
|
7. Ein Dashboard-Widget, dessen Modul dem Benutzer nicht freigegeben ist, erscheint nicht auf seinem Dashboard
|
|
|
|
**Design-Entscheidungen** (mit User geklärt am 2026-08-04):
|
|
|
|
- Gruppenquelle: Tessera-eigene Gruppen mit optionaler AD-Bindung (`Group.ldapDn`), nicht reine AD-Spiegelung
|
|
- Default: geschlossen — ohne Grant kein Zugriff (Migration verhindert Lockout)
|
|
- Bypass: ADMIN + SUPER_ADMIN umgehen Grants innerhalb ihres Mandanten
|
|
- Tiefe: nur Modulzugriff an/aus, keine Rechtestufen (read/write) innerhalb der Module
|
|
|
|
**Neue Modelle**: `Group` (tenantId, name, ldapDn?), `GroupMembership` (userId, groupId, source MANUAL|LDAP), `ModuleGrant` (tenantId, moduleId, groupId? | userId?)
|
|
|
|
**Plans**: 7/8 plans executed
|
|
|
|
Plans:
|
|
**Wave 1**
|
|
|
|
- [x] 15-01-PLAN.md — Schema, Migration mit Bestandsübernahme und Zugriffsauflösung (Tracer)
|
|
|
|
**Wave 2** *(blocked on Wave 1 completion)*
|
|
|
|
- [x] 15-02-PLAN.md — Gruppen-API und automatische Standardgruppen-Mitgliedschaft
|
|
- [ ] 15-04-PLAN.md — AD-Gruppenbindung im bestehenden LDAP-Sync
|
|
- [x] 15-05-PLAN.md — Modulfilter für Dashboard-Widgets
|
|
|
|
**Wave 3** *(blocked on Wave 2 completion)*
|
|
|
|
- [x] 15-03-PLAN.md — Freigabe-API für Gruppen und Benutzer plus Modulkatalog-Endpoint
|
|
- [x] 15-06-PLAN.md — Gruppenverwaltung im Admin-UI und alle i18n-Schlüssel der Phase
|
|
|
|
**Wave 4** *(blocked on Wave 3 completion)*
|
|
|
|
- [x] 15-07-PLAN.md — Freigabe-Matrix, Benutzer-Detail und Aktivierungsdialog
|
|
- [x] 15-08-PLAN.md — Serverseitige 403-Modulsperre und Marketplace-Kennzeichnung
|
|
|
|
**Wellen**: 1 → 15-01 · 2 → 15-02, 15-04, 15-05 · 3 → 15-03, 15-06 · 4 → 15-07, 15-08
|
|
|
|
**UI hint**: yes
|
|
|
|
### Phase 16: AD-Gruppen-Synchronisation
|
|
|
|
**Goal:** Ausgewählte AD-Gruppen werden als Tessera-Gruppen angelegt und dauerhaft nachgeführt, statt jede Gruppe von Hand anzulegen und zu binden. Der Admin wählt aus der AD-Gruppenliste aus, welche Gruppen übernommen werden; der bestehende Benutzer-Sync hält Bestand, Namen und Mitgliedschaften danach aktuell.
|
|
**Depends on**: Phase 15
|
|
**Requirements**: PERM-02
|
|
**Success Criteria** (what must be TRUE):
|
|
|
|
1. Ein Admin wählt aus der AD-Gruppenliste einzelne Gruppen zur Übernahme aus; für jede ausgewählte Gruppe entsteht eine Tessera-Gruppe mit gesetzter AD-Bindung
|
|
2. Nicht ausgewählte AD-Gruppen werden nicht angelegt — es gibt keine pauschale Übernahme einer ganzen OU
|
|
3. Wird eine übernommene Gruppe im AD umbenannt, zieht der Name der Tessera-Gruppe beim nächsten Sync nach
|
|
4. Verschwindet eine übernommene Gruppe aus dem AD, wird die Tessera-Gruppe samt ihrer Mitgliedschaften und Modulfreigaben entfernt
|
|
5. Manuell angelegte Gruppen ohne AD-Bindung bleiben vom Gruppen-Sync unberührt
|
|
|
|
**Design-Entscheidungen** (mit User geklärt am 2026-08-05):
|
|
|
|
- Umfang: nur ausdrücklich ausgewählte AD-Gruppen, keine OU-weite Automatik
|
|
- Löschen im AD löscht die Tessera-Gruppe mit — inklusive der daran hängenden Modulfreigaben
|
|
- Umbenennen im AD zieht in Tessera nach
|
|
|
|
**Bekannte Folge, bewusst akzeptiert**: Ein Löschvorgang im AD nimmt betroffenen Benutzern schlagartig die über diese Gruppe vergebenen Modulzugriffe, ohne den Warndialog aus D-17 zu durchlaufen — der greift nur beim Löschen über die Tessera-Oberfläche.
|
|
|
|
**Offen für die Planung**: ob ein Admin eine automatisch angelegte Gruppe in Tessera umbenennen darf (würde beim nächsten Sync überschrieben), und wie sich die Auswahl-Oberfläche zur bestehenden AD-Gruppenauswahl in `/admin/groups` verhält.
|
|
|
|
**Plans**: 3/5 plans executed
|
|
|
|
Plans:
|
|
**Wave 1**
|
|
|
|
- [x] 16-01-PLAN.md — Tracer: Schema-Erweiterung (internalName, ldapObjectGuid) + AD-Gruppen-Import end-to-end (D-01, D-02, D-04)
|
|
|
|
**Wave 2** *(blocked on Wave 1 completion)*
|
|
|
|
- [x] 16-02-PLAN.md — GroupsService: Standardgruppen-Handoff, Namenssperre, interner Name, Anzeige-Fallback (D-03, D-04, D-06, D-07)
|
|
|
|
**Wave 3** *(blocked on Wave 2 completion)*
|
|
|
|
- [x] 16-03-PLAN.md — Sync-Rekonziliation: Umbenennung, Loeschung, Alt-Bindungen; eingehaengt vor dem Mitgliedschafts-Abgleich (D-03, D-05, D-06)
|
|
- [ ] 16-04-PLAN.md — GroupFormModal ohne AD-Bindung, gesperrtes Namensfeld, interner Name, i18n-Bereinigung (D-03, D-04, D-07)
|
|
|
|
**Wave 4** *(blocked on Wave 3 completion)*
|
|
|
|
- [ ] 16-05-PLAN.md — Sync-Bericht vollstaendig verdrahtet + Anzeigename in der Freigabe-Matrix (D-04, D-05, D-06)
|
|
|
|
**Waves**: 1 → 16-01 · 2 → 16-02 · 3 → 16-03, 16-04 (parallel) · 4 → 16-05
|
|
|
|
**UI hint**: yes
|
|
|
|
## Progress
|
|
|
|
**Execution Order:**
|
|
Phases execute in numeric order: 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> 11 -> 12 -> 13 -> 14 -> 15
|
|
|
|
| Phase | Plans Complete | Status | Completed |
|
|
|-------|----------------|--------|-----------|
|
|
| 1. Foundation & Portal Shell | 3/3 | Complete | 2026-06-18 |
|
|
| 2. Authentication & Multi-Tenancy | 4/5 | Incomplete — 02-05 visual verification never run | - |
|
|
| 3. Module System & Domaincheck | 4/4 | Complete | 2026-06-20 |
|
|
| 4. Marketplace & Portal Navigation | 4/4 | Complete | 2026-06-23 |
|
|
| 5. Dashboard & Calendar | 5/5 | Complete | 2026-06-24 |
|
|
| 6. Desktop Client & CI/CD | 3/3 | Complete | 2026-06-25 |
|
|
| 7. DKV Fleet Module | 6/6 | Complete | 2026-06-27 |
|
|
| 8. Dashboard Widgets Vollimplementierung | 4/4 | Complete | 2026-07-01 |
|
|
| 9. Cert Manager Module | 6/6 | Complete | 2026-07-02 |
|
|
| 10. Ausschreibungs-Radar Foundation & DÖE Ingestion | 6/6 | Complete | 2026-07-21 |
|
|
| 11. Filter Engine, Results UI & Saved Searches | 6/6 | In Progress| |
|
|
| 12. Tender Notifications | 4/4 | In Progress| |
|
|
| 13. Scraping Adapters & Cross-Source Deduplication | 6/6 | In Progress| |
|
|
| 14. RSS, Email-Alert Ingestion & Module Rollout | 5/5 | In Progress| |
|
|
| 15. Modul-Berechtigungen: Gruppen & User-Grants | 7/8 | In Progress| |
|