Optionele ASR-serverroute voor batchtranscriptie (#2524) #2555

Merged
brenno merged 1 commit from feat/transcriptie-16-asr-server into main 2026-10-23 13:53:54 +00:00
Owner

Samenvatting

De optionele ASR-serverinterface van #2524: een door de gebruiker gekozen endpoint voor batchtranscriptie, zonder ooit de local-first belofte stil te doorbreken.

  • Eigen profiel, eigen poort — AsrServerProfile is géén modus van AiClientService; AsrServerGate beslist puur en I/O-vrij óf en hóe een verzoek mag vertrekken (drie tiers: loopback / LAN-met-opt-in / cloud-met-HTTPS-plus-bevestiging, elk fail-closed).
  • Per-taakconsent — ServerConsent benoemt host én audiobron; de engine weigert elke mismatch als ConsentRequired. Geen retries, geen stille fallback (ook geen locale→server of andersom).
  • Transport — desktop pint de socket via buildPinnedClient en weigert redirects; web gebruikt CORS-fetch + AbortController (de browser is daar de grens; LAN-http wordt eerlijk geweigerd als gegarandeerde mixed-content).
  • Geheimen — de API-sleutel staat in SecretStore onder een eigen prefix, per verzoek gelezen, alleen in de Authorization-header; URL's met user:pass@ zijn per definitie ongeldig.
  • Begrensd en afbreekbaar — upload ≤ 400 MB, respons ≤ 16 MB, timeouts, cancel() vertaalt naar Cancelled (ook een abort vóór openUrl hangt nooit).
  • Protocol — het bewezen whisper.cpp-whisper-server-contract (POST /inference, multipart file, verbose_json); universele ASR-compatibiliteit wordt niet geclaimd. probe() toetst bereikbaarheid zonder audio.

Tests: 15 gate-, 18 engine-, 7 echte-socket-transport-, 10 profiel- en 7 route/provider-tests. Lokale poort: make check + check-secrets + sast + check-web allemaal groen.

Afwegingen (security/privacy)

  • Dit is dé bewuste egress-uitzondering van de epic: audio verlaat het apparaat alleen via een profiel dat de gebruiker aanzette én per taak bevestigde. PRIVACY.md noemt de route expliciet, inclusief dat serverretentie serverbeleid is en géén OciDeck-garantie.
  • Op web mag cloud juist wél (dat is de route die dit ticket bedient); LAN-http wordt daar geweigerd omdat het onder mixed content nooit kan werken.
  • ServerConsent is een token op TranscriptionOptions — de zichtbare consentdialoog komt met #2515/#2522; de instellingskaart met #2514. De engine kan nu al niet worden misleid.

Testplan

  • flutter test test/transcription/ — 190+ tests groen
  • make check, make check-secrets, make sast, make check-web — allemaal groen
  • Handmatig: echte whisper-server loopback-acceptatie volgt in #2515's flow

Generated with Devin

## Samenvatting De optionele ASR-serverinterface van #2524: een door de gebruiker gekozen endpoint voor batchtranscriptie, zonder ooit de local-first belofte stil te doorbreken. - **Eigen profiel, eigen poort** — `AsrServerProfile` is géén modus van `AiClientService`; `AsrServerGate` beslist puur en I/O-vrij óf en hóe een verzoek mag vertrekken (drie tiers: loopback / LAN-met-opt-in / cloud-met-HTTPS-plus-bevestiging, elk fail-closed). - **Per-taakconsent** — `ServerConsent` benoemt host én audiobron; de engine weigert elke mismatch als `ConsentRequired`. Geen retries, geen stille fallback (ook geen locale→server of andersom). - **Transport** — desktop pint de socket via `buildPinnedClient` en weigert redirects; web gebruikt CORS-`fetch` + `AbortController` (de browser is daar de grens; LAN-`http` wordt eerlijk geweigerd als gegarandeerde mixed-content). - **Geheimen** — de API-sleutel staat in `SecretStore` onder een eigen prefix, per verzoek gelezen, alleen in de `Authorization`-header; URL's met `user:pass@` zijn per definitie ongeldig. - **Begrensd en afbreekbaar** — upload ≤ 400 MB, respons ≤ 16 MB, timeouts, `cancel()` vertaalt naar `Cancelled` (ook een abort vóór `openUrl` hangt nooit). - **Protocol** — het bewezen whisper.cpp-`whisper-server`-contract (`POST /inference`, multipart `file`, `verbose_json`); universele ASR-compatibiliteit wordt niet geclaimd. `probe()` toetst bereikbaarheid zonder audio. Tests: 15 gate-, 18 engine-, 7 echte-socket-transport-, 10 profiel- en 7 route/provider-tests. Lokale poort: `make check` + `check-secrets` + `sast` + `check-web` allemaal groen. ## Afwegingen (security/privacy) - Dit is dé bewuste egress-uitzondering van de epic: audio verlaat het apparaat **alleen** via een profiel dat de gebruiker aanzette én per taak bevestigde. PRIVACY.md noemt de route expliciet, inclusief dat serverretentie serverbeleid is en géén OciDeck-garantie. - Op web mag `cloud` juist wél (dat is de route die dit ticket bedient); LAN-`http` wordt daar geweigerd omdat het onder mixed content nooit kan werken. - `ServerConsent` is een token op `TranscriptionOptions` — de zichtbare consentdialoog komt met #2515/#2522; de instellingskaart met #2514. De engine kan nu al niet worden misleid. ## Testplan - [x] `flutter test test/transcription/` — 190+ tests groen - [x] `make check`, `make check-secrets`, `make sast`, `make check-web` — allemaal groen - [ ] Handmatig: echte whisper-server loopback-acceptatie volgt in #2515's flow Generated with [Devin](https://devin.ai)
De enige plaats waar audio het apparaat mag verlaten — en alleen omdat
de gebruiker het zo instelde: een eigen serverprofiel (géén modus van
AiClientService) in drie vertrouwensklassen, elk achter een eigen
opt-in. De egresspoort beslist puur vóór er een byte vertrekt; het
transport pint de socket via buildPinnedClient (desktop) of laat de
browser via CORS/preflight de grens zijn (web). Consent is een per-taak
token dat host én audiobron exact benoemt; de engine weigert elke
mismatch als ConsentRequired. Geen retries, geen stille fallback naar
of van lokaal. De API-sleutel staat in de sleutelbos en reist alleen in
de Authorization-header. Protocol: het bewezen whisper.cpp
whisper-server POST /inference-contract — geen claim van universele
ASR-compatibiliteit. probe() toetst bereikbaarheid zonder audio.
brenno merged commit 9bcd49f0b6 into main 2026-10-23 13:53:54 +00:00
Sign in to join this conversation.
No description provided.