# Vertrag 2: Input-API Was ein Modul beim Start von der Plattform bekommt und wie es die restlichen Daten anfragt. **Module dürfen NICHT direkt auf die DB zugreifen für User-Daten** — alles über die API. ## URL-Aufruf Wenn ein:e Schüler*in im V2-Cockpit auf das Modul klickt, ruft die Plattform `entryHtml` mit definierten Query-Parametern auf: ``` https://geograsim.at/v2beta/sims/logistik/public/game.html ?session_token=eyJhbGc... &student_id=4711 &class_id=42 &mode=teacher_started &difficulty=L1 &lang=de-AT-easy &resume=1 ``` ### Pflicht-Parameter | Parameter | Typ | Beschreibung | |---|---|---| | `session_token` | JWT-String | Auth-Token, vom Modul für alle API-Calls verwendet. Gültigkeit und Refresh-Fenster aus `/api/runtime-config` (Default 1h Lebensdauer, 5min Refresh-Fenster vor Ablauf). Plattform-Helper-Lib (`telemetry-client.js`) übernimmt Auto-Refresh transparent. | | `student_id` | Integer | DB-ID Schüler*in | | `class_id` | Integer | DB-ID Klasse | | `mode` | Enum | `free` / `teacher_started` / `assessment` / `demo` | | `difficulty` | String | Ein Level-ID aus `manifest.difficultyLevels` | | `lang` | String | Locale-Code `--`, z.B. `de-AT-standard`, `de-AT-easy`. Aus Profil-Default oder Lehrer-Override. Heute Pflicht: AT-Varianten; später `de-DE-*`, `de-CH-*`. | | `resume` | `0`/`1` | Soll das Modul den letzten Stand wiederherstellen | ### Modus-Bedeutung - `free` — Schüler*in arbeitet selbstgewählt. Wählt Level aus `levelUnlocks[moduleSlug].highestUnlocked` (Default L1). Bei `nachteilsausgleich=true` darf jeder Level gewählt werden. Ergebnis wird gespeichert aber zählt nicht für die Lehrperson-Bewertung. - `teacher_started` — Lehrperson hat einen **Auftrag** mit fester Schwierigkeit angelegt (`class_assignments_v2`). `difficulty`-Parameter ist vorgegeben, Schüler*in kann nicht wechseln. **Ausnahme bei `nachteilsausgleich=true`**: Schüler*in darf trotzdem frei wählen. Live-Telemetry wird priorisiert im Lehrperson-Dashboard dargestellt. - `assessment` — Bewertungs-Modus, das Modul soll Hilfen reduzieren und das Ergebnis fließt in die Schüler-Bewertung ein. Hinweis im UI: „Du bearbeitest gerade eine Bewertung — keine Tipps verfügbar." - `demo` — Demo-Mode für Lehrperson-Vorführung, kein Speichern, keine Telemetry an die DB (Heartbeat trotzdem schicken, aber Plattform verwirft sie still). ## API: Profil holen Direkt nach Start ruft das Modul das Profil ab: ```http GET /v2beta/api/student/me Authorization: Bearer ``` **Response 200:** ```json { "studentId": 4711, "displayName": "Lena", "avatarSlug": "fuchs-explorer", "avatarUrl": "/v2beta/assets/avatars/avatar-fuchs-explorer.png", "easyLanguage": true, "locale": "de-AT-easy", "country": "AT", "classId": 42, "className": "1A 2025/26", "schoolName": "MS Test", "preferences": { "soundOn": true, "musicOn": false, "highContrast": false, "reducedMotion": false, "screenReader": false, "textScale": "normal" } } ``` **A11y-Settings** (siehe [platform-standards.md § 9](platform-standards.md)): - `highContrast` — aktiviert High-Contrast-Token-Set (`body[data-high-contrast="light"]` default) - `reducedMotion` — Modul muss Auto-Play-Animationen unterdrücken - `screenReader` — Schüler*in nutzt Screen-Reader; Modul soll visuell-zwingende Aufgaben vermeiden oder per Telemetry-Event `accessibility-blocker` melden - `textScale` — `"normal"` / `"large"` / `"xlarge"` — Modul kann eigene Text-Tokens entsprechend skalieren (Stufe 2) **Nachteilsausgleich + Level-Unlocks**: - `nachteilsausgleich` (Boolean) — wenn `true`, darf Schüler*in **alle** Level frei wählen, auch im Auftragsmodus (siehe [level-unlock-konzept.md](level-unlock-konzept.md)) - `levelUnlocks` (Object) — Map `moduleSlug → { highestUnlocked, highestCompleted, bestScorePerLevel, attemptsPerLevel }`. Modul nutzt das im freien Modus, um die Level-Auswahl zu rendern. **Locale und Country**: - `locale` — der effektive Locale-Code (kombiniert aus Profil + Modus) - `country` — Kurz-Code des Heimat-Landes (`AT`, `DE`, `CH`, ...) für geografisch sinnvolle Default-Beispiele (z.B. „Hauptstadt deines Landes") **Response 401**: Token ungültig → Modul zeigt „Bitte erneut einloggen" und ruft `parent.location = '/v2beta/'` auf. ## API: Resume-State holen (wenn `resume=1`) ```http GET /v2beta/api/module/state?slug=logistik Authorization: Bearer ``` **Response 200** (wenn Stand existiert): ```json { "exists": true, "lastUpdated": "2026-05-15T14:23:00Z", "state": { "": "..." }, "summary": "Tag 3, Level 2, 4 von 8 Aufträgen erledigt" } ``` **Response 200** (kein Stand): ```json { "exists": false } ``` Modul speichert seinen State per `PUT /v2beta/api/module/state` (siehe Output-API). ## API: Glossar-Tooltip holen ```http GET /v2beta/api/glossary/intermodalverkehr?lang=de-AT-easy Authorization: Bearer ``` **Response 200:** ```json { "slug": "intermodalverkehr", "title": "Kombi-Verkehr", "shortText": "Wenn du Sachen erst mit dem Lkw und dann mit der Bahn schickst.", "longTextHtml": "

...

", "imageUrl": "/v2beta/assets/glossar/intermodalverkehr.png" } ``` Modul nutzt das für Tooltip/Modal beim Tap auf einen Fachbegriff. Plattform cached pro Sprache. ## API: Runtime-Config holen (Pflicht beim Start) Beim Start (vor dem ersten Heartbeat) holt das Modul die Plattform- Konfiguration. Werte können von einer Lehrperson mit Admin-Rolle im Admin-Board justiert werden — Modul nutzt sie statt fixer Konstanten. ```http GET /v2beta/api/runtime-config Authorization: Bearer ``` **Response 200:** ```json { "heartbeat": { "minIntervalS": 10, "maxIntervalS": 30 }, "stuck": { "thresholdS": 90 }, "telemetry": { "rateLimitPerS": 1, "eventCapPerSession": 2000, "retentionDays": 30 }, "auth": { "tokenTTLs": 3600, "refreshWindowS": 300 } } ``` Modul wählt Heartbeat-Intervall **innerhalb der Plattform-Grenzen** (Default 10–30s): ruhige Module eher Richtung 30s, schnelle Richtung 10s. Stuck-Schwellwert wird vom Modul übernommen (kein Override). Plattform-Helper-Lib `telemetry-client.js` macht das transparent — Modul muss den Endpoint nicht selbst aufrufen, wenn die Lib genutzt wird. ## API: Lehrplan-Anker holen (wenn das Modul es braucht) ```http GET /v2beta/api/lehrplan/anker/AT-GW-1.4.2 Authorization: Bearer ``` **Response 200:** ```json { "code": "AT-GW-1.4.2", "country": "AT", "scheme": "GW", "level": "Sekundarstufe 1, Klasse 2", "topic": "Wirtschaftsräume Europas", "competence": "Verkehrsnetze beschreiben und bewerten" } ``` Lehrplan-Codes sind immer mit Land-Prefix (`AT-...`, `DE-...`, `CH-...`). Module sollen Codes ihres `lehrplanAnker`-Manifests referenzieren, nicht hardcoden. ## Was das Modul NICHT direkt darf - ❌ Direkter Zugriff auf `students`, `classes`, `teachers`, `licenses`, `assessments` Tabellen (alles via API) - ❌ Eigene Login-Logik bauen - ❌ Cookies setzen mit Session-Daten (nur eigene Modul-Cookies erlaubt) - ❌ Andere Module aufrufen oder deren DB-Tabellen lesen - ❌ Glossar-Datenbank direkt querien (nur API) ## Was das Modul darf - ✅ Eigene `m__*`-Tabellen frei nutzen (CRUD per eigene PHP-Endpoints unter `/server/`) - ✅ Eigene Modul-Cookies setzen (z.B. „Tutorial gesehen") - ✅ localStorage frei nutzen (für UI-State, nicht für Lerndaten) - ✅ Externe APIs aufrufen (z.B. OSRM, Tile-Server) — auf eigene Verantwortung ## ✅ Geklärt mit Thomas (2026-05-17) - **Token-TTL**: Default 1h mit Auto-Refresh-Fenster 5min vor Ablauf. Wert ist Admin-konfigurierbar (siehe `/api/runtime-config`). - **`mode=assessment`**: wird dem Sch*in **sichtbar** angezeigt („Du bearbeitest eine Bewertung — keine Tipps verfügbar"), damit sie weiß warum sich das Modul anders verhält. - **Modul-eigene PHP-Endpoints**: dürfen mit `session_token` aufgerufen werden, müssen aber das Token via `v2_auth_require()` selbst verifizieren. Plattform-Helper steht zur Verfügung (`v2-platform/php/lib/auth.php` includen).