Skip to main content

Functionele architectuurcontext

23.1 Doel

Dit hoofdstuk vertaalt de beschikbare C4-architectuurdocumentatie naar functionele context voor het FO.

Het hoofdstuk is geen Technisch Ontwerp en geen volledige beschrijving van componentklassen, interne API’s, database-implementatie of deployment. Het beschrijft welke architectuurkeuzes functioneel relevant zijn voor rollen, processen, autorisatie, brondata, readmodels, realtime gedrag, background jobs, exports en externe afhankelijkheden.

De functionele architectuurcontext helpt vooral om consistent te blijven in de andere FO-hoofdstukken:

  • welke systeemgrens OefenHub heeft;
  • welke externe systemen functioneel afhankelijk zijn;
  • welke onderdelen binnen de webapp bronhoudend zijn;
  • welke onderdelen alleen presentatie, transport, export of afleiding leveren;
  • waar server-side autorisatie opnieuw moet plaatsvinden;
  • welke data historisch reconstrueerbaar moet blijven;
  • welke technische middelen functioneel gedrag ondersteunen zonder zelf bron van waarheid te worden.

23.2 Domeinafbakening

OnderwerpBinnen scope van dit FO-hoofdstukBuiten scope van dit FO-hoofdstuk
SysteemgrensOefenHub als Nederlandstalige webapplicatie met afgebakende rollen en externe afhankelijkheden.Deploymenttopologie, hostingkeuzes, netwerksegmentatie en infrastructuurdetails.
C4-contextFunctionele interpretatie van C4 niveau 1 t/m 4.Volledige C4-brontekst of diagramgeneratie dupliceren.
Externe systemenFunctionele rol van Keycloak en mailvoorziening.Identity-providerconfiguratie, mailserverconfiguratie, protocoldetails en secrets.
WebappcontainerFunctionele betekenis van de modulaire monolithische Blazor/.NET-webapp.Interne class diagrams, namespaces, service-interfaces en technische dependency-injectie.
DatabasecontainerRelationele brondata, configuratie, historie, audit en operationele gegevens.Fysiek databasemodel per tabel, indexstrategie en SQL-implementatie.
RealtimeSignalR of gelijkwaardige realtimefunctionaliteit als transport voor updates.Hubimplementatie, reconnectprotocol op laag niveau en transportoptimalisatie.
Background jobsFunctionele verwerking van periodieke taken zoals cleanup en termijnverwerking.Schedulerconfiguratie, workerhosting en retrymechaniek op infrastructuurniveau.
PDF-exportFunctionele export vanuit historische runcontext.QuestPDF-layoutimplementatie, fonts, rendering-code en technische streamafhandeling.
AutorisatieOverkoepelende server-side contextcontrole en objectniveau-autorisatie.Volledige autorisatiematrix per command; die blijft in de ontwerpbron en domeinhoofdstukken.

Dit hoofdstuk beschrijft dus de functionele samenhang tussen architectuuronderdelen. Detailflows blijven in usecases, schermdocumentatie, database-informatie, ontwerpbronnen en domeinspecifieke FO-hoofdstukken staan.

23.3 Bronpositie

Voor functionele architectuurcontext gelden de volgende bronlagen.

BronlaagBetekenis
C4-architectuurdocumentatieBeschrijft systeemcontext, containers, componenten en interne bouwblokken op hoofdlijnen.
FO-hoofdstukkenVertalen architectuurkeuzes naar functioneel gedrag per domein.
UsecasesBeschrijven concrete procesflows, precondities, postcondities en uitzonderingsstromen.
Database-informatieBeschrijft persistente brondata, readmodels, auditobjecten en hybride payloadgrenzen.
OntwerpbronnenLeggen business rules, autorisatiematrix, statusmodellen, commands, events en popupkeys vast.
SchermdocumentatieBeschrijft routecontext, zichtbare onderdelen, acties, lege toestanden en UX-gedrag per scherm.
MockupsOndersteunen visuele interpretatie, maar bepalen geen systeemgrens of brondata.

De C4-documentatie is leidend voor architectuurbegrippen. Het FO vertaalt die begrippen alleen naar functionele consequenties.

23.4 Systeemgrens

OefenHub is één Nederlandstalige webapplicatie voor oefenen, voortgang, beheer en ondersteuning van leerlingen, ouders/voogden, docenten en beheerders.

Binnen de systeemgrens vallen functioneel onder meer:

  • accountcontext binnen OefenHub;
  • rollen en rolcontext;
  • relaties en uitnodigingen;
  • oefencatalogus;
  • technische oefenmodules als geïntegreerde modulebibliotheek;
  • oefenruns, voortgang, resultaten en geschiedenis;
  • gedeelde oefeningen;
  • live meekijken;
  • systeemberichten en privéberichtthreads;
  • meldingen en ticketafhandeling;
  • contentbeheer, popups, templates, features en systeemnotificaties;
  • beheerderfunctionaliteit;
  • PDF-export vanuit resultaatcontext;
  • audit, history en functionele logging.

Buiten de systeemgrens vallen functioneel onder meer:

  • primaire authenticatie en credential lifecycle bij de identity provider;
  • e-mailtransport via mailvoorziening;
  • mobiele apps buiten de huidige productscope;
  • publieke API’s voor externe consumenten;
  • vrije CMS- of pagebuilderfunctionaliteit;
  • externe rapportageplatformen die niet als OefenHub-functie zijn uitgewerkt.

23.5 Primaire actoren

De C4-systeemcontext benoemt vijf primaire actoren. Deze actoren corresponderen met rolcontexten in het FO, maar een rolnaam alleen is niet voldoende voor iedere actie.

ActorFunctionele betekenis binnen OefenHubBelangrijke grens
LeerlingMaakt oefeningen, hervat runs, bekijkt eigen resultaten en gebruikt gedeelde oefeningen.Kan niet gecombineerd worden met ouder-/voogd-, docent- of beheerderrol.
Ouder/voogdBekijkt gekoppelde kinderen, resultaten en geschiedenis en kan live meekijken.Kan geen oefening namens kind starten, beantwoorden, afronden, corrigeren of delen.
DocentBeheert niveaus, categorieën, oefeningen en leerlingtoegang binnen docentcontext.Ziet resultaten en livebeschikbaarheid alleen binnen geldige docentcontext.
BeheerderBeheert accounts, centrale inhoud, categorieën, modules, meldingen, ondersteuning en instellingen.Heeft geen vrije bypass op eindgebruikersflows en mag niet live meekijken in actieve leerlingruns.
TestDocentGebruikt testmodules in een gecontroleerde docentcontext.Niet-publieke rol; testresultaten zijn geen blijvende leerlinggeschiedenis.

Voor alle actoren geldt dat zichtbare routes, knoppen of UI-blokken geen autorisatiebewijs zijn. Iedere detail-, export-, mutatie- en liveactie voert opnieuw server-side contextcontrole uit.

23.6 Externe systemen

OefenHub heeft in de C4-context twee primaire externe systemen.

Extern systeemFunctionele rolFunctionele grens
Keycloak / identity providerVerzorgt authenticatie, registratie, sessies en credential lifecycle.OefenHub beheert geen wachtwoorden, credential-reset, identity-providerrollen of tokens als domeindata.
MailvoorzieningVerzorgt e-mailafhandeling voor verificaties, uitnodigingen en notificatiegerelateerde processen.OefenHub bewaart niet de technische mailserverstatus als functionele domeinwaarheid, tenzij een domeinflow expliciet een OefenHub-record vereist.

23.7 Keycloak en interne OefenHub-context

Authenticatie bij Keycloak of een gelijkwaardige identity provider geeft nog geen volledige OefenHub-toegang.

Na succesvolle externe authenticatie moet OefenHub server-side bepalen:

  • of een intern OefenHub-account bestaat;
  • of provisioning nodig en succesvol is;
  • of Users.IsActive toegang toestaat;
  • welke rollen op het interne account actief zijn;
  • welke rolcontext bruikbaar is;
  • welke frontpage of vervolgroute veilig geopend mag worden;
  • of aanvullende profiel- of niveaucontext nodig is.

Een geldig identity-providerresultaat mag dus niet rechtstreeks worden gelijkgesteld aan toegang tot een leerling-, docent-, ouder-/voogd- of beheerderroute.

Wanneer interne accountinitialisatie faalt, ontstaat geen gedeeltelijk bruikbare OefenHub-sessie. De gebruiker krijgt een veilige accountfout of contactroute, terwijl technische details alleen in beheer- of technische logging thuishoren.

23.8 Mailvoorziening

De mailvoorziening ondersteunt OefenHub-processen, maar is geen functionele bron van waarheid voor OefenHub-domeinen.

Voorbeelden van domeinen die mail kunnen gebruiken:

  • registratie- en verificatieflows;
  • relatie-uitnodigingen naar onbekende e-mailadressen;
  • notificatiegerelateerde processen;
  • mogelijk beheer- of supportcommunicatie wanneer later uitgewerkt.

Voor OefenHub geldt:

  • een relatie-uitnodiging wordt functioneel vastgelegd in OefenHub, niet in het mailsysteem;
  • een systeembericht ontstaat pas wanneer er een interne ontvanger bekend is;
  • mails mogen geen autorisatie vervangen;
  • klikken op een mail- of berichtlink vereist opnieuw server-side contextcontrole;
  • mailfouten mogen geen gevoelige tokens, credentials of technische details aan eindgebruikers tonen.

23.9 Hoofdcontainers

De C4-containercontext kiest in de huidige fase bewust voor een modulaire monolithische opzet.

ContainerFunctionele betekenis
OefenHub WebappPrimaire Blazor/.NET-webapp waarin gebruikersinterface, usecase-orkestratie, domeinlogica, objectniveau-autorisatie, realtime updates, background jobs en PDF-export samenkomen.
OefenHub DatabaseRelationele opslag voor domeindata, configuratie, historie, auditrecords en operationele applicatiegegevens.

Deze containerindeling betekent functioneel niet dat alle verantwoordelijkheden ongescheiden zijn. Binnen de modulaire monolithische webapp blijven domeingrenzen, usecasegrenzen, autorisatiegrenzen en brondata-afbakening verplicht. De technische concretisering van deze keuze staat in het Technisch Ontwerp: architectuuroverzicht en solution-opbouw.

23.10 Functionele betekenis van de modulaire monolithische webapp

De modulaire monolithische webapp ondersteunt in fase 1 eenvoud en consistentie.

Functionele voordelen zijn:

  • één centrale plek voor server-side autorisatie;
  • consistente verwerking van route-, rol-, relatie- en objectcontext;
  • directe samenhang tussen schermacties en usecase-services;
  • uniforme toegang tot domeindata en history;
  • minder risico dat realtime, PDF, cleanup of mailboxlogica een eigen afwijkende bron van waarheid krijgt.

Functionele aandachtspunten zijn:

  • UI-logica mag domeinregels niet vervangen;
  • domeinen moeten logisch gescheiden blijven binnen de applicatie;
  • beheerderfunctionaliteit mag niet onbedoeld eindgebruikersflows omzeilen;
  • background jobs moeten dezelfde domeinregels respecteren als interactieve flows;
  • realtime transport en exportlogica mogen geen zelfstandige mutatiepaden worden.

23.11 Database als functionele bron voor domeindata

De OefenHub Database is de persistente bron voor domeindata, configuratie, historie, audit en operationele gegevens.

Voorbeelden van brondata zijn:

  • interne accounts en gebruikersinstellingen;
  • rollen en roltoekenningen;
  • relaties en uitnodigingen;
  • niveaus, categorieën, oefeningen en modulemetadata;
  • oefenruns, voortgang, resultaten en gedeelde oefeningen;
  • systeemberichten, privéthreads en participants;
  • tickets, discussies, closures en reopen requests;
  • contentblokken, links, popups, templates, featuretoggles en systeemnotificaties;
  • audit- en historyrecords.

Voor gewone raadpleegscenario’s geldt dat readmodels, schermwaarden, badges, tellers, exports en realtimeweergaven uit deze brondata of expliciet afgeleide readmodels worden opgebouwd.

23.12 Hybride opslag en modulepayloads

OefenHub gebruikt functioneel een hybride opslagmodel.

GegevenstypeOpslagkarakterFunctionele reden
Uniforme kernveldenRelationele kolommenNodig voor filters, overzichten, autorisatie, geschiedenis, resultaten, statistieken en audit.
Modulespecifieke configuratieJSON/base64-payload binnen concrete oefeningconfiguratieVariatie per technische module zonder relationeel model per module.
Vraag- en antwoorddataJSON/base64-payload binnen run- en voortgangscontextVariatie in vraagvormen, antwoorden en modulespecifieke presentatie.
Voortgang en totalenUniforme run- en voortgangsveldenNodig voor hervatten, live meekijken, resultaten en snelle uitlezing.
History en auditDomeinspecifieke history/auditrecordsNodig voor reconstructie, beheeranalyse en support.

Uitbreiding van technische contextobjecten leidt niet automatisch tot nieuwe databasekolommen. Alleen gegevens die persistent, historisch relevant, querybaar, rapporteerbaar of auditbaar moeten zijn, komen in aanmerking voor relationele uitbreiding.

23.13 Logische hoofdcomponenten binnen de webapp

De C4-componentcontext splitst de webapp logisch op in verantwoordelijkheden. Deze componenten zijn functionele grenzen, geen zelfstandige FO-hoofdstukken.

ComponentFunctionele verantwoordelijkheid
Web UI / Blazor schermlaagToont pagina’s, componenten, navigatie, formulieren, feedback en interactie.
Application Services / usecase-orkestratieCoördineert schermacties en domeinflows.
Autorisatie- en frontendcontextcomponentBepaalt actieve context, frontpage-opbouw, routecontext en objectniveau-autorisatie.
Identity- en accountlifecycle-integratieVerwerkt provisioning, interne accountcontext, accountstatus en lifecycle-acties.
Relatie- en toegangsbeheerVerwerkt relaties, uitnodigingen, niveauautorisaties, collaborators en toegangscontext.
Catalogus-, configuratie- en contentbeheerBeheert niveaus, categorieën, oefeningen, modules, content en beheerbare instellingen binnen codegedreven grenzen.
Technische module-integratie en strategylaagOntsluit technische oefenmodules via vaste contracten.
Oefenrun-, resultaat- en statistiekverwerkingVerwerkt runs, voortgang, antwoordstatus, geschiedenis, statistieken en resultaatbrondata.
Realtime en live-viewOndersteunt live meekijken, badges en realtime UI-updates als transport.
Mailbox- en systeemberichtenVerwerkt systeemberichten, privéthreads, participants, readstates en mailboxreadmodels.
Site-notificaties en UI-notificatieafhandelingVerwerkt systeemnotificaties, doelgroepcontext en browsergebonden weergaveregels.
Ticketing en meldingsafhandelingVerwerkt meldingen, discussie, closures, reopen requests, doorzetten en tickethistory.
Document- en PDF-exportGenereert tijdelijke resultaat-PDF’s vanuit historische runcontext.
Background jobs en cleanupVerwerkt periodieke taken, cleanup en termijnverwerking.
Data access / persistence-laagLeest en schrijft brondata, hybride payloads, history en auditrecords.

23.14 Schermlaag en usecase-orkestratie

De schermlaag vertaalt domeinregels naar gebruikersinteractie.

Voor de schermlaag geldt functioneel:

  • zij presenteert gegevens uit brondata of readmodels;
  • zij toont alleen acties die in de actuele context zinvol lijken;
  • zij mag nooit de enige autorisatiecontrole zijn;
  • zij mag routeparameters, filters of browserstate niet als bron van toegang gebruiken;
  • zij mag popupteksten of template-inhoud niet dupliceren wanneer registers of templates leidend zijn;
  • zij mag mockupwaarden niet als definitieve domeinwaarden behandelen.

Usecase-orkestratie vormt de brug tussen UI-acties en domeinlogica.

Voor usecase-orkestratie geldt:

  • precondities worden server-side gecontroleerd;
  • domeinregels worden toegepast vóór mutatie;
  • fouten worden veilig teruggegeven;
  • bij mutaties worden history, events, systeemberichten of readmodelupdates veroorzaakt waar het domein dat voorschrijft;
  • een schermactie mag niet rechtstreeks om domeinservices of autorisatie heen schrijven.

23.15 Autorisatie- en contextcomponent

De autorisatie- en contextcomponent heeft functioneel een centrale rol.

Deze component bepaalt of afleidt onder meer:

  • actieve accountstatus;
  • actieve rolcontext;
  • leerlingniveaucontext;
  • ouder-/voogdrelatiecontext;
  • docentcontext;
  • niveau-eigenaarschap of collaboratorstatus;
  • beheerdercontext of supportcontext;
  • toegestane frontpagecontext;
  • objecttoegang voor detail-, mutatie-, export- en liveacties.

Voor alle afgeschermde domeinen geldt:

  • frontend-zichtbaarheid is nooit voldoende;
  • routeparameters zijn nooit voldoende;
  • directe URL’s zijn nooit voldoende;
  • oude clientstate is nooit voldoende;
  • iedere kritieke actie herhaalt actuele server-side controle;
  • bij ontbrekende toegang wordt geen gedeeltelijke gevoelige inhoud getoond.

23.16 Rolcontexten en combinatierollen

Rolcontext is een functionele architectuurgrens.

ContextFunctionele bepalersVoorbeeld van vervolgcontrole
LeerlingcontextActieve leerlingrol, actief account, geldige niveaucontext en toegankelijke oefencatalogus.Starten of hervatten van een oefening controleert oefening, niveau, categorie en modulebeschikbaarheid opnieuw.
Ouder-/voogdcontextActieve ouder-/voogdrol en actieve GuardianStudent-relatie.Resultaatdetail, PDF-export en live meekijken controleren de relatie opnieuw per actie.
DocentcontextActieve docentrol, docent-leerlingrelatie, niveauautorisatie, eigenaarschap of collaboratorstatus.Resultaatinzage, leerlingautorisatie en oefeningbeheer blijven begrensd tot docentcontext.
BeheerdercontextActieve beheerderrol en expliciete beheer- of supportflow.Beheerderacties blijven domeingebonden en auditbaar; geen vrije bypass op eindgebruikersflows.
TestDocentcontextNiet-publieke testrol binnen gecontroleerde docent-/modulecontext.Testmodules en testruns tellen niet als normale leerlinggeschiedenis.

Ouder/voogd, docent en beheerder kunnen gecombineerd voorkomen. De rol Leerling is niet combineerbaar met deze rollen. Combinatierollen worden runtime samengesteld; zij vormen geen aparte persistente architectuurcontext.

23.17 Frontpages en contextopbouw

Frontpages zijn architecturaal gezien afgeleide startweergaven, geen zelfstandige persistente domeinentiteiten.

Een frontpage wordt opgebouwd uit:

  • accountcontext;
  • rolcontext;
  • relatie- of docentcontext;
  • contentblokken;
  • domeinreadmodels;
  • tellerdefinities;
  • systeemnotificatiebeoordeling na normale paginaload.

Voor frontpages geldt:

  • zij zijn primair read-only oriëntatieschermen;
  • zij starten geen diepe mutaties zonder vervolgselectie;
  • samenvattingswaarden zijn readmodels;
  • zichtbare blokken zijn geen autorisatiebewijs;
  • gecombineerde frontpages worden runtime samengesteld;
  • er worden geen aparte persistente frontpageontwerpen per rolcombinatie beheerd.

23.18 Relatie- en toegangsbeheer als architectuurgrens

Relaties en toegang zijn functioneel bronhoudend voor meerdere domeinen.

Voorbeelden:

  • vriendschap bepaalt of een leerling oefeningen mag delen;
  • ouder-/voogdrelatie bepaalt kinderen, resultaten, PDF en live meekijken;
  • docent-leerlingrelatie en niveauautorisatie bepalen leerlingtoegang en docentinzage;
  • docent-docentrelatie ondersteunt samenwerking en collaborators;
  • beheerder-beheerderrelatie ondersteunt beheercommunicatie.

Relaties worden niet impliciet aangemaakt door berichten, frontpageweergave, live meekijken, gedeelde oefeningen of beheerondersteuning.

Ontkoppelen beëindigt toekomstige relatieafhankelijke toegang, maar herschrijft geen historische oefenruns, berichten, resultaten, auditrecords of PDF-broncontexten.

23.19 Oefendomeincomponenten

Het oefendomein bestaat functioneel uit meerdere samenhangende lagen.

LaagFunctionele betekenis
OefencatalogusNiveaus, centrale categorieën, niveau-categorie-koppelingen en concrete oefeningen.
Module-integratieTechnische modulecontracten voor configuratie, generatie, antwoordcontrole, weergave en exportrepresentatie.
OefenrunverwerkingAanmaken, hervatten, voortgang opslaan, antwoorden verwerken en afronden van runs.
ResultaatverwerkingUniforme totalen, statistieken, geschiedenisdetail en resultaatweergave.
DelenAdministratief shared-record en zelfstandige ontvangerruns.
PDF/exportTijdelijke export vanuit historische runcontext.
Live-viewRead-only voortgangsweergave vanuit opgeslagen run- en voortgangsdata.

Deze lagen mogen elkaar gebruiken, maar niet elkaars brondata vervangen.

Voorbeelden:

  • een module levert logica, maar beheert geen autorisatie;
  • een oefenrun bewaart historische context, ook na latere categorie- of modulewijzigingen;
  • een gedeelde oefening maakt pas bij start een zelfstandige ontvangerrun;
  • PDF-export leest resultaatdata en muteert geen run;
  • live meekijken leest voortgang en muteert geen antwoorddata.

23.20 Technische module-integratie

Technische oefenmodules zijn geïntegreerde codecomponenten achter een vast modulecontract.

Functioneel geldt:

  • beschikbare modules worden administratief beheerd via modulemetadata;
  • modules worden niet willekeurig runtime ontdekt als vrije pluginbron;
  • een concrete oefening verwijst naar precies één technische module;
  • modulespecifieke configuratie wordt generiek opgeslagen als payload;
  • moduleKey en schemaVersion in de bestaande payload zijn leidend voor schemaherleidbaarheid;
  • er wordt geen extra generieke databasekolom geïntroduceerd wanneer payloadvelden voldoende zijn;
  • oude runs blijven interpreteerbaar via historische payloadcontext;
  • modulemigraties herschrijven historische runs, resultaten of PDF-contexten niet.

De module-integratie is daarmee een functionele extensiegrens, geen vrije beheerbare scriptingomgeving.

23.21 Oefenruns, resultaten en geschiedenis

Oefenruns zijn de centrale functionele bron voor leerlingvoortgang, resultaten, geschiedenis, PDF-export en live meekijken.

Architecturaal geldt:

  • een run ontstaat alleen door een geldige startactie;
  • voortgang wordt server-side opgeslagen na bevestigde stappen;
  • onderbreken rondt een run niet af;
  • afronden gebeurt pas wanneer de laatste vraag definitief is verwerkt;
  • uniforme totalen en statistieken worden op runniveau opgeslagen of consistent afgeleid volgens domeinregels;
  • historische runcontext blijft leidend voor resultaatweergave en PDF-export;
  • niet-afgeronde runs verschijnen niet als normale afgeronde geschiedenis;
  • docenttestruns worden niet blijvend als leerlinggeschiedenis behandeld.

Deze regels zorgen dat frontpages, geschiedenis, live meekijken, ouderinzage, docentinzage en PDF-export niet ieder hun eigen interpretatie van resultaatdata krijgen.

23.22 Communicatie- en notificatiearchitectuur

OefenHub kent meerdere communicatielagen die functioneel gescheiden blijven.

CommunicatielaagFunctionele bronArchitectuurgrens
Mailbox-systeemberichtenSystemMessagesGebruikergebonden systeemcommunicatie met eventuele domeinverwijzing.
PrivéberichtthreadsThread, participants, berichten en thread-eventsRelatie- of systeemcontext bepaalt verzend- en leesrechten.
TicketdiscussieTicketdiscussion binnen meldingenGeen privéberichtthread, behalve expliciete doorzetflow.
SysteemnotificatiesSiteNotificationsFrontpage-overlay, geen mailboxitem en geen popupregister-popup.
PopupfeedbackPopupregister en PopupDetailsActie-, validatie- of foutfeedback.
Realtime updatesSignalR of gelijkwaardig transportVersnelt UI-updates, maar is geen bron van waarheid.

Deze scheiding voorkomt dat bijvoorbeeld een systeemnotificatie een systeembericht vervangt, of dat ticketcommunicatie ongecontroleerd als privébericht wordt opgeslagen.

23.23 Realtime en live-view

Realtime-functionaliteit ondersteunt snelle gebruikerservaring, maar is functioneel nooit bron van waarheid.

Realtime kan worden gebruikt voor:

  • live meekijken;
  • voortgangsupdates;
  • mailboxbadges;
  • systeemcommunicatie-indicaties;
  • online-overzichten;
  • notificatie van relevante wijzigingen;
  • statusupdates na acties.

Voor realtime geldt:

  • opslag in de database blijft leidend;
  • bij gemiste realtimeberichten wordt bij herladen opnieuw server-side gelezen;
  • live meekijken is read-only;
  • browsemodus in live meekijken is presentatiestate;
  • realtime updates mogen autorisatie niet verruimen;
  • reconnect mag geen data wijzigen;
  • audit ontstaat bij domeingebeurtenissen, niet omdat transport actief is.

23.24 Background jobs en cleanup

Background jobs ondersteunen periodieke of asynchrone verwerking binnen OefenHub.

Functioneel relevante voorbeelden zijn:

  • verlopen relatie-uitnodigingen verwerken;
  • tijdelijke docenttestruns opschonen;
  • verlopen ticket-heropentermijnen periodiek beoordelen;
  • cacheverversing of afgeleide housekeeping waar expliciet uitgewerkt;
  • toekomstige domeinspecifieke cleanup met expliciete regels.

Voor background jobs geldt:

  • zij volgen dezelfde domeincriteria als interactieve flows;
  • zij zijn idempotent waar dat functioneel vereist is;
  • zij maken geen extra sluit- of historyrecords wanneer het domein dat uitsluit;
  • zij versturen geen extra communicatie tenzij een domeinregel dat voorschrijft;
  • falen van één record mag verwerking van andere kandidaten niet onnodig blokkeren;
  • een gemiste run moet bij een volgende verwerking kunnen worden ingehaald wanneer het domein dat vereist.

Background jobs mogen geen verborgen alternatieve mutatieroute worden die autorisatie, statusmodellen of auditregels omzeilt.

23.25 PDF-export en documentgeneratie

PDF-export is functioneel een tijdelijke export vanuit bestaande historische brondata.

Voor resultaat-PDF’s geldt:

  • de export gebruikt dezelfde historische runcontext als de resultaatweergave;
  • de export muteert geen run, voortgang, resultaat of geschiedenis;
  • er ontstaat geen verplicht permanent PDF-record;
  • bestandsnaam, inhoud, tabellen, vervolgpagina’s en footerregels volgen het PDF-exporthoofdstuk;
  • module-specifieke vraag- of antwoordpresentatie mag via module-exportrepresentatie worden ondersteund;
  • roltoegang wordt opnieuw server-side gecontroleerd voor leerling, docent of ouder/voogd.

QuestPDF of een gelijkwaardige PDF-generator is dus technisch ondersteunend. De functionele bron blijft de geautoriseerde historische resultaatcontext.

23.26 Content, instellingen en beheerbare configuratie

OefenHub maakt onderscheid tussen codegedreven structuur en beheerbare inhoud.

OnderdeelFunctionele regel
ContentblokkenBeheren tekst op vaste plekken; geen pagebuilder.
FooterlinksGebruiken herbruikbare URL-records en vaste footersecties.
PopupsWorden aangestuurd door popupkeys en popupregister; beheer wijzigt alleen toegestane velden.
SysteemberichttemplatesBeheren inhoud voor toekomstige systeemcommunicatie; concrete systeemberichten blijven eigen records.
FeaturetogglesSchakelen expliciet togglebare functies, maar verwijderen geen bestaande data.
SysteeminstellingenBeheren bestaande configuratiesleutels met datatype en invoervorm.
SysteemnotificatiesPlanbare overlays na frontpageload; geen mailboxitems.

Beheerbare configuratie mag geen nieuwe technische domeinen, routes, popupflows, layoutstructuren of autorisaties creëren buiten code en documentatie om.

23.27 Beheerderfunctionaliteit binnen de architectuur

Beheerderfunctionaliteit is een expliciete beheercontext binnen OefenHub, geen onbeperkte technische toegang.

Voor beheerderacties geldt:

  • iedere actie vereist actuele server-side beheercontext;
  • acties blijven domeingebonden;
  • beheerderondersteuning corrigeert of inspecteert binnen supportflows;
  • beheerder kan niet vrij namens eindgebruikers alle eindgebruikershandelingen uitvoeren;
  • beheerder mag geen leerlingrun live volgen buiten de toegestane live-meekijkrollen;
  • mutaties zijn auditbaar wanneer het domein dat vereist;
  • technische details blijven alleen zichtbaar waar beheerautorisatie en functionele noodzaak bestaan.

Deze grens is belangrijk omdat de webapp als één modulaire monolithische applicatie is gepositioneerd: beheerderfunctionaliteit zit technisch in dezelfde applicatie, maar functioneel in gescheiden flows.

23.28 Audit, historie en reconstructie

OefenHub gebruikt per domein passende vormen van audit en historie.

Voorbeelden:

  • RelationshipEvents voor relatiegebeurtenissen;
  • CategoryHistory en ExerciseHistory voor cataloguswijzigingen;
  • modulegeschiedenis en modulemigratiehistorie;
  • TicketHistory, TicketClosures en TicketReopenRequests voor meldingen;
  • LiveViewAudit voor daadwerkelijk gestarte live-meekijksessies;
  • content-, popup-, template-, feature- en notificatiehistorie;
  • accountlifecyclelogging;
  • technische applicatielogs met beperkte persoonsgegevens.

Niet elk domein gebruikt hetzelfde patroon.

PatroonVoorbeeldFunctionele betekenis
Append-only historyTicketclosures, reopen requests, historyrecordsEerdere formele gebeurtenissen blijven intact.
Soft deleteURL-records, relaties, footerlinktoewijzingen waar relevantZichtbaarheid stopt, historie blijft.
IsActive / statusRollen, categorieën, modules, oefeningen, relatiesActuele beschikbaarheid zonder historische reconstructie te verliezen.
Auditrecord per sessieLiveViewAuditVastleggen dat live meekijken daadwerkelijk is gestart.
Technische logAccountlifecycle, provisioningfouten, schedulerfoutenAnalyse zonder onnodige persoonsgegevens te tonen.

Audit en historie zijn geen vrije gebruikersweergave. Welke history zichtbaar is, hangt af van rolcontext, beheercontext en domeinregels.

23.29 Events, commands en statusmodellen

Ontwerpbronnen zoals command-register, event-register, statusmodellen en business rules vormen een functionele brug tussen FO, TO en SRS.

Voor de architectuurcontext geldt:

  • commands beschrijven welke functionele acties bestaan;
  • events beschrijven relevante domeingebeurtenissen of auditmomenten;
  • statusmodellen bepalen toegestane procesovergangen;
  • business rules leggen domeinbrede regels vast;
  • de autorisatiematrix bepaalt rol- en contextgrenzen per actie.

Dit hoofdstuk dupliceert die registers niet. Het legt alleen vast dat uitvoering van commands, events en statusovergangen via de server-side domeinlaag loopt en niet via losse UI-state.

23.30 Readmodels, tellers en samenvattingswaarden

Veel schermen tonen afgeleide waarden.

Voorbeelden:

  • frontpageblokken;
  • ongelezenbadges;
  • meldingentellers;
  • leerling-, docent- en ouder-/voogdoverzichten;
  • populaire categorieën;
  • recent geoefend;
  • online-overzichten;
  • beheerderfrontpage-indicatoren;
  • resultaat- en geschiedenisfilters.

Voor readmodels geldt:

  • zij zijn afgeleid uit brondata;
  • zij verruimen geen autorisatie;
  • zij mogen geen eigen afwijkende statuswaarheid introduceren;
  • tellerdefinities moeten eenduidig zijn;
  • filters en sortering zijn presentatiegedrag tenzij het domein anders bepaalt;
  • cache mag geen context- of autorisatiegrens doorbreken.

23.31 Privacy- en securityprincipes

Functionele architectuurkeuzes ondersteunen de volgende privacy- en securityprincipes.

  • Server-side autorisatie is leidend.
  • Clientstate, routeparameters, browsergeschiedenis en filters verruimen toegang nooit.
  • Bij geweigerde toegang wordt geen gedeeltelijke gevoelige inhoud getoond.
  • Eindgebruikers zien geen stacktraces, tokens, technische payloads of interne identifiers.
  • Beheerders zien alleen technische context waar dat functioneel nodig en geautoriseerd is.
  • PDF-export, live meekijken, resultaatdetails en geschiedenis controleren opnieuw objecttoegang.
  • Realtime transport en browserwaarden zijn geen autorisatiebron.
  • Browserwaarden voor toegankelijkheid of OncePerBrowser mogen geen persoonsgegevens of autorisatiedata bevatten.
  • Accountanonimisering beëindigt actuele toegang, maar behoudt audit en functionele reconstructie waar nodig.

23.32 Geen publieke API-scope

De huidige productscope gaat uit van een webapplicatie.

Er worden geen publieke API-endpoints ontworpen voor:

  • een aparte mobiele app;
  • externe integraties;
  • derde partijen;
  • openbare dataconsumptie;
  • generieke rapportagetools.

Interne server calls, Blazor-interactie, SignalR-hubs of backendendpoints kunnen technisch bestaan, maar vallen buiten dit FO tenzij zij functioneel zichtbaar gedrag bepalen.

Wanneer later publieke API’s nodig zijn, vraagt dat een aparte scopebeslissing, autorisatie-uitwerking, datacontract, rate limiting, privacybeoordeling en documentatie.

23.33 Geen microservice- of pluginplatformscope

De huidige architectuurcontext beschrijft geen microserviceplatform.

Functioneel betekent dit:

  • domeinen blijven logisch gescheiden, maar draaien binnen één webappcontext;
  • modules zijn geïntegreerde technische componenten achter een vast contract, geen vrije externe plugins;
  • beheer kan geen code of scripts uploaden om nieuwe modulelogica te maken;
  • realtime, jobs, PDF en mail zijn ondersteunende onderdelen binnen dezelfde functionele applicatiegrens;
  • externe systemen blijven beperkt tot de expliciet beschreven afhankelijkheden.

Wanneer later microservices, externe pluginmechanismen of publieke modulemarktplaatsen nodig zijn, vallen die buiten deze FO-scope.

23.34 Lege toestanden

Lege toestanden in de functionele architectuur zijn normale toestanden wanneer de gebruiker wel toegang heeft, maar er geen relevante data is.

Voorbeelden:

  • gebruiker heeft geen actieve rolcontext;
  • leerling heeft geen toegankelijke oefeningen;
  • docent heeft geen leerlingen of niveaus;
  • ouder/voogd heeft geen gekoppelde kinderen;
  • beheerderfrontpage heeft geen recente wijzigingen;
  • mailbox heeft geen berichten;
  • systeemnotificatiebeoordeling vindt geen actieve notificatie;
  • background job vindt geen kandidaten;
  • PDF-export heeft geen toegang tot een afgeronde run;
  • live-overzicht toont geen online leerlingen of kinderen.

Een lege toestand mag informatief zijn, maar mag geen verborgen objectnamen, technische details of autorisatie-informatie lekken.

23.35 Fouttoestanden

Fouttoestanden ontstaan wanneer de architectuurcontext niet veilig of consistent kan worden toegepast.

Voorbeelden:

  • identity-providerlogin slaagt, maar interne provisioning faalt;
  • account is inactief;
  • rolcontext is ongeldig of ontbreekt;
  • routeparameter verwijst naar een object buiten toegestane context;
  • readmodelopbouw faalt;
  • modulepayload kan niet veilig geïnterpreteerd worden;
  • realtimeverbinding valt weg;
  • background job faalt op één of meer records;
  • PDF-export kan historische runcontext niet lezen;
  • mailafhandeling faalt;
  • databaseopslag of historyregistratie mislukt;
  • beheerder probeert een technische read-only waarde via de GUI te wijzigen.

Bij fouttoestanden geldt:

  • de gebruiker krijgt veilige foutfeedback;
  • gevoelige inhoud wordt niet gedeeltelijk getoond;
  • mutaties worden niet half functioneel zichtbaar wanneer transactieconsistentie vereist is;
  • technische logging bevat voldoende correlatie voor analyse;
  • tokens, credentials en identity-providerinterne gegevens worden niet als OefenHub-domeindata opgeslagen.

23.36 Functionele architectuurrelaties met andere FO-hoofdstukken

FO-hoofdstukRelatie met functionele architectuurcontext
Bronnen en afbakeningBepaalt bronhiërarchie, DRY-principes en linkbeleid.
Productvisie en scopeBepaalt productscope, doelgroep en geen-publieke-API uitgangspunt.
Rollen, context en autorisatieWerkt rolcontext, combinatierollen en autorisatieprincipes inhoudelijk uit.
Applicatieschil, header, footer en navigatieVertaalde schermcontext voor navigatie, badges en responsiviteit.
Frontpages en overzichtsschermenBeschrijft frontpages als read-only afgeleide contextweergaven.
Account, profiel en voorkeurenBeschrijft identity-providergrens, provisioning, profiel en voorkeuren.
RelatiebeheerBeschrijft relaties als autorisatiebron voor meerdere domeinen.
Oefencatalogus, niveaus, categorieën en oefeningenBeschrijft catalogus-, module- en oefeningstructuur.
Leerling: oefenen, voortgang en resultatenBeschrijft run-lifecycle, voortgang, resultaten en geschiedenis.
Gedeelde oefeningenBeschrijft shared-records, bronruns en ontvangerruns.
DocentfunctionaliteitBeschrijft docentcontext, oefenaanbod, leerlingen, autorisaties en samenwerking.
Ouder-/voogdfunctionaliteitBeschrijft ouder-/voogdcontext en read-only inzage.
BeheerderfunctionaliteitBeschrijft beheercontext, support, centrale beheerfuncties en audit.
Berichten, communicatie en notificatiesBeschrijft communicatievormen en realtime/badgegrenzen.
Meldingen en ticketafhandelingBeschrijft ticketlifecycle, statusmodellen, closures en heropenen.
Live meekijkenBeschrijft realtime read-only voortgangsweergave en LiveViewAudit.
Contentbeheer, vaste pagina’s en footerBeschrijft codegedreven contentbeheergrenzen.
Popups, templates, features en systeemnotificatiesBeschrijft beheerbare feedback, templates, toggles en notificaties.
PDF-export en resultaatpresentatieBeschrijft export vanuit historische resultaatcontext.
Functionele beslisregels en uitgangspuntenBundelt domeinbrede beslisregels en uitgangspunten.
Open punten en buiten scopeHoudt resterende keuzes en uitgesloten onderwerpen bij.
Schermlaag en UX-specificatiesBeschrijft schermbronpositie, read-only gedrag en UX-principes.
Oefenmodules en modulepayloadsBeschrijft technische modulegrenzen en payloadinterpretatie.

23.37 Gerelateerde bronverwijzingen

BronLink
Technisch Ontwerp — architectuuroverzichtArchitectuuroverzicht en solution-opbouw
Technisch Ontwerp — applicatielagenApplicatielagen, projectstructuur en dependency-richting
Technisch Ontwerp — domeinmodelDomeinmodel en datamodel-overzicht
Technisch Ontwerp — background jobsBackground jobs, TickerQ en periodieke verwerking
Architectuur — introArchitectuur
C4 — introC4 intro
C4 niveau 1 — System ContextSystem Context
C4 niveau 2 — Container DiagramContainer Diagram
C4 niveau 3 — Component DiagramComponent Diagram
C4 niveau 4 — Interne bouwblokkenInterne bouwblokken
Database-informatie — identiteit en autorisatieIdentiteit en autorisatie
Database-informatie — relatiebeheerRelatiebeheer
Database-informatie — docentstructuur en leerlingtoegangDocentstructuur en leerlingtoegang
Database-informatie — communicatie en notificatiesCommunicatie en notificaties
Database-informatie — configuratie en contentbeheerConfiguratie en contentbeheer
Database-informatie — ticket- en meldingsbeheerTicket- en meldingsbeheer
Database-informatie — oefenruns, delen en voortgangOefenruns, delen en voortgang
Database-informatie — audit, historie en technische uitgangspuntenAudit, historie en technische uitgangspunten
Ontwerpbron — business rulesBusiness rules
Ontwerpbron — autorisatiematrixAutorisatiematrix
Ontwerpbron — domeinobjectenDomeinobjecten
Ontwerpbron — statusmodellenStatusmodellen
Ontwerpbron — command-registerCommand-register
Ontwerpbron — event-registerEvent-register
FO — rollen, context en autorisatieRollen, context en autorisatie
FO — schermlaag en UX-specificatiesSchermlaag en UX-specificaties
FO — oefenmodules en modulepayloadsOefenmodules en modulepayloads