Zuletzt aktualisiert:

Notification-Taxonomie (B1.4 Notification-Center)

StratoClaude → MacClaude, 08.06.2026. kind → Icon → Route-Zuordnung für den nativen Center. Open-ended: neue Arten kommen dazu; der Client mappt über kind/icon/link (nicht über den Titeltext). Erzeuger ist immer notify(user_id, title, body, kind=…, icon=…, link=…, dedupe_key=…) in backend/main.py. Row-Shape + Endpoints siehe b1-push-contract §7.

Row-Felder (Wiederholung, fürs Mapping)

{ id, user_id (NULL=Broadcast), kind, title, body, icon, link, dedupe_key (UNIQUE), created_at, read_at }. icon ist der kanonische Anzeige-Icon (Emoji-String); Titel sind emoji-frei (Marken-Regel: kein 🤖, KI-Einträge tragen icon="✨"; nativ rendert ihr dafür euer ai-assistant-2-Asset). Fürs Icon auf icon verlassen.

Aktuelle kind-Typen (live)

kind Auslöser (Backend) icon title body (Beispiel) link Empfänger
ai KI-Job fertig (finish_job, B1.5) Claude fertig Foto-Analyse abgeschlossen ✓ / Broadcast (user_id NULL)
garmin Garmin-Sync, neue Aktivität ⌚️ Neue Garmin-Aktivität Laufen · 480 kcal /activities/{id} der jeweilige User
egym eGYM-Sync, neue Aktivität 🏋️ Neue eGYM-Aktivität Krafttraining (eGYM) · 320 kcal /activities/{id} der jeweilige User
receipt Bon-Import (/api/receipts/import, nur bei created) 🧾 Neuer Kassenbon Kaufland · 5.13 € · 4 Artikel /einkauf/{receipt_id} Broadcast
info generischer Default (keiner gesetzt) frei frei / je nach Aufruf
Link Ziel Quelle der ID
/activities/{id} eine Aktivität (Tagebuch-Aktivität) activities.id
/einkauf/{receipt_id} ein Kassenbon im Bon-Archiv receipts.id (deterministische Bon-ID, z. B. kfl-…)
/diary/{date} Tagebuch-Tag (YYYY-MM-DD) reserviert (noch kein notify nutzt es)
/ Home/Heute Default

Routes sind stabil zugesichert, auch wenn der native Zielscreen noch nicht existiert — du kannst jetzt drauf routen/vorbereiten. Brauchst du ein weiteres Schema (z. B. /dish/{id}, /plan/{week}), sag's, dann setze ich es beim passenden Erzeuger.

Idempotenz (dedupe_key)

Jeder Erzeuger setzt einen stabilen dedupe_key, damit Crons/Re-Syncs nicht doppelt benachrichtigen (UNIQUE-Constraint):

kind dedupe_key
ai aijob-{job_id}-done
garmin/egym act-{activity_id}
receipt receipt-{receipt_id}

Abdeckung / offen

Interner Notify-Endpoint (für Host-Worker)

Host-Prozesse außerhalb des App-Containers (Lidl-Cron etc.) erzeugen Notifications über POST /api/notify (nur X-Internal-Token):

{ "user_id": null, "title": "Neuer Kassenbon", "body": "Lidl · 12,50 € · 5 Artikel",
  "kind": "receipt", "icon": "🧾", "link": "/einkauf/lidl-xyz",
  "dedupe_key": "receipt-lidl-xyz" }

→ ruft serverseitig notify() (Center-Row + APNs + VAPID), Response wie notify ({created:true,id} bzw. {deduped:true}). user_id weglassen/null = Broadcast.

Neue kind hinzufügen (für mich, fürs Protokoll)

Ein neuer Typ = ein notify(...)-Aufruf am Auslöser mit neuem kind, passendem icon, stabilem link + dedupe_key — plus eine Zeile in der Tabelle oben. Sag mir Auslöser + gewünschten Link, den Rest setze ich serverseitig (Anti-Drift: Server erzeugt die fertige Bedeutung, der Client rendert sie nur).