--- gsd_state_version: 1.0 milestone: v1.0 milestone_name: milestone current_phase: 9 current_phase_name: cert-manager-module status: complete stopped_at: UAT 8/8 passed — Phase 9 complete (2026-07-02) last_updated: "2026-07-02T06:46:00.000Z" last_activity: 2026-07-02 last_activity_desc: Phase 9 UAT complete — all 9 phases done progress: total_phases: 9 completed_phases: 9 total_plans: 40 completed_plans: 40 percent: 100 --- # Project State ## Project Reference See: .planning/PROJECT.md (updated 2026-06-18) **Core value:** Eine zentrale Plattform, in der beliebige Workflow-Tools als Module lizenziert, aktiviert und genutzt werden koennen -- ohne zwischen verschiedenen Anwendungen wechseln zu muessen. **Current focus:** Phase 9 — cert-manager-module ## Current Position Phase: 9 (cert-manager-module) — EXECUTING Plan: 5 of 6 Status: Ready to execute Last activity: 2026-07-01 — Phase 9 execution started Progress: [█████████░] 93% ## Performance Metrics **Velocity:** - Total plans completed: 2 - Average duration: 12 min - Total execution time: 0.38 hours **By Phase:** | Phase | Plans | Total | Avg/Plan | |-------|-------|-------|----------| | 01-foundation-portal-shell | 2/3 | 23 min | 12 min | **Recent Trend:** - Last 5 plans: 01-01 (16 min), 01-02 (7 min) - Trend: improving *Updated after each plan completion* | Phase 02-authentication-multi-tenancy P02 | 8min | 3 tasks | 26 files | | Phase 02-authentication-multi-tenancy P03 | 5min | 2 tasks | 20 files | | Phase 05-dashboard-calendar P01 | 14min | 4 tasks | 28 files | | Phase 05-dashboard-calendar P02 | 4min | 4 tasks | 16 files | | Phase 05-dashboard-calendar P03 | 11min | 4 tasks | 14 files | | Phase 05-dashboard-calendar PP04 | 5min | 2 tasks | 11 files | | Phase 06-desktop-client-ci-cd P01 | 5min | 2 tasks | 13 files | | Phase 06 P03 | 3min | 3 tasks | 3 files | | Phase 07-dkv-fleet-module P03 | 5min | 4 tasks | 8 files | | Phase 07-dkv-fleet-module P04 | 7min | 3 tasks | 8 files | | Phase 07-dkv-fleet-module P05 | 8min | 3 tasks | 11 files | | Phase 07-dkv-fleet-module P06 | 5min | 2 tasks | 7 files | | Phase 09 P03 | 17 | 3 tasks | 6 files | | Phase 09-cert-manager-module P04 | 4 | 3 tasks | 5 files | | Phase 09-cert-manager-module P05 | 8 | 3 tasks | 6 files | | Phase 09 P06 | 7 | 3 tasks | 7 files | ## Accumulated Context ### Decisions Decisions are logged in PROJECT.md Key Decisions table. Recent decisions affecting current work: - [Roadmap]: 6 phases derived from 44 v1 requirements, standard granularity - [Roadmap]: Research recommends NestJS + Next.js + PostgreSQL RLS + Keycloak + Tauri stack - [01-01]: Used Traefik v2.11 instead of v3.4 due to Docker API version incompatibility on host - [01-01]: Traefik placed on frontend-net + backend-net for routing to both web and api services - [01-01]: API Dockerfile copies full monorepo node_modules structure for pnpm workspace compatibility - [01-02]: OKLCH color space for all design tokens (Tailwind v4 native, perceptually uniform) - [01-02]: Dark mode uses oklch(0.17 0.01 260) dark gray-blue for comfortable contrast with yellow primary - [01-02]: Cookie-based locale (NEXT_LOCALE) instead of URL routing for portal app - [01-02]: CSS custom property --current-sidebar-width for responsive main content margin - [Phase ?]: Route groups (auth)/(portal) for layout separation: auth pages standalone, portal pages wrapped in AppShell - [Phase ?]: Controller-level tenant isolation for ADMIN role as defense-in-depth alongside RLS - [Phase ?]: Remember-me controls cookie maxAge (30d session vs browser-session) not separate token type - [Phase ?]: react-grid-layout v2 uses dragConfig/resizeConfig instead of isDraggable/isResizable - [05-02]: SearchProvider defaults as constants merged with user DB rows (no seed migration) - [05-02]: useRef with explicit undefined initial value for React 19 strict TypeScript - [05-03]: DAVClient class constructor instead of createDAVClient factory (tsdav v2 type compatibility) - [05-03]: Dynamic imports for ews-javascript-api and @microsoft/microsoft-graph-client (lazy-load) - [05-03]: In-memory Map cache with 5-min TTL for calendar events (Redis not needed at current scale) - [05-03]: ews-javascript-api imported as any (no TypeScript definitions available) - [Phase ?]: Optimistic UI for calendar visibility toggle — reverts on API error - [Phase ?]: Auto-run testSource after adding new calendar source for immediate feedback - [Phase ?]: URL constructor for client-side https-only validation (T-05-14) - [Phase ?]: StoreExt trait import required for app.store() in Tauri 2.x - [Phase ?]: frontendDist=../src local page, navigate() for runtime URL override - [Phase ?]: CSP connect-src wildcard for configurable server URL (D-02) - [Phase ?]: Plain docker compose build statt build-push-action (Gitea JWT Pitfall 4) - [Phase ?]: Ephemeral runner mode (GITEA_RUNNER_EPHEMERAL=1) fuer Credential-Revokation pro Job - [Phase ?]: Separate docker-compose.ci.yml fuer opt-in CI-Infrastruktur - [07-01]: DKV PDF uses two extraction formats: single-tx (tab-separated) vs multi-tx (columnar) — both handled in DkvParserService - [07-01]: Research Pattern 4 regex replaced with empirical dual-format tab/columnar parser after testing against real invoice.pdf - [07-01]: CalendarCryptoService exported from CalendarModule for DKV credential encryption reuse - [07-02]: Max attachment size 25MB enforced in both ImapProvider and ExchangeInboxProvider before buffering (T-07-05) - [07-02]: ExchangeInboxProvider uses WellKnownFolderName.Inbox + FindItems (not FindAppointments — email vs calendar EWS API) - [07-02]: export type {} required for type-only re-exports under isolatedModules TypeScript setting - [07-03]: SettingsService.getStartupSmtpConfig uses findFirst (tenant-agnostic) for MailModule startup transport - [07-03]: MailModule forRootAsync factory priority: DB SmtpConfig → MAIL_* env → TESSERA_SMTP_* env → localhost:1025 fallback - [07-03]: DkvMailService injects SettingsService (not PrismaService directly) to reuse decryption logic - [07-03]: user-files/ path resolved via path.resolve(__dirname, 4 levels up) from apps/api/dist/dkv/ to monorepo root - [07-03]: Export prune sorted by mtime ascending (oldest first), delete all beyond last 10 - [07-04]: DkvScheduler v1 uses findFirst() — single-tenant; multi-tenant scheduling deferred - [07-04]: Circular dep DkvService<->DkvScheduler avoided via controller coordination after PUT config - [07-04]: CronJob resolved via require() workaround (pnpm strict isolation: transitive dep) - [07-04]: rechnungsnummer from email subject regex /d{2}-d{9}-d{3}/; fallback=email-{uid} - [07-05]: refreshKey lift: parent increments on checkNow success; InvoiceHistoryTable reruns useEffect - [07-05]: onItemsLoaded callback: InvoiceHistoryTable notifies parent; parent passes items to ExportFileList (avoids second fetch) - [07-05]: Password blank on load: configToForm() always sets password=''; hasPassword boolean drives UX hint only - [07-05]: CsvImportButton replace: two-step inline confirm (not full modal); accept=".csv" client-side guard - [Phase ?]: T-09-01/T-09-02 - [Phase ?]: 09-03 - [Phase ?]: 09-03 - [Phase ?]: 09-03 - [Phase ?]: splitCerts PEM path reuses parsePemChain; P7B sniffs first bytes - [Phase ?]: splitCerts format crt comparison removed — detectFormat returns pem|der|pfx|p7b only ### Pending Todos None yet. ### Blockers/Concerns None yet. ### Quick Tasks Completed | # | Description | Date | Commit | Directory | |---|-------------|------|--------|-----------| | 260630-gbh | User Settings: Passwort ändern (nur non-LDAP) + Profilbild setzen | 2026-06-30 | merge | [260630-gbh-user-settings-passwort-ndern-nur-non-lda](.planning/quick/260630-gbh-user-settings-passwort-ndern-nur-non-lda/) | | 260701-abc | Fix i18n: marketplace.accessDenied + calendar form hardcoded EN strings | 2026-07-01 | e5b76b7 | [260701-abc-i18n-missing-keys](.planning/quick/260701-abc-i18n-missing-keys/) | | 260707-csw | LDAP AD Anbindung: Zugangsdaten aus XWiki vorbefuellen und Import-Filter fuer Benutzer/Gruppen | 2026-07-07 | a5c500d | [260707-csw-ldap-ad-anbindung-zugangsdaten-aus-xwiki](.planning/quick/260707-csw-ldap-ad-anbindung-zugangsdaten-aus-xwiki/) | | 260707-lgh | Favoriten-Widget: Icon-Proxy fuer Cross-Origin-Resource-Policy-Seiten (claude.ai) | 2026-07-07 | f06a2ff | [260707-lgh-favoriten-widget-icon-proxy-fuer-cross-o](.planning/quick/260707-lgh-favoriten-widget-icon-proxy-fuer-cross-o/) | | 260708-cuc | Fix: FavoriteLink-Tabelle fehlt in Prod-DB, nie als Migration committed (500 auf GET /favorites) | 2026-07-08 | afef9b2 | [260708-cuc-fix-favoritelink-tabelle-fehlt-in-prod-d](.planning/quick/260708-cuc-fix-favoritelink-tabelle-fehlt-in-prod-d/) | ## Deferred Items Items acknowledged and carried forward from previous milestone close: | Category | Item | Status | Deferred At | |----------|------|--------|-------------| | *(none)* | | | | ## Session Continuity Last session: 2026-07-08T07:22:00.000Z Stopped at: context exhaustion at 77% (2026-07-02) Resume file: .planning/phases/08-dashboard-widgets-vollimplementierung/08-CONTEXT.md Last activity: 2026-07-08 - Completed quick task 260708-cuc: Fix FavoriteLink-Tabelle fehlt in Prod-DB; deployed and verified live on alpha.tessera.ctl.de