Bouw de opnamegrens van transcriptie: sessie, indicator en eindwegen (#2510) #2551

Merged
brenno merged 1 commit from feat/transcriptie-02-opnamegrens into main 2026-10-22 22:50:44 +00:00
Owner

Tweede deel van de transcriptie-epiek (#2508), op het contract uit #2509.

Wat dit is

De provider-neutrale grens lib/services/transcription/ plus alles wat "een opname loopt" betekent:

  • CaptureSource (§4.1): probeerbare capaciteit zónder permissieprompt — toestemming volgt pas op de bewuste startknop. CaptureRequest draagt de bevestigde deelnemersmelding; bronnen die andermans stemmen kunnen vangen eisen hem, microfoon-only niet.
  • TranscriptionEngine (§4.2–4.3): eigen profiel, nooit een modus van AiClientService. transcriptionEngineProvider is null tot een platformengine landt (#2512+); de grens beantwoordt dat als engineUnavailable.
  • Fouttaxonomie (§4.4): sealed TranscriptionError — permissie, bronverlies, niet-ondersteunde bron, decode, engine, capaciteit, serverweigering, consent, annulering en io zijn elk een eigen benoemde vervolgstap.
  • RecordingManager/RecordingHandle: stagingmap bestaat vóór de bron start (gefaalde start = geen weesmap), stop is idempotent, een gefaalde stop eindigt in failed, en elke eindweg — Stop, module uit, app quit, bronverlies — loopt door dezelfde shutdown.
  • Indicator: root-scoped strook in de app-shellbanner (bron + duur + echte Stop-knop, live-region Semantics), overleeft tabwissels en kan niet verborgen worden door de moduleschakelaar.
  • Module: ModuleId.transcription in register, kaart op Uitbreidingen, uit-by-default met bewaarde voorkeur. Module uitzetten stopt een lopende opname — de kaart zegt dat ook.
  • Staging: sessiemap onder OS-temp, sweep met de 7-daagse herstelperiode (gedeeld met documentrecovery); op web een eerlijke no-op (mem:-assets). PRIVACY.md beschrijft de tijdelijke opslag.

Botsing die bewust is genomen

Privacy (opgenomen audio op schijf) tegen betrouwbaarheid (crasherstel): de opname landt in een tijdelijke stagingmap, nooit in het deck; de sweep deelt de bestaande herstelperiode en de bewaar/weg-keuze bij save (#2515) sluit de levenscyclus. Gedocumenteerd in PRIVACY.md. Verder geen formaatwijziging, geen egress, geen nieuwe partij te vertrouwen.

Bewijs

  • make check groen op 2f31bb643 (incl. golden-suite; één herhaling nodig wegens de bekende loader-flake #798, niet gerelateerd).
  • make check-secrets groen (gitleaks + trufflehog, werkbon én historie).
  • make sast groen (semgrep, 0 findings).
  • Beeldkeuring: strook en kaart gerenderd in licht én donker — bron/duur/Stop leesbaar, kaart uit-by-default.

Nog niet in deze PR (later tickets)

Geen echte microfoonbron, geen engine, geen transcript-marker in .md (#2511), geen save-flow met bewaar/weg-keuze (#2515). De grens is er klaar voor; de routes volgen.

Tweede deel van de transcriptie-epiek (#2508), op het contract uit #2509. ## Wat dit is De provider-neutrale grens `lib/services/transcription/` plus alles wat "een opname loopt" betekent: - **CaptureSource** (§4.1): probeerbare capaciteit zónder permissieprompt — toestemming volgt pas op de bewuste startknop. `CaptureRequest` draagt de bevestigde deelnemersmelding; bronnen die andermans stemmen kunnen vangen eisen hem, microfoon-only niet. - **TranscriptionEngine** (§4.2–4.3): eigen profiel, nooit een modus van `AiClientService`. `transcriptionEngineProvider` is `null` tot een platformengine landt (#2512+); de grens beantwoordt dat als `engineUnavailable`. - **Fouttaxonomie** (§4.4): `sealed TranscriptionError` — permissie, bronverlies, niet-ondersteunde bron, decode, engine, capaciteit, serverweigering, consent, annulering en io zijn elk een eigen benoemde vervolgstap. - **RecordingManager/RecordingHandle**: stagingmap bestaat vóór de bron start (gefaalde start = geen weesmap), stop is idempotent, een gefaalde stop eindigt in `failed`, en elke eindweg — Stop, module uit, app quit, bronverlies — loopt door dezelfde shutdown. - **Indicator**: root-scoped strook in de app-shellbanner (bron + duur + echte Stop-knop, live-region `Semantics`), overleeft tabwissels en kan niet verborgen worden door de moduleschakelaar. - **Module**: `ModuleId.transcription` in register, kaart op Uitbreidingen, uit-by-default met bewaarde voorkeur. Module uitzetten stopt een lopende opname — de kaart zegt dat ook. - **Staging**: sessiemap onder OS-temp, sweep met de 7-daagse herstelperiode (gedeeld met documentrecovery); op web een eerlijke no-op (`mem:`-assets). `PRIVACY.md` beschrijft de tijdelijke opslag. ## Botsing die bewust is genomen Privacy (opgenomen audio op schijf) tegen betrouwbaarheid (crasherstel): de opname landt in een tijdelijke stagingmap, nooit in het deck; de sweep deelt de bestaande herstelperiode en de bewaar/weg-keuze bij save (#2515) sluit de levenscyclus. Gedocumenteerd in `PRIVACY.md`. Verder geen formaatwijziging, geen egress, geen nieuwe partij te vertrouwen. ## Bewijs - `make check` groen op `2f31bb643` (incl. golden-suite; één herhaling nodig wegens de bekende loader-flake #798, niet gerelateerd). - `make check-secrets` groen (gitleaks + trufflehog, werkbon én historie). - `make sast` groen (semgrep, 0 findings). - Beeldkeuring: strook en kaart gerenderd in licht én donker — bron/duur/Stop leesbaar, kaart uit-by-default. ## Nog niet in deze PR (later tickets) Geen echte microfoonbron, geen engine, geen transcript-marker in .md (#2511), geen save-flow met bewaar/weg-keuze (#2515). De grens is er klaar voor; de routes volgen.
Provider-neutrale grens onder lib/services/transcription/ zoals het
contract (TRANSCRIPTION.md §4) voorschrijft: CaptureSource met
probeerbare capaciteit zonder permissieprompt, TranscriptionEngine als
eigen profiel (nooit een modus van AiClientService), en een getypte
fouttaxonomie die permissie, bronverlies, engine-afwezigheid, consent,
annulering en io-fouten uit elkaar houdt.

RecordingManager/RecordingHandle bezit "een opname loopt": de
stagingmap bestaat vóór de bron start (een gefaalde start laat geen
wees achter), bronnen die andermans stemmen kunnen vangen eisen een
bevestigde deelnemersmelding, stop is idempotent, en elke eindweg —
Stop, module uit, app quit, bronverlies — loopt door dezelfde
shutdown. De indicator hangt root-scoped in de app-shellbanner met
bron, duur en een echte Stop-knop, met live-region-semantiek, en
overleeft een tabwissel; module uitzetten stopt de opname maar kan de
strook niet verbergen. De module staat uit-by-default in Uitbreidingen.

Staging is een sessiemap onder de OS-temp, met dezelfde
7-daagse herstelperiode als documentrecovery — PRIVACY.md beschrijft
die tijdelijke opslag nu. Bewaker-toets: geen formaatwijziging, geen
egress, geen nieuwe partij te vertrouwen; de botsing die er is —
opgenomen audio ligt tijdelijk op schijf voor crasherstel — is
benoemd en gedocumenteerd, met de sweep en de bewaar/wegkeuze bij
save als begrenzing.

Signed-off-by: Brenno de Winter <brennodewinter@users.noreply.github.com>
brenno force-pushed feat/transcriptie-02-opnamegrens from 7e029950c0 to 2f31bb6431 2026-10-22 22:38:09 +00:00 Compare
brenno merged commit 1c879a4f13 into main 2026-10-22 22:50:44 +00:00
Sign in to join this conversation.
No description provided.