Silverscale – Stand 06.06.2026 (Tagesabschluss)
Einstieg für neue Sessions: Diese Datei zuerst, dann
app/ARCHITEKTUR.md(ADR-16–29 = alles von heute), dann CLAUDE.md. Vorgänger: REPORT-2026-06-05.md.
1. Was heute passiert ist (v1.7, Commits 10c65ce → e1c144d)
Infrastruktur — App ist öffentlich:
- https://silverscale.dennisfisch.de live: Traefik v3 (80/443, Let's Encrypt
per DNS-01/Cloudflare, Config traefik/), Pocket ID (Passkeys) auf
id.silverscale.dennisfisch.de. DNS via CF-API auf DNS-only umgestellt.
- Auth (ADR-16): Backend-OIDC (Code+PKCE, public client) in backend/auth.py,
180-Tage-HttpOnly-Cookie, sessions/oidc_identities (Dennis gemappt; Jaqueline
folgt beim Erstlogin). Host-Worker umgehen per X-Internal-Token (Repo-.env).
Notausstieg AUTH_DISABLED=1 (nur mit Traefik aus!). WG bleibt Netz-Fallback.
Stolperfalle behoben: Pocket-ID-Client war group-restricted ohne Gruppe +
confidential → per SQLite auf public/unrestricted gesetzt.
- Web Push (ADR-17): VAPID, push_subscriptions, minimaler sw.js (kein
Offline-Cache), Trigger: Test-Button, Bon-Import (Broadcast via Internal-Token),
ai_jobs-finish. iPhone-Test erfolgreich. PWA-Meta/PNG-Icons ergänzt.
Features:
- Kamera-EAN-Scan (ADR-18): ScanSheet + lib/scan.js — nativer
BarcodeDetector, iOS-Fallback zxing-wasm (self-hosted, eigener Chunk).
Einbau: Artikel, Artikel-Anlage, Bon („EAN fehlt 📷"), Essen-Loggen.
Scan-Ergebnis-Popup (ADR-24): OFF-Vorschau via /api/foods/off-preview,
Countdown-Auto-Akzeptieren, Verwerfen/Anpassen. EAN-Korrektur (amber
Affordance, barcode-POST replace:true).
- Einkaufsliste (ADR-19): persistent je Woche (shopping_items),
generate=Merge (done/manuell überleben), Gruppen-Sortierung, Vorrats-/Preis-
Hinweis, „Zuletzt verwendet"-Panel, 📋-Plan-Markierung, ✕ überall,
„Plan-Artikel raus". Route #/liste/{montag}.
- Nachkoch-Preisvergleich (ADR-20): HF-Boxpreis automatisch aus
data/hf-subscriptions.json (61,00 € + 5,99 € / 5×2 = 6,70 €/Portion);
Modi kg/pack/none; Staples (ADR-21) via shipped-Flag raus aus Liste+PVG
(Philly: 9,86 → 2,69 €/Portion, „spart 60 %").
- HF-Anbindung: feedback (favorite/rating/comment) + aggregateRating
importiert (ADR-26) → Gerichte-Seite: HF-Woche oben, Bewertungs-Chips,
HF-Filter-Toggle. Markdown-Zubereitungsschritte (marked, autogrow, ADR-26).
- Plan/Tagebuch: diary.plan_id (ADR-23, gegessen↔zurücknehmbar),
Artikel im Plan + dish_favorites + Picker-Sortierung HF→Fav→zuletzt→oft
(ADR-25), Gericht-Historie + „Für heute planen"/„👫 Gemeinsam" (Wir-Modus:
essen → beide Tagebücher, ADR-28).
- AI-Flow (ADR-27+29): Ursachen gefunden: minütlicher Cron (0–60 s Pickup)
+ cron ohne PATH (claude nicht gefunden = stille insights-Fehler).
Fix: PATH-Kopfzeile in Crontab, Worker als 55-s-Schleife/2-s-Takt,
adaptives Polling. estimate-Job (Freitext→kcal, 10,9 s end-to-end).
Fortschritts-Donut AiProgress.svelte mit ECHTEN Stages
(picked/model/gen via claude -p --output-format stream-json), lernender
Erwartung (Ø letzte 5 je kind), Overrun-Puls — ersetzt alle Hand-Poller.
- Kleinkram: Preis-Charts ohne Null-Linie (grace 15 %), Bon-Deeplink mit
Scroll+Puls, Dark-Tint-Fix (--ss-aqua-100/700 im Dark-Theme), Profil 2
heißt Jaqueline.
2. ✅ GELÖST: HF-Dauerbetrieb läuft (Nachtrag 06.06. vormittags)
Der localStorage-Ansatz war falsch (kein @@auth0spajs@@-Key — HF nutzt kein
auth0-spa-js). Dennis hat stattdessen die Login-Response von /gw/auth/token
aus dem Network-Tab geliefert: sie enthält refresh_token (v1.…) +
refresh_expires_in: 5184000 (= 60 Tage, gleitend).
Wichtige Erkenntnisse (nicht neu entdecken):
- Auth0 DIREKT refreshen geht NICHT (401 access_denied) — der Client
B1n0Q24… ist confidential, das Secret hält das HF-Gateway.
- Der funktionierende Endpoint ist POST https://www.hellofresh.de/gw/refresh
mit JSON {"refresh_token": "..."} (kein client_id nötig). Antwort: neues
access_token (30 min) + rotierter refresh_token.
(/gw/auth/token mit grant_type=refresh_token → unsupported/server_error.)
- hellofresh.py refresh_access_token() nutzt jetzt das Gateway;
_load_weeks() heilt sich selbst (verifiziert: kaputtes Access-Token →
Auto-Refresh → Live-Wochen ohne Warnung; Rotation in
data/hf-refresh-token.txt bestätigt; voller Sync grün).
- Der tägliche 08:10-Sync rotiert den Token → 60-Tage-Fenster verlängert sich
laufend = Dauerbetrieb. Stirbt er doch (Passwortwechsel o. ä.):
einmal neu einloggen, Login-Response → refresh_token ins
Einstellungs-Token-Feld (erkennt den Typ automatisch).
3. Weitere offene Punkte
- iPhone-Verifikation ausstehend: Scan-Ergebnis-Popup (Kamera), Wir-Modus- essen, Markdown-Schritte, AiProgress-Donut am Gerät.
- Jaqueline: Pocket-ID-User anlegen (Name
jaqueline→ Heuristik mappt auf Profil 2; sonstoidc_identitiesvon Hand). - Roadmap: 🤖 Woche füllen · PVG verfeinern (Packungsgewicht je Artikel → pack-Modus anteilig) · Mehrfach-Scan fürs Listen-Abhaken (bewusst zurückgestellt) · AI noch schneller falls nötig (persistenter Worker-Daemon, OpenRouter-Synchron-Pfad mit grok-4.1-fast aus .env, SSE).
- Dauerläufer: Grocy-admin-Passwort, EANs scannen (Werkzeug jetzt da), DSGVO-Kopie, mittelfristig Grocy abschalten.
4. Betriebszustand (Kurzreferenz)
- Container: traefik (80/443) · pocket-id · silverscale (127.0.0.1+WG :9300)
· grocy (WG-only). Deploy: Frontend-Build →
docker compose up -d --build silverscale. - Crontab (PATH-Kopfzeile!): 07:30 Grocy-Sync · 07:45 Bon-Import (+Push) · 08:10 HF-Sync · minütlich ai-jobs/dish-ai/ai-resolve (je 55-s-Schleife, 2-s-Takt) · 22:00 ai-resolve · 03:30 DB-Backup.
- Secrets Repo-
.env: CF-Token, POCKET_ID_ENCRYPTION_KEY (nie rotieren!), VAPID, INTERNAL_API_TOKEN.lidl-grocy/.env: LIDL_REFRESH_TOKEN (rotiert täglich automatisch). HF:data/hf-token.txt(Access, 30 min),data/hf-refresh-token.txt(FEHLT noch, s. §2). - Login: Passkey via Pocket ID; Session 180 Tage; Playwright-Checks gegen
127.0.0.1:9300mitX-Internal-Token-Header.