Skip to main content

Domeinmodel en datamodel-overzicht

6.1 Doel van dit hoofdstuk

Dit hoofdstuk beschrijft het technische overzicht van de belangrijkste domeinen, data-eigenaarschappen, modulegrenzen, readmodels, snapshots en cross-module verwijzingen binnen OefenHub. Het hoofdstuk vormt de brug tussen de functionele domeinbeschrijving, de database-informatie en de technische uitwerking van de afzonderlijke modules.

Het doel is niet om alle tabellen, kolommen, constraints en enumwaarden opnieuw te specificeren. De detaildefinities blijven in database_informatie staan. Dit hoofdstuk beschrijft hoe het domeinmodel technisch wordt geordend binnen de modulaire monoliet en welke ontwerpregels gelden voor brondata, readmodels, soft links, snapshots en domeinoverschrijdende afhankelijkheden.

6.2 Scope

Dit hoofdstuk behandelt:

  • de technische bounded contexts van OefenHub;
  • de relatie tussen project, DbContext, schema en domeineigenaarschap;
  • brondata versus readmodels, runtime-state en technische logs;
  • cross-module verwijzingen en snapshotgebruik;
  • globale lifecycle-objecten;
  • domeinoverschrijdende flows;
  • de rol van ERD- en domeindiagrammen in het Technisch Ontwerp;
  • technische kwaliteitsregels voor datamodelwijzigingen.

Dit hoofdstuk behandelt niet:

  • volledige tabeldefinities;
  • volledige ERD-reconstructie;
  • schermspecifieke requirements;
  • acceptatiecriteria uit de Software Requirements Specification;
  • concrete EF Core entityconfiguraties per tabel;
  • implementatiecode.

Die details horen respectievelijk in database_informatie, de Software Requirements Specification, schermdocumentatie, hoofdstuk 07 of de modulehoofdstukken.

6.3 Bronnen en leidende documenten

De bronvolgorde voor dit hoofdstuk is:

  1. database_informatie voor tabellen, kolommen, relaties, enumwaarden, constraints, snapshots en databronnen;
  2. Software Requirements Specification voor requirements, acceptatiecriteria, prioriteiten en traceability;
  3. Functioneel Ontwerp voor functionele domeinregels, rollen, lifecycle en bron-van-waarheid;
  4. architectuurdocumentatie voor systeemcontext en technische hoofdkeuzes;
  5. modulehoofdstukken in het Technisch Ontwerp voor technische implementatiekeuzes per domein;
  6. ERD-documenten als ondersteunende visualisatie en navigatielaag.

Belangrijke inputbronnen zijn:

6.4 Ontwerpprincipes

Het domein- en datamodel volgt de gekozen middel-zware modulaire monoliet. De applicatie wordt als één deploybare applicatie gebouwd, maar de interne domeinen worden technisch gescheiden via projecten, DbContexts, schema’s, publieke contracts en internal implementaties.

PrincipeRegel
Eén databaseOefenHub gebruikt één relationele database voor de applicatiegegevens.
Eén connectionstringDe eerste baseline gebruikt één applicatieconnectionstring voor alle module-DbContexts.
Module-eigenaarschapEén moduleproject is eigenaar van maximaal één DbContext en één database-schema.
Schema als eigendomsgrensEen schema maakt zichtbaar welke module eigenaar is van de tabellen.
Geen schema als securityboundarySchema’s ondersteunen ordening en eigenaarschap, maar vervangen geen autorisatie of securitymaatregelen.
Hard FK binnen moduleHarde foreign keys zijn vooral bedoeld binnen dezelfde modulegrens.
Soft link over modulegrensCross-module verwijzingen zijn standaard soft links, eventueel aangevuld met snapshots.
Readmodel is geen bronReadmodels mogen gegevens presenteren of versnellen, maar zijn geen zelfstandige functionele bron.
Authorisatie blijft server-sideDatamodelstructuur, readmodels en UI-state mogen autorisatie niet verruimen.
Historie blijft reconstrueerbaarHistorische runs, tickets, relaties, berichten en audit/history blijven functioneel herleidbaar binnen privacygrenzen.

6.5 Project, DbContext en schema

De basisregel is:

Project → DbContext → schema → tabellen

Daarmee is vanuit de database altijd herleidbaar welk project functioneel eigenaar is van een tabel.

ProjectDbContextSchemaPrimaire verantwoordelijkheid
OefenHub.IdentityIdentityDbContextidentityInterne accounts, profielkern, accountstatus, provisioning en account lifecycle.
OefenHub.AuthorizationAuthorizationDbContextauthorizationRollen, roltoekenningen, rolcontext, policies en autorisatiegerelateerde referentiedata.
OefenHub.RelationshipsRelationshipsDbContextrelationshipsRelaties, uitnodigingen, relatie-events en relatieafhankelijke toegangsvragen.
OefenHub.CatalogCatalogDbContextcatalogNiveaus, categorieën, oefeningen, modulemetadata, catalogushistorie en catalogusmigraties.
OefenHub.ExerciseModuleHostgeen eigen domein-DbContextgeen eigen schemaRuntime-resolving en aanroep van technische oefenmodules.
OefenHub.PracticePracticeDbContextpracticeExercise runs, voortgang, resultaten, gedeelde oefeningen, duplicaten, statistieken en PDF-brondata.
OefenHub.CommunicationCommunicationDbContextcommunicationInterne systeemberichten, privéthreads, thread-events, notificaties, systeemberichttemplates en mailbox-readmodels.
OefenHub.MailMailDbContextmailApplicatiegestuurde externe e-mail, mailtemplates, templatehistory en mailverzendpogingen.
OefenHub.SupportSupportDbContextsupportMeldingen/tickets, discussies, sluitingen, heropeningen, doorzetten naar docent en ticketgeschiedenis.
OefenHub.LiveMonitoringLiveMonitoringDbContextliveLivebeschikbaarheid, live sessiecoördinatie, online presence en LiveViewAudit.
OefenHub.AdminAdminDbContextadminBeheerbare content, vaste pagina’s, footercontent, URL-records, popups, systeemnotificaties, featuretoggles, systeeminstellingen en beheerlogs.
OefenHub.Reportingoptioneel ReportingDbContextreporting indien nodigExportorkestratie, rapportage-/exportreadmodels en eventuele persistente exportmetadata.
OefenHub.SchedulingSchedulingDbContext indien nodigschedulingTickerQ-persistence, joblifecycle, retrystatussen, technische jobhistorie en interne jobbeheerbaarheid.
OefenHub.Infrastructuregeen domein-DbContextgeen schemaTechnische infrastructuur, externe koppelingen, configuratie, hostingondersteuning en generieke adapters.
OefenHub.Webgeen DbContextgeen schemaBlazor/Razor UI, routing, componenten, layouts, state, viewmodels en page composition.

OefenHub.Audit, OefenHub.Security, OefenHub.Workflows en OefenHub.ReadModels worden niet als basisprojecten opgenomen. Audit/history, security, workflows en readmodels worden domeingericht of technisch verdeeld volgens de regels in dit hoofdstuk en de betreffende Technisch Ontwerp-hoofdstukken.

6.6 Domeinmodules op hoofdlijnen

6.6.1 Identity

Identity beheert het interne OefenHub-account en de koppeling met de externe identity provider. De externe identity provider blijft eigenaar van credentials, wachtwoorden, provider-sessies en identity-providerinterne gegevens. OefenHub bewaart alleen de interne accountcontext die nodig is voor applicatiegebruik.

Voorbeelden van Identity-brondata:

  • interne gebruikersrecords;
  • externe provider-id-verwijzing;
  • accountstatus;
  • profielkerngegevens voor applicatiegebruik;
  • account lifecycle- en anonimiseringstoestand;
  • provisioningstatus waar nodig.

Identity is niet eigenaar van autorisatiebeslissingen. Rollen en rolcontext horen bij Authorization.

6.6.2 Authorization

Authorization beheert rollen, roltoekenningen, rolcontext en policies. De module bepaalt niet inhoudelijk of een gebruiker toegang heeft tot elk individueel object; daarvoor gebruikt zij de eigenaar-module van dat object. Authorization levert wel de generieke autorisatiebasis, policystructuur en contextresolving.

Voorbeelden van Authorization-brondata:

  • rollen;
  • roltoekenningen;
  • publieke versus niet-publieke rollen;
  • rolcontextregels;
  • policy- en contextconfiguratie;
  • feature- of contextafhankelijke autorisatie-invoer wanneer die technisch bij autorisatie hoort.

Objecttoegang blijft eigendom van de module die het object bezit. Een ouder-/voogdrelatie wordt dus niet door Authorization zelf geïnterpreteerd als datasettoegang; daarvoor wordt Relationships geraadpleegd.

6.6.3 Relationships

Relationships is eigenaar van gebruikersrelaties en relatie-uitnodigingen. De module beantwoordt relatievragen via publieke contracts, bijvoorbeeld of twee leerlingen actieve vrienden zijn of of een ouder/voogd actief gekoppeld is aan een kind.

Voorbeelden van Relationships-brondata:

  • relatie-uitnodigingen;
  • actieve en gedeactiveerde relaties;
  • relatietype en rolcontext;
  • relatie-events;
  • uitnodigingstatussen;
  • ontkoppelingsinformatie.

Andere modules mogen relationship-tabellen niet rechtstreeks lezen of muteren. Zij gebruiken publieke relationshipcontracts.

6.6.4 Catalog

Catalog is eigenaar van de oefencatalogus: niveaus, centrale categorieën, concrete oefeningen en modulemetadata. De module bewaart welke technische module bij een oefening hoort en welke configuratiepayload daarbij is opgeslagen, maar voert de technische oefenlogica niet zelf uit.

Voorbeelden van Catalog-brondata:

  • niveaus;
  • centrale categorieën;
  • niveau-categorie-koppelingen;
  • concrete oefeningen;
  • oefeningstatussen;
  • modulemetadatarecords;
  • configuratiepayloads;
  • categorie- en modulemigraties;
  • catalogushistorie.

Technische module-implementaties zitten niet in Catalog, maar in concrete OefenHub.Modules.<ModuleCategory>.<ModuleName> projecten en worden via ExerciseModuleHost aangesproken.

6.6.5 ExerciseModuleHost en concrete oefenmodules

ExerciseModuleHost is geen bronhoudend domein voor oefenresultaten of catalogusdata. Het is de technische hostlaag voor het ontdekken, registreren, valideren en aanroepen van concrete oefenmodules.

Concrete oefenmodules:

  • hebben een projectnaam volgens OefenHub.Modules.<ModuleCategory>.<ModuleName>;
  • gebruiken primair OefenHub.Modules.Abstractions;
  • hebben normaal geen eigen databasecontext;
  • leveren configuratievalidatie, vraaggeneratie, antwoordcontrole, rendering en PDF-representatie;
  • bewaren geen runresultaten als eigen brondata.

6.6.6 Practice

Practice is eigenaar van oefenruns, voortgang, resultaten, gedeelde oefeningen, duplicaten en PDF-brondata. Dit domein vormt de bron voor geschiedenis, resultaatweergave, live meekijken en PDF-export.

Voorbeelden van Practice-brondata:

  • exercise runs;
  • vraagvoortgang;
  • antwoordpayloads;
  • uniforme totalen;
  • statistiekvelden;
  • modulepayloads;
  • runcontext-snapshots;
  • gedeelde oefeningen;
  • duplicate-of-relaties;
  • docenttestruns;
  • exportbronmodellen.

Practice verwijst naar identity-, catalogus- en modulecontext via soft links en snapshots. De historische runcontext mag niet afhankelijk worden van later gewijzigde catalogusnamen, accountstatussen of moduleconfiguraties.

6.6.7 Communication

Communication is eigenaar van mailbox-systeemberichten, privéthreads, thread-events, systeemnotificaties en communicatie-readmodels. De module is niet eigenaar van de domeinobjecten waarnaar systeemberichten verwijzen.

Voorbeelden van Communication-brondata:

  • systeemberichten;
  • privéberichtthreads;
  • threaddeelnemers;
  • privéberichten;
  • thread-events;
  • readstates;
  • berichttemplates;
  • systeemnotificaties;
  • mailbox- en badge-readmodels.

Systeemberichten verwijzen naar domeinobjecten via EntityType en EntityId. De vervolgactie wordt altijd opnieuw server-side geautoriseerd door de eigenaar-module.

6.6.8 Support

Support is eigenaar van meldingen/tickets, discussies, sluitingen, heropeningen, doorzetten naar docent en ticketgeschiedenis. Opgelost is een afgeleide gebruikersstatus en geen zelfstandige backendstatus.

Voorbeelden van Support-brondata:

  • tickets;
  • ticketstatussen;
  • ticketcategorieën;
  • assignments;
  • discussion messages;
  • closures;
  • reopen requests;
  • forwarded-to-teacher-records;
  • technical snapshots;
  • ticket history.

Support gebruikt Communication voor systeemcommunicatie en privéberichtintegratie, maar de ticketbron blijft in support.

6.6.9 LiveMonitoring

LiveMonitoring is eigenaar van livebeschikbaarheid, live-sessiecoördinatie en LiveViewAudit. De actuele oefenvoortgang blijft brondata van Practice. SignalR is transport en geen bron van waarheid.

Voorbeelden van LiveMonitoring-brondata:

  • live view auditregels;
  • live sessie-start en -einde;
  • viewerrolsnapshot;
  • online presence indien persistent nodig;
  • technische live-session state wanneer die niet uit runtime kan worden afgeleid.

Het openen van een online-overzicht maakt geen LiveViewAudit aan. Alleen een bewuste live-start doet dat.

6.6.10 Admin

Admin is eigenaar van beheerbare sitecontent, frontpageblokken, vaste pagina’s, footercontent, URL-records, popups, featuretoggles, systeemnotificaties, systeeminstellingen en beheerlogs voor beheerhandelingen die niet logisch tot een specifieker domein behoren. De beheerderinterface kan daarnaast beheerflows voor andere domeinen starten, maar wordt daardoor niet automatisch eigenaar van de brondata van die domeinen.

Voorbeelden van Admin-brondata en afgeleide beheerobjecten:

ObjectgroepTechnische bron of afleidingEigenaarschapsregel
Beheerbare tekstblokkenContentBlocks en ContentBlockHistoryBeheerbare tekstuele content voor frontpages, vaste pagina’s en codegedreven posities. Layout en renderstructuur blijven codegedreven.
URL-recordsSiteLinks en SiteLinkHistoryHerbruikbare interne of externe links voor vaste pagina’s en footerplaatsingen. URL-validatie gebeurt server-side.
FooterstructuurFooterSections, FooterLinkAssignments en FooterLinkAssignmentHistoryContextgebonden footerindeling en linkplaatsingen. Een gebruikte link mag niet hard worden verwijderd zolang plaatsingen bestaan.
PopupregisterPopupDetails, PopupDetailsHistory en PopupDetailsHistoryItemsBestaande popupdefinities zijn beheerbaar binnen de toegestane velden. Technische keys, varianten, acties en custom renderers blijven codegedreven of read-only.
FeaturetogglesSiteFeatureToggles en SiteFeatureToggleHistoryAlleen expliciet togglebare functies worden gemodelleerd. Verplichte kernfunctionaliteit wordt niet als featuretoggle ingericht.
SysteeminstellingenSystemSettingsBestaande sleutels met datatype, invoervorm en validatie. Nieuwe sleutels ontstaan via code en migratie, niet vrij via de beheerinterface.
SysteemnotificatiesSiteNotifications en SiteNotificationHistoryPlanbare frontpage-overlays. Zij zijn geen mailbox-systeemberichten en geen popupregister-popups.
BeheerloggingManagementLogEntries of domeinspecifieke historyBeheerhandelingen blijven reconstructief herleidbaar met actor, rolcontext, object, tijdstip en oude/nieuwe waarde waar relevant.
Beheerder-frontpageAfgeleid readmodelOriëntatiepagina op basis van bestaande beheer-, content-, account- en notificatiebronnen; geen zelfstandige brondata.

Systeemberichttemplates worden functioneel via beheerpagina’s onderhouden, maar blijven technisch onderdeel van het communicatiedomein wanneer zij door Communication worden gebruikt voor systeemcommunicatie. Admin levert in dat geval de beheerroute en beheercontext, terwijl Communication eigenaar blijft van de templatebron, validatie en history.

Docentondersteuning is een supportgerichte beheercontext rondom één geselecteerde docent. Deze context mag docentstructuur, niveaus, categorieën, oefeningen, leerlingtoegang, collaborators en eigenaarschap supportmatig inspecteren of corrigeren via de eigenaar-modules, maar vormt geen aparte brondata naast Catalog, Relationships, Practice en Authorization.

Wanneer een beheerhandeling inhoudelijk een ander domein wijzigt, blijft dat andere domein eigenaar van de bronmutatie. Admin kan dan wel beheercontext, beheerlogging of beheerbare UI-inhoud leveren.

6.6.11 Reporting

Reporting is eigenaar van exportorkestratie en documentopbouw, maar niet van de onderliggende oefenresultaten. Voor PDF-export vraagt Reporting een geautoriseerd exportmodel op bij Practice en gebruikt module-specifieke renderinformatie via het modulecontract.

Voorbeelden van Reporting-verantwoordelijkheden:

  • QuestPDF-documentopbouw;
  • bestandsnaamnormalisatie;
  • tijdelijke exportbestanden;
  • exportfoutafhandeling;
  • exportlogging;
  • eventuele exportmetadata wanneer persistent nodig.

PDF-bestanden zijn tijdelijke output. Bij opnieuw downloaden wordt de PDF opnieuw opgebouwd uit brondata en snapshots.

6.6.12 Scheduling

Scheduling is eigenaar van de technische lifecycle van jobs nadat een job succesvol is aangemaakt. Domeinen blijven eigenaar van de domeinlogica die door jobs wordt uitgevoerd.

Voorbeelden van Scheduling-brondata:

  • TickerQ-jobrecords;
  • retrystatussen;
  • jobpogingen;
  • technische jobfouten;
  • jobcorrelatiegegevens;
  • interne jobbeheerinformatie.

Scheduling mag domeinacties alleen via publieke contracts uitvoeren.

6.7 Brondata, readmodels, snapshots en runtime-state

Niet alle opgeslagen of weergegeven data heeft dezelfde status. Het Technisch Ontwerp maakt expliciet onderscheid tussen brondata, readmodels, snapshots, runtime-state, technische logs en tijdelijke output.

TypeBetekenisVoorbeeldenMag autorisatie verruimen?
BrondataPrimaire functionele waarheid van een domein.ExerciseRuns, Tickets, UserRelationships, SystemMessages.Nee, autorisatie wordt opnieuw bepaald.
ReadmodelAfgeleide weergave- of queryvorm.mailboxoverzicht, dashboardteller, geschiedenisregel.Nee.
SnapshotHistorische vastlegging van context op een bepaald moment.naam, categorie, niveau, rolnaam, moduleversie.Nee.
Runtime-stateTijdelijke staat in sessie, component, SignalR of memory.actieve liveverbinding, browserselectie, open menu.Nee.
Technische logHerleidbaarheid en foutanalyse.requestlog, joblog, access-denied log.Nee.
Tijdelijke outputBestand of response afgeleid uit brondata.PDF-download, tijdelijke exportfile.Nee.

6.8 Brondata per hoofdfunctionaliteit

FunctionaliteitBrondataOndersteunende data
Login en accountcontextidentityproviderclaims, sessiecontext, logging.
Rolcontext en policycontroleauthorizationidentity-accountstatus, objecttoegang via domeincontracts.
Relatie-uitnodigingenrelationshipssysteemberichten in communication.
Leerling-oefenaanbodcatalog, authorization, relationshipsreadmodels en Web-compositie.
Oefening startenpracticecatalogusconfiguratie, modulehost, autorisatiecontracts.
Vraag beantwoordenpracticeconcrete module voor evaluatie.
Resultaatweergavepracticemodule-rendering, Web-viewmodel.
PDF-exportpractice als bron, reporting als orkestratormodule-PDF-rendering, tijdelijke opslag.
Live meekijkenpractice als voortgangsbron, live als sessie-/auditbronSignalR transport.
Berichtenbadgecommunication readmodelSignalR transport, Web-header.
Meldingen/ticketssupportcommunication, scheduling en authorization.
Beheerbare contentadminWeb-compositie.
Periodieke verwerkingdomeineigen brondata, scheduling als joblifecycleTickerQ-persistence en joblogging.

6.9 Cross-module verwijzingen

Cross-module verwijzingen zijn standaard soft links. Dat betekent dat een veld functioneel verwijst naar een record in een andere module, maar dat de database geen harde foreign key afdwingt. De eigenaar-module valideert de verwijzing server-side op het moment van gebruik.

VerwijzingStandaard technische vormReden
practice naar identitysoft link + gebruikerssnapshot waar nodigRuns moeten historisch leesbaar blijven bij account lifecycle en anonimisering.
practice naar catalogsoft link + catalogussnapshotResultaten/PDF’s moeten historische naamgeving/context behouden.
practice naar technische modulesoft link + module-key/version snapshotModulemigraties mogen historische runs niet onleesbaar maken.
communication naar domeinobjectenEntityType + EntityId soft referenceSysteemberichten kunnen naar meerdere domeintypen verwijzen.
support naar identitysoft link + actor/user snapshotTickets blijven historisch raadpleegbaar na accountwijzigingen.
live naar practicesoft link naar run + snapshotsLive audit moet herleidbaar zijn zonder directe lifecycleblokkade.
admin naar beheeractorensoft link + actor snapshotBeheerlogs blijven leesbaar na accountanonimisering.

Cross-module harde FK’s zijn alleen toegestaan wanneer ze expliciet zijn gemotiveerd, geen historische reconstructie blokkeren, geen ongewenste lifecycle-coupling veroorzaken en in het Technisch Ontwerp-besluitenregister zijn vastgelegd.

6.10 Snapshotbeleid op domeinniveau

Snapshots worden gebruikt wanneer latere wijzigingen aan bronobjecten niet mogen doorwerken in historische weergaven of auditregels.

SnapshotcontextVullen bijVoorbeelden
Exercise run contextstarten van de run of uiterlijk bij afronding volgens modulekeuzeniveau-, categorie-, oefening-, module- en gebruikerscontext.
Gedeelde oefeningmoment van delenniveau-, categorie-, oefening- en afzendersnapshot.
PDF-exportmodelmoment van exportopbouw vanuit historische runbronbestandsnaamdelen, resultaatcontext, moduleweergave.
LiveViewAuditstart van live-meekijksessieviewerrol, kind/leerling, runcontext.
Ticket technical snapshotaanmaken van meldingbrowser, pagina, rolcontext, user agent en relevante technische context.
Management logmoment van beheeractieactor, rolcontext, oude waarde en nieuwe waarde.

Snapshotwaarden worden niet stilzwijgend bijgewerkt wanneer de live bron verandert. Bij anonimisering mogen snapshots met persoonsgegevens wel worden overschreven met vooraf gedefinieerde anonimiseringswaarden wanneer privacyregels dat vereisen.

6.11 Readmodels en tellerwaarden

Readmodels zijn afgeleide gegevensvormen voor schermen, overzichten, badges, frontpages, dashboards en exports. Zij hebben geen eigen functionele waarheid.

Regels:

  • module-eigen readmodels staan onder Models/ReadModels in de eigenaar-module;
  • samengestelde UI-viewmodels staan in OefenHub.Web/ViewModels of OefenHub.Web/PageComposition;
  • readmodels mogen geen data tonen waarvoor de gebruiker niet opnieuw server-side geautoriseerd is;
  • readmodels worden opnieuw opgebouwd of hersteld vanuit brondata;
  • tellerdefinities moeten eenduidig vastleggen welke records meetellen;
  • readmodelmaterialisatie mag performance verbeteren, maar mag geen tweede bron van waarheid worden.

Voorbeelden:

ReadmodelEigenaarBron
mailboxoverzichtCommunicationsystem messages, private threads, readstates.
message badgeCommunicationongelezen systeemberichten en thread-readstate.
leerlinggeschiedenisregelPracticeafgeronde non-test exercise runs.
ouderresultaatsamenvattingPracticeafgeronde runs van actief gekoppelde kinderen.
ticketoverzichtSupporttickets, status, discussieactiviteit en sluitingen.
docentcatalogussamenvattingCatalogniveaus, categorieën, oefeningen en statusvelden.
livebeschikbaarheidLiveMonitoring met Practice als broninputactieve runstatus en relatie/autorisatiecontrole.

6.12 Lifecycle-objecten

Sommige domeinobjecten sturen belangrijke lifecycleprocessen. De eigenaar-module is verantwoordelijk voor consistente statusovergangen, historie en foutafhandeling.

LifecycleEigenaarKernstatussen of fasen
Account lifecycleIdentityprovisioned, active, inactive, anonymized/incomplete volgens implementatiekeuze.
Rolcontext lifecycleAuthorizationtoegekend, actief, ingetrokken, niet-publiek.
Relatie-uitnodigingRelationshipspending, accepted, rejected, expired.
User relationshipRelationshipsactief, gedeactiveerd, historisch.
OefeningconfiguratieCatalogin onderhoud, actief, gemigreerd, historisch.
Exercise runPracticeaangemaakt, lopend, onderbroken, afgerond, test/opruimbaar.
Gedeelde oefeningPracticeontvangen, gestart, afgerond, verwijderd uit overzicht.
PrivéthreadCommunicationzichtbaar per participant, verwijderd per participant, readstate per participant.
SysteemberichtCommunicationongelezen, gelezen, eventueel niet-beschikbare vervolgactie.
TicketSupportnew, in progress, waiting for user, closed, opgelost als afgeleide gebruikersstatus.
Live meekijksessieLiveMonitoringgestart, actief, beëindigd, reconnect-falen.
JobSchedulingpending, processing, succeeded, failed, cancelled of equivalent volgens TickerQ-configuratie.

6.13 Domeinoverschrijdende flows

Cross-module workflows worden uitgevoerd door de module die functioneel eigenaar is van de gebruikersactie. Er komt geen generiek OefenHub.Workflows project in de basis.

FlowFunctionele eigenaarBetrokken modulesTransaction boundary
Accountprovisioning met pending uitnodigingenIdentityIdentity, Relationships, CommunicationKritieke stappen per workflow expliciet bepalen.
Relatie-uitnodiging versturenRelationshipsRelationships, CommunicationUitnodiging en primaire ingang kunnen samen kritiek zijn.
Relatie accepterenRelationshipsRelationships, CommunicationRelatiebronmutaties atomair; notificaties afhankelijk van functionele rol.
Oefening startenPracticePractice, Catalog, ExerciseModuleHost, AuthorizationRun-aanmaak atomair binnen Practice na preflightvalidatie.
Oefening delenPracticePractice, Relationships, CommunicationShared-record is kritiek; systeembericht kan kritiek zijn als dit primaire ingang is.
Ticket doorzetten naar docentSupportSupport, Relationships, Communication, AuthorizationKritieke supportmutaties atomair; communicatie per workflow bepalen.
PDF-exportReportingReporting, Practice, ExerciseModuleHostGeen bronmutatie in Practice; tijdelijke output na autorisatie.
Live meekijken startenLiveMonitoringLiveMonitoring, Practice, Relationships, AuthorizationAudit-start atomair binnen LiveMonitoring na toegangscontrole.
Periodieke cleanupSchedulingScheduling en eigenaar-moduleJoblifecycle bij Scheduling; domeinmutatie via contract.

Per workflow wordt expliciet vastgesteld welke mutaties kritiek zijn. Een mutatie is kritiek wanneer de gebruikersactie zonder die mutatie leidt tot een ongeldige, onbereikbare, misleidende of niet-herstelbare functionele toestand.

6.14 Autorisatie en datamodel

Het datamodel ondersteunt autorisatie, maar vervangt autorisatie niet. Geen enkel ID-veld, snapshot, readmodel of routeparameter geeft op zichzelf toegang.

Regels:

  • Iedere command en query valideert server-side de actuele account-, rol- en objectcontext.
  • Objecttoegang wordt gecontroleerd bij de eigenaar-module van het object of via diens publieke contracts.
  • Readmodels worden altijd gevuld of gefilterd binnen de geautoriseerde dataset.
  • Oude browserstate, bookmarks, routeparameters en verborgen formulierwaarden mogen geen toegang verruimen.
  • Systeemberichtverwijzingen worden opnieuw geautoriseerd wanneer de gebruiker doorklikt.
  • Soft links worden bij gebruik functioneel gevalideerd, niet blind vertrouwd.

Voorbeeld:

Een ouder/voogd opent een resultaatdetail via een RunId.

Niet voldoende:
- RunId bestaat.

Wel vereist:
- gebruiker heeft actieve ouder-/voogdrol;
- actieve GuardianStudent-relatie bestaat;
- run is afgerond;
- run hoort bij het gekoppelde kind;
- run is geen uitgesloten test-/technische run;
- resultaatdata wordt pas daarna gelezen.

6.15 Audit, history en technische logs

Er komt geen centrale OefenHub.Audit module in de basis. Audit/history blijft bij het domein waar de betekenis ontstaat.

TypeEigenaarVoorbeeld
Domeinhistorieeigenaar-moduleTicketHistory, ExerciseHistory, CategoryHistory.
Relatie-eventsRelationshipsacceptatie, afwijzing, ontkoppeling.
Live auditLiveMonitoringLiveViewAudit.
BeheerloggingAdmin of eigenaar-modulebeheeractie rond content of domeinobject.
Technische logslogginginfrastructuurrequestfouten, databasefouten, jobfouten.
Security-/access-denied logsWeb/Authorization/eigenaar-module met logginginfrastructuurgeweigerde objecttoegang, verdachte requests.

Technische logs zijn bedoeld voor analyse en monitoring. Domeinhistorie is bedoeld voor functionele reconstructie. Deze twee mogen niet worden vermengd tot één onduidelijke generieke auditlaag.

6.16 Security en privacy binnen het datamodel

Er komt geen apart OefenHub.Security project in de basis, maar security- en privacyregels worden wel expliciet toegepast in alle domeinen.

Datamodelregels:

  • credentials, wachtwoorden, tokens en identity-providerinterne gegevens worden niet in domeintabellen opgeslagen;
  • technische logs bevatten geen wachtwoorden, tokens, volledige payloads met gevoelige antwoorddata of vrije persoonsgegevens zonder noodzaak;
  • snapshots met persoonsgegevens worden alleen gevuld wanneer functioneel nodig;
  • anonimisering gebruikt vooraf gedefinieerde anonimiseringswaarden;
  • historische records blijven waar nodig functioneel reconstrueerbaar zonder actuele persoonsgegevens;
  • tijdelijke exports zijn geen permanente brondata;
  • TickerQ/jobdata mag geen onnodige persoonsgegevens in payloads bewaren.

6.17 ERD's en diagrammen in het Technisch Ontwerp

Dit hoofdstuk mag vereenvoudigde domein- en ERD-weergaven bevatten om de technische samenhang leesbaar te maken. Deze diagrammen zijn ondersteunend en mogen tabellen groeperen, versimpelen of thematisch tonen.

De detaildefinities van tabellen, kolommen, relaties, constraints, enumwaarden en snapshotvelden blijven leidend in database_informatie.

Wanneer een diagram in het Technisch Ontwerp afwijkt van de database-informatie, moet het diagram worden gecorrigeerd of expliciet als vereenvoudigde uitleg worden gelabeld. Het Technisch Ontwerp-diagram mag nooit als zelfstandige bron dienen voor EF-modelgeneratie.

6.17.1 Vereenvoudigde domeinkaart

Deze kaart toont technische afhankelijkheden op contractniveau. Zij betekent niet dat modules elkaars entities, DbContexts of interne services mogen gebruiken.

6.18 Naamgevingsregels op datamodelniveau

ObjectRegelVoorbeeld
Schemakleine letterspractice, communication, support.
TabelPascalCaseExerciseRuns, SystemMessages.
KolomPascalCaseCreatedAtUtc, IsActive.
ProjectPascalCase met OefenHub. prefixOefenHub.Practice.
DbContextmodule + DbContextPracticeDbContext.
Readmodelbetekenisvolle naam + ReadModelGuardianResultSummaryReadModel.
Snapshotveldbetekenis + Snapshot waar nuttigCategoryNameSnapshot.

6.19 Technische kwaliteitsregels voor datamodelwijzigingen

Bij iedere datamodelwijziging moet worden gecontroleerd:

VraagVerwachte beoordeling
Welke module is eigenaar van deze data?Eén duidelijke eigenaar-module.
Hoort de tabel in het schema van die module?Ja, tenzij expliciete uitzondering.
Is de relatie binnen of over modulegrens?Bepaalt hard FK versus soft link/snapshot.
Is historische reconstructie nodig?Zo ja, snapshot of history toevoegen.
Raakt dit autorisatie?Server-side policy/queryscoping aanpassen.
Raakt dit privacy of anonimisering?Snapshot- en retentieregels controleren.
Is seeddata nodig?Module-eigen, idempotent en niet blind overschrijvend.
Is readmodelmaterialisatie nodig?Alleen als performance of schermcomplexiteit dat rechtvaardigt.
Moet ERD worden bijgewerkt?Ja bij structurele relatie- of tabelwijziging.
Moet Software Requirements Specification en Functioneel Ontwerp worden bijgewerkt?Alleen bij functionele wijziging of nieuwe requirement.
Moet Technisch Ontwerp-hoofdstuk worden bijgewerkt?Ja bij technische ontwerpimpact.

6.20 Relatie met modulehoofdstukken

Dit hoofdstuk geeft de overkoepelende kaart. De technische details staan in de modulehoofdstukken:

DetailgebiedHoofdstuk
Identity en provisioningtechnisch_ontwerp/04-identiteit-authenticatie-en-rolcontext
Autorisatie en contextcontroletechnisch_ontwerp/05-autorisatie-policies-en-server-side-contextcontrole
Database, migrations, seeddata en constraintstechnisch_ontwerp/07-databaseontwerp-migraties-seeddata-en-constraints
Catalogustechnisch_ontwerp/08-oefencatalogus-niveaus-categorieen-oefeningen-en-modules
Oefenmodulecontracttechnisch_ontwerp/09-oefenmodulecontract-en-dynamische-module-integratie
Practice/oefenrunstechnisch_ontwerp/10-oefenruns-voortgang-resultaten-statistieken-en-pdf-brondata
Relaties en gedeelde oefeningentechnisch_ontwerp/12-relatiebeheer-uitnodigingen-en-gedeelde-oefeningen
Communicationtechnisch_ontwerp/13-berichten-systeemberichten-notificaties-en-priveberichten
Support/ticketstechnisch_ontwerp/14-meldingen-tickets-en-beheerafhandeling
LiveMonitoringtechnisch_ontwerp/15-realtime-live-meekijken-met-signalr
Reporting/PDFtechnisch_ontwerp/16-pdf-export-met-questpdf
Scheduling/TickerQtechnisch_ontwerp/18-background-jobs-tickerq-en-periodieke-verwerking
Logging en foutafhandelingtechnisch_ontwerp/19-logging-audit-securitylogging-en-technische-foutafhandeling
Security-infrastructuurtechnisch_ontwerp/20-security-infrastructuur-secrets-en-omgevingen
Frontend/Blazortechnisch_ontwerp/24-frontend-blazor-routing-state-en-componentopbouw
Privacy en anonimiseringtechnisch_ontwerp/25-privacy-retentie-anonimisering-en-gegevensbescherming

6.21 Implementatiechecklist

Voor implementatie van het domein- en datamodeloverzicht geldt:

  • ieder bronobject heeft één eigenaar-module;
  • ieder eigenaarproject heeft maximaal één eigen DbContext en schema;
  • cross-module verwijzingen worden standaard als soft link of soft link + snapshot gemodelleerd;
  • harde FK’s over modulegrenzen zijn expliciete uitzonderingen;
  • readmodels staan bij de eigenaar-module onder Models/ReadModels;
  • UI-viewmodels worden in Web samengesteld via publieke query-services;
  • technische logs en domeinhistorie worden gescheiden gehouden;
  • security- en privacyregels worden per domein toegepast;
  • ERD-diagrammen worden gebruikt als ondersteunende visualisatie, niet als detailbron;
  • datamodelwijzigingen worden getoetst aan Functioneel Ontwerp, Software Requirements Specification, database-informatie, ERD en Technisch Ontwerp-impact.

6.22 Implementatieverificaties

PuntVerificatie / besluit
Cross-module FK-uitzonderingenVastleggen of er in de eerste implementatie toch harde FK’s over modulegrenzen nodig zijn.
Snapshotvelden per modulePer module controleren welke snapshots exact nodig zijn en waar anonimisering invloed heeft.
Persistent Reporting-schemaVaststellen of Reporting eigen persistente tabellen nodig heeft of alleen tijdelijke exportoutput.
Live presence persistenceBepalen welke online/live-state runtime mag blijven en welke persistent onder live moet worden opgeslagen.
TickerQ-schemaVerifiëren dat TickerQ-tabellen in schema scheduling geplaatst kunnen worden.
ReadmodelmaterialisatiePer readmodel bepalen of live query, cache, projection of materialized tabel nodig is.
ERD-synchronisatieControleren dat wijzigingen in dit Technisch Ontwerp-hoofdstuk geen afwijkende tabelwaarheid creëren naast database_informatie.