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>
197 lines
6.6 KiB
Markdown
197 lines
6.6 KiB
Markdown
# Vertrag 4: Telemetry-API (Pflicht)
|
||
|
||
Was ein Modul **kontinuierlich** während der Sitzung an die Plattform
|
||
pushen muss, damit das Lehrer-Live-Dashboard funktioniert.
|
||
|
||
**Das ist Spec-Pflicht, kein Add-on.** Wer keine Telemetry liefert,
|
||
wird nicht integriert. Live-Sicht für Lehrpersonen ist der
|
||
pädagogische Kern-USP von GeoGraSim — Module müssen sie tragen.
|
||
|
||
## Drei Event-Typen
|
||
|
||
### 1. Heartbeat — alle 10–30 Sekunden bei Aktivität
|
||
|
||
Sagt: „Schüler*in ist da, aktueller Stand ist X."
|
||
|
||
```http
|
||
POST /v2beta/api/telemetry
|
||
Authorization: Bearer <session_token>
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"type": "heartbeat",
|
||
"moduleSlug": "logistik",
|
||
"moduleVersion": "2.0.0",
|
||
"phase": "auftrag-bearbeiten",
|
||
"phaseLabel": "Auftrag wird bearbeitet",
|
||
"step": "3/7",
|
||
"currentScore": 42,
|
||
"scoreMax": 100,
|
||
"timeInPhaseS": 252,
|
||
"totalTimeS": 1023,
|
||
"ts": "2026-05-15T14:23:45Z"
|
||
}
|
||
```
|
||
|
||
| Feld | Pflicht | Beschreibung |
|
||
|---|---|---|
|
||
| `type` | ✓ | `"heartbeat"` |
|
||
| `moduleSlug` | ✓ | aus Manifest |
|
||
| `moduleVersion` | ✓ | aus Manifest |
|
||
| `phase` | ✓ | Modul-interne Phase-ID (string, frei wählbar) |
|
||
| `phaseLabel` | ✓ | Anzeigename der Phase für Lehrer-Dashboard |
|
||
| `step` | – | „X/Y"-Format wenn Modul Schritt-Konzept hat, sonst weglassen |
|
||
| `currentScore` | – | aktueller Score wenn vorhanden |
|
||
| `scoreMax` | – | maximaler Score wenn vorhanden |
|
||
| `timeInPhaseS` | ✓ | Sekunden in der aktuellen Phase |
|
||
| `totalTimeS` | ✓ | Sekunden seit Modul-Start (ohne Pausen >5min) |
|
||
| `ts` | ✓ | ISO-Timestamp |
|
||
|
||
**Frequenz**: aus `/api/runtime-config` (Default 10–30s). Modul wählt
|
||
innerhalb der Plattform-Grenzen, je nach Geschwindigkeit. Bei sehr
|
||
schnellen Modulen (Klick-Spiel) eher 10s, bei Reflexions-Modulen 30s.
|
||
**Bei Inaktivität (Schüler*in hat 60s nichts getan)**: Heartbeat
|
||
pausieren bis wieder Aktivität.
|
||
|
||
Plattform-Helper-Lib `telemetry-client.js` macht das transparent — Modul
|
||
übergibt seine bevorzugte Frequenz, Lib clamped auf Plattform-Grenzen.
|
||
|
||
### 2. Milestone — bei definiertem Fortschritt
|
||
|
||
Sagt: „Schüler*in hat etwas Konkretes geschafft."
|
||
|
||
```json
|
||
{
|
||
"type": "milestone",
|
||
"moduleSlug": "logistik",
|
||
"milestoneId": "first-order-accepted",
|
||
"milestoneLabel": "Erster Auftrag angenommen",
|
||
"scoreDelta": 15,
|
||
"currentScore": 42,
|
||
"phase": "auftrag-bearbeiten",
|
||
"ts": "..."
|
||
}
|
||
```
|
||
|
||
| Feld | Pflicht | Beschreibung |
|
||
|---|---|---|
|
||
| `type` | ✓ | `"milestone"` |
|
||
| `milestoneId` | ✓ | Aus `manifest.telemetryMilestones[].id` |
|
||
| `milestoneLabel` | ✓ | Anzeigetext |
|
||
| `scoreDelta` | – | Punkte für diesen Milestone (kann negativ sein) |
|
||
|
||
**Wichtig**: `milestoneId` muss vorab im Manifest deklariert sein.
|
||
Plattform lehnt unbekannte IDs ab. Erweiterung erfordert Modul-Update.
|
||
|
||
### 3. Stuck — bei Inaktivität trotz aktivem Tab
|
||
|
||
Sagt: „Schüler*in zögert / hängt fest. Lehrperson sollte hinschauen."
|
||
|
||
```json
|
||
{
|
||
"type": "stuck",
|
||
"moduleSlug": "logistik",
|
||
"phase": "auftrag-bearbeiten",
|
||
"phaseLabel": "Auftrag wird bearbeitet",
|
||
"step": "4/7",
|
||
"idleS": 95,
|
||
"lastActionLabel": "Container ausgewählt",
|
||
"hint": "Möglicherweise unsicher bei Routenwahl",
|
||
"ts": "..."
|
||
}
|
||
```
|
||
|
||
| Feld | Pflicht | Beschreibung |
|
||
|---|---|---|
|
||
| `type` | ✓ | `"stuck"` |
|
||
| `idleS` | ✓ | Sekunden seit letzter sinnvoller Eingabe |
|
||
| `lastActionLabel` | – | Was war die letzte Aktion (Lehrperson-Hilfe) |
|
||
| `hint` | – | Modul-Diagnose was wahrscheinlich los ist |
|
||
|
||
**Wann auslösen**: bei `idleS >= 90` Sekunden ohne sinnvolle
|
||
Eingabe (Mouse-Move zählt nicht, Klick/Tap/Drag schon). Sobald
|
||
wieder Aktivität: einmaliger neuer Heartbeat, kein „unstuck"-Event.
|
||
|
||
### 4. Accessibility-Blocker — bei A11y-Hindernis
|
||
|
||
Sagt: „Schüler*in mit A11y-Bedarf kann an dieser Stelle nicht weiter."
|
||
|
||
```json
|
||
{
|
||
"type": "accessibility-blocker",
|
||
"moduleSlug": "logistik",
|
||
"blockerType": "visual-required",
|
||
"hint": "Karten-Tap zur Routenwahl ist nicht per Tastatur ersetzbar in dieser Modul-Version",
|
||
"phase": "auftrag-bearbeiten",
|
||
"ts": "..."
|
||
}
|
||
```
|
||
|
||
| Feld | Pflicht | Beschreibung |
|
||
|---|---|---|
|
||
| `type` | ✓ | `"accessibility-blocker"` |
|
||
| `blockerType` | ✓ | `"visual-required"` / `"audio-required"` / `"mouse-required"` / `"motor-required"` |
|
||
| `hint` | ✓ | Was genau ist das Hindernis (für Lehrperson) |
|
||
|
||
**Wann auslösen**: wenn das Modul aus den Profil-Settings sieht
|
||
(`preferences.screenReader === true` o.ä.), dass eine Aufgabe für
|
||
diese Schüler*in nicht bearbeitbar ist. Lehrer-Cockpit zeigt das
|
||
prominent — Lehrperson kann ein anderes Modul anbieten.
|
||
|
||
## Idempotenz und Reliability
|
||
|
||
- Plattform akzeptiert dasselbe Event mehrfach (z.B. nach Netz-Hiccup);
|
||
Deduplizierung über `ts` + `type` + `moduleSlug` + `session_token`
|
||
- Modul soll bei Netz-Fehler **maximal 1× retryen**, dann verwerfen
|
||
(kein Endlos-Queue im Browser, sonst Memory-Leak)
|
||
- Bei Tab-Close: ein finaler Heartbeat mit `type: "heartbeat"` und
|
||
`phase: "tab-closed"` falls möglich (`navigator.sendBeacon`)
|
||
|
||
## Was die Plattform damit macht
|
||
|
||
- **Tabelle `telemetry_events_v2`** — alle Events landen dort
|
||
- **Live-Push an Lehrer-Dashboard** via Server-Sent-Events
|
||
(`/v2beta/api/teacher/live-stream?classId=42`)
|
||
- **Lehrer-Dashboard zeigt pro Schüler*in**:
|
||
- Aktuelles Modul + Phase + Step
|
||
- Score-Bar
|
||
- Zeit in aktueller Phase (rot wenn >> erwartet)
|
||
- Stuck-Indikator (orange Warning bei aktivem Stuck-Event)
|
||
- Letzter Milestone
|
||
|
||
## Performance-Limits
|
||
|
||
- Plattform nimmt **maximal 1 Event pro Sekunde pro Schüler*in** an.
|
||
Mehr wird gedrosselt (HTTP 429).
|
||
- Pro Sitzung **maximal 2000 Events**. Danach werden Heartbeats
|
||
ignoriert (Milestones noch akzeptiert).
|
||
- Payload-Max: 4 KB pro Event.
|
||
|
||
## Mock-Endpoint für Modul-Entwicklung
|
||
|
||
Während der Modul-Entwicklung (vor Integration) liefert die Plattform
|
||
einen Mock-Endpoint:
|
||
|
||
```
|
||
http://localhost/v2beta-mock/api/telemetry
|
||
```
|
||
|
||
Akzeptiert alle Events, gibt 200 OK zurück, loggt nach
|
||
`v2-platform/logs/mock-telemetry.log`. Modul-Instanzen können damit
|
||
ihren Code testen, bevor sie liefern.
|
||
|
||
## ✅ Geklärt mit Thomas (2026-05-17)
|
||
|
||
- **Heartbeat-Frequenz**: Modul wählt selbst innerhalb der Plattform-
|
||
Grenzen (`/api/runtime-config`, Default 10–30s). Admin-Board justierbar.
|
||
- **Stuck-Schwellwert**: zentrale Plattform-Konfig (Default 90s).
|
||
Module können im Manifest keinen eigenen Wert setzen — wenn ein
|
||
Modul stark abweichende Werte braucht, im Inbox-Ping an Atlas
|
||
begründen.
|
||
- **Stuck-Events**: vorerst nur visuell im Lehrperson-Dashboard
|
||
(Rot-blinkender Indikator), keine Push-Notifications. Push folgt
|
||
in Phase 2 wenn Auto-Tuning + Alerting kommt.
|
||
- **Speicherdauer**: 30 Tage Default, Admin-konfigurierbar bis 365 Tage.
|
||
Für Bildungsforschungs-Auswertungen einzelne Klassen auf 90 Tage
|
||
oder mehr hochsetzen.
|