feat(meetings): de aanbieder-neutrale laag van onlinevergaderingen #971

Merged
brenno merged 10 commits from feat/onlinevergaderingen-laag into main 2026-07-29 21:02:15 +00:00
Owner

De eerste, aanbieder-neutrale laag van de onlinevergaderingen-functie
(ontwerp: docs/design/TEAMS_GUEST_CLIENT.md T13–T15/§6–§8 en
docs/design/COLLABORATION.md §7.1 — stap 1 van de leveringsvolgorde in
§7.1.5).

Wat erin zit

  • lib/meetings/ — het domein dat de schil en elke toekomstige adapter
    delen: het MeetingProvider/MeetingSession-contract, de
    MeetingLinkResolver met harde weigeringen en achtervoegselveilige
    hostkeuze, de gesloten sealed eventboom, MeetingPhase met expliciete
    overgangstabel plus MeetingState-reducer, MeetingCapabilities,
    MeetingRole en de MeetingFailureKind-taxonomie. Vrij van Flutter en van
    elke netwerkroute.
  • Eén nep-adapter (alleen in debugbouwen, release spike, host op
    .invalid) die elk verloop deterministisch doorloopt: direct, wachten op
    toelating, geweigerd, herverbinden, beëindigd door de organisator, en
    gasten-niet-toegestaan.
  • De modulepoort van T13: ModuleId.meetings in het register, een kaart
    op Uitbreidingen in de stijl van de andere modules, standaard uit, en
    onthulling = aan of sessie actief — een lopend gesprek valt nooit stil
    door een schakelaar.
  • Negen testbestanden (86 tests), 155 vertalingen (5 teksten × 31 talen), en
    documentatie in USER_GUIDE, SOURCE_MAP, ARCHITECTURE en CHANGELOG.

Er gaat geen byte naar buiten — als test, niet als belofte

meeting_privacy_boundary_test.dart scant de bron: niets onder
lib/meetings/ mag een netwerk- of platformlaag importeren, en
meeting_state.dart kent geen Uri en geen token (T5).
meeting_provider_scope_test.dart klinkt T6 vast: de sessie is
wortelgeschikt en staat niet in de tab-scope.

Afwijkingen van het ontwerp, hardop

  1. Geen MeetingClient (§8.2). Dat is de Teams-specifieke naad naar de
    JavaScript-brug, één laag dieper; de schil praat met MeetingProvider
    zoals T14 en §7.1.5 stap 1 voorschrijven. De ACS-adapter-PR mag er straks
    een MeetingClient achter zetten. (Staat ook in de kop van
    meeting_provider.dart.)
  2. Eventnamen dragen het voorvoegsel MeetingParticipantJoined uit
    §8.3 is te algemeen voor één gedeelde Dart-ruimte waarin samenwerking
    straks eigen deelnemers krijgt. Begrippen en velden zijn ongewijzigd.
  3. De apparaatlijsten uit §8.1 (microphones/cameras/speakers in
    MeetingState) zitten er nog niet in: apparaatkeuze hoort bij de
    pre-join-stap van de schil-PR en bij de clientlaag die hem levert.
  4. De fasetabel is op twee punten ruimer dan het diagram, met de reden in
    de code: uit élke levende fase mag je naar leaving (§17 eist bereikbaar
    Verlaten), en terminale fasen gaan naar idle terug (de reset).

Scope-keuze

De schil-UI (dialoog, wachtindicator, gespreksvenster) zit er bewust niet
in — de laag zelf is al ~2.500 regels plus tests; de schil krijgt zijn eigen
PR op dit fundament.

Bewaker

Gedraaid (publieke belofte in de interface + contract voor toekomstig
uitgaand verkeer): geen botsing. Het .md-formaat wordt niet geraakt, er is
geen nieuwe partij om te vertrouwen, en de kaartbelofte "module uit = geen
contact" is met de bronscan-test aan de code vastgeklonken. Spanningsveld
benoemd: de kaart is zichtbaar terwijl meedoen nog niet kan — de kaart zegt
dat zelf eerlijk, liever dan een schakelaar die stil niets doet.

Poorten

  • make check groen: volledige suite (7485 tests), dekking 87,0%,
    per-bestandsvloer 0 overtredingen.
  • make check-secrets groen: gitleaks en trufflehog, 0 geheimen
    (geverifieerd én ongeverifieerd).
  • make sast groen: semgrep, 0 bevindingen.
  • DAST (ZAP) is niet gedraaid: niet geïnstalleerd op deze machine, en deze
    wijziging heeft geen geserveerd oppervlak.

🤖 Generated with Claude Code

De eerste, aanbieder-neutrale laag van de onlinevergaderingen-functie (ontwerp: `docs/design/TEAMS_GUEST_CLIENT.md` T13–T15/§6–§8 en `docs/design/COLLABORATION.md` §7.1 — stap 1 van de leveringsvolgorde in §7.1.5). ## Wat erin zit - **`lib/meetings/`** — het domein dat de schil en elke toekomstige adapter delen: het `MeetingProvider`/`MeetingSession`-contract, de `MeetingLinkResolver` met harde weigeringen en achtervoegselveilige hostkeuze, de gesloten `sealed` eventboom, `MeetingPhase` met expliciete overgangstabel plus `MeetingState`-reducer, `MeetingCapabilities`, `MeetingRole` en de `MeetingFailureKind`-taxonomie. Vrij van Flutter en van elke netwerkroute. - **Eén nep-adapter** (alleen in debugbouwen, release `spike`, host op `.invalid`) die elk verloop deterministisch doorloopt: direct, wachten op toelating, geweigerd, herverbinden, beëindigd door de organisator, en gasten-niet-toegestaan. - **De modulepoort van T13**: `ModuleId.meetings` in het register, een kaart op Uitbreidingen in de stijl van de andere modules, standaard uit, en onthulling = aan **of** sessie actief — een lopend gesprek valt nooit stil door een schakelaar. - Negen testbestanden (86 tests), 155 vertalingen (5 teksten × 31 talen), en documentatie in USER_GUIDE, SOURCE_MAP, ARCHITECTURE en CHANGELOG. ## Er gaat geen byte naar buiten — als test, niet als belofte `meeting_privacy_boundary_test.dart` scant de bron: niets onder `lib/meetings/` mag een netwerk- of platformlaag importeren, en `meeting_state.dart` kent geen `Uri` en geen token (T5). `meeting_provider_scope_test.dart` klinkt T6 vast: de sessie is wortelgeschikt en staat niet in de tab-scope. ## Afwijkingen van het ontwerp, hardop 1. **Geen `MeetingClient` (§8.2).** Dat is de Teams-specifieke naad naar de JavaScript-brug, één laag dieper; de schil praat met `MeetingProvider` zoals T14 en §7.1.5 stap 1 voorschrijven. De ACS-adapter-PR mag er straks een `MeetingClient` achter zetten. (Staat ook in de kop van `meeting_provider.dart`.) 2. **Eventnamen dragen het voorvoegsel `Meeting`** — `ParticipantJoined` uit §8.3 is te algemeen voor één gedeelde Dart-ruimte waarin samenwerking straks eigen deelnemers krijgt. Begrippen en velden zijn ongewijzigd. 3. **De apparaatlijsten uit §8.1** (`microphones`/`cameras`/`speakers` in `MeetingState`) zitten er nog niet in: apparaatkeuze hoort bij de pre-join-stap van de schil-PR en bij de clientlaag die hem levert. 4. **De fasetabel is op twee punten ruimer dan het diagram**, met de reden in de code: uit élke levende fase mag je naar `leaving` (§17 eist bereikbaar Verlaten), en terminale fasen gaan naar `idle` terug (de reset). ## Scope-keuze De schil-UI (dialoog, wachtindicator, gespreksvenster) zit er bewust **niet** in — de laag zelf is al ~2.500 regels plus tests; de schil krijgt zijn eigen PR op dit fundament. ## Bewaker Gedraaid (publieke belofte in de interface + contract voor toekomstig uitgaand verkeer): geen botsing. Het `.md`-formaat wordt niet geraakt, er is geen nieuwe partij om te vertrouwen, en de kaartbelofte "module uit = geen contact" is met de bronscan-test aan de code vastgeklonken. Spanningsveld benoemd: de kaart is zichtbaar terwijl meedoen nog niet kan — de kaart zegt dat zelf eerlijk, liever dan een schakelaar die stil niets doet. ## Poorten - `make check` groen: volledige suite (7485 tests), dekking 87,0%, per-bestandsvloer 0 overtredingen. - `make check-secrets` groen: gitleaks en trufflehog, 0 geheimen (geverifieerd én ongeverifieerd). - `make sast` groen: semgrep, 0 bevindingen. - DAST (ZAP) is niet gedraaid: niet geïnstalleerd op deze machine, en deze wijziging heeft geen geserveerd oppervlak. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Drie ontwerpbesluiten die het Teams-ontwerp nog niet kende, en waarvan
er één de bestaande tekst tegensprak.

T13 — bellen wordt een module op Uitbreidingen, uit tenzij aangezet. Uit
betekent geen schilactie en geen verkeer, wat T8 ook toetsbaar maakt voor
wie de functie nooit wil. Onthullen is `aan || sessie actief`, want de
projectregel "uitzetten maakt bestaand werk niet onbereikbaar" betekent
hier letterlijk: geen gesprek dat stilvalt door een schakelaar.

T14 — §6 is de gedeelde schil, niet de Teams-schil. Een adapter levert
feiten (naam, linkherkenning, egress-tekst, capabilities, rol) en nooit
eigen schermen. Een aanbieder erbij mag niets veranderen voor wie een
andere aanbieder gebruikt.

T15 — §6.3 schreef een echt lobbyscherm voor. Dat neemt je werk af terwijl
toelating minuten kan duren. Het wachten verhuist naar de chrome: een
knipperend icoon met een zittende kat plus één niet-modale strook met
annuleren, en bij toelating opent het gespreksvenster vanzelf.

Alleen documentatie; de code kent deze functie nog niet.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
De woordenschat en contracten uit COLLABORATION.md §7.1.1 en
TEAMS_GUEST_CLIENT.md §8: MeetingProvider/MeetingSession, de
MeetingLinkResolver met achtervoegselveilige hostkeuze, getypeerde
events als gesloten sealed-boom, MeetingPhase met expliciete
overgangstabel, MeetingState als domme reducer, MeetingCapabilities,
MeetingRole en de MeetingFailureKind-taxonomie. Geen Flutter, geen
netwerk, geen SDK.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
De nep-adapter doorloopt elk verloop deterministisch — direct, lobby,
geweigerd, herverbinden, beëindigd door de organisator en gasten
geweigerd — zonder klok en zonder één byte netwerk. Het register zet
hem er alleen onder kDebugMode in en biedt spike-adapters nooit als
deelnamemogelijkheid aan (§7.1.4).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
De sessienotifier houdt link en toegangsbewijs buiten de inspecteerbare
toestand, zet opdrachten in de rij en laat dubbele klikken samenvallen
(§8.2). De module Onlinevergaderingen staat als ModuleId in het
register, standaard uit; onthulling is aan || sessie actief, zodat een
lopend gesprek nooit stilvalt door een schakelaar (T13, §17).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Negen bestanden langs §7.4 van het ontwerp: de resolver met zijn harde
weigeringen en achtervoegselveilige hostkeuze, de reducer tegen de
fasetabel van §8.1, het gesloten eventcontract, de log-redactie van
§16.4, de zes draaiboeken van de nep-adapter afgespeeld door de
reducer, de opdrachtenrij en het idempotente verlaten van de notifier,
en de modulepoort van T13 met de kaart. Twee bronscans klinken de
beloften uit de code vast: geen netwerkroute onder lib/meetings, en
geen link of token in inspecteerbare toestand.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
De modulekaart van Onlinevergaderingen: de naam, de uitleg, de
lopend-gesprek-melding, de nog-geen-dienst-voettekst en de
plak-een-link-aanwijzing — 155 vertalingen via make add-l10n. En één
dartdoc-regel in meeting_failure.dart geherformuleerd: het voorbeeld
las voor de bronscanner als echte d()-aanroep.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
USER_GUIDE krijgt de zesde module op Uitbreidingen — met de eerlijke
stand: nog geen dienst aangesloten, geen byte naar buiten. SOURCE_MAP
beschrijft lib/meetings/ bestand voor bestand plus de twee nieuwe
providers en de modulekaart; ARCHITECTURE neemt de map op in de
laagindeling. CHANGELOG vat de laag samen onder Unreleased.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
test(meetings): de registervolgorde-toets kent Onlinevergaderingen
All checks were successful
scans / scans (pull_request) Successful in 3m15s
fb186befb4
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
brenno merged commit 4b7e4baf90 into main 2026-07-29 21:02:15 +00:00
Sign in to join this conversation.
No description provided.