4. C4 niveau 4 — Interne bouwblokken
Tekstuele modellering
Op C4 niveau 4 wordt in dit document niet geprobeerd om volledige class diagrams of broncode-structuren te tonen. De uitwerking blijft bewust op het niveau van interne bouwblokken binnen de OefenHub Webapp.
Hoofdinterne bouwblokken binnen de webapp
- Blazor UI en schermclusters
- use-case-services
- autorisatie- en frontendcontext
- account-, relatie- en toegangslogica
- catalogus- en configuratiebeheer
- oefenrun- en resultaatverwerking
- technische modulegrenzen
- communicatie- en notificatielogica
- background jobs
- persistence
Toelichting bij het diagram
Dit overzichtsdiagram vormt het instappunt voor de niveau-4-uitwerking. Het laat op hoofdlijnen zien hoe UI, use-case-orkestratie, account- en toegangslogica, catalogus- en oefenlogica, communicatie, persistence en technische ondersteuning zoals realtime, documentgeneratie en background processing zich binnen de monoliet tot elkaar verhouden.

Figuur 8 — OefenHub C4 niveau 4: Interne bouwblokken overzicht
workspace "OefenHub" "C4 model niveau 4 - Interne bouwblokken overzicht" {
model {
leerling = person "Leerling" "Gebruikt de webapp voor oefeningen, voortgang en resultaten."
ouder = person "Ouder/voogd" "Gebruikt de webapp voor gekoppelde leerlinginzage en live meekijken."
docent = person "Docent" "Gebruikt de webapp voor beheer van niveaus, oefeningen en leerlingtoegang."
beheerder = person "Beheerder" "Gebruikt de webapp voor systeembeheer, inhoudsbeheer en support."
testdocent = person "TestDocent" "Gebruikt de webapp voor testmodules en gecontroleerde testscenario’s."
oefenhub = softwareSystem "OefenHub" "Architectuurweergave van de webappcontainer." {
webapp = container "OefenHub Webapp" "Modulaire monolithische .NET / C# / Blazor Web App." ".NET / C# / Blazor Web App" {
webui = component "Web UI / Blazor schermlaag" "Verzorgt pagina’s, componenten, navigatie en gebruikersinteractie." "Blazor UI"
appservices = component "Application Services / Use-case-orkestratie" "Coördineert use-cases, schermacties en applicatieflows." "Application layer"
authctx = component "Autorisatie- en frontendcontextcomponent" "Bepaalt actieve context, frontpage-opbouw en toegestane acties." "Authorization / context"
identityaccess = component "Identity-, relatie- en toegangscomponenten" "Verwerken accountcontext, rollen, relaties, uitnodigingen en niveautoegang." "Domain component"
exercise = component "Oefendomeincomponenten" "Verwerken catalogus, configuratie, technische modules, runs, voortgang en resultaten." "Domain component"
communication = component "Communicatie- en achtergrondcomponenten" "Verwerken systeemberichten, privéberichten, tickets, notificaties en achtergrondafhandeling." "Domain component"
integrations = component "Integratie- en infrastructuurcomponenten" "Ontsluiten Keycloak, SignalR, TickerQ, QuestPDF en mailafhandeling." "Integration / infrastructure"
persistence = component "Data access / persistence-laag" "Verzorgt relationele opslag, hybride payloadopslag, historie en audit." "Persistence"
}
database = container "OefenHub Database" "Slaat domeindata, configuratie, historie en auditrecords op." "SQL Database"
}
keycloak = softwareSystem "Keycloak" "Externe identity provider voor authenticatie, registratie, sessies en credential-lifecycle."
mail = softwareSystem "Mailvoorziening" "Externe e-mailafhandeling voor verificaties, uitnodigingen en notificatiegerelateerde processen."
leerling -> webui "Gebruikt via browser"
ouder -> webui "Gebruikt via browser"
docent -> webui "Gebruikt via browser"
beheerder -> webui "Gebruikt via browser"
testdocent -> webui "Gebruikt via browser"
webui -> appservices "Start schermacties en use-cases"
appservices -> authctx "Valideert context en toegestane acties"
appservices -> identityaccess "Gebruikt voor account-, relatie- en toegangsflows"
appservices -> exercise "Gebruikt voor oefenflows, runs en resultaten"
appservices -> communication "Gebruikt voor berichten, tickets en notificaties"
appservices -> integrations "Gebruikt voor realtime, jobs, PDF en externe koppelingen"
identityaccess -> persistence "Leest en schrijft domeindata"
exercise -> persistence "Leest en schrijft domeindata"
communication -> persistence "Leest en schrijft domeindata"
integrations -> persistence "Leest en schrijft ondersteunende brondata"
integrations -> keycloak "Gebruikt voor authenticatie en identity-gerelateerde flows"
integrations -> mail "Verstuurt verificaties, uitnodigingen en notificatie-e-mails"
persistence -> database "Persistente opslag"
}
views {
component webapp "ComponentDiagram4Overview" {
include leerling
include ouder
include docent
include beheerder
include testdocent
include webui
include appservices
include authctx
include identityaccess
include exercise
include communication
include integrations
include persistence
include keycloak
include mail
include database
autolayout lr
title "OefenHub - C4 niveau 4 - Interne bouwblokken overzicht"
}
theme default
}
}
C4 niveau 4A — Web/UI en use-case-orkestratie
Deze deeluitwerking richt zich op de voorkant van de webapp: Blazor pagina- en componentclusters, navigatie, schermkeuze, frontendcontext, browserlokale state en de use-case-services die tussen gebruikersinteractie en domeinlogica staan.
Deze deeluitwerking is vooral bruikbaar voor schermgedrag, contextcompositie, browserstate vóór en na inloggen en de scheiding tussen presentatie en applicatielogica.

Figuur 9 — OefenHub C4 niveau 4A: Web/UI en use-case-orkestratie
workspace "OefenHub" "C4 model niveau 4A - Web/UI en use-case-orkestratie" {
model {
leerling = person "Leerling" "Gebruikt de webapp via browser."
ouder = person "Ouder/voogd" "Gebruikt de webapp via browser."
docent = person "Docent" "Gebruikt de webapp via browser."
beheerder = person "Beheerder" "Gebruikt de webapp via browser."
testdocent = person "TestDocent" "Gebruikt de webapp via browser."
oefenhub = softwareSystem "OefenHub" "Architectuurweergave van de webappcontainer." {
webapp = container "OefenHub Webapp" "Modulaire monolithische .NET / C# / Blazor Web App." ".NET / C# / Blazor Web App" {
pages = component "Pagina- en schermcomponenten" "Verzorgen routegebonden pagina's en schermcompositie." "Blazor pages"
sharedui = component "Gedeelde UI-componenten" "Leveren herbruikbare OefenHub-schermonderdelen, formulieren, overzichtsblokken en wrappercomponenten bovenop MudBlazor." "Blazor / MudBlazor components"
navigation = component "Navigatie- en interactiecomponent" "Verwerkt menu's, schermnavigatie en contextgebonden interactie." "UI interaction"
appservices = component "Application Services / Use-case-orkestratie" "Coördineert schermacties, validatievolgorde en applicatieflows." "Application layer"
authctx = component "Autorisatie- en frontendcontextcomponent" "Bepaalt actieve context, rolgebonden frontpage-opbouw en toegestane acties." "Authorization / context"
preferences = component "Profiel-, voorkeuren- en toegankelijkheidscomponent" "Verwerkt profielinstellingen, voorkeuren, cookie-sync en toegankelijkheidskeuzes." "User settings"
presentationmodels = component "Presentatie- en viewmodelmapping" "Vertaalt domeinuitkomsten naar schermgerichte representaties." "Presentation mapping"
}
}
leerling -> pages "Gebruikt via browser"
ouder -> pages "Gebruikt via browser"
docent -> pages "Gebruikt via browser"
beheerder -> pages "Gebruikt via browser"
testdocent -> pages "Gebruikt via browser"
pages -> sharedui "Gebruikt voor schermopbouw"
pages -> navigation "Gebruikt voor route- en interactieafhandeling"
pages -> appservices "Start schermacties en use-cases"
sharedui -> appservices "Start contextgebonden acties"
navigation -> authctx "Gebruikt voor context- en routekeuze"
appservices -> authctx "Valideert context en toegestane acties"
appservices -> preferences "Leest en schrijft profiel-, voorkeuren- en toegankelijkheidsinstellingen"
appservices -> presentationmodels "Vertaalt uitkomsten naar schermmodellen"
authctx -> presentationmodels "Levert actieve context voor schermrepresentatie"
preferences -> presentationmodels "Levert gebruikersinstellingen voor presentatie"
}
views {
component webapp "ComponentDiagram4A" {
include leerling
include ouder
include docent
include beheerder
include testdocent
include pages
include sharedui
include navigation
include appservices
include authctx
include preferences
include presentationmodels
autolayout lr
title "OefenHub - C4 niveau 4A - Web/UI en use-case-orkestratie"
}
theme default
}
}
C4 niveau 4B — Relatie-, toegang- en accountdomein
Deze deeluitwerking zoomt in op interne accountidentiteit, provisioning, profiel en instellingen, rollen, relaties, uitnodigingen, teacher levels, collaboratorlogica en niveautoegang.
Dit diagram is vooral relevant voor het scheiden van externe identity, interne accountlifecycle, relatiebeheer en toegangsautorisatie.

Figuur 10 — OefenHub C4 niveau 4B: Relatie-, toegang- en accountdomein
workspace "OefenHub" "C4 model niveau 4B - Relatie-, toegang- en accountdomein" {
model {
oefenhub = softwareSystem "OefenHub" "Architectuurweergave van de webappcontainer." {
webapp = container "OefenHub Webapp" "Modulaire monolithische .NET / C# / Blazor Web App." ".NET / C# / Blazor Web App" {
appservices = component "Application Services / Use-case-orkestratie" "Coördineert account-, relatie- en toegangsuse-cases." "Application layer"
authctx = component "Autorisatie- en frontendcontextcomponent" "Bepaalt actieve context, rolcombinatie en objectniveau-autorisatie." "Authorization / context"
identity = component "Identity- en accountlifecycle-integratie" "Verwerkt interne accountvorming, identity-koppeling en lifecycle-afhandeling." "Integration"
profiles = component "Profiel- en gebruikersinstellingencomponent" "Verwerkt profielgegevens, avatars, voorkeuren en geselecteerde contextinstellingen." "Domain component"
roles = component "Rollen- en contextcomponent" "Verwerkt roltoekenning, actieve rolcontext en rolgebonden schermlogica." "Domain component"
relationships = component "Relatie- en uitnodigingscomponent" "Verwerkt vriendschappen, ouder/voogdrelaties, docentrelaties en uitnodigingen." "Domain component"
access = component "Docentniveau- en toegangscomponent" "Verwerkt docentniveaus, collaborators en leerlingtoegang per niveau." "Domain component"
persistence = component "Data access / persistence-laag" "Verzorgt opslag en uitlezing van account-, relatie- en toegangsdata." "Persistence"
}
database = container "OefenHub Database" "Slaat domeindata, configuratie, historie en auditrecords op." "SQL Database"
}
keycloak = softwareSystem "Keycloak" "Externe identity provider voor authenticatie, registratie, sessies en credential-lifecycle."
appservices -> authctx "Valideert context en toegestane acties"
appservices -> identity "Gebruikt voor account- en identityflows"
appservices -> profiles "Gebruikt voor profiel- en instellingenflows"
appservices -> roles "Gebruikt voor rol- en contextflows"
appservices -> relationships "Gebruikt voor relaties en uitnodigingen"
appservices -> access "Gebruikt voor docentniveaus en leerlingtoegang"
authctx -> roles "Gebruikt voor actieve rolcontext"
authctx -> relationships "Gebruikt voor relatiecontext"
authctx -> access "Gebruikt voor niveau- en toegangscontext"
identity -> keycloak "Gebruikt voor authenticatie en identity-gerelateerde flows"
profiles -> persistence "Leest en schrijft domeindata"
roles -> persistence "Leest en schrijft domeindata"
relationships -> persistence "Leest en schrijft domeindata"
access -> persistence "Leest en schrijft domeindata"
persistence -> database "Persistente opslag"
}
views {
component webapp "ComponentDiagram4B" {
include appservices
include authctx
include identity
include profiles
include roles
include relationships
include access
include persistence
include keycloak
include database
autolayout lr
title "OefenHub - C4 niveau 4B - Relatie-, toegang- en accountdomein"
}
theme default
}
}
C4 niveau 4C — Oefendomein
Deze deeluitwerking richt zich op de inhoudelijke kern van OefenHub: catalogus- en configuratiebeheer, technische modulegrenzen, exercise run generation, voortgangsverwerking, resultaten, historie, statistieken, live-view en PDF-uitvoer.
Dit diagram helpt vooral om de samenhang te zien tussen generieke applicatielogica en de begrensde strategy-/moduleboundary voor technische oefenmodules.

Figuur 11 — OefenHub C4 niveau 4C: Oefendomein
workspace "OefenHub" "C4 model niveau 4C - Oefendomein" {
model {
oefenhub = softwareSystem "OefenHub" "Architectuurweergave van de webappcontainer." {
webapp = container "OefenHub Webapp" "Modulaire monolithische .NET / C# / Blazor Web App." ".NET / C# / Blazor Web App" {
appservices = component "Application Services / Use-case-orkestratie" "Coördineert oefenflows, configuratie, runs en resultaten." "Application layer"
catalog = component "Catalogus- en configuratiecomponent" "Verwerkt niveaus, categorieën, oefeningen, modulekoppelingen en beheerbare configuratie." "Domain component"
modules = component "Technische module-integratie en strategylaag" "Ontsluit technische oefenmodules via vaste contracten en databasegestuurde vrijgave." "Module integration"
generation = component "Oefengeneratiecomponent" "Genereert nieuwe exercise runs en modulespecifieke vraagsets." "Domain component"
progress = component "Voortgangs- en antwoordverwerking" "Verwerkt antwoordbevestiging, server-side voortgang en hybride payloadopslag." "Domain component"
results = component "Resultaat-, historie- en statistiekcomponent" "Verwerkt afronding, resultaten, samenvattingen en historisch uitleesbare statistieken." "Domain component"
liveview = component "Realtime en live-view" "Ondersteunt SignalR-gebaseerd live meekijken en actuele oefenstatus." "Realtime"
pdf = component "Document- en PDF-export" "Genereert resultaten en documentuitvoer met QuestPDF." "Document generation"
persistence = component "Data access / persistence-laag" "Verzorgt relationele opslag en hybride JSON/base64-payloadopslag." "Persistence"
}
database = container "OefenHub Database" "Slaat domeindata, configuratie, historie en auditrecords op." "SQL Database"
}
appservices -> catalog "Gebruikt voor catalogus- en configuratieflows"
appservices -> modules "Gebruikt voor modulespecifieke logica"
appservices -> generation "Gebruikt voor start van nieuwe exercise runs"
appservices -> progress "Gebruikt voor antwoord- en voortgangsverwerking"
appservices -> results "Gebruikt voor historie, detailweergaven en statistieken"
appservices -> liveview "Gebruikt voor live meekijken en actuele status"
appservices -> pdf "Gebruikt voor document- en PDF-export"
catalog -> persistence "Leest en schrijft domeindata"
modules -> catalog "Gebruikt modulevrijgave en configuratiekoppeling"
generation -> modules "Gebruikt voor vraaggeneratie"
generation -> persistence "Leest en schrijft domeindata"
progress -> persistence "Leest en schrijft domeindata"
results -> persistence "Leest en schrijft domeindata"
liveview -> persistence "Leest actuele status en context"
pdf -> persistence "Leest historisch consistente brondata"
persistence -> database "Persistente opslag"
}
views {
component webapp "ComponentDiagram4C" {
include appservices
include catalog
include modules
include generation
include progress
include results
include liveview
include pdf
include persistence
include database
autolayout lr
title "OefenHub - C4 niveau 4C - Oefendomein"
}
theme default
}
}
C4 niveau 4D — Communicatie en achtergrondverwerking
Deze deeluitwerking focust op systeemberichten, privéberichten, ticketing, site-notificaties, geplande verwerking, cleanup en mailafhandeling.
Deze deeluitwerking is vooral relevant voor de scheiding tussen interactieve communicatie, notificatielogica en achtergrondtaken.

Figuur 12 — OefenHub C4 niveau 4D: Communicatie en achtergrondverwerking
workspace "OefenHub" "C4 model niveau 4D - Communicatie en achtergrondverwerking" {
model {
oefenhub = softwareSystem "OefenHub" "Architectuurweergave van de webappcontainer." {
webapp = container "OefenHub Webapp" "Modulaire monolithische .NET / C# / Blazor Web App." ".NET / C# / Blazor Web App" {
appservices = component "Application Services / Use-case-orkestratie" "Coördineert bericht-, ticket-, notificatie- en achtergrondflows." "Application layer"
systemmessages = component "Systeemberichtencomponent" "Verwerkt mailboxgerichte systeemberichten met een begrensde domeinverwijzing naar precies drie toegestane objecttypen." "Domain component"
privatemessages = component "Privéberichten- en threadcomponent" "Verwerkt threads, deelnemers, berichten en threadgebeurtenissen." "Domain component"
tickets = component "Ticket- en meldingscomponent" "Verwerkt meldingen, statusafhandeling, discussie en tickethistorie." "Domain component"
notifications = component "Site-notificatie- en contentcomponent" "Verwerkt sitebrede notificaties, contentblokken en andere UI-gerichte berichtinhoud." "Domain component"
backgroundjobs = component "Background jobs en cleanupcomponent" "Verwerkt scheduler-taken, cleanup en tijdsafhankelijke afhandeling binnen de monoliet." "Background processing"
mailintegration = component "Mailintegratie" "Verstuurt notificatie-, verificatie- en uitnodigingsemails." "Integration"
realtime = component "Realtime en SignalR-ondersteuning" "Verwerkt directe updates voor live meekijken en interactieve berichtverversing." "Realtime"
persistence = component "Data access / persistence-laag" "Verzorgt opslag en uitlezing van communicatie-, ticket- en notificatiedata." "Persistence"
}
database = container "OefenHub Database" "Slaat domeindata, configuratie, historie en auditrecords op." "SQL Database"
}
mail = softwareSystem "Mailvoorziening" "Externe e-mailafhandeling voor verificaties, uitnodigingen en notificatiegerelateerde processen."
appservices -> systemmessages "Gebruikt voor mailboxgerichte systeemberichten"
appservices -> privatemessages "Gebruikt voor privéberichten en threadflows"
appservices -> tickets "Gebruikt voor meldingen en ticketafhandeling"
appservices -> notifications "Gebruikt voor site-notificaties en berichtinhoud"
appservices -> backgroundjobs "Start en bewaakt tijdsafhankelijke afhandeling"
appservices -> mailintegration "Gebruikt voor e-mailafhandeling"
appservices -> realtime "Gebruikt voor directe updates"
systemmessages -> tickets "Kan verwijzen naar Ticket"
systemmessages -> privatemessages "Kan verwijzen naar PrivateMessageThread"
tickets -> persistence "Leest en schrijft domeindata"
privatemessages -> persistence "Leest en schrijft domeindata"
systemmessages -> persistence "Leest en schrijft domeindata"
notifications -> persistence "Leest en schrijft domeindata"
backgroundjobs -> persistence "Leest en schrijft domeindata"
realtime -> persistence "Leest actuele status en context"
mailintegration -> mail "Verstuurt e-mails"
persistence -> database "Persistente opslag"
}
views {
component webapp "ComponentDiagram4D" {
include appservices
include systemmessages
include privatemessages
include tickets
include notifications
include backgroundjobs
include mailintegration
include realtime
include persistence
include mail
include database
autolayout lr
title "OefenHub - C4 niveau 4D - Communicatie en achtergrondverwerking"
}
theme default
}
}