1e51ef7def
- Konzept/, didaktik_geografie/, didaktik_simulation/, v2-modules/, v2-platform/ - 12 code-workspace-Files - STATUS-*.md - viele M/D/R-Änderungen an bereits getrackten Files - .gitignore verstärkt: **/.humaninput/, **/secret_keys.txt Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
231 lines
8.1 KiB
Markdown
231 lines
8.1 KiB
Markdown
# 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 `<sprache>-<land>-<variante>`, 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 <session_token>
|
||
```
|
||
|
||
**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 <session_token>
|
||
```
|
||
|
||
**Response 200** (wenn Stand existiert):
|
||
```json
|
||
{
|
||
"exists": true,
|
||
"lastUpdated": "2026-05-15T14:23:00Z",
|
||
"state": {
|
||
"<modul-spezifisches JSON>": "..."
|
||
},
|
||
"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 <session_token>
|
||
```
|
||
|
||
**Response 200:**
|
||
```json
|
||
{
|
||
"slug": "intermodalverkehr",
|
||
"title": "Kombi-Verkehr",
|
||
"shortText": "Wenn du Sachen erst mit dem Lkw und dann mit der Bahn schickst.",
|
||
"longTextHtml": "<p>...</p>",
|
||
"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 <session_token>
|
||
```
|
||
|
||
**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 <session_token>
|
||
```
|
||
|
||
**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_<slug>_*`-Tabellen frei nutzen (CRUD per eigene
|
||
PHP-Endpoints unter `<modul>/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).
|