feat(ociserve): sluit de deelnemersketen op OciServe (#2422–#2430) #2444

Merged
brenno merged 15 commits from feat/ociserve-deelnemer-keten into main 2026-10-15 20:15:24 +00:00
Owner

Samenvatting

Sluit de deelnemersgerichte integratiegaten uit de keten-audit van 2026-10-14 (#2422–#2430). PR #2432 had evidence-items en me/exam-results al aangesloten; deze PR bouwt daarop verder.

  • #2422 badge-leesmodel per kwalificatie in Mijn bewijs; openstaande bewijseis opent het aanleverscherm met de soort ingevuld
  • #2423 echte portefeuille-flow: externe credentials ophalen, selecteren, als bewijsstuk delen; bewijsstukken intrekbaar
  • #2424 al gedekt door me/exam-results uit #2432
  • #2425 uitnodigingswizard: preview → registratie (nieuw) of acceptatie (bestaand), met login_hint + prompt=login
  • #2426 certificatenlijst + PDF in Mijn bewijs, incl. zichtbare intrekking
  • #2427 agenda-abonnement uitgeven/roteren/intrekken; feed-URL wordt nooit opgeslagen
  • #2428 login-audit, les-open-audit (via versleutelde outbox), avatar PUT/DELETE met handtekeningcontrole
  • #2429 organisatie-themaregister: delen/ophalen/bijwerken met ETag, expliciete 409-keuze, ingebouwde thema's niet verwijderbaar
  • #2430 omgekeerde contractpoort: elke deelnemersroute in de pin is aangeroepen óf staat met reden in unusedSpecRoutes

Testplan

  • flutter test ociserve-suite groen (incl. nieuwe gateway/provider/UI-tests)
  • test/ociserve_api_drift_test.dart 170 tests groen (forward + reverse)
  • make l10n-check groen, 96 strings × 30 talen
  • make check-secrets en make sast schoon
  • make check lokaal

Generated with Devin

## Samenvatting Sluit de deelnemersgerichte integratiegaten uit de keten-audit van 2026-10-14 (#2422–#2430). PR #2432 had `evidence-items` en `me/exam-results` al aangesloten; deze PR bouwt daarop verder. - **#2422** badge-leesmodel per kwalificatie in Mijn bewijs; openstaande bewijseis opent het aanleverscherm met de soort ingevuld - **#2423** echte portefeuille-flow: externe credentials ophalen, selecteren, als bewijsstuk delen; bewijsstukken intrekbaar - **#2424** al gedekt door `me/exam-results` uit #2432 - **#2425** uitnodigingswizard: preview → registratie (nieuw) of acceptatie (bestaand), met `login_hint` + `prompt=login` - **#2426** certificatenlijst + PDF in Mijn bewijs, incl. zichtbare intrekking - **#2427** agenda-abonnement uitgeven/roteren/intrekken; feed-URL wordt nooit opgeslagen - **#2428** login-audit, les-open-audit (via versleutelde outbox), avatar PUT/DELETE met handtekeningcontrole - **#2429** organisatie-themaregister: delen/ophalen/bijwerken met ETag, expliciete 409-keuze, ingebouwde thema's niet verwijderbaar - **#2430** omgekeerde contractpoort: elke deelnemersroute in de pin is aangeroepen óf staat met reden in `unusedSpecRoutes` #### Testplan - [x] `flutter test` ociserve-suite groen (incl. nieuwe gateway/provider/UI-tests) - [x] `test/ociserve_api_drift_test.dart` 170 tests groen (forward + reverse) - [x] `make l10n-check` groen, 96 strings × 30 talen - [x] `make check-secrets` en `make sast` schoon - [x] `make check` lokaal Generated with [Devin](https://devin.ai)
De deelnemersapp registreert nu bij OciServe wanneer een cursist zich
interactief aanmeldt (POST /api/v1/auth/ocideck-login) en wanneer een les
na digest-controle opent (lessons/{}/opened). De les-audit gaat via de
bestaande versleutelde wachtrij als lesson_opened_v1, zodat afspelen nooit
op het auditpunt wacht.

Daarnaast krijgt de profielfoto een echte beheerflow: PUT en DELETE op
/api/v1/me/avatar met beeldhandtekening-controle en een 5-MB-grens, en
wijzig-/verwijderknoppen in het leerprofiel.

Issue #2428.

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

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Mijn bewijs haalt nu het badge-leesmodel op (badge-readiness) per
kwalificatie-versie van de cursist en toont onder elke badge welke eisen
al kloppen en welke nog openstaan. Een openstaande bewijseis opent het
bestaande aanleverscherm met de bewijssoort al ingevuld.

Geeft het leesmodel geen antwoord, dan blijft het scherm volledig bruikbaar:
de badges staan er, de eisenlijst valt weg.

Issue #2422.

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

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
De placeholder-portefeuille wordt een echte reis: de cursist plakt een
publieke verificatielink of kiest een credential-bestand, OciDeck haalt de
documenten veilig op (geen token, geen redirects), legt ze via
portfolio-imports voor aan de organisatie, laat de cursist kiezen welke hij
deelt en maakt er OciDeck-bewijsstukken van aan de nieuwste gepubliceerde
bewijssoort-versie.

Ook nieuw: een ingediend of in-behandeling bewijsstuk kan worden
ingetrokken (evidence-items/{}/withdraw), zodat een per ongeluk gedeeld
stuk niet bij de beoordelaar blijft liggen.

Issue #2423.

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

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Mijn bewijs krijgt een certificatensectie die de organisatie-uitgegeven
verklaringen toont — ook ingetrokken exemplaren, die zichtbaar blijven met
hun intrekkingsreden. De PDF opent in de bestaande alleen-lezen viewer en
kan bewust worden bewaard via de atomaire schrijver; het
verificatiegeheim in de PDF reist daarom nooit langs een deelknop of
tussencache.

Issue #2426.

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

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Mijn inschrijvingen krijgt een kaart "Agenda koppelen" die via OciServe
een kalenderfeed uitgeeft. De feed-URL wordt precies één keer getoond —
OciDeck bewaart hem bewust nergens, alleen de verloopdatum gaat lokaal in
SharedPreferences. Wie de URL kwijt is roteert een nieuwe link, wie de
feed wil stoppen trekt het abonnement in.

Issue #2427.

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

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Nieuwe deelnemers registreren zich via de uitnodigingswizard
(invitation-registrations), bestaande deelnemers accepteren op hun eigen
sessie (invitation-acceptances). De aanmelding stuurt login_hint en
prompt=login mee in de authorize-URL zodat een nog open sessie van de
uitnodiger niet stilletjes wordt hergebruikt — een herstelde sessie wordt
daarvoor juist overgeslagen.

Issue #2425.

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

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Stijlinstellingen krijgen een organisatie-themaregister: een eigen
presentatieprofiel delen als thema, een organisatiethema overnemen als
lokale kopie, en bijwerken met ETag/If-Match. Op een 409-conflict kiest de
gebruiker bewust tussen overschrijven en de serverversie aannemen; een
ingebouwd of nog-gebruikt thema laat de server niet verwijderen en dat
wordt uitgelegd in plaats van stil gefaald.

Issue #2429.

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

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
De drift-test kende alleen de forward-richting: elke route die de gateway
aanroept moet in de gepinde spec bestaan. Nu geldt dat ook andersom —
elke deelnemersroute in de pin moet of aangeroepen worden, of met een
reden in unusedSpecRoutes staan. Uitzonderingen bestaan maar zolang ze
echt onaangeroepen zijn en in de spec voorkomen; wie ze aansluit ruimt
de regel op, wie de pin vernieuwt ziet nieuwe routes rood worden.

CHECKS.md legt uit hoe de pin werkt en hoe hij wordt bijgewerkt.

Issue #2430.

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

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
96 nieuwe bronzinnen uit de uitnodigings-, portefeuille-, certificaat-,
agenda- en thema-reizen zijn via de l10n-spec vertaald naar alle
ondersteunde talen; de uitgeserveerde placeholders en afgebroken
letterlijke fragmenten zijn als eigen sleutels opgenomen.

Issues #2422–#2430.

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

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
USER_GUIDE (nl + en) documenteert uitnodigingen, badge-eisen,
portefeuille-imports, certificaten, agenda-koppeling en thema-deling.
PRIVACY.md legt uit welke gegevens daarbij bewegen — met name dat de
agenda-feed-URL nergens wordt bewaard en externe credentials niet
worden vastgehouden. SOURCE_MAP registreert de nieuwe modellen,
gateway- en provider-parts en dialogen.

Issues #2422–#2430.

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

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
ociserve_provider.dart groeide door de nieuwe deelnemersmethodes over de
bestandsgrens van duizend regels. De outbox-hulpmethodes (enqueue, lezen,
schrijven, flush) verhuizen naar ociserve_provider_outbox.dart als eigen
mixin, zoals de andere domeinmethodes al deden; de basis houdt alleen de
abstracte handtekeningen die de andere parts aanroepen.

Ook binnen de poort: de mislukte agenda-verloopdatum leest nu met een
getypte catch en logWarning (bare-catch-ratchet), en de
settings_dialog-baseline krijgt een gedocumenteerde +1 voor de
org_themes-import.

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

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
De vier stappen van de uitnodigingsdialoog en de inlog-/uitlogrij van de
integratiekaart zijn eigen buildermethodes — beide parents zaten over de
150-regels-grens van de methodelengtepoort.

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

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
De 'https://…'-hint in de portefeuille-flow omzeilde l10n.d() — de
hardcoded-tekstpoort ving hem. Als voorbeeldwaarde staat hij nu in
unchangedInAllLanguages (en de Engelse pendant), zoals de andere
voorbeeld-URL's.

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

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
# Conflicts:
#	tool/check_conventions.dart
Na het samenvoegen met main viel de per-bestand-dekkingsvloer: negen bestanden
van deze PR (zes provider-lagen, de uitnodigingswizard, het themaregister en de
bewijsacties) draaiden vrijwel niet in tests, omdat de bestaande tests alleen de
gateway raakten. Nieuwe tests dekken de providers (lidmaatschapscheck, argumenten,
foutgevallen), de wizard en het themadialoog als gebruiker, en de bewijsacties.

De wizard toonde na registratie + aanmelden de acceptatietekst, want de
gebruiker is dan ook "aangemeld"; de welkomsttekst voor nieuwe deelnemers kon
nooit verschijnen. Nu onthoudt de dialoog dat de uitnodiging via registratie
werd gebruikt.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
brenno merged commit 5446218c72 into main 2026-10-15 20:15:24 +00:00
Sign in to join this conversation.
No description provided.