Lokale transcriptie op web: whisper.cpp-WASM achter een isolatiepoort (#2513) #2554

Merged
brenno merged 1 commit from feat/transcriptie-05-web-engine into main 2026-10-23 13:10:25 +00:00
Owner

Samenvatting

Bewijst en bouwt de lokale inferentieroute voor de webbundel (#2513). De browser draait whisper.cpp v1.9.5 als WASM in de eigen tab — audio en transcript verlaten die tab nooit; de enige egress is de expliciete, door de gebruiker gestarte modeldownload van huggingface.co met sha256-toegangscontrole.

  • web/whisper/: pthreads-WASM + libmain.js, gebouwd uit dezelfde gepinde bron als de desktop-cli via emscripten/emsdk:3.1.74 (Docker), plus eigen bridge.js (window.ocideckWhisper) en manifest.json met herkomst, toolchain en hashes. De cancel-binding komt van native/whisper_wasm/emscripten-cancel.patch.
  • Drie _web-impls achter de bestaande naden: IndexedDB-modelopslag (.part nooit geïnstalleerd, WebCrypto-sha256, evictie = absent), fetch-downloader (browser-CORS als hopguard, AbortController, streamingvoortgang, falende opruiming kan done niet ophouden), js_interop-engine met exacte ArrayBuffer-slice en module-reset na harde abort.
  • Isolatiepoort: de wasm eist SharedArrayBuffer → crossOriginIsolated → COOP/COEP. web/.htaccess + HOSTING.md schrijven die headers nu voor; zonder ze meldt de engine noIsolation i.p.v. te falen of te beloven.
  • Catalogus: webCapable erbij; large-v3-turbo uitgesloten op web (gemeten abort aan het ~2 GB-WASM-geheugenplafond). base is de lichtste weboptie; tiny blijft bewust weg (kwaliteit onvoldoende, §4.6).
  • Bewijs: native/whisper_wasm/probe/ — reproduceerbare harness + 21 resultaten uit echte Chrome, Firefox en Safari/WebKit, incl. cancel-run en no-COI-abort.

Waarom een test niet kon

De _web-bestanden importeren dart:js_interop en laden niet in de VM-runner — conditional imports kiezen onder flutter test altijd de io-/stub-helft. Ze staan daarom in uncoveredBaseline; het webgedrag is bewezen via de browserprobe in plaats van een widgettest (contracten worden wel gedeeld met de geteste io-helften).

Waardenbotsing

De COI-eis beperkt waar de webbundel inferentie kan doen (soevereiniteit/uitwisselbaarheid vs. functie). De belofte is eerlijk afgegrensd: capability-status in plaats van een breed claim, en HOSTING.md beschrijft de headers. Andere gedachte als er een werkbare niet-pthreads WASM-route blijkt.

Poort

  • make check volledig groen op commit f6fe5c3bb (format, analyze, conventies, 14.301 tests, dekking, golden-suite)
  • make check-web groen (bundled-JS-integriteit, SBOM-check, hardened build, hardening-check, release-artefacten, docs-freshness)
  • make check-secrets (gitleaks + trufflehog, werkmap én historie): schoon
  • make sast (semgrep ocideck.yaml): 0 findings
  • Echte-browserproef: tiny/base/small in Chrome, Firefox, Safari/WebKit — RTF 0,10–0,97; turbo abort zichtbaar; no-COI abort zichtbaar

Generated with Devin (https://devin.ai)

## Samenvatting Bewijst en bouwt de lokale inferentieroute voor de webbundel (#2513). De browser draait whisper.cpp v1.9.5 als WASM in de eigen tab — audio en transcript verlaten die tab nooit; de enige egress is de expliciete, door de gebruiker gestarte modeldownload van huggingface.co met sha256-toegangscontrole. - `web/whisper/`: pthreads-WASM + `libmain.js`, gebouwd uit dezelfde gepinde bron als de desktop-cli via `emscripten/emsdk:3.1.74` (Docker), plus eigen `bridge.js` (`window.ocideckWhisper`) en `manifest.json` met herkomst, toolchain en hashes. De cancel-binding komt van `native/whisper_wasm/emscripten-cancel.patch`. - Drie `_web`-impls achter de bestaande naden: IndexedDB-modelopslag (`.part` nooit geïnstalleerd, WebCrypto-sha256, evictie = `absent`), fetch-downloader (browser-CORS als hopguard, `AbortController`, streamingvoortgang, falende opruiming kan `done` niet ophouden), js_interop-engine met exacte ArrayBuffer-slice en module-reset na harde abort. - Isolatiepoort: de wasm eist `SharedArrayBuffer` → `crossOriginIsolated` → COOP/COEP. `web/.htaccess` + HOSTING.md schrijven die headers nu voor; zonder ze meldt de engine `noIsolation` i.p.v. te falen of te beloven. - Catalogus: `webCapable` erbij; `large-v3-turbo` uitgesloten op web (gemeten abort aan het ~2 GB-WASM-geheugenplafond). `base` is de lichtste weboptie; `tiny` blijft bewust weg (kwaliteit onvoldoende, §4.6). - Bewijs: `native/whisper_wasm/probe/` — reproduceerbare harness + 21 resultaten uit echte Chrome, Firefox en Safari/WebKit, incl. cancel-run en no-COI-abort. ## Waarom een test niet kon De `_web`-bestanden importeren `dart:js_interop` en laden niet in de VM-runner — conditional imports kiezen onder `flutter test` altijd de io-/stub-helft. Ze staan daarom in `uncoveredBaseline`; het webgedrag is bewezen via de browserprobe in plaats van een widgettest (contracten worden wel gedeeld met de geteste io-helften). ## Waardenbotsing De COI-eis beperkt waar de webbundel inferentie kan doen (soevereiniteit/uitwisselbaarheid vs. functie). De belofte is eerlijk afgegrensd: capability-status in plaats van een breed claim, en HOSTING.md beschrijft de headers. Andere gedachte als er een werkbare niet-pthreads WASM-route blijkt. ## Poort - `make check` volledig groen op commit f6fe5c3bb (format, analyze, conventies, 14.301 tests, dekking, golden-suite) - `make check-web` groen (bundled-JS-integriteit, SBOM-check, hardened build, hardening-check, release-artefacten, docs-freshness) - `make check-secrets` (gitleaks + trufflehog, werkmap én historie): schoon - `make sast` (semgrep `ocideck.yaml`): 0 findings - Echte-browserproef: tiny/base/small in Chrome, Firefox, Safari/WebKit — RTF 0,10–0,97; turbo abort zichtbaar; no-COI abort zichtbaar Generated with Devin (https://devin.ai)
De browser draait whisper.cpp als WASM in eigen tabblad — audio verlaat
die tab nooit, de enige egress is de expliciete modeldownload van
Hugging Face met sha256-toegangscontrole. Drie WebAssembly-impls achter
de bestaande conditionele naden: IndexedDB-modelopslag met .part-
semantiek en WebCrypto-verificatie, een fetch-downloader met AbortController
en streamingvoortgang, en een js_interop-engine die via een dunne eigen
bridge (web/whisper/bridge.js) het pthreads-wasm aanstuurt.

De route bestaat alleen achter cross-origin-isolatie: de wasm gebruikt
pthreads en dus SharedArrayBuffer. .htaccess en HOSTING.md schrijven
COOP/COEP nu voor; zonder die headers meldt de engine eerlijk
noIsolation in plaats van een belofte die niet klopt. large-v3-turbo is
met webCapable: false uitgesloten — gemeten abort aan het 2 GB-WASM-
plafond. Dekt §4.6 en §5.3 van het contract; het meetbewijs per browser
(Chrome, Firefox, Safari/WebKit) ligt in native/whisper_wasm/probe/.

Botsing benoemd: de COI-eis beperkt waar de webbundel werkt, maar de
belofte wordt daardoor eerlijk in plaats van breed en onwaar.

Generated with Devin (https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
brenno merged commit 02ced407f0 into main 2026-10-23 13:10:25 +00:00
Sign in to join this conversation.
No description provided.