diff --git a/docs/craftvia/lanes/benachrichtigungen.md b/docs/craftvia/lanes/benachrichtigungen.md
new file mode 100644
index 0000000..62dd2f6
--- /dev/null
+++ b/docs/craftvia/lanes/benachrichtigungen.md
@@ -0,0 +1,108 @@
+# Lane L6 – Benachrichtigungen & Audit
+
+Branch `lane/benachrichtigungen` (Basis `bf44567`, `feature/craftvia-mvp`). Spec §19.4, §20, §26, §33, ARCHITEKTUR §4.1.
+
+## Umfang / erfüllte Spec-Punkte
+
+| Punkt | Umsetzung |
+|---|---|
+| §20.1 Ereignisse, ARCHITEKTUR §4.1 | `handleEvent` (Signatur unverändert) löst alle 17 `EVENT_TYPES` auf: In-App-`Notification` über `ctx.db` + E-Mail über `enqueueMail` |
+| §20.2 Kanäle | In-App (Glocke, `/notifications`) + E-Mail (Mail-Queue, MailLog) |
+| §19.4 Notdienst | Pflichtmail an Backoffice + feste Notdienst-Empfänger, Format „Neuer Notdiensteinsatz abgeschlossen / Monteur / Kunde / Einsatzbeginn / Einsatzende / Status" |
+| §33.1 E-Mail-Ereignisse | Templates `craftvia_team_assigned`, `craftvia_report_review`, `craftvia_billing_release`, `craftvia_emergency`, `craftvia_document_failed`, `craftvia_notification` (de/en, Link in die App über `APP_BASE_URL`, Craftvia-Fußzeile mit Grund des Empfangs) |
+| §33.2 Konfiguration | `/settings/email` (tenant:manage): Absendername, Antwortadresse, Empfänger Notdienst, Empfänger Abrechnung (je max. 20). Absenderadresse bleibt Plattform-Domain (SPF/DKIM) – nur Hinweis. Vorlagen je Mandant: nicht im MVP |
+| §26 Audit | `/settings/audit` (audit:read): Filter Zeitraum/Benutzer/Aktion/Objektart/Objekt-ID, Pagination, Detail-Popup mit before/after-Diff, Ergebnis (erfolgreich/abgelehnt), IP/User-Agent (derzeit „nicht erfasst", s. Fundament-Bedarf) |
+| Nutzer-Einstellungen | `/account` Abschnitt „Benachrichtigungen": E-Mail-Opt-out je Typ, Notdienst als Pflicht (nicht abwählbar) |
+
+### Empfängerregeln (`src/server/services/notifications/recipients.ts`)
+
+| Event | In-App | E-Mail |
+|---|---|---|
+| `work_order.assigned` / `changed` / `cancelled` | aktive Teammitglieder (validFrom/validTo) + Teamleiter des Teams + `teamLeadUserId` + Einzel-Assignees | dieselben |
+| `work_order.started` / `daily_report_created` / `technically_completed` / `signature_missing` / `missing_required` | Backoffice = Nutzer mit `work_order:read_all` **und** `report:approve` | dieselben |
+| `report.submitted` | `data.approvalStage="team"` → Teamleiter des Auftrags mit `report:approve_team`; `"backoffice"` → Backoffice; ohne Angabe → beide | dieselben |
+| `report.approved` / `rejected` | Ersteller (`createdById`) + Team des Auftrags | dieselben |
+| `work_order.released_for_billing` | Nutzer mit `work_order:release_billing` | feste Abrechnungsempfänger; sind keine hinterlegt, die Nutzer selbst |
+| `emergency.created` / `completed` | Backoffice | Backoffice + feste Notdienst-Empfänger, **Pflicht** (Opt-out wirkungslos) |
+| `import.ready_for_review` / `import.failed` | importierender Nutzer (`importedById`) | derselbe |
+| `sync.failed` | betroffener Nutzer (`SyncOperation.userId`) + Backoffice | dieselben |
+
+Allgemein: Akteur (`ctx.userId`) ausgenommen – außer bei System-Ergebnis-Events (`import.*`, `sync.failed`), deren Betroffener sonst nie informiert würde. Alle IDs werden über `ctx.db.user` (Status ACTIVE) neu aufgelöst → nie Nutzer anderer Mandanten. Feste Adressen, die zugleich einem Nutzer-Empfänger gehören, erhalten keine Doppelmail. Sprache je Empfänger: `Identity.uiLocale` → Mandanten-Locale → `de`. Link je Empfänger: Backoffice (`work_order:read_all`) → `/work-orders/…`, `/reports/…`; sonst mobile Routen `/m/orders/…`, `/m/sync`.
+
+### Verträge für andere Lanes (über `DomainEvent.data`)
+
+- `occurrenceId` (string/number): für wiederholbare Events (z. B. Tagesbericht je Tag, mehrere `changed`) – wird an den Mail-`dedupeKey` gehängt. Ohne `occurrenceId` gilt `event:entity:user` (gleiches Event zweimal → eine Mail).
+- `approvalStage` (`"team"` | `"backoffice"`) bei `report.submitted` (L5).
+- `startedAt` / `endedAt` (ISO) und optional `technician` bei `emergency.*` (L8); Fallback: geplanter Beginn bzw. Erstellzeit, Ende = Eventzeit, Monteur = Akteur.
+- `reason` bei `sync.failed` (Fallback, falls `SyncOperation.errorCode` leer).
+- In-App-Dedupe: existiert eine **ungelesene** Benachrichtigung gleichen Typs zur selben Entität, wird sie aufgefrischt statt verdoppelt.
+
+## Dateien
+
+Neu:
+- `src/server/services/notifications/{recipients,texts,inbox,preferences,mail-settings,page-ctx}.ts`, `handle-event.ts` (Platzhalter ersetzt)
+- `src/server/services/audit/viewer.ts` (Audit-Viewer-Service; neuer Pfad ohne Owner, fachlich Teil dieser Lane)
+- `src/server/actions/notifications/{inbox,preferences,mail-settings}.ts` (je `moduleGuard("notifications")` + `await guard(...)`)
+- `src/components/notifications/{bell,preferences-section,preferences-form}.tsx`
+- `src/app/(app)/notifications/page.tsx` (Platzhalter ersetzt), `src/app/(app)/settings/email/{layout,page}.tsx`, `src/app/(app)/settings/audit/page.tsx`
+- `messages/{de,en}/notifications.json`
+- `prisma/migrations/20260914120000_benachrichtigungen_tenant_mail_settings/migration.sql`
+- `scripts/test-benachrichtigungen-events.ts`, `scripts/test-benachrichtigungen-inbox-audit.ts`
+
+Erlaubte Fremd-Eingriffe:
+- `src/server/mail/templates.ts`: nur neue Template-Keys + `CRAFTVIA_TEMPLATE_KEYS` + Craftvia-Fußzeilen (SEC1-`TEMPLATE_KEYS` unverändert, damit `test-mail.ts` gleich bleibt)
+- `src/app/(app)/layout.tsx`: `` im Header (Import + 1 Zeile)
+- `src/app/(app)/account/page.tsx`: `` (Import + neuer Abschnitt)
+- `src/lib/nav.ts`: Einträge `/notifications`, `/settings/email`, `/settings/audit` (+ Icons) und passende Labels in `messages/{de,en}/nav.json`
+- `src/components/audit-trail.tsx`: Entity-Labels der Craftvia-Entitäten
+- `prisma/schema.prisma`: 4 Felder an `TenantSettings`
+
+## Migration (begründet)
+
+`TenantSettings` hatte keine Mailfelder (nur Fundament-`smtp Json`, das für SMTP-Zugangsdaten gedacht ist). Neue Spalten `mail_from_name`, `mail_reply_to`, `emergency_recipients TEXT[]`, `billing_recipients TEXT[]`. Keine neue Tabelle → kein `enable_tenant_rls`, keine TENANT_MODELS-Änderung (tenant_settings ist bereits mandantengebunden).
+
+## Tests
+
+| Skript | Prüfungen | Ergebnis |
+|---|---|---|
+| `test-benachrichtigungen-events.ts` | 63: Empfänger je Eventgruppe (assigned inkl. Einzel-Assignee, cancelled, started, report.submitted team/ohne Stufe, report.approved, released_for_billing, emergency.completed, import.failed, sync.failed), Akteur ausgenommen, Mandantentrennung (fremder Kontext, fremde Entität, fremde User-ID als Ersteller), Dedupe, occurrenceId, Opt-out, Pflichtmail Notdienst trotz Opt-out, feste Empfänger ohne Doppelmail, handleEvent/emitEvent werfen nie, Templates de/en + §19.4-Format | grün |
+| `test-benachrichtigungen-inbox-audit.ts` | 46: Posteingang nur eigene + Filter, Monteur/Mandant B → `not_found` bei fremder Benachrichtigung, ohne `notification:read` → `forbidden`, markAllRead mandantengetrennt, Audit bei markRead, Open-Redirect-Schutz, Präferenz-Defaults, Mailkonfiguration nur `tenant:manage` + Validierung (Header-Injection, ungültige/zu viele Adressen) + Mandantentrennung + Audit, Audit-Viewer nur mit `audit:read`, nur eigener Mandant, Filter, Detail-Diff | grün |
+
+**Gate (`npm run gate`): grün** – prisma generate, tsc, lint, build inkl. Modul-Guard-Check (16 Action-Dateien), 24/24 Testskripte.
+
+Hinweis Umgebung: Mit eigener Lane-Datenbank muss `RLS_DATABASE_URL` auf dieselbe DB zeigen
+(`postgresql://craftvia_app:craftvia_app_local@localhost:5432/craftvia_benachrichtigungen?schema=public`),
+sonst schlägt `test-rls-enforcement.ts` fehl: Owner-Client und `craftvia_app`-Client landen dann in verschiedenen Datenbanken. Das hat nichts mit dem Code dieser Lane zu tun; in der kopierten `.env` ist die Zeile auskommentiert.
+
+**Smoke (Dev-Server :3106, Server-Rendering per HTTP, Seed-Mandant „demo")**, 13 Prüfungen grün:
+`/notifications` inkl. Filter Status/Typ, `/settings/email`, `/settings/audit` inkl. Detail-Popup, `/account` (Abschnitt Benachrichtigungen), Glocke und Navigation im Header/Sidebar (Admin);
+Backoffice sieht das Audit-Protokoll, wird von `/settings/email` umgeleitet; Monteur wird von `/settings/audit` umgeleitet und sieht keine Admin-Navigation.
+Sitzungen wurden lokal ohne Passworteingabe erzeugt (`finalizeIdentityLogin` + `AUTH_SECRET`); die Smoke-Daten wurden danach entfernt. Visuelle Prüfung (Responsive 1024/768/375 px) steht noch aus.
+
+## Stubs / Abhängigkeiten
+
+- Keine Stubs nötig: Empfängerauflösung liest direkt die Domänentabellen (WorkOrder, Team, TeamMember, WorkOrderAssignee, Report, ImportJob, Document, SyncOperation).
+- **L4 (Mobile-Header):** Glocke einbinden mit `import { NotificationBell } from "@/components/notifications/bell";` und `` (48-px-Touchziel). Server-Komponente, blendet sich ohne `notification:read`/bei deaktiviertem Modul selbst aus.
+- **L2/L4/L5/L8:** Links zeigen auf `/work-orders/[id]`, `/work-orders/conflicts`, `/reports/[id]`, `/m/orders/[id]`, `/m/orders/[id]/report`, `/m/sync`, `/imports/[id]` (Routen laut ARCHITEKTUR §5).
+- Settings-Übersicht (`/settings/page.tsx`, Fundament) verlinkt die neuen Seiten noch nicht; erreichbar über die Sidebar.
+
+## Fundament-Bedarf (nicht selbst geändert)
+
+1. **IP/User-Agent im Audit-Log (Spec §26):** `writeAuditLog` erfasst weder IP noch User-Agent, `AuditLog` hat keine Spalten dafür. Vorschlag: Spalten `ip`, `user_agent` + Ermittlung aus `headers()` im action-guard. Der Viewer zeigt die Werte bereits an, sobald `after.ip`/`after.userAgent` bzw. künftige Spalten gefüllt sind (derzeit „nicht erfasst").
+2. **Absendername/Reply-To je Mandant im Mail-Kern:** `deliverMail` nutzt nur globale `MAIL_FROM_NAME`/`MAIL_REPLY_TO`. Benötigt: optionale `fromName`/`replyTo` in `EnqueueInput`/`MailJob` und deren Verwendung in `deliver.ts`. Die gespeicherten Werte liefert `tenantMailSender(ctx)` (`services/notifications/mail-settings.ts`); bis dahin werden sie gespeichert, aber beim Versand noch nicht angewendet.
+3. `src/server/mail/notifications.ts#notifyUser` (SEC1) bleibt bestehen; Craftvia-Fachmodule nutzen ausschließlich `emitEvent`. AGENTS.md-Andockpunkt „Benachrichtigungen" sollte auf `emitEvent` zeigen.
+
+## Bekannte Lücken
+
+- Mandanteneigene E-Mail-Vorlagen (§33.2 „E-Mail-Vorlagen") nicht umgesetzt.
+- Glocke aktualisiert sich bei Navigation/Aktion (Server-Rendering), kein Live-Push/Polling.
+- Kein Aufräumen alter Benachrichtigungen (Löschfrist) – Kandidat für einen Job.
+- In-App-Opt-out gibt es bewusst nicht (nur E-Mail).
+
+## Screens / Routen
+
+- `/notifications` – Liste mit Filter Status/Typ, „Öffnen" (markiert gelesen + springt zur Entität), „Als gelesen markieren", „Alle als gelesen markieren"
+- Glocke im Backoffice-Header – Zähler ungelesen, Dropdown letzte 10, „Alle gelesen", „Alle anzeigen"
+- `/account` – Abschnitt „Benachrichtigungen"
+- `/settings/email` – Mandanten-Mailkonfiguration
+- `/settings/audit` – Audit-Protokoll mit Filter und Detail-Popup (`?detail=`)