Skip to content

Commit e6b29bf

Browse files
Merge branch 'main' into chore/zad-verbindingsgrens-documenteren
2 parents 26353b7 + 185fbb8 commit e6b29bf

1 file changed

Lines changed: 83 additions & 0 deletions

File tree

docs/vergelijking-fbs-vorijk.md

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,3 +201,86 @@ Voor de huidige PoC: **nog niet implementeren**, maar wel de architectuur voorbe
201201
- [NL-Wallet (EDI-wallet) open source repository](https://github.com/MinBZK/nl-wallet)
202202
- [EDI-wallet informatie (edi.pleio.nl)](https://edi.pleio.nl)
203203
- [SD-JWT VC specificatie (IETF draft)](https://datatracker.ietf.org/doc/draft-ietf-oauth-sd-jwt-vc/)
204+
205+
---
206+
207+
## Appendix: Berichten cachen en doorzoeken in de client (Proton Mail-model)
208+
209+
### Aanleiding
210+
211+
In het blauwe-knop-model ligt de aggregatie bij de burger-app en niet bij een uitvraagsysteem. Daarmee verschuift ook de vraag waar opgehaalde berichten blijven staan en hoe je erin zoekt. Browseropslag leek daarvoor eerder te krap — zeker in Safari, waar de opslag bovendien tijdelijk bleek.
212+
213+
Proton Mail doet het wel. Hun server kan de berichten niet lezen (client-side encryptie), dus zoeken op inhoud kán alleen lokaal. Dat maakt hun ontwerp interessant als referentie: het is een werkend voorbeeld van een aggregaat dat volledig in de client leeft.
214+
215+
### Hoe Proton het oplost
216+
217+
De index is een **versleutelde forward index in IndexedDB** — geen inverted index.
218+
219+
1. Bericht van de server halen en lokaal OpenPGP-decrypten
220+
2. HTML-markup strippen tot platte tekst (scheelt fors in volume)
221+
3. Opnieuw versleutelen met **AES-GCM** via de Web Crypto API
222+
4. Wegschrijven in IndexedDB, met het message-ID als key
223+
224+
De symmetrische indexsleutel is zelf versleuteld onder de sleutel van de gebruiker. De index verlaat de browser nooit en moet per browser per apparaat opnieuw worden opgebouwd.
225+
226+
**Zoeken is een lineaire scan**: alle berichten worden in het geheugen ontsleuteld en op substring gematcht, met resultaten die incrementeel binnenkomen. Geen tokenisatie, geen postings-lijsten.
227+
228+
Proton motiveert die keuze met eenvoud en met exacte frase-matching, die in een inverted index extra structuur vereist. Veelzeggend is dat hun losse bibliotheek `ProtonMail/encrypted-search` — een getokeniseerde inverted index mét `AND`/`OR`/`PHRASE`/`PROXIMITY`/`WILDCARD` — in november 2021 is gearchiveerd. Dat is de weg die ze niet zijn ingeslagen.
229+
230+
### De opslaggrens wordt niet opgelost, maar toegegeven
231+
232+
Proton omzeilt de beperking niet; ze degraderen zichtbaar:
233+
234+
> "In rare cases, the contents of a large inbox may require more storage capacity than your browser offers."
235+
236+
Past de mailbox niet, dan indexeren ze **partieel en nieuwste-eerst**, en toont de UI een datum die aangeeft hoe ver terug het zoeken op inhoud reikt. Die datum schuift mee als er nieuwe berichten binnenkomen. In private/incognito-modus werkt de functie niet. Raakt de index corrupt, dan is het advies: browserdata wissen en opnieuw opbouwen.
237+
238+
De index is bij hen dus een **wegwerpbare cache** die altijd herbouwbaar is uit de server — nooit een bron van waarheid.
239+
240+
### Wat er sinds de eerdere analyse veranderd is (Safari)
241+
242+
| Aspect | Stand van zaken |
243+
|--------|-----------------|
244+
| **Quota per origin** | WebKit staat een origin tot **60% van de totale schijfruimte** toe (browser-apps), met 80% als totaal over alle origins. Voor niet-browser-apps is dat 15%/20%. Ruimte is daarmee niet meer de knellende factor. |
245+
| **Eviction** | De ITP-regel blijft: een origin zonder user-interaction binnen zeven dagen browsergebruik verliest **alle** script-writable storage — in één keer, niet gedeeltelijk. |
246+
| **Ontsnapping** | Safari 17+ ondersteunt de Storage API volledig. `navigator.storage.persist()` kan persistent mode geven, maar WebKit kent die toe op heuristiek; het genoemde voorbeeld is een site die als Home Screen Web App is geopend. Als gewoon tabblad is het geen garantie. |
247+
248+
De conclusie verschuift daarmee van "er is te weinig ruimte" naar "de ruimte is er, maar de bewaartermijn is niet gegarandeerd".
249+
250+
### Waarom het model niet zomaar overdraagbaar is
251+
252+
De drijfveer verschilt fundamenteel, en dat bepaalt de kosten van een verloren cache.
253+
254+
| | Proton Mail | Blauwe knop / VoRijk | FBS (deze PoC) |
255+
|--|-------------|----------------------|----------------|
256+
| **Waarom in de client?** | Cryptografisch — de server *kan* niet lezen | Architectonisch — er *mag* geen intermediair een kopie houden | Niet in de client; sessiecache in Redis, server-side |
257+
| **Herstel na verlies** | Eén server opnieuw bevragen | Fan-out naar álle bronorganisaties, mét sessie-opzet per organisatie | Opnieuw ophalen bij de magazijnen via de uitvraag |
258+
| **Kosten van eviction** | Laag | Hoog | N.v.t. — TTL-gestuurd en bedoeld |
259+
260+
Voor Proton is een weggegooide index een vervelende, maar goedkope her-synchronisatie. Bij blauwe knop is opnieuw opbouwen precies de dure operatie: een fan-out over alle bronorganisaties, waarbij elke organisatie een eigen challenge/response en credential-presentatie vereist. Eviction na zeven dagen betekent dan dat de hele keten wekelijks opnieuw wordt aangeslingerd.
261+
262+
Daar staat tegenover dat **VoRijk een native mobiele app is, geen browser**. Dan gelden er geen IndexedDB-quota en geen ITP: je hebt gewone bestandsopslag plus Keychain/Keystore voor de sleutels. Het Safari-vraagstuk is in dat geval een browser-probleem, geen blauwe-knop-probleem. Het speelt alleen als je blauwe knop óók in een webcontext wil aanbieden — en dan is een PWA op het beginscherm de enige route naar opslag die blijft staan.
263+
264+
### Wat wél overneembaar is
265+
266+
1. **Behandel de client-cache als wegwerpbaar.** De cache is een prestatie-optimalisatie, nooit de bron van waarheid. Dat is dezelfde keuze als bij de FBS-sessiecache, die met een sliding TTL in Redis staat en altijd opnieuw gevuld kan worden uit de magazijnen.
267+
268+
2. **Partiële index, nieuwste-eerst, met een expliciete grens in de UI.** Een zichtbare melding "zoeken in inhoud vanaf <datum>" is eerlijker dan stilzwijgend onvolledige resultaten tonen. Dit patroon is bruikbaar ongeacht welke opslagstrategie verder gekozen wordt.
269+
270+
3. **Lineaire scan volstaat ruimschoots.** Proton doet dit over mailboxen met tienduizenden berichten. Hier zijn berichten enkele kilobytes groot — `Bericht.MAX_INHOUD_BYTES` (1 MiB) is een validatieplafond, geen werkpunt. Een inverted index bouwen zou over-engineering zijn; neem hun conclusie over, niet hun gearchiveerde bibliotheek.
271+
272+
4. **Versleutel de lokale opslag alsnog.** Ook als de inhoud onderweg niet end-to-end versleuteld is, beschermt een AES-GCM-laag over de lokale index tegen een aanvaller met toegang tot het apparaat of het browserprofiel.
273+
274+
### Open punten
275+
276+
- De exacte opslaglimiet die Proton in de client hanteert is niet uit de openbare bronnen te halen; ze noemen wel het gedrag bij overschrijding, niet de drempel.
277+
- Hoe hun **native** clients (iOS/Android) dit doen is niet gedocumenteerd in de engineering-post — die gaat uitsluitend over de webclient. Juist dat is voor een app-gebaseerd blauwe-knop-model de relevantere vraag.
278+
- Of `navigator.storage.persist()` in Safari buiten de Home Screen Web App betrouwbaar wordt toegekend, is niet gespecificeerd; WebKit noemt alleen "heuristics".
279+
280+
### Bronnen
281+
282+
- [Behind the scenes of Proton Mail's message content search](https://proton.me/blog/engineering-message-content-search)
283+
- [Search message content in Proton Mail (support)](https://proton.me/support/search-message-content)
284+
- [ProtonMail/encrypted-search (gearchiveerd, MIT)](https://github.com/ProtonMail/encrypted-search)
285+
- [Updates to Storage Policy — WebKit](https://webkit.org/blog/14403/updates-to-storage-policy/)
286+
- [Storage quotas and eviction criteria — MDN](https://developer.mozilla.org/en-US/docs/Web/API/Storage_API/Storage_quotas_and_eviction_criteria)

0 commit comments

Comments
 (0)