Files
Mieterportal/kimi.md
T
ah-admin 5503ce5fc5 v1.2: E-Mail-Benachrichtigungen an Portal angeschlossen
- nginx-Proxy POST /api/mail/send -> mp-mail-api:8080 (nur POST, 64k Limit)
- Token serverseitig via envsubst-Template + portal.env (gitignored, nur Server)
- src/lib/mail.ts: fire-and-forget Versand, Empfaenger-Aufloesung (Verwaltung/Mieter)
- Benachrichtigung: neue Schadensmeldung -> Verwaltung, Nachrichten/Antworten -> Gegenstelle
- E2E live verifiziert (versandt: true an axel@hocks.eu), GET 403
- Doku (kimi.md, README) nachgefuehrt
2026-10-02 12:21:12 +02:00

13 KiB
Raw Blame History

Kimi-Kontext: Hinterstein Immobilien · Mieterportal (mieterportal.hocks.eu)

Projekt-Kontextdatei für Kimi Work. Stand: 02.10.2026, 14:30 Uhr. Bitte bei größeren Änderungen am Projekt aktualisieren. Konventionen und Workflow sind am Projekt Schulportal (sfg.hocks.eu) orientiert.

1. Projektüberblick

Mieterportal der Hinterstein Immobilien (Demo, Inhaber Joseph Hinterstein) für 50 Wohnungen in 3 Häusern (Hauptstraße 12 · Ringweg 3 · Am Park 5). Analog zum Schulportal: alle Mietangelegenheiten digital an einem Ort.

Authentifizierung (echtes Login seit v1.1): Startseite /login mit Login-Pflicht (Route-Guard RequireAuth in App.tsx leitet unangemeldete Besucher auf /login um). Gruppen: verwaltung und mieter. Mieter können sich über einen Registrierungscode selbst registrieren (/registrieren); Codes legt die Verwaltung in der Benutzerverwaltung an (einmalig nutzbar, Wohnungsbezug). Passwörter als SHA-256-Hash in localStorage, Session 8 h (Key mp_benutzer_session). Demo-Zugänge (Passwort 0815): j.hinterstein (Verwaltung, Joseph Hinterstein), a.berger (Mieterin, Hauptstraße 12 Whg. 7), m.wolf (Mieter). Demo-Registrierungscode: MP-2026-0815.

Die 6 Module:

  1. Dashboard (/) – Mieter: Begrüßung, nächste Zahlung, Mietdiagramm, Ankündigungen, offene Meldungen. Verwaltung: Kennzahlen (Vermietungsquote, Miet-Soll, Rückstände), Einnahmenverlauf + Belegung pro Haus (Recharts).
  2. Mietkonto & Zahlungen (/mietkonto) – Buchungsverlauf 2026 mit Statusfilter, Nebenkostenguthaben, Zahlungsdaten. Verwaltung: Zahlungsstatus aller Wohnungen, Rückstandsliste, Haus-Filter.
  3. Schadensmeldungen (/schadensmeldungen) – Tickets mit Kategorie, Dringlichkeit, Status; Neuanlage per Dialog; Verwaltung pflegt Status per Select.
  4. Dokumente (/dokumente) – Verträge/Abrechnungen/Hausordnung/Protokolle, Suche + Kategorie-Chips. Mieter sieht eigene + Hausdokumente (unitId=null).
  5. Nachrichten (/nachrichten) – Chat Mieter ↔ Verwaltung, Ungelesen-Markierung, neue Unterhaltungen.
  6. Benutzerverwaltung (/benutzer, nur Gruppe verwaltung) – Nutzerliste mit Gruppen und Wohnungsbezug, Registrierungscodes erzeugen/deaktivieren, Demo-Zugänge zurücksetzen.

2. Technischer Stack

Teil Technologie
Frontend React 18 + TypeScript, Vite 7, Tailwind v3.4 + shadcn/ui (Radix), React Router 7 (BrowserRouter), Recharts
State React Context + useReducer, Persistenz in localStorage (hinterstein-mieterportal-v2)
Daten src/data/seed.ts (handschriftlich) + src/data/generated.json (maschinell via beispieldaten.py)
Auth src/lib/auth.ts (SHA-256, Session 8 h, Keys mp_benutzer/mp_benutzer_session), Route-Guard in App.tsx
Branding Kunde: src/assets/hinterstein/ (logo.png, joseph-hinterstein.jpg, kontakt.jpg); KI-generiert: src/assets/logo.png, hero.jpg, modules.jpg
Webserver (Ziel) Docker-Container mp-portal (nginx), statisches dist/, gemountet /opt/mieterportal/dist
Mail mail-server/: Postfix-Relay (mp-mail) + Python-API (mp-mail-api) – live, /opt/mp-mail auf dem Server; verkabelt: Portal-nginx proxyt POST /api/mail/send → mp-mail-api:8080 und injiziert das Token aus portal.env (serverseitig, nie im Browser/Repo)
Server Root-VPS hocks.eu (IONOS), Docker + Portainer, Subdomain via NPM (Nginx Proxy Manager, Let's Encrypt)

3. Wichtige Dateien

Projektverzeichnis: C:\Users\ah\Documents\Kimi\Workspaces\Mieterportal Git: https://git.hocks.eu/ah-admin/Mieterportal (Branch main). Secrets ausgesperrt via .gitignore (mail-server/mail.env etc.).

Datei Inhalt
src/store/store.tsx Store-Provider, Reducer, Actions (setRole/addTicket/setTicketStatus/addMessage/newThread/markThreadRead), fmtEUR
src/data/seed.ts Tickets, Dokumente, Nachrichten-Threads, Ankündigungen + Re-Export units/transactions aus generated.json
src/data/generated.json 50 Wohnungen + 552 Buchungen, erzeugt von beispieldaten.py (Seed 20261002)
beispieldaten.py Deterministischer Generator: python beispieldaten.py [seed]
src/types/index.ts Alle Typen (Unit, Transaction, Ticket, DocumentItem, Thread, Announcement)
src/components/AppLayout.tsx Sidebar (Desktop) + Mobile Top-Bar/Nav, Rollenwechsel, Ungelesen-Badge, ThemeToggle
src/components/ThemeToggle.tsx Dark-Mode-Umschalter (Sonne/Mond)
src/lib/theme.ts mp-theme in localStorage, Init vor erstem Render (main.tsx)
src/pages/Login.tsx Login-Pflicht: Hero mit Joseph-Hinterstein-Portrait, Logo, Feature-Liste, Login-Formular + Registrierung-Link + Demo-Einstiege
src/lib/mail.ts E-Mail-Benachrichtigungen: sendeBenachrichtigung (fire-and-forget) an /api/mail/send, Empfänger-Auflösung (Verwaltung / Mieter je Wohnung)
docker/templates/default.conf.template nginx-Site als envsubst-Template; proxiet POST /api/mail/send → mp-mail-api:8080 mit ${MAIL_API_TOKEN} aus portal.env
src/pages/Benutzer.tsx Benutzerverwaltung (nur Verwaltung): Nutzer, Gruppen, Registrierungscodes
Dockerfile Optionaler All-in-One-Build (node build → nginx) für docker build-Workflow
docker/nginx.conf nginx-Site: SPA-Fallback, Gzip, Cache-Header für /assets/, Security-Header
docker-compose.yml mp-portal (nginx + gemountetes dist) im externen Netz npm_default; Mail-Stack separat
deploy.sh Bewährter Deploy-Workflow (s. Kap. 4)
mail-server/ Postfix-Relay + schlanke Mail-API (Muster Schulportal, angepasst)

4. Deploy-Workflow (bewährt, aus Schulportal übernommen)

# 1. Bauen (im Projektverzeichnis)
npm run build

# 2. Paketieren + Hochladen (pscp braucht cwd = Projektverzeichnis)
tar -czf mp-dist.tar.gz -C dist .
"/c/Program Files/PuTTY/pscp.exe" -batch \
  -hostkey "SHA256:4G3UxsugNkHH6BrPXScLXh+vX8P1sLgWKn8cZBKSRxw" \
  -i "Z:\Devel\ssh\priv_ionos_hocks_vps.ppk" -P 38592 \
  mp-dist.tar.gz root@hocks.eu:/tmp/

# 3. Entpacken + Container neu starten + Hash prüfen
"/c/Program Files/PuTTY/plink.exe" -batch -hostkey "SHA256:4G3UxsugNkHH6BrPXScLXh+vX8P1sLgWKn8cZBKSRxw" \
  -i "Z:\Devel\ssh\priv_ionos_hocks_vps.ppk" -P 38592 root@hocks.eu \
  "rm -rf /opt/mieterportal/dist && mkdir -p /opt/mieterportal/dist && \
   tar -xzf /tmp/mp-dist.tar.gz -C /opt/mieterportal/dist && \
   cd /opt/mieterportal && docker compose up -d && sleep 2 && \
   curl -s https://mieterportal.hocks.eu/ | grep -o 'index-[^\"]*\.js'"

# Alternativ alles in einem Schritt:
./deploy.sh
  • SSH: Port 38592, Key Z:\Devel\ssh\priv_ionos_hocks_vps.ppk (Pageant), Hostkey-Flag zwingend.
  • portal.env auf dem Server wird vom compose als env_file gebraucht (liefert MAIL_API_TOKEN für den nginx-envsubst). Einmalig angelegt: grep '^MAIL_API_TOKEN=' /opt/mp-mail/mail.env > /opt/mieterportal/portal.env Liegt nur auf dem Server (gitignored), wird von deploy.sh nicht hochgeladen.
  • Vorsicht Fail2Ban: zu viele gescheiterte SSH-Versuche von einer IP führen zu einem Ban (Timeout-Verbindungsbild). Ban aufheben auf dem Server: fail2ban-client unban --all.
  • Live (seit 02.10.2026): Container mp-portal läuft auf hocks.eu, statisches dist/ unter /opt/mieterportal/dist (gemountet). NPM-Proxy-Host id 7 (Datei /data/compose/1/data/nginx/proxy_host/7.conf, DB-Tabelle proxy_host), Zertifikat npm-9 (Let's Encrypt, läuft bis 31.12.2026; via certbot/webroot erstellt, liegt im npm-Container unter /etc/letsencrypt/live/npm-9/). HTTP→HTTPS-Redirect aktiv (HSTS, Block-Exploits, HTTP/2). Änderungen am Proxy-Host im NPM-UI werden die DB-Konfiguration konsistent halten; manuelle Conf-Edits werden beim nächsten UI-Speichern überschrieben.
  • HTML wird mit no-cache geliefert (nginx-Config), Assets hash-benannt → Reload genügt. Der eingebettete Kimi-Browser cached hart → beim Testen Cache-Buster anhängen: ?v=X.

5. Zugänge & Konfiguration

  • Demo-Zugänge (Passwort 0815): j.hinterstein (Verwaltung), a.berger (Mieterin, Hauptstraße 12 Whg. 7), m.wolf (Mieter). Demo-Registrierungscode: MP-2026-0815. Passwörter werden als SHA-256-Hash gespeichert; Store-Reset über Browser-DevTools (localStorage-Keys mp_benutzer, mp_benutzer_session, hinterstein-mieterportal-v2 löschen).
  • Mail-API-Token: bewusst nicht hier dokumentiert – liegt auf dem Server in /opt/mp-mail/mail.env (Vorlage mail.env.example im Repo).
  • Mail-Stack live (seit 02.10.2026): Container mp-mail + mp-mail-api laufen auf hocks.eu unter /opt/mp-mail (Relay über hocks-eu.mail.protection.outlook.com). Testmail und API-/send (mit X-Api-Token) verifiziert (status=sent); ohne Token 401.
  • Mail-Benachrichtigungen im Portal (seit 02.10., v1.2): Der Portal-nginx (docker/templates/default.conf.template, envsubst) proxiet ausschließlich POST /api/mail/send an http://mp-mail-api:8080/send und setzt das Token aus /opt/mieterportal/portal.env (chmod 600, nicht im Repo, gitignored). Das Frontend (src/lib/mail.ts) sendet fire-and-forget: neue Schadensmeldung → alle aktiven Verwaltungsbenutzer, neue Nachricht/Antwort → Gegenstelle (Mieter ↔ Verwaltung, Empfänger über Wohnungsbezug). E2E verifiziert: POST über https://mieterportal.hocks.eu/api/mail/send → versandt: true (Test an axel@hocks.eu); GET wird mit 403 blockiert. Demo-Empfängeradressen (z. B. joseph@hinterstein-immo.de) sind fiktiv → dort kein Empfang möglich, echte Adressen in der Benutzerverwaltung pflegen.

6. Konventionen & Besonderheiten

  • Dark Mode: class-Strategie, Präferenz mp-theme, Init vor erstem Render. Feste Farbklassen werden in index.css für .dark umrechnen (.dark .bg-white/.bg-slate-50/.bg-teal-50); Sidebar ist eigenes Dunkel-Teal.
  • Barrierefreiheit: aria-pressed/labels am ThemeToggle und Rollenwechsel, Fokus-Ringe.
  • Formatierung: Beträge via fmtEUR (Intl de-DE), Datumsformate TT.MM.JJJJ.
  • Datenpflege: Bestandsdaten ändern → beispieldaten.py anpassen und neu ausführen, nicht generated.json von Hand editieren.
  • Sicherheit: kein offenes Relay (Postfix mynetworks loopback + Docker-Netz, sender_canonical zentral). Upload/Download-Funktionen sind Demo-Darstellungen.
  • Keine destruktiven Aktionen auf dem Server ohne ausdrückliche Bestätigung.

7. Testing

  • npm run build (tsc -b) ist die echte Typprüfung; npx tsc --noEmit prüft wegen Solution-tsconfig ggf. nichts.
  • Headless-Screenshots (Dark Mode = Systempräferenz): "/c/Program Files/Google/Chrome/Application/chrome.exe" --headless --disable-gpu --screenshot=... --window-size=WxH "URL"
  • Screenshots ausgeliefert nach preview/.

8. Verlauf / offene Punkte

Erledigt 02.10. (v1.0): Portal komplett neu aufgesetzt (5 Module, Mieter-/Verwaltungsansicht, KI-Branding: Logo/Hero/Illustration), Docker-Setup (Dockerfile, nginx, compose), Repo in git.hocks.eu angelegt, Deploy-Workflow + Dark Mode + beispieldaten.py aus dem Schulportal übernommen, mail-server-Struktur angelegt (noch nicht live verkabelt).

Erledigt 02.10. (v1.0 live): Deployment auf hocks.eu durchgeführt: Container mp-portal läuft (/opt/mieterportal, compose + gemountetes dist), NPM-Proxy-Host id 7 + LE-Zertifikat npm-9 eingerichtet (per certbot/webroot, DB-Insert, 7.conf aus 5.conf abgeleitet, nginx reload). Live geprüft: https://mieterportal.hocks.eu/ → HTTP 200, Titel korrekt, SPA-Routing (/mietkonto) 200, HTTP→HTTPS-Redirect 301, Zertifikat CN=mieterportal.hocks.eu gültig bis 31.12.2026. Zertifikatsdateien liegen im npm-Container unter /etc/letsencrypt/live/npm-9/ (Backup der Zertifikate auf dem Host: /root/le-mp/). Fail2Ban-Ban nach frühen Fehlversuchen ist nach ~40 min automatisch ausgelaufen.

Erledigt 02.10. (v1.1 live): Rebrand auf „Hinterstein Immobilien" (Kunden-Logo, Joseph-Hinterstein-Portrait auf der Login-Seite, Kontakt-Banner), echtes Authentifizierungssystem (Login-Pflicht, Gruppen Verwaltung/Mieter, SHA-256, Session 8 h), Mieter-Registrierung per einmaligem Code, Benutzerverwaltung als 6. Modul (/benutzer), Demo-Zugänge mit Passwort 0815. Mail-Stack auf dem Server aktiviert (/opt/mp-mail, Testmail + API-/send verifiziert). Store-Key auf hinterstein-mieterportal-v2 gehoben. Live deployed und geprüft (HTTP 200, Titel „Hinterstein Immobilien · Mieterportal").

Erledigt 02.10. (v1.2 live): E-Mail-Benachrichtigungen an das Portal angeschlossen: nginx-Proxy /api/mail/send mit serverseitig injiziertem Token (envsubst-Template + portal.env auf dem Server), src/lib/mail.ts sendet bei neuen Schadensmeldungen (→ Verwaltung) und Nachrichten/Antworten (→ Gegenstelle). E2E-Versand live verifiziert (versandt: true), GET auf den Endpunkt 403.

Offen:

  • Zertifikatserneuerung prüfen (per 01.12.2026): NPM-Renewer sollte cert 9 über HTTP-Challenge erneuern; sonst certbot/webroot + Kopie nach npm-9 wiederholen.
  • Demo-Empfängeradressen durch echte ersetzen, sobald bekannt.
  • Mögliche nächste Schritte: serverseitige Datenbank (PostgreSQL/Node-API) statt localStorage, Mehrseitigkeit für 50 echte Mietverhältnisse.

9. Sonstiges

  • User kommuniziert auf Deutsch; alle UI-Texte und Antworten auf Deutsch.
  • Dateien außerhalb des Workspaces immer erst in den Workspace kopieren.
  • Vorsicht mit destruktiven Aktionen (Explizite Bestätigung einholen).