# Configuratie en omgeving

## Omgevingsvariabelen

`config.py` leest de omgevingsconfiguratie (lokaal via een `.env`-bestand, in
productie via de procesomgeving) en exporteert alle instellingen. De
belangrijkste groepen:

- **Spraak/Azure:** `AZURE_SPEECH_KEY`, `AZURE_SPEECH_REGION`,
  `AZURE_SPEECH_ENDPOINT` (optioneel). Deze zijn allemaal optioneel: zonder
  key/region blijft de app draaien op de eigen engine en Piper (Azure is enkel
  vangnet voor uitspraak en TTS); een Azure-aanroep geeft dan een duidelijke
  fout. Voor de **uitspraakbeoordeling** is Azure bovendien een **opt-in per
  leerling** (`azure_modus`, standaard `niets`, pas na e-mailverificatie) en
  nooit beschikbaar voor docent-accounts, accounts onder de 16 of
  gastleerlingen. De **TTS-fallback** naar Azure staat daar los van en is niet
  per leerling instelbaar.
- **Database:** `DATABASE_URL` (standaard SQLite; productie PostgreSQL).
- **App:** `SECRET_KEY`, `APP_DOMAIN`, `APP_BASE_URL`.
- **AI/Mistral:** `MISTRAL_API_KEY`; optioneel `GESPREK_MODEL` (default
  `mistral-large-latest`, gelezen in `mistral_client.py`) voor de
  gespreksmodus.
- **Content Safety:** `AZURE_CS_ENDPOINT`, `AZURE_CS_KEY`, `CS_THRESHOLD`.
- **E-mail (SMTP):** host, poort, gebruikersnaam, wachtwoord en
  afzenderadressen.
- **OAuth:** `GOOGLE_CLIENT_ID`/`SECRET`, `GITHUB_CLIENT_ID`/`SECRET`.
- **Rate limit:** `RATE_LIMIT_VRIJ_EMAILS` (vrijstelling voor specifieke
  e-mailadressen) en `REDIS_URL` (gedeelde teller; zonder deze is de limiter
  in-memory per proces en dus alleen correct met één webworker).
- **Lokale engine (testfase):**
  - `UITSPRAAK_ENGINE_URL` — interne URL van de eigen engine
  - `LOKALE_ENGINE_AAN`, `BEOORDELING_LOKAAL_EERST` — engine aan/uit en leidend maken
  - `LOKAAL_TIMEOUT_S`, `LOKAAL_CORRECT_DREMPEL` — timeout en correctheid-drempel
  - `AZURE_STEEKPROEF_OP` — hoe vaak Azure meedraait bij de steekproef (0 = nooit);
    alleen relevant als een leerling de steekproef heeft aangezet
  - `UITSPRAAK_OVERBELAST_POGINGEN` / `UITSPRAAK_OVERBELAST_WACHT_S` — herkansingen
    als de engine bereikbaar maar vol is (standaard 3 pogingen, 1 s basiswachttijd)
  - `UITSPRAAK_WACHT_TIMEOUT_S` (enginekant) — hoe lang een verzoek op capaciteit
    mag wachten voordat de engine 503 + `Retry-After` stuurt (standaard 8 s)
  - `UITSPRAAK_WORKERS`, `UITSPRAAK_MAX_GELIJKTIJDIG` (enginekant) — aantal
    uvicorn-workers en gelijktijdige opnames per worker
  - `UITSPRAAK_ONNX` (enginekant) — INT8 ONNX Runtime in plaats van torch
    (gemeten ~2-3,4x sneller; zie `/llm/uitspraak-engine.md`)
  - `UITSPRAAK_LAZY` (enginekant) — modellen pas laden als een taal nodig is,
    in plaats van de warm-up bij het opstarten (offline/desktop; standaard uit)
  - `UITSPRAAK_BRUG_URL` — online engine-brug voor de offline desktopbundel;
    leeg in productie, alleen de bundel zet hem (standaard `https://zeg-t.nl`,
    override via `OFFLINE_BRUG_URL`)
  - `PRODUCTIE_BASIS` — basis-URL waarnaar de offline webapp de online-status
    (`GET /api/offline/online/status`) en de online setlijst
    (`GET /api/offline/online/sets`) proxyt; standaard `https://zeg-t.nl`,
    env-overrule mogelijk
- **Mobiel-offline (native Android):**
  - `MOBIEL_BUNDEL_DIR` — cachemap voor de set-bundels en modelbestanden
    (standaard `data/mobiel-offline`)
  - `MOBIEL_MODEL_VERSIE` — versie van referentiemateriaal/modellen; deel van de
    cachesleutel, zodat een nieuwe ONNX-export of TTS-stem niet stil verouderde
    referenties hergebruikt (standaard `onnx-int8-v2`)
  - `MOBIEL_HF_REPO` — HuggingFace-repo met de INT8 ONNX-grafen en `manifest.json`
    (standaard `zegt/uitspraak-onnx-int8`)
- **Publieke snelheidspagina (`/snelheid`):**
  - `SNELHEID_MONITOR_AAN` — aan/uit van de anonieme achtergrondmeting
    (standaard `true`)
  - `SNELHEID_MONITOR_INTERVAL_S` — seconden tussen de achtergrondmetingen
    (standaard `90`; de lus wacht effectief minimaal 15 s)
  - `SNELHEID_TAAL` — taal (2-lettercode) van de gesynthetiseerde oefenzin
    (standaard `en`)
- **Publieke spraaktest (`/praat`):**
  - `PRAAT_OPNAME_DIR` — map met de diagnose-opnames/jobs en de oogst
    (trainingsclips) van de spraaktest (standaard `data/praat-opnames`; zie
    `/llm/api.md`)

## Server en omgevingen

- De FastAPI-app draait als een afzonderlijk applicatieproces achter een reverse
  proxy, beheerd met een process manager; na een code-wijziging wordt het proces
  opnieuw opgestart.
- Er bestaat een afzonderlijke stagingomgeving, afgeschermd van productie, met
  een eigen database; e-mail en OAuth zijn daar bewust uit.

## Lokaal ontwikkelen

- Een dev-script zet een virtuele omgeving op en start de server met hot-reload.

## Uitspraak-engine (losse service)

- De eigen engine draait als aparte service buiten het webproces, bereikbaar via
  een beveiligde privéverbinding. De client in de backend (`lokale_engine.py`)
  stuurt de audio naar deze service.
