- CLAUDE.md gets a new section summarising the two feature strands, pitfalls (Timefold name, JSX quotes, LOC budget), the auth/messaging outsourcing, and pointers to the three memory files for next session. - docs-src/services/schulkalender/ — 5 MkDocs pages mirroring the stundenplan structure: index, architecture, holidays, parent-flow, notifications. Each with DB tables, endpoints, and the dispatch payload contract for the colleague's Matrix/Email services. - mkdocs.yml gains the Schulkalender nav entry under Services. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2.7 KiB
Architektur
Datenmodell
Phase 9a — Kalender-Stammdaten
| Tabelle | Inhalt | Owner |
|---|---|---|
cal_public_event |
Ferien + Feiertage (region, type, name, start, end) | global (alle Bundeslaender) |
cal_school_config |
Bundesland-Auswahl + Schuljahr-Daten | 1 row per user_id |
Phase 9b — Schul-Events
| Tabelle | Inhalt | Owner |
|---|---|---|
cal_school_event |
Titel + Typ + Datum/Zeit + affected_class_ids + Notification-Flags | created_by_user_id |
Event-Typen (CHECK constraint): fortbildung, schulfeier, klassenfahrt, projekttag, eltern_info, andere.
Phase 9c — Parent-Accounts
| Tabelle | Inhalt |
|---|---|
parent_account |
Email + preferred_language, UNIQUE pro (Lehrer, Email) |
parent_child |
Vorname/Nachname + FK auf tt_class |
parent_magic_link |
Einmal-Token (SHA-256 in DB), expires_at 7 Tage |
parent_session |
Browser-Session-Token (SHA-256 in DB), expires_at 30 Tage |
Phase 9d — Notifications
| Tabelle | Inhalt |
|---|---|
notification_log |
Idempotenz: UNIQUE(event_id, lead_days, audience, channel) |
Auth-Modell
Zwei voneinander unabhaengige Auth-Wege:
- Lehrer: JWT in Authorization-Header (oder Dev-Bypass mit Default-User wenn
ENVIRONMENT != "production"). Routen unter/api/v1/school/.... - Eltern: Session-Cookie
bp_parent_session(HttpOnly, SameSite=Lax), gesetzt vom/api/v1/parent/auth/redeemEndpoint. ParentSessionMiddleware resolved Cookie → parent_account.
Eltern sehen nie Daten anderer Eltern. Privacy-Check via ChildBelongsToParent in jedem GET, Plus Filterung der Lessons gegen tt_solution des einladenden Lehrers.
Bundesland-Wizard
Erster Aufruf von /schulkalender → kein cal_school_config → BundeslandWizard UI → POST /calendar/config mit {bundesland: "DE-NI"} → MonthView lädt für die naechsten ~6 Wochen.
Schuljahres-Rollover
POST /calendar/school-year-rollover (optional {new_year_start, new_year_end}):
DELETE FROM tt_class WHERE grade_level >= 13(Abschlusskohorte)UPDATE tt_class SET grade_level = grade_level + 1UPDATE cal_school_config SET school_year_start/end = ...
Alles in einer Transaction. Stundenplan-Lehrer-Faecher-Raum-Bestand bleibt unangetastet.
Auth + Messaging outsourced
Production-Auth, Matrix-Bridge und Email-Gateway werden vom Kollegen gepflegt — siehe globale Memory stundenplan_auth_and_messaging.md. Wir definieren nur:
- Dispatch-Payload-Struct (siehe notifications.md)
- Env-Vars
MATRIX_SERVICE_URL,EMAIL_SERVICE_URL(leer = Stub-Mode) - Endpoint-Vertrag (POST mit JSON-Body, HTTP 2xx = sent)