fix(privacy): redactie liet de afbeelding gewoon staan #372

Merged
brenno merged 2 commits from fix/image-redaction into main 2026-07-19 16:53:57 +00:00
Owner

Twee dingen: de gemelde bug, en de CI/module-vraag.

De bug

De beeldcontrole meldt keurig een herkenbaar gezicht, je zet de slide op redact — en de foto blijft staan. Detectie zonder consequentie is erger dan geen detectie, want de auteur denkt dat het geregeld is.

De oorzaak is architectonisch: de projectie is synchroon en redigeert tekstvelden, terwijl de beeldbevindingen uit een asynchrone provider komen en als kwaliteitsmelding eindigen. De projectie zag ze nooit.

Op een geredigeerde slide verdwijnt nu de héle mediaverwijzing — afbeelding, tweede afbeelding, video en audio. De bestaande placeholder toont een zichtbaar vak, zodat de ontvanger ziet dát er iets weg is. De bron blijft ongemoeid.

Waarom niet alleen het gezicht zwart maken. Dat zou aantrekkelijker lijken en is precies de val. De detector vindt gezichten en mist er aantoonbaar; hij leest geen HEIC, ziet geen tekst in beeld — een gefotografeerd formulier met een BSN erop dus niet — en de gebruiker mag hem uitzetten. Het resultaat zou een afbeelding zijn die eruitziet alsof ze is afgehandeld, met een gemist gezicht er nog op. Dezelfde fout als het zwarte blok op "diagnose" dat niets verborg. De afweging staat al in statementSpan: te ruim redigeren is hinderlijk, te krap redigeren is een lek.

Een tweede lek van dezelfde soort, onderweg gevonden

struct.user_path detecteert een gebruikersnaam in een mediapad. Het ontwerp meldde die wel maar redigeerde hem niet, omdat een pad met blokjes erin een kapotte verwijzing oplevert. Die redenering klopt — maar het gevolg was dat op een redact-slide /Users/<voornaam.achternaam>/… letterlijk in de geëxporteerde markdown belandde. Gedetecteerd, gemeld, en vervolgens meegeleverd. Gemeten, niet vermoed.

De test die dat oude gedrag vastlegde is omgedraaid met de reden erbij, en er staat een tweede test naast die bewaakt dat zonder redactie het pad wél ongemoeid blijft.

CI: Linux en Windows erbij

De Linux-gate draait al de volledige suite, dus daar hoefde alleen de build ervoor plus de apt-pakketten. Windows krijgt hetzelfde patroon als macOS met een ander pad (CMake in plaats van CocoaPods). Beide falen hard als de bibliotheek er niet staat.

Module-selectie: uitgezocht, niet aangezet

En hier moet ik een correctie maken op wat ik zelf in §13.8 had opgeschreven. Ik gaf include_modules als recept. Dat doet niets. Uit gen_cmake_vars.dart:

e: exclude.contains(e) ? "OFF" : defaultModuleSettings[e]!

Alleen exclude_modules zet een module uit; include_modules beschermt er één tégen uitsluiting. Wie mijn oude tekst volgde kreeg een build die er geconfigureerd uitzag en niets uitsloot. De juiste vorm staat er nu, met de acht modules die eruit mogen — afgeleid uit defaultModuleSettings, niet uit een blogpost.

Bewust nog niet aangezet. Ik kon het niet meten: geen Linux- of Windows-machine. En een uitgesloten module houdt zijn Dart-API maar gooit "symbol not found" bij aanroep — blind aanzetten zou precies de stille runtimefout zetten die hier al twee keer is voorgekomen. Het experiment staat in vier stappen beschreven, inclusief de verificatie die je niet mag overslaan: bouwen is geen bewijs.

Ook vastgelegd: macOS en iOS krijgen een voorgebouwde CocoaPod en kunnen sowieso niet snoeien. De 27 MB daar blijft.

make check groen.

🤖 Generated with Claude Code

Twee dingen: de gemelde bug, en de CI/module-vraag. ## De bug De beeldcontrole meldt keurig een herkenbaar gezicht, je zet de slide op `redact` — en de foto blijft staan. **Detectie zonder consequentie is erger dan geen detectie**, want de auteur denkt dat het geregeld is. De oorzaak is architectonisch: de projectie is synchroon en redigeert tekstvelden, terwijl de beeldbevindingen uit een asynchrone provider komen en als kwaliteitsmelding eindigen. De projectie zag ze nooit. Op een geredigeerde slide verdwijnt nu de **héle mediaverwijzing** — afbeelding, tweede afbeelding, video en audio. De bestaande placeholder toont een zichtbaar vak, zodat de ontvanger ziet dát er iets weg is. De bron blijft ongemoeid. **Waarom niet alleen het gezicht zwart maken.** Dat zou aantrekkelijker lijken en is precies de val. De detector vindt gezichten en mist er aantoonbaar; hij leest geen HEIC, ziet geen tekst in beeld — een gefotografeerd formulier met een BSN erop dus niet — en de gebruiker mag hem uitzetten. Het resultaat zou een afbeelding zijn die eruitziet alsof ze is afgehandeld, met een gemist gezicht er nog op. Dezelfde fout als het zwarte blok op "diagnose" dat niets verborg. De afweging staat al in `statementSpan`: *te ruim redigeren is hinderlijk, te krap redigeren is een lek.* ## Een tweede lek van dezelfde soort, onderweg gevonden `struct.user_path` detecteert een gebruikersnaam in een mediapad. Het ontwerp meldde die wel maar redigeerde hem niet, omdat een pad met blokjes erin een kapotte verwijzing oplevert. Die redenering klopt — maar het gevolg was dat op een `redact`-slide `/Users/<voornaam.achternaam>/…` **letterlijk in de geëxporteerde markdown belandde**. Gedetecteerd, gemeld, en vervolgens meegeleverd. Gemeten, niet vermoed. De test die dat oude gedrag vastlegde is omgedraaid met de reden erbij, en er staat een tweede test naast die bewaakt dat zonder redactie het pad wél ongemoeid blijft. ## CI: Linux en Windows erbij De Linux-gate draait al de volledige suite, dus daar hoefde alleen de build ervoor plus de apt-pakketten. Windows krijgt hetzelfde patroon als macOS met een ander pad (CMake in plaats van CocoaPods). Beide falen hard als de bibliotheek er niet staat. ## Module-selectie: uitgezocht, niet aangezet En hier moet ik een correctie maken op wat ik zelf in §13.8 had opgeschreven. Ik gaf `include_modules` als recept. **Dat doet niets.** Uit `gen_cmake_vars.dart`: ```dart e: exclude.contains(e) ? "OFF" : defaultModuleSettings[e]! ``` Alleen `exclude_modules` zet een module uit; `include_modules` beschermt er één tégen uitsluiting. Wie mijn oude tekst volgde kreeg een build die er geconfigureerd uitzag en niets uitsloot. De juiste vorm staat er nu, met de acht modules die eruit mogen — afgeleid uit `defaultModuleSettings`, niet uit een blogpost. **Bewust nog niet aangezet.** Ik kon het niet meten: geen Linux- of Windows-machine. En een uitgesloten module houdt zijn Dart-API maar gooit "symbol not found" bij aanroep — blind aanzetten zou precies de stille runtimefout zetten die hier al twee keer is voorgekomen. Het experiment staat in vier stappen beschreven, inclusief de verificatie die je niet mag overslaan: bouwen is geen bewijs. Ook vastgelegd: macOS en iOS krijgen een voorgebouwde CocoaPod en kunnen sowieso niet snoeien. De 27 MB daar blijft. `make check` groen. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Gemeld na testen: de beeldcontrole meldt keurig een herkenbaar gezicht, je
zet de slide op `redact` — en de foto blijft staan. Detectie zonder
consequentie is erger dan geen detectie, want de auteur denkt dat het
geregeld is.

De oorzaak is architectonisch: de projectie is synchroon en redigeert
tekstvelden, terwijl de beeldbevindingen uit een asynchrone provider komen
en als kwaliteitsmelding eindigen. De projectie zag ze dus nooit.

Op een geredigeerde slide verdwijnt nu de héle mediaverwijzing —
afbeelding, tweede afbeelding, video en audio. De bestaande placeholder
toont een zichtbaar vak, zodat de ontvanger ziet dát er iets weg is. De bron
blijft ongemoeid.

Alléén het gedetecteerde gezicht zwart maken zou aantrekkelijker lijken, en
is precies de val. De detector vindt gezichten en mist er aantoonbaar; hij
leest geen HEIC, ziet geen tekst in beeld — een gefotografeerd formulier met
een BSN erop dus niet — en de gebruiker mag hem uitzetten. Het resultaat zou
een afbeelding zijn die eruitziet alsof ze is afgehandeld, met een gemist
gezicht er nog op. Dat is dezelfde fout als het zwarte blok op "diagnose"
dat niets verborg. De afweging staat al in `statementSpan` en geldt
onverkort: te ruim redigeren is hinderlijk, te krap redigeren is een lek.
Dat een logo op zo'n slide meesneuvelt is de hinderlijke kant.

Onderweg bleek er een tweede lek van dezelfde soort te zitten, en die is nu
ook dicht. `struct.user_path` detecteert een gebruikersnaam in een mediapad;
het ontwerp meldde die wel maar redigeerde hem niet, omdat een pad met
blokjes erin een kapotte verwijzing oplevert. Die redenering klopt — maar het
gevolg was dat op een `redact`-slide `/Users/jan.jansen/…` letterlijk in de
geëxporteerde markdown belandde. Gedetecteerd, gemeld, en vervolgens gewoon
meegeleverd. Gemeten, niet vermoed.

De test die dat oude gedrag vastlegde is omgedraaid, met de reden erbij, en
er staat een tweede test naast die bewaakt dat zonder redactie het pad wél
ongemoeid blijft. Karakters weglakken ín een pad gebeurt nog steeds niet.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
ci(privacy): de beeldtests draaien nu ook op Linux en Windows
Some checks failed
CI / Gate (Linux) · Format · Analyze · Coverage (push) Has been cancelled
CI / Test (macos-latest) (push) Has been cancelled
CI / Test (windows-latest) (push) Has been cancelled
CI / Web hardening (push) Has been cancelled
CI / Docs links (push) Has been cancelled
CI / Supply-chain (Trivy · advisory) (push) Has been cancelled
CI / Gate (Linux) · Format · Analyze · Coverage (pull_request) Has been cancelled
CI / Test (macos-latest) (pull_request) Has been cancelled
CI / Test (windows-latest) (pull_request) Has been cancelled
CI / Web hardening (pull_request) Has been cancelled
CI / Docs links (pull_request) Has been cancelled
CI / Supply-chain (Trivy · advisory) (pull_request) Has been cancelled
03ca76fd2b
Vervolg op de macOS-stap uit #364. OciDeck komt op zoveel mogelijk
platformen uit, dus de detectietests horen niet op één ervan te leunen.

De Linux-gate draait al de volledige suite, dus daar hoefde alleen de build
ervoor — plus de apt-pakketten die `flutter build linux` nodig heeft. Windows
zit in de matrix en krijgt hetzelfde patroon als macOS, met een ander pad:
CMake in plaats van CocoaPods. Beide stappen falen hard als de bibliotheek
niet staat waar ze wordt verwacht, in plaats van stil terug te vallen op
overslaan — dat is de hele reden dat deze stappen bestaan.

── En een correctie op wat ik zelf had opgeschreven ──

§13.8 gaf `include_modules` als recept om de bundel te snoeien. Dat doet
niets. Lees `gen_cmake_vars.dart`:

    e: exclude.contains(e) ? "OFF" : defaultModuleSettings[e]!

Alleen `exclude_modules` zet een module uit; `include_modules` dient
uitsluitend om er één tégen uitsluiting te beschermen. Wie mijn oude tekst
volgde, kreeg een build die er geconfigureerd uitzag en niets uitsloot. De
juiste vorm staat er nu, met de acht modules die eruit mogen, afgeleid uit
`defaultModuleSettings` en niet uit een blogpost.

Het staat bewust nog niet áán. Dit is nooit gemeten — er was geen Linux- of
Windows-machine — en een uitgesloten module houdt zijn Dart-API maar gooit
"symbol not found" bij aanroep. Blind aanzetten zou precies de stille
runtimefout zetten die deze codebase al twee keer heeft opgeleverd. Het
experiment staat er in vier stappen bij, inclusief de verificatie die je
níét mag overslaan: bouwen is geen bewijs, de detector moet daarna nog
werken.

Ook vastgelegd: macOS en iOS krijgen een voorgebouwde CocoaPod en kunnen dus
sowieso niet snoeien. De 27 MB daar blijft.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
brenno merged commit c821321c7c into main 2026-07-19 16:53:57 +00:00
Sign in to join this conversation.
No description provided.