Realtime/live meekijken met SignalR
15.1 Doel van dit hoofdstuk
Dit hoofdstuk beschrijft de technische inrichting van realtime functionaliteit in OefenHub, met nadruk op live meekijken tijdens actieve oefenruns. SignalR wordt gebruikt als transportlaag voor snelle updates, maar is nooit de bron van waarheid. De actuele oefenvoortgang, vraagstatussen, totalen en live-beschikbaarheid worden server-side bepaald en opgeslagen binnen de daarvoor verantwoordelijke modules.
De live-meekijkfunctionaliteit ondersteunt in de eerste technische baseline twee rolcontexten:
- docentcontext, begrensd door docent-leerlingrelaties en niveauautorisaties;
- ouder-/voogdcontext, begrensd door actieve ouder-/voogdrelaties.
Beheerders krijgen geen reguliere live-meekijkfunctie. Beheerders mogen historische gegevens analyseren waar hun beheercontext dat toestaat, maar kijken niet live mee in actieve leerlingruns.
15.2 Scope
Dit hoofdstuk behandelt:
- SignalR-hubs, hubgroepen en connection lifecycle;
- online- en oefenstatus als afgeleide informatie;
- livebeschikbaarheid en start van meekijksessies;
- realtime voortgangsupdates vanuit
OefenHub.Practice; - autorisatiecontrole bij live meekijken;
- browse-modus versus live-modus in de UI;
- reconnect, stale state en herstel vanuit server-side brondata;
LiveViewAuditen technische herleidbaarheid;- relatie met berichtenbadges en afleidingsvrije oefencontext;
- logging, correlation en securitygrenzen;
- teststrategie voor live en SignalR.
Dit hoofdstuk behandelt niet de inhoudelijke generatie of beoordeling van oefenvragen. Die verantwoordelijkheid ligt bij OefenHub.Practice, OefenHub.ExerciseModuleHost en de concrete technische oefenmodules. Dit hoofdstuk behandelt ook niet de volledige Blazor-componentopbouw; die staat in het frontendhoofdstuk.
15.3 Ontwerpprincipes
| Principe | Uitwerking |
|---|---|
| SignalR is transport | SignalR verspreidt updates, maar bewaart geen functionele waarheid. |
| Practice is bron van waarheid | Actieve run, actuele vraag, antwoorden, totalen en voortgang worden uit practice gelezen. |
| Autorisatie per actie | Online-overzicht, live-start, voortgangsupdate en detailraadpleging herhalen server-side autorisatie. |
| Geen clientvertrouwen | Routeparameters, zichtbare knoppen, hubgroepnamen of browserstate zijn nooit autorisatiebewijs. |
| Read-only meekijken | Meekijkers kunnen geen antwoord, score, voortgang, status of runinhoud wijzigen. |
| Herstelbaar na gemiste updates | Bij reconnect of stale state wordt de actuele stand opnieuw uit server-side voortgang opgebouwd. |
| Audit bij daadwerkelijke live-start | Alleen bewust starten van live meekijken maakt een LiveViewAudit-record aan. |
| Afleidingsvrije oefenrun | Leerlingen krijgen tijdens actieve runs geen zichtbare badges of systeemnotificatie-overlays. |
15.4 Moduleverantwoordelijkheden
| Module/project | Verantwoordelijkheid |
|---|---|
OefenHub.Web | Blazor UI, SignalR clientverbinding, live popup, browse/live UI-state, foutweergave. |
OefenHub.LiveMonitoring | Live-overzichten, livebeschikbaarheid, live-sessiecoördinatie, hubcontracten en LiveViewAudit. |
OefenHub.Practice | Server-side oefenvoortgang, actieve runstatus, actuele vraag, vraagresultaten en voortgangsreaders. |
OefenHub.Authorization | Server-side rolcontext, objecttoegang en policies voor docent/ouder-/voogd live-toegang. |
OefenHub.Relationships | Actieve docent-leerling-, ouder-/voogd- en relevante relatietoegang. |
OefenHub.Catalog | Cataloguscontext, niveau-, categorie-, oefening- en modulemetadata voor weergave. |
OefenHub.Communication | Berichtenbadges en notificaties, met onderdrukking in leerling-oefencontext. |
OefenHub.Scheduling | Eventuele cleanup of periodieke correctie van stale live-/presencegegevens. |
OefenHub.LiveMonitoring krijgt een eigen LiveMonitoringDbContext en schema live wanneer live-audit, presence of technische sessieregistraties persistent worden opgeslagen. SignalR-verbindingen zelf worden niet als brondata gezien.
15.5 Kernobjecten en technische gegevens
Dit hoofdstuk dupliceert geen volledige tabeldefinities uit de database-informatie. Technisch zijn minimaal de volgende objectcategorieën relevant.
| Object | Eigenaar | Doel |
|---|---|---|
| Actieve exercise run | Practice | Bepaalt of een leerling daadwerkelijk oefent. |
| Vraagvoortgang | Practice | Bron voor actuele vraag, beantwoorde vragen, goed/fout/geen idee en timing. |
| Online presence | LiveMonitoring of runtime readmodel | Afgeleide online-status van gebruikers/sessies. |
| Live availability readmodel | LiveMonitoring | Bepaalt of live meekijken nu beschikbaar is. |
| LiveViewAudit | LiveMonitoring | Audit van daadwerkelijk gestarte live-meekijksessies. |
| Hub connection state | runtime | Technische SignalR-verbinding; geen functionele brondata. |
15.6 SignalR-hubs
De eerste technische baseline gebruikt een beperkt aantal hubs. Het exacte aantal kan bij implementatie worden aangescherpt, maar verantwoordelijkheden blijven gescheiden.
| Hub | Doel | Belangrijke grens |
|---|---|---|
LiveMonitoringHub | Live-meekijkupdates voor actieve oefenruns. | Alleen read-only updates naar geautoriseerde meekijkers. |
PresenceHub | Online-/presence-updates waar nodig. | Presence is afgeleid en mag geen autorisatiebron worden. |
NotificationHub | Badges, systeemnotificatie-indicaties en niet-oefenupdates. | Zichtbare leerlingbadges worden tijdens actieve oefenruns onderdrukt. |
Wanneer de implementatie eenvoudiger blijft met één gecombineerde hub, moeten de hubmethodes alsnog logisch gescheiden blijven. Een gecombineerde hub mag geen reden worden om autorisatie-, live- en notificatielogica te mengen.
15.7 Hubgroepen
SignalR-groepen worden alleen gebruikt als transportmechanisme. De groepsnaam mag geen gevoelige gegevens lekken en mag niet als autorisatiebewijs worden gebruikt.
Voorbeeld van conceptuele groepen:
run:{RunId}:viewers
user:{UserId}:notifications
role-context:{ContextId}:presence
De exacte groepsnaamgeving wordt implementatietechnisch bepaald, maar voldoet aan deze regels:
- geen kindnaam, leerlingnaam, e-mailadres of oefeningnaam in de groepsnaam;
- geen betekenisvolle persoonsgegevens in groepsnamen;
- geen autorisatiebeslissing uitsluitend op basis van groepslidmaatschap;
- toetreden tot een livegroep gebeurt alleen na server-side controle;
- verlaten van een groep is technisch, maar beëindigt niet automatisch brondata in
Practice.
15.8 Connection lifecycle
| Fase | Technische verwerking |
|---|---|
| Connect | SignalR-verbinding wordt gekoppeld aan de server-side sessie- en gebruikerscontext. |
| Authenticate | Identity- en sessiegegevens worden gevalideerd via bestaande authenticatie-infrastructuur. |
| Context resolve | Actieve rolcontext wordt server-side bepaald of expliciet uit veilige context gehaald. |
| Join overview | Gebruiker kan online-/live-overzicht ontvangen na autorisatie. |
| Start live | Live meekijken wordt bewust gestart en maakt audit aan. |
| Receive updates | Meekijker ontvangt updates nadat Practice voortgang heeft opgeslagen. |
| Reconnect | Client haalt actuele stand opnieuw op uit server-side brondata. |
| Disconnect | Technische verbinding eindigt; audit wordt waar mogelijk idempotent afgesloten. |
Een reconnect is geen nieuwe functionele live-start wanneer de bestaande live-auditcontext nog geldig is en de gebruiker dezelfde run binnen dezelfde rolcontext opnieuw volgt. Wel moet de autorisatie opnieuw worden gecontroleerd.
15.9 Online-overzicht
Het online-overzicht toont alleen gebruikers die binnen de actieve rolcontext zichtbaar mogen zijn.
| Rolcontext | Dataset |
|---|---|
| Docent | Leerlingen met geldige docent-leerlingrelatie en relevante docentcontext. |
| Ouder/voogd | Kinderen met actieve ouder-/voogdrelatie. |
| Beheerder | Geen reguliere live-meekijkdataset. |
Het openen van het online-overzicht:
- maakt geen
LiveViewAuditaan; - start geen live-sessie;
- wijzigt geen oefenrun;
- toont alleen afgeleide online- en oefenstatus;
- herhaalt server-side autorisatie voor de gevraagde rolcontext.
15.10 Livebeschikbaarheid
Livebeschikbaarheid wordt server-side bepaald. Een actieve knop in de UI is alleen presentatie en geen bewijs dat live-toegang werkelijk is toegestaan.
| Controle | Docent | Ouder/voogd |
|---|---|---|
| Gebruiker is ingelogd | Ja | Ja |
| Rolcontext is geldig | Ja | Ja |
| Relatie met leerling/kind is actief | Ja | Ja |
| Run is actief en niet afgerond | Ja | Ja |
| Oefening valt binnen docentniveauautorisatie | Ja | Nee |
| Ouder-/voogdrelatie is actief | Nee | Ja |
| Feature/toggle staat toe | Ja | Ja |
Wanneer livebeschikbaarheid tussen het tonen van het overzicht en het klikken op de knop wijzigt, wint de server-side controle bij de live-start. De UI toont dan een veilige niet-beschikbaarmelding zonder gedeeltelijke rungegevens te tonen.
15.11 Start van live meekijken
Een live-meekijksessie start pas wanneer een geautoriseerde docent of ouder/voogd bewust kiest voor live meekijken.
De startflow:
1. Web roept live-startcontract aan.
2. LiveMonitoring valideert sessie en rolcontext.
3. Authorization controleert objecttoegang.
4. Relationships controleert actieve relatie.
5. Practice bevestigt actieve run en levert initiële live-state.
6. LiveMonitoring maakt LiveViewAudit aan.
7. SignalR voegt de viewer toe aan de run-viewergroep.
8. Web toont de live-popup met actuele server-side stand.
Wanneer stap 2 t/m 5 faalt, wordt geen LiveViewAudit aangemaakt. Wanneer auditregistratie zelf faalt, wordt de live-sessie niet gestart, omdat de live-start functioneel auditplichtig is.
15.12 LiveViewAudit
LiveViewAudit registreert daadwerkelijk gestarte live-meekijksessies. Het is geen autorisatiebron en geen volledige eventstream van alle SignalR-berichten.
Minimaal vast te leggen gegevens:
| Veldcategorie | Voorbeelden |
|---|---|
| Viewer | ViewerUserId, ViewerRoleId, ViewerRoleNameSnapshot. |
| Subject | StudentUserId of kind/leerlingverwijzing. |
| Run | ExerciseRunId, eventueel snapshot van runcontext waar nodig. |
| Tijd | StartedAtUtc, EndedAtUtc. |
| Context | docent/ouder-/voogdcontext, correlation-id. |
| Einde | reden zoals ViewerClosed, RunCompleted, StudentLeft, Disconnected, AuthorizationLost. |
Het afsluiten van audit gebeurt idempotent. Meerdere disconnect- of eindevents mogen niet leiden tot dubbele of conflicterende eindregistraties.
15.13 Voortgangsupdates vanuit Practice
Practice verwerkt ieder bevestigd antwoord server-side. Pas nadat de voortgang succesvol is opgeslagen, mag een realtime update worden gepubliceerd.
Leerling bevestigt antwoord
→ Practice valideert run en vraagstatus
→ Practice roept technische module aan voor antwoordcontrole
→ Practice slaat voortgang, totalen en vraagstatus op
→ Practice publiceert live-update of roept LiveMonitoring-contract aan
→ LiveMonitoring verstuurt SignalR-update naar geautoriseerde viewers
Hierdoor geldt:
- een gemiste SignalR-update veroorzaakt geen dataverlies;
- een viewer kan actuele stand opnieuw ophalen;
- SignalR faalt niet terug op clientstate;
- live meekijken volgt dezelfde opgeslagen voortgang als hervatten en resultaatweergave.
15.14 Updatepayloads
Realtime payloads bevatten alleen gegevens die nodig zijn voor de liveweergave en waarvoor de viewer is geautoriseerd.
| Payloadtype | Inhoud |
|---|---|
LiveRunStateUpdated | Actuele vraagindex, voortgang, totalen, runstatus, timestamp. |
QuestionAnswered | Vraagnummer, status goed/fout/geen idee, eventueel gegeven antwoord wanneer toegestaan. |
CurrentQuestionChanged | Nieuwe actuele vraag en voortgangspositie. |
RunCompleted | Run is afgerond; liveweergave moet sluiten of naar afgeronde status gaan. |
RunInterrupted | Leerling heeft oefencontext verlaten of sessie is niet langer actief. |
ViewerAuthorizationChanged | Viewer mag livecontext niet langer zien. |
Payloads bevatten geen tokens, credentials, e-mailadressen, interne technische stackdetails of ruwe modulepayloads wanneer die niet nodig zijn voor de liveweergave.
15.15 Browse-modus versus live-modus
De live-popup ondersteunt twee UI-modi:
| Modus | Betekenis |
|---|---|
| Live-modus | Viewer volgt automatisch de actuele vraag van de leerling. |
| Browse-modus | Viewer bekijkt handmatig eerdere of toekomstige vragen binnen de toegestane runweergave. |
Browse-modus is lokale UI-state in OefenHub.Web. De brondata blijft server-side. Wanneer de viewer terugkeert naar live-modus, haalt de client de actuele livepositie opnieuw op of gebruikt de laatste gevalideerde serverupdate.
De knop “Kijk live mee” in de popup betekent technisch: terugkeren naar de actuele server-side livepositie. De knop start geen tweede LiveViewAudit zolang dezelfde geautoriseerde live-sessie actief is.
15.16 Docentautorisatie
Docenten mogen alleen live meekijken binnen hun eigen docentcontext. Hiervoor moet minimaal gelden:
- de viewer heeft een actieve docentrolcontext;
- er is een actieve docent-leerlingrelatie;
- de actieve run hoort bij een leerling die binnen deze docentcontext zichtbaar is;
- de run valt binnen een niveau waarvoor de docent relevante autorisatie heeft toegekend of waarvoor de docent binnen de geldende context toegang heeft;
- de oefening/run is niet buiten de docentcontext gestart door een andere onderwijscontext waarvoor deze docent geen inzage heeft.
Een docent-docentcollaboratorrelatie geeft op zichzelf geen live-meekijktoegang tot leerlingen. Collaboratorrechten zijn gericht op onderwijsinhoud, niet op leerlingresultaten of live meekijken.
15.17 Ouder-/voogdautorisatie
Ouders/voogden mogen live meekijken wanneer:
- de viewer een actieve ouder-/voogdrolcontext heeft;
- er een actieve ouder-/voogdrelatie met het kind bestaat;
- het kind daadwerkelijk een actieve, niet-afgeronde run heeft;
- de live-meekijkfeature beschikbaar is;
- server-side geen blokkade of beëindigde relatie wordt vastgesteld.
Ouder-/voogd-live-meekijken is niet beperkt tot de docent die de oefening oorspronkelijk heeft aangeboden. De autorisatiegrens is de actieve ouder-/voogdrelatie, niet de docentniveauautorisatie.
15.18 Autorisatiewijzigingen tijdens live meekijken
Tijdens een actieve live-sessie kan de toegangscontext wijzigen, bijvoorbeeld door ontkoppeling, intrekking van docentautorisatie, logout of accountstatuswijziging.
Bij relevante wijzigingen:
- wordt de toegang bij de volgende serverinteractie opnieuw gecontroleerd;
- kan een actief hubgroep-lidmaatschap worden beëindigd;
- wordt de live-popup veilig afgesloten;
- wordt
LiveViewAudit.EndedAtUtcidempotent gevuld; - wordt geen gedeeltelijke nieuwe runinformatie meer verzonden.
Als directe push van autorisatiewijzigingen niet betrouwbaar beschikbaar is, moet reconnect, polling of eerstvolgende live-update alsnog de hercontrole afdwingen.
15.19 Reconnect en stale state
SignalR kan tijdelijk onderbreken. De client mag na reconnect niet aannemen dat de oude live-state nog klopt.
Reconnectflow:
1. Client reconnect of maakt nieuwe SignalR-verbinding.
2. Web vraagt actuele live-state opnieuw op.
3. Server controleert sessie, rolcontext en objecttoegang opnieuw.
4. Practice levert actuele runstand.
5. LiveMonitoring herstelt groepstoegang of sluit de sessie veilig af.
Na maximaal ingestelde reconnectpogingen toont de UI een foutmelding dat de liveverbinding is verbroken. De oefenrun van de leerling wordt hierdoor niet beëindigd.
Voor V1.0 gelden de volgende reconnectinstellingen voor de live-meekijkverbinding:
| Onderdeel | Baseline |
|---|---|
| Automatische reconnect | Ingeschakeld voor de live SignalR-client. |
| Retrydelays | 0, 2, 10, 30 en 60 seconden. |
| Aantal automatische pogingen | 5 pogingen; daarna geen onbeperkte reconnectloop. |
| Startfout | Handmatig afhandelen met veilige melding en mogelijkheid opnieuw te proberen of te verversen. |
| Tijdens reconnect | Liveweergave markeren als tijdelijk onderbroken; acties die actuele live-state suggereren blokkeren of duidelijk markeren. |
| Na succesvolle reconnect | Actuele live-state opnieuw ophalen en autorisatie opnieuw controleren voordat nieuwe livegegevens worden getoond. |
| Na definitief falen | Live-popup of livepaneel veilig afsluiten of op verbroken status zetten met actie “Opnieuw verbinden”/“Vernieuwen”. |
| Logging | Technische reconnectstatussen loggen zonder vraaginhoud, antwoorden of volledige payloads. |
Deze waarden zijn bewust lichtgewicht en volgen de functionele grens van maximaal vijf herverbindingspogingen. OefenHub krijgt geen always-on realtimegarantie; bij twijfel wordt teruggevallen op opnieuw ophalen uit server-side brondata.
15.20 Beëindiging van live-sessies
Een live-sessie eindigt wanneer:
- de viewer de live-popup sluit;
- de leerling de oefening afrondt;
- de leerling de oefencontext verlaat;
- de run niet langer actief is;
- de viewer uitlogt;
- reconnect definitief faalt;
- autorisatie vervalt;
- de server de sessie beëindigt vanwege technische cleanup.
Het einde van een live-sessie wijzigt geen oefenrunresultaten. Alleen audit- en technische sessiestatus worden bijgewerkt.
15.21 Online presence
Online presence is een afgeleid readmodel of runtime-status. Het is geen bron voor accountstatus, rolcontext of autorisatie.
Presence mag gebaseerd zijn op:
- actieve websessie;
- SignalR-verbinding;
- recente heartbeat;
- actuele oefenrunstatus uit
Practice; - laatst bekende activiteit.
Presence mag niet gebruikt worden om:
- toegang toe te kennen;
- rollen te bepalen;
- accountstatus te wijzigen;
- oefenruns te starten of af te ronden.
15.22 Berichtenbadges en afleidingsvrije oefencontext
Tijdens een actieve leerling-oefenrun worden zichtbare badges, meldingenindicaties en systeemnotificatie-overlays voor de leerling tijdelijk verborgen of uitgesteld. De onderliggende berichten, readstates en notificatiedata blijven server-side correct opgeslagen.
Realtime notificatie-updates mogen technisch binnenkomen, maar OefenHub.Web toont ze niet zichtbaar in de oefencontext. Na verlaten, onderbreken of afronden van de oefening worden badges opnieuw beoordeeld.
Live-meekijkupdates aan ouders/docenten blijven wel doorgaan, omdat die niet zichtbaar zijn voor de leerling in de oefencontext.
15.23 Relatie met Communication
Communication is eigenaar van mailboxitems, systeemberichten, privéberichten, badges en notificatietellers. LiveMonitoring is geen eigenaar van mailboxcommunicatie.
Wel kan livefunctionaliteit indirect communicatie veroorzaken, bijvoorbeeld een systeembericht dat iemand live meekijkt wanneer dat functioneel is vastgelegd. In dat geval wordt Communication via een publiek contract aangeroepen. Of die communicatie kritiek is voor de live-start wordt per workflow bepaald.
15.24 Transaction boundaries
De live-start is auditplichtig. Daarom geldt:
| Actie | Transactiebeleid |
|---|---|
| Livebeschikbaarheid lezen | Read-only, geen auditrecord. |
Live-start + LiveViewAudit aanmaken | Atomair binnen LiveMonitoring waar mogelijk. |
| Hubgroep joinen | Na succesvolle autorisatie en auditstart. |
| Voortgang opslaan | Eigendom van Practice, vóór live-update. |
| SignalR-update versturen | Na commit van voortgang; retry/herstel via brondata. |
| Live-audit afsluiten | Idempotent; mag door meerdere eindtriggers veilig worden aangeroepen. |
Een mislukte SignalR-verzending draait een opgeslagen antwoord niet terug. Een mislukte voortgangsopslag leidt juist tot geen live-update, omdat er geen betrouwbare bronmutatie is.
15.25 Securitygrenzen
| Risico | Maatregel |
|---|---|
| Meekijken zonder relatie | Server-side autorisatie per live-start en relevante update. |
| Routeparameter-manipulatie | RunId/StudentId uit route is nooit voldoende. |
| Hubgroep raden | Groepslidmaatschap alleen na servercontrole. |
| Gegevenslek via payload | Alleen geautoriseerde liveweergavevelden verzenden. |
| Sessiekaping of verlopen sessie | Hubcontext koppelen aan geldige identity- en sessiecontext. |
| Te veel reconnects of spam | Rate limits en connection limits waar nodig. |
| XSS via vraaginhoud | Rendering blijft veilig geëncodeerd; module-output wordt niet als vrije HTML vertrouwd. |
15.26 Logging en correlation
Elke live-start en relevante live-fout krijgt een CorrelationId. Bij job- of eventgedreven naverwerking wordt dezelfde correlation waar mogelijk doorgegeven.
Minimaal loggen bij live-start:
- correlation-id;
- viewer user-id;
- viewer rolcontext;
- subject user-id;
- run-id;
- autorisatieresultaat;
- auditrecord-id indien aangemaakt;
- starttijd;
- foutcode indien mislukt.
Niet loggen:
- antwoorden van de leerling;
- volledige vraagpayloads;
- tokens of cookies;
- e-mailadressen tenzij functioneel noodzakelijk en veilig gemaskeerd;
- ruwe modulepayloads.
15.27 Foutafhandeling
| Fout | UI-reactie | Technische afhandeling |
|---|---|---|
| Geen livebeschikbaarheid | Knop uitgeschakeld of melding niet beschikbaar. | Geen auditrecord. |
| Toegang geweigerd | Veilige toegang-geweigerdmelding. | Security/access-denied logging zonder inhoudslek. |
| Run net afgerond | Live-popup toont sessie beëindigd. | Audit idempotent afsluiten. |
| Reconnect mislukt | Melding verbinding verbroken. | Geen wijziging aan run. |
| SignalR-update gemist | Client haalt actuele stand opnieuw op. | Brondata blijft in Practice. |
| Auditstart faalt | Live-start faalt. | Fout loggen, geen groepstoegang. |
15.28 Performance en schaalbaarheid
Live meekijken moet efficiënt blijven bij meerdere gelijktijdige viewers.
Ontwerpregels:
- updates worden alleen verzonden naar geautoriseerde viewers van de betreffende run;
- payloads blijven compact;
- zware reconstructie uit volledige JSON/base64-payloads wordt vermeden in realtime pad;
Practicehoudt uniforme voortgangsvelden bij die snel uit te lezen zijn;- reconnect gebruikt actuele server-side stand en geen volledige eventreplay;
- presence- en live-overzichten gebruiken readmodels of efficiënte queries waar nodig.
In fase 1 wordt geen externe SignalR backplane als uitgangspunt genomen. Wanneer horizontale schaalvergroting meerdere app-instances vereist, moet het Technisch Ontwerp worden aangevuld met backplane- of sticky-sessionkeuzes.
15.29 Publieke contracten
LiveMonitoring publiceert contracten voor andere modules en Web. Voorbeelden:
public interface ILiveAvailabilityReader
{
Task<LiveAvailabilityResult> GetLiveAvailabilityAsync(LiveAvailabilityRequest request, CancellationToken cancellationToken);
}
public interface ILiveSessionService
{
Task<StartLiveSessionResult> StartLiveSessionAsync(StartLiveSessionCommand command, CancellationToken cancellationToken);
Task EndLiveSessionAsync(EndLiveSessionCommand command, CancellationToken cancellationToken);
}
Practice publiceert eigen readers voor livebrondata, bijvoorbeeld:
public interface IPracticeLiveStateReader
{
Task<PracticeLiveState> GetLiveStateAsync(PracticeLiveStateRequest request, CancellationToken cancellationToken);
}
Andere modules gebruiken deze contracten en lezen niet rechtstreeks uit live- of practice-entities.
15.30 Teststrategie
Minimaal te testen:
| Testtype | Doel |
|---|---|
| Unit tests | Livebeschikbaarheidsregels, auditstart/einde, payloadmapping. |
| Module integration tests | LiveMonitoringDbContext, auditregistratie, idempotent afsluiten. |
| Cross-module integration tests | Docent/ouder autorisatie met Relationships, Authorization en Practice. |
| SignalR integration tests | Join, update ontvangen, disconnect, reconnect, groepstoegang. |
| Security tests | Geen live-start zonder relatie/autorisatie; geen data bij route-manipulatie. |
| UI/componenttests | Browse/live-modus, reconnectmelding, sessie-einde, knopstatussen. |
| Performance tests | Meerdere viewers op dezelfde run en compacte payloads. |
15.31 Implementatiechecklist
LiveMonitoringHubof logisch equivalente hub ingericht.- Live-start verloopt via server-side contract, niet direct via hubgroep join.
- Online-overzicht maakt geen
LiveViewAuditaan. LiveViewAuditwordt alleen bij daadwerkelijke live-start aangemaakt.LiveViewAudit.EndedAtUtcwordt idempotent gevuld.Practiceslaat voortgang op vóór realtime publicatie.- Reconnect haalt actuele stand opnieuw op uit server-side brondata.
- Docent- en ouder-/voogdautorisatie zijn gescheiden geïmplementeerd.
- Collaboratorrechten geven geen live-meekijktoegang.
- SignalR-payloads bevatten geen tokens, credentials of onnodige persoonsgegevens.
- Leerlingbadges/notificaties worden tijdens actieve oefenrun visueel onderdrukt.
- Access denied en live-fouten worden met correlation-id gelogd.
- Tests dekken autorisatie, reconnect, audit en gemiste updates.
15.32 Implementatieverificaties
| Punt | Actie |
|---|---|
| SignalR hostingmodel | Bepalen of fase 1 single instance, sticky sessions of backplane nodig heeft. |
| Hubindeling | Besluiten of aparte hubs of één gecombineerde hub met gescheiden methodes wordt gebruikt. |
| Presence persistence | Bepalen welke presencegegevens runtime blijven en welke persistent moeten zijn. |
| Reconnectinstellingen | Definitieve retry-aantallen, timeouts en UI-meldingen bepalen. |
| LiveViewAudit-schema | Controleren of alle auditvelden in database-informatie aanwezig zijn. |
| Payloadcontracten | Exacte DTO’s voor live-updates uitwerken bij implementatie. |
| TickerQ cleanup | Bepalen of stale live/presence cleanup periodiek nodig is. |
| SignalR-tests | Keuze maken voor testtooling voor hubintegratietests. |