L10b Betrieb & Aufräumen: Deploy – craftvia-worker, CI-Testjob, DEPLOY.md, Certvia-Doku archiviert

- docker-compose.coolify(.prebuilt).yml: Service craftvia-worker (Target worker, Chromium,
  shm_size 1gb, gleiche Härtung), Craftvia-Variablen für app und worker.
- Dockerfile: worker-Stage mit HOME=/home/app (Chromium-Profil für non-root); lokaler
  docker build der Targets runner und worker erfolgreich, PDF-Erzeugung im Image geprüft.
- .env.example/.env.prod.example/.env.coolify.example: alle Craftvia-Variablen inkl. RLS,
  KI-Provider, PDF_CHROMIUM_PATH, OFFLINE_MAX_DAYS, API_RATE_LIMIT_*, AI_GENERATION_RETENTION_DAYS,
  AI_MONTHLY_TOKEN_LIMIT.
- CI (.github, .gitea): Job gate mit Postgres (pgvector) und Redis als Service: migrate deploy,
  seed, Passwort für craftvia_app, tsc, lint, build, npm run test.
- docs/craftvia/DEPLOY.md (aus den Certvia-Deploy-Docs abgeleitet): Architektur, Domains, Secrets,
  Worker, Migrationen, RLS-Aktivierung, Backup/Restore, KI, Rate Limits, Aufbewahrung, Smoke,
  Update/Rollback. build-and-push-images.sh baut craftvia-worker.
- Certvia-/ISMS-Dokumente aus docs/ nach docs/_certvia-archiv/ (mit README); Verweise in README.md
  und Skript-Kommentaren angepasst.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-14 18:19:19 +02:00
co-authored by Claude Opus 5
parent 21d6dc016a
commit cadaedc6cc
38 changed files with 902 additions and 76 deletions
+50
View File
@@ -0,0 +1,50 @@
# Konzept — Betreiber-Konsole-UX + vollständige i18n (parallele Lane)
> Status: **Backlog/Feindesign-Skizze** (kein Code). Produkt: **certvia** (ISMS-Tool). Unabhängig von Identity/Backup/Härtung → **parallel** abarbeitbar. Enthält die zwei gemeldeten „Bugfixes" + zwei kleine Ergänzungen.
## Bugfix 1 — Betreiber-Konsole: Module & Benutzer als Popup, Stammdaten sichtbar
**Betrifft:** `src/app/(platform)/admin/[id]/page.tsx` (Mandanten-Detailseite im Betreiber-Portal).
**Ist:** Module-Liste und Benutzerverwaltung liegen **inline direkt auf dem Kundenprofil**; die eigentlichen Stammdaten des Kunden sind dort **nicht** prominent.
**Soll:**
- **Module → Popup:** nicht mehr inline, sondern per Button „Module verwalten" → Popup (Muster wie gehabt über searchParam, z. B. `?modules=1`, `<Modal>`). Toggle/Import bleiben im Popup.
- **Benutzer → Popup:** die Benutzer-Tabelle/-Verwaltung nicht mehr im Hauptfenster, sondern Button „Benutzer verwalten" → Popup (`?users=1`). Anlage/Bearbeiten laufen wie bisher als verschachtelte Modals (`?new`/`?edit`).
- **Hauptfenster stattdessen:** **Stammdaten** (aus `TenantSettings`: Unternehmensname/Kurzname, Adresse, Sektor, D-U-N-S, TISAX-Level, Status) **+ Hauptkontakt** prominent sichtbar. „Hauptkontakt" = neues/abgeleitetes Feld (z. B. designierter Mandanten-Admin oder ein Stammdaten-Kontaktfeld) — **offene Kleinentscheidung:** eigenes Feld in `TenantSettings` (`mainContactName/Email/Phone`) vs. Ableitung aus dem `tenant-admin`.
**Muster ist vorhanden:** die Seite nutzt bereits `<Modal>` + searchParams (`?new`/`?edit`/`?audit`) → Module/Benutzer analog kapseln, keine neue Infrastruktur.
**Dateien:** `src/app/(platform)/admin/[id]/page.tsx`, ggf. `src/components/*` (Auslagerung Module-/Benutzer-Block), optional Migration für `mainContact*` in `TenantSettings`.
## Bugfix 2 — Vollständige UI-Sprache (Menü + Beschreibungen) + per-Mitarbeiter-Umschaltung
**Wichtiger Befund:** Der **englische UI-Katalog existiert bereits** (`messages/en.json`, ~95 % vs. `messages/de.json`). Bisher ist **nur der Richtlinien-Inhalt** EN (über `TenantSettings.locale`, das die **Import-Sprache der Vorlagen** steuert). Das **Menü/die Beschreibungen** sind EN im Katalog vorhanden, werden aber **nie angezeigt**, weil:
```
src/i18n/request.ts:8 → const locale = "de"; // hart verdrahtet
// Kommentar: "MVP is fixed to de; per-user locale (en) is prepared — switch here later"
```
**Soll:** die UI-Sprache **per Mitarbeiter individuell** umschaltbar.
- **Speicherort (Option-C-konform):** persönliche Präferenz gehört an die **`Identity`** (folgt der Person über alle Mandanten) — neues Feld `Identity.uiLocale` (`de`|`en`, Default `de`). *(Alternative: pro Mitgliedschaft — verworfen, weil Menüsprache eine Personen-, keine Mandantenpräferenz ist.)*
- **Aktivierung:** `src/i18n/request.ts` liest statt der Konstante die `uiLocale` der aktiven Session-Identity (Fallback `de`).
- **Umschalter:** im **Nutzer-Menü** (Header/Profil) ein Sprachauswahl-Control → Server-Action `setUiLocale` → `Identity.uiLocale` speichern, Seite neu laden.
- **Restsprache:** `messages/en.json` auf 100 % prüfen/auffüllen (Lücken, neue Strings aus TISAX/Identity-Umbau). Sicherstellen, dass **alle** sichtbaren Strings über den Katalog laufen (keine hartkodierten deutschen Texte in Komponenten).
**Abgrenzung:** `TenantSettings.locale` bleibt für die **Vorlagen-Import-Sprache** (Inhalt); **neu** ist die **UI-Sprache je Person** (`Identity.uiLocale`) — zwei getrennte Achsen.
**Dateien:** `prisma/schema.prisma` (`Identity.uiLocale` + Migration), `src/i18n/request.ts`, Nutzer-Menü-Komponente (Header/Profil) + `setUiLocale`-Action, `messages/en.json` (Lückenschluss), Audit der hartkodierten Strings.
## Ergänzung A — Login-Maske: Organisationsfeld entfällt
**Ist:** `src/app/login/page.tsx` zeigt weiterhin ein optionales Feld **„Organisation"** (`tenant`, als Hinweis behalten).
**Soll:** Feld **entfernen** — nach Option C ist es überflüssig (Login gegen globale Identity; Mandant wird **nach** dem Login über `/select-tenant` gewählt). Die `tenant`-Durchreichung in `login`-Action / `signMfaPending` / `signLoginTicket` kann entfallen bzw. leer bleiben.
**Dateien:** `src/app/login/page.tsx` (Feld raus), ggf. `src/server/login-ticket.ts`-Signaturen entschlacken.
## Ergänzung B — Konsistenz-Check „Stammdaten"
Beim Sichtbarmachen der Stammdaten (Bugfix 1) prüfen, dass die Quelle **eine** bleibt (`TenantSettings` speist die ISMS-Variablen) — keine Doppelpflege einführen.
## Reihenfolge / Parallelität
- **Bugfix 1** (Betreiber-Konsole) und **Bugfix 2** (i18n) sind unabhängig → parallel.
- **Ergänzung A** (Login) ist ein 10-Minuten-Fix, gern zusammen mit Bugfix 2 (beide Auth-/UI-nah).
- Keine Abhängigkeit zu Backup/Härtung; Bezug zu Option C nur konzeptuell (`Identity.uiLocale`, `/select-tenant` existiert bereits).
## Gate (wie immer)
tsc/lint/build + `scripts/test-*.ts` grün; UI-Änderungen im Browser verifizieren (Betreiber-Popups, Sprachumschaltung DE↔EN, Login ohne Organisationsfeld).