Zum Inhalt

SNLO – Spittank.net Ladeorganisation – Implementierungsumfang 0.5.12

Produktidentität

  • Produktname: SNLO – Spittank.net Ladeorganisation
  • Kurzname in App und PWA: SNLO
  • Claim in App und Logo: Laden organisiert.
  • technischer Python-Paketname, Compose-Projektname, Cookies und Exportpräfix: snlo

Komponenten

API/PWA

  • FastAPI
  • SQLAlchemy 2
  • lokale Cookie-Sitzungen und Argon2id
  • OpenID Connect Authorization Code mit PKCE S256
  • OIDC-Rollen aus Nutzer- und Administratorgruppen; Administratorgruppe hat Vorrang
  • automatische OIDC-Nutzeranlage oder Verknüpfung vorhandener Konten über verifizierte E-Mail
  • CSRF- und Origin-Prüfung
  • statische Vanilla-JavaScript-PWA mit getrennten Browser-/PWA-Sitzungslaufzeiten
  • rollenabhängige Oberfläche
  • datensparsame Liveanzeige fremder Sitzungen

Datenbank

  • PostgreSQL im Compose-Stack
  • SQLite für Tests und Migrationsprüfung
  • Alembic-Revisionen:
  • f720b52d7094: 0.1-Basisschema
  • a9d4b6f278c1: benannte Tarife, Familienzuordnung, Zahler und KEBA-RFID
  • c4f8e2a1b7d9: OIDC-Identitäten, Authentifizierungsmethode und einmalige Login-States
  • unveränderte EVCC-Messwerte plus getrennte Kostenkomponenten
  • historische Tarifsnapshots und Tarifreferenz je Sitzung
  • Audit-Ereignisse

Collector

  • dynamische EVCC-Instanzliste aus der Datenbank
  • EVCC-Normalisierung für unterschiedliche State-/Session-Formen
  • EVCC-Fahrzeugabgleich über internen Namen und sichtbaren Titel
  • positiver Batteriefluss als Entladung
  • keine Extrapolation über Messlücken
  • proportionale Verteilung bei mehreren gleichzeitig ladenden Ladepunkten
  • Import und Abgleich historischer Sitzungen
  • automatische Zuordnung zum zeitlich gültigen Zahler

Dokumentation und Veröffentlichung

  • Zensical 0.0.53 mit Markdown-Quellen unter docs/
  • deutschsprachige Navigation und SNLO-Wortmarke über zensical.toml
  • feste kanonische Repository-Pages-URL https://daniel.snii.de/snlo/ in zensical.toml
  • Forgejo-Workflow für Tests, Migrationen, Dokumentationsbuild und git-pages
  • separater Tag-Workflow für ein gemeinsames Multi-Arch-OCI-Image
  • migrate, api und worker verwenden dasselbe Image; nur Befehl und Lebenszyklus unterscheiden sich

KEBA-Adapter

  • Home-Assistant-kompatible start <UID> 01010400000000000000-Autorisierung mit report 2-Verifikation
  • optionale Displaytexte Hallo <Benutzername> und Auf Wiedersehen (best effort)

  • optionaler P30_UDP-Connector je EVCC-Ladepunkt

  • verschlüsselte RFID-UIDs je Nutzer; 8-stellige KEBA-UIDs werden unverändert zusammen mit dem internen Standard-RFID-Class-Wert gesendet
  • Live-Lockstatus wie Home Assistant aus report 2/Authreq; UI-Polling alle fünf Sekunden, Pending-Autorisierung nur als Besitzer-/RFID-Hinweis
  • report 1 für Verbindungstest
  • start <tag> 01010400000000000000 für Freigabe; ein vorhandener Legacy-Klassifikator wird aus Kompatibilitätsgründen weiterhin unterstützt
  • stop <tag> für Beenden
  • kurzfristige ausstehende Autorisierung zur sicheren Nutzerzuordnung beim anschließenden EVCC-Ladebeginn

OIDC-Sicherheit

  • serverseitig gespeicherter, nur als SHA-256 abgelegter und einmal verwendbarer state
  • Nonce-Prüfung des ID-Tokens
  • PKCE-S256-Code-Verifier
  • Discovery- und JWKS-Abruf mit TLS-Prüfung und kurzen Caches
  • Signaturprüfung ausschließlich mit konfigurierten asymmetrischen Algorithmen; none ist verboten
  • Prüfung von Issuer, Audience, Ablauf, iat, Subject und gegebenenfalls azp
  • UserInfo wird nur mit identischem Subject übernommen
  • sichere Begrenzung interner Rücksprungpfade gegen Open Redirects
  • Anwendungssitzung endet spätestens mit dem Ablauf des ID-Tokens
  • Client-Secret ausschließlich als Umgebungsvariable; keine Ausgabe über API oder UI

Fachregeln

Fahrzeugmitgliedschaft und Zahler

Ein Fahrzeug -> 1..n Nutzerzuweisungen je Zeitraum
             -> höchstens eine überlappende Zahlerzuweisung

Eine einzelne alte 0.1-Zuweisung ohne expliziten Zahler bleibt als Kompatibilitätsfallback abrechenbar. Die Migration markiert bestehende Zuordnungen ausdrücklich als zahlend.

Automatische Zuordnungspriorität:

  1. KEBA-App-Freigabe
  2. expliziter Fahrzeugzahler zum Sitzungsbeginn
  3. einzelnes Familienmitglied als Legacy-Fallback
  4. unzugeordnet

ADMIN_CORRECTION wird durch automatische Abgleiche nicht überschrieben.

Sichtbarkeit

Normaler Nutzer:

Breite Ansicht = billed_user_id == Nutzer
              ODER Fahrzeugmitgliedschaft zum Sitzungsbeginn

Nur zahlend = billed_user_id == Nutzer

Eine fremde aktive Sitzung ohne Fahrzeugmitgliedschaft liefert nur:

{"occupied": true, "redacted": true}

Tarifauflösung

Nutzer-Tarifzuordnung im Zeitraum
    > globale Tarifzuordnung im Zeitraum
    > erster aktiver Tarif als defensiver Fallback
    > Nulltarif

Tarifpläne enthalten Titel, Beschreibung, Revision und vier Komponenten. Nutzer und Zeiträume liegen ausschließlich in tariff_assignments.

Kosten

Solarenergie = Energie × EVCC-Solaranteil
Netzenergie = Energie - Solarenergie
Batteriebasis = min(Energie, live gemessene Batterieentladung)

Gesamt = EVCC-Kosten
       + Energie × Allgemeinsatz
       + Solarenergie × Solarsatz
       + Netzenergie × Netzsatz
       + Batteriebasis × Batteriesatz

INCLUDED erhöht die sichtbaren Stromkosten; ITEMIZED erscheint unter Aufschläge. Der Gesamtbetrag ist unabhängig von der Darstellung identisch.

Relevante API-Gruppen

  • /api/auth/config, /api/auth/login, /api/auth/oidc/login, /api/auth/oidc/callback
  • /api/dashboard, /api/live
  • /api/sessions/*
  • /api/control/loadpoints/*
  • /api/admin/instances/*
  • /api/admin/users/*
  • /api/admin/vehicles/*
  • /api/admin/vehicle-assignments/*
  • /api/admin/tariffs/*
  • /api/admin/tariff-assignments/*
  • /api/admin/keba-connections/*
  • /api/admin/rfid-credentials/*
  • /api/admin/audit
  • /healthz

Reservierungs- oder Claim-Endpunkte existieren nicht mehr. Die alte Tabelle bleibt ausschließlich als verlustarme Migrationsspur bestehen und wird nicht verwendet.

Bewusste Grenzen

  • keine zentrale RFID-Whitelist-Verwaltung der KEBA
  • kein E-Mail-Rechnungsversand und keine Zahlungsabwicklung
  • kein exakter physikalischer Nachweis, welcher Hausverbraucher Batterieenergie erhielt
  • keine nachträgliche Erfindung historischer Batterieentladung
  • kein standortübergreifendes Lastmanagement; dies bleibt Aufgabe der jeweiligen EVCC-Site
  • kein providerseitiger OIDC-Single-Logout; Abmelden beendet nur die SNLO-Sitzung
  • OIDC-Konfiguration erfolgt über Umgebung und erfordert einen Neustart der API