77c720e2df
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-school (push) Successful in 50s
CI / test-go-edu-search (push) Successful in 45s
CI / test-python-klausur (push) Failing after 3m50s
CI / test-python-agent-core (push) Successful in 36s
CI / test-nodejs-website (push) Successful in 49s
- 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>
65 lines
2.7 KiB
Markdown
65 lines
2.7 KiB
Markdown
# 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:**
|
|
|
|
1. **Lehrer:** JWT in Authorization-Header (oder Dev-Bypass mit Default-User wenn `ENVIRONMENT != "production"`). Routen unter `/api/v1/school/...`.
|
|
2. **Eltern:** Session-Cookie `bp_parent_session` (HttpOnly, SameSite=Lax), gesetzt vom `/api/v1/parent/auth/redeem` Endpoint. 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}`):
|
|
|
|
1. `DELETE FROM tt_class WHERE grade_level >= 13` (Abschlusskohorte)
|
|
2. `UPDATE tt_class SET grade_level = grade_level + 1`
|
|
3. `UPDATE 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](notifications.md))
|
|
- Env-Vars `MATRIX_SERVICE_URL`, `EMAIL_SERVICE_URL` (leer = Stub-Mode)
|
|
- Endpoint-Vertrag (POST mit JSON-Body, HTTP 2xx = sent)
|