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:
database_informatievoor tabellen, kolommen, relaties, enumwaarden, constraints, snapshots en databronnen;- Software Requirements Specification voor requirements, acceptatiecriteria, prioriteiten en traceability;
- Functioneel Ontwerp voor functionele domeinregels, rollen, lifecycle en bron-van-waarheid;
- architectuurdocumentatie voor systeemcontext en technische hoofdkeuzes;
- modulehoofdstukken in het Technisch Ontwerp voor technische implementatiekeuzes per domein;
- ERD-documenten als ondersteunende visualisatie en navigatielaag.
Belangrijke inputbronnen zijn:
- Functioneel Ontwerp: functionele architectuurcontext
- Database-informatie: introductie en bronafbakening
- Database-informatie: ERD-overzicht
- Software Requirements Specification: readmodel- en tellerdefinities
- Technisch Ontwerp: architectuuroverzicht en solution-opbouw
- Technisch Ontwerp: applicatielagen, projectstructuur en dependency-richting
- Technisch Ontwerp: databaseontwerp, migraties, seeddata en constraints
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.
| Principe | Regel |
|---|---|
| Eén database | OefenHub gebruikt één relationele database voor de applicatiegegevens. |
| Eén connectionstring | De eerste baseline gebruikt één applicatieconnectionstring voor alle module-DbContexts. |
| Module-eigenaarschap | Eén moduleproject is eigenaar van maximaal één DbContext en één database-schema. |
| Schema als eigendomsgrens | Een schema maakt zichtbaar welke module eigenaar is van de tabellen. |
| Geen schema als securityboundary | Schema’s ondersteunen ordening en eigenaarschap, maar vervangen geen autorisatie of securitymaatregelen. |
| Hard FK binnen module | Harde foreign keys zijn vooral bedoeld binnen dezelfde modulegrens. |
| Soft link over modulegrens | Cross-module verwijzingen zijn standaard soft links, eventueel aangevuld met snapshots. |
| Readmodel is geen bron | Readmodels mogen gegevens presenteren of versnellen, maar zijn geen zelfstandige functionele bron. |
| Authorisatie blijft server-side | Datamodelstructuur, readmodels en UI-state mogen autorisatie niet verruimen. |
| Historie blijft reconstrueerbaar | Historische 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.
| Project | DbContext | Schema | Primaire verantwoordelijkheid |
|---|---|---|---|
OefenHub.Identity | IdentityDbContext | identity | Interne accounts, profielkern, accountstatus, provisioning en account lifecycle. |
OefenHub.Authorization | AuthorizationDbContext | authorization | Rollen, roltoekenningen, rolcontext, policies en autorisatiegerelateerde referentiedata. |
OefenHub.Relationships | RelationshipsDbContext | relationships | Relaties, uitnodigingen, relatie-events en relatieafhankelijke toegangsvragen. |
OefenHub.Catalog | CatalogDbContext | catalog | Niveaus, categorieën, oefeningen, modulemetadata, catalogushistorie en catalogusmigraties. |
OefenHub.ExerciseModuleHost | geen eigen domein-DbContext | geen eigen schema | Runtime-resolving en aanroep van technische oefenmodules. |
OefenHub.Practice | PracticeDbContext | practice | Exercise runs, voortgang, resultaten, gedeelde oefeningen, duplicaten, statistieken en PDF-brondata. |
OefenHub.Communication | CommunicationDbContext | communication | Interne systeemberichten, privéthreads, thread-events, notificaties, systeemberichttemplates en mailbox-readmodels. |
OefenHub.Mail | MailDbContext | mail | Applicatiegestuurde externe e-mail, mailtemplates, templatehistory en mailverzendpogingen. |
OefenHub.Support | SupportDbContext | support | Meldingen/tickets, discussies, sluitingen, heropeningen, doorzetten naar docent en ticketgeschiedenis. |
OefenHub.LiveMonitoring | LiveMonitoringDbContext | live | Livebeschikbaarheid, live sessiecoördinatie, online presence en LiveViewAudit. |
OefenHub.Admin | AdminDbContext | admin | Beheerbare content, vaste pagina’s, footercontent, URL-records, popups, systeemnotificaties, featuretoggles, systeeminstellingen en beheerlogs. |
OefenHub.Reporting | optioneel ReportingDbContext | reporting indien nodig | Exportorkestratie, rapportage-/exportreadmodels en eventuele persistente exportmetadata. |
OefenHub.Scheduling | SchedulingDbContext indien nodig | scheduling | TickerQ-persistence, joblifecycle, retrystatussen, technische jobhistorie en interne jobbeheerbaarheid. |
OefenHub.Infrastructure | geen domein-DbContext | geen schema | Technische infrastructuur, externe koppelingen, configuratie, hostingondersteuning en generieke adapters. |
OefenHub.Web | geen DbContext | geen schema | Blazor/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:
| Objectgroep | Technische bron of afleiding | Eigenaarschapsregel |
|---|---|---|
| Beheerbare tekstblokken | ContentBlocks en ContentBlockHistory | Beheerbare tekstuele content voor frontpages, vaste pagina’s en codegedreven posities. Layout en renderstructuur blijven codegedreven. |
| URL-records | SiteLinks en SiteLinkHistory | Herbruikbare interne of externe links voor vaste pagina’s en footerplaatsingen. URL-validatie gebeurt server-side. |
| Footerstructuur | FooterSections, FooterLinkAssignments en FooterLinkAssignmentHistory | Contextgebonden footerindeling en linkplaatsingen. Een gebruikte link mag niet hard worden verwijderd zolang plaatsingen bestaan. |
| Popupregister | PopupDetails, PopupDetailsHistory en PopupDetailsHistoryItems | Bestaande popupdefinities zijn beheerbaar binnen de toegestane velden. Technische keys, varianten, acties en custom renderers blijven codegedreven of read-only. |
| Featuretoggles | SiteFeatureToggles en SiteFeatureToggleHistory | Alleen expliciet togglebare functies worden gemodelleerd. Verplichte kernfunctionaliteit wordt niet als featuretoggle ingericht. |
| Systeeminstellingen | SystemSettings | Bestaande sleutels met datatype, invoervorm en validatie. Nieuwe sleutels ontstaan via code en migratie, niet vrij via de beheerinterface. |
| Systeemnotificaties | SiteNotifications en SiteNotificationHistory | Planbare frontpage-overlays. Zij zijn geen mailbox-systeemberichten en geen popupregister-popups. |
| Beheerlogging | ManagementLogEntries of domeinspecifieke history | Beheerhandelingen blijven reconstructief herleidbaar met actor, rolcontext, object, tijdstip en oude/nieuwe waarde waar relevant. |
| Beheerder-frontpage | Afgeleid readmodel | Orië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.
| Type | Betekenis | Voorbeelden | Mag autorisatie verruimen? |
|---|---|---|---|
| Brondata | Primaire functionele waarheid van een domein. | ExerciseRuns, Tickets, UserRelationships, SystemMessages. | Nee, autorisatie wordt opnieuw bepaald. |
| Readmodel | Afgeleide weergave- of queryvorm. | mailboxoverzicht, dashboardteller, geschiedenisregel. | Nee. |
| Snapshot | Historische vastlegging van context op een bepaald moment. | naam, categorie, niveau, rolnaam, moduleversie. | Nee. |
| Runtime-state | Tijdelijke staat in sessie, component, SignalR of memory. | actieve liveverbinding, browserselectie, open menu. | Nee. |
| Technische log | Herleidbaarheid en foutanalyse. | requestlog, joblog, access-denied log. | Nee. |
| Tijdelijke output | Bestand of response afgeleid uit brondata. | PDF-download, tijdelijke exportfile. | Nee. |
6.8 Brondata per hoofdfunctionaliteit
| Functionaliteit | Brondata | Ondersteunende data |
|---|---|---|
| Login en accountcontext | identity | providerclaims, sessiecontext, logging. |
| Rolcontext en policycontrole | authorization | identity-accountstatus, objecttoegang via domeincontracts. |
| Relatie-uitnodigingen | relationships | systeemberichten in communication. |
| Leerling-oefenaanbod | catalog, authorization, relationships | readmodels en Web-compositie. |
| Oefening starten | practice | catalogusconfiguratie, modulehost, autorisatiecontracts. |
| Vraag beantwoorden | practice | concrete module voor evaluatie. |
| Resultaatweergave | practice | module-rendering, Web-viewmodel. |
| PDF-export | practice als bron, reporting als orkestrator | module-PDF-rendering, tijdelijke opslag. |
| Live meekijken | practice als voortgangsbron, live als sessie-/auditbron | SignalR transport. |
| Berichtenbadge | communication readmodel | SignalR transport, Web-header. |
| Meldingen/tickets | support | communication, scheduling en authorization. |
| Beheerbare content | admin | Web-compositie. |
| Periodieke verwerking | domeineigen brondata, scheduling als joblifecycle | TickerQ-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.
| Verwijzing | Standaard technische vorm | Reden |
|---|---|---|
practice naar identity | soft link + gebruikerssnapshot waar nodig | Runs moeten historisch leesbaar blijven bij account lifecycle en anonimisering. |
practice naar catalog | soft link + catalogussnapshot | Resultaten/PDF’s moeten historische naamgeving/context behouden. |
practice naar technische module | soft link + module-key/version snapshot | Modulemigraties mogen historische runs niet onleesbaar maken. |
communication naar domeinobjecten | EntityType + EntityId soft reference | Systeemberichten kunnen naar meerdere domeintypen verwijzen. |
support naar identity | soft link + actor/user snapshot | Tickets blijven historisch raadpleegbaar na accountwijzigingen. |
live naar practice | soft link naar run + snapshots | Live audit moet herleidbaar zijn zonder directe lifecycleblokkade. |
admin naar beheeractoren | soft link + actor snapshot | Beheerlogs 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.
| Snapshotcontext | Vullen bij | Voorbeelden |
|---|---|---|
| Exercise run context | starten van de run of uiterlijk bij afronding volgens modulekeuze | niveau-, categorie-, oefening-, module- en gebruikerscontext. |
| Gedeelde oefening | moment van delen | niveau-, categorie-, oefening- en afzendersnapshot. |
| PDF-exportmodel | moment van exportopbouw vanuit historische runbron | bestandsnaamdelen, resultaatcontext, moduleweergave. |
| LiveViewAudit | start van live-meekijksessie | viewerrol, kind/leerling, runcontext. |
| Ticket technical snapshot | aanmaken van melding | browser, pagina, rolcontext, user agent en relevante technische context. |
| Management log | moment van beheeractie | actor, 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/ReadModelsin de eigenaar-module; - samengestelde UI-viewmodels staan in
OefenHub.Web/ViewModelsofOefenHub.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:
| Readmodel | Eigenaar | Bron |
|---|---|---|
| mailboxoverzicht | Communication | system messages, private threads, readstates. |
| message badge | Communication | ongelezen systeemberichten en thread-readstate. |
| leerlinggeschiedenisregel | Practice | afgeronde non-test exercise runs. |
| ouderresultaatsamenvatting | Practice | afgeronde runs van actief gekoppelde kinderen. |
| ticketoverzicht | Support | tickets, status, discussieactiviteit en sluitingen. |
| docentcatalogussamenvatting | Catalog | niveaus, categorieën, oefeningen en statusvelden. |
| livebeschikbaarheid | LiveMonitoring met Practice als broninput | actieve runstatus en relatie/autorisatiecontrole. |
6.12 Lifecycle-objecten
Sommige domeinobjecten sturen belangrijke lifecycleprocessen. De eigenaar-module is verantwoordelijk voor consistente statusovergangen, historie en foutafhandeling.
| Lifecycle | Eigenaar | Kernstatussen of fasen |
|---|---|---|
| Account lifecycle | Identity | provisioned, active, inactive, anonymized/incomplete volgens implementatiekeuze. |
| Rolcontext lifecycle | Authorization | toegekend, actief, ingetrokken, niet-publiek. |
| Relatie-uitnodiging | Relationships | pending, accepted, rejected, expired. |
| User relationship | Relationships | actief, gedeactiveerd, historisch. |
| Oefeningconfiguratie | Catalog | in onderhoud, actief, gemigreerd, historisch. |
| Exercise run | Practice | aangemaakt, lopend, onderbroken, afgerond, test/opruimbaar. |
| Gedeelde oefening | Practice | ontvangen, gestart, afgerond, verwijderd uit overzicht. |
| Privéthread | Communication | zichtbaar per participant, verwijderd per participant, readstate per participant. |
| Systeembericht | Communication | ongelezen, gelezen, eventueel niet-beschikbare vervolgactie. |
| Ticket | Support | new, in progress, waiting for user, closed, opgelost als afgeleide gebruikersstatus. |
| Live meekijksessie | LiveMonitoring | gestart, actief, beëindigd, reconnect-falen. |
| Job | Scheduling | pending, 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.
| Flow | Functionele eigenaar | Betrokken modules | Transaction boundary |
|---|---|---|---|
| Accountprovisioning met pending uitnodigingen | Identity | Identity, Relationships, Communication | Kritieke stappen per workflow expliciet bepalen. |
| Relatie-uitnodiging versturen | Relationships | Relationships, Communication | Uitnodiging en primaire ingang kunnen samen kritiek zijn. |
| Relatie accepteren | Relationships | Relationships, Communication | Relatiebronmutaties atomair; notificaties afhankelijk van functionele rol. |
| Oefening starten | Practice | Practice, Catalog, ExerciseModuleHost, Authorization | Run-aanmaak atomair binnen Practice na preflightvalidatie. |
| Oefening delen | Practice | Practice, Relationships, Communication | Shared-record is kritiek; systeembericht kan kritiek zijn als dit primaire ingang is. |
| Ticket doorzetten naar docent | Support | Support, Relationships, Communication, Authorization | Kritieke supportmutaties atomair; communicatie per workflow bepalen. |
| PDF-export | Reporting | Reporting, Practice, ExerciseModuleHost | Geen bronmutatie in Practice; tijdelijke output na autorisatie. |
| Live meekijken starten | LiveMonitoring | LiveMonitoring, Practice, Relationships, Authorization | Audit-start atomair binnen LiveMonitoring na toegangscontrole. |
| Periodieke cleanup | Scheduling | Scheduling en eigenaar-module | Joblifecycle 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.
| Type | Eigenaar | Voorbeeld |
|---|---|---|
| Domeinhistorie | eigenaar-module | TicketHistory, ExerciseHistory, CategoryHistory. |
| Relatie-events | Relationships | acceptatie, afwijzing, ontkoppeling. |
| Live audit | LiveMonitoring | LiveViewAudit. |
| Beheerlogging | Admin of eigenaar-module | beheeractie rond content of domeinobject. |
| Technische logs | logginginfrastructuur | requestfouten, databasefouten, jobfouten. |
| Security-/access-denied logs | Web/Authorization/eigenaar-module met logginginfrastructuur | geweigerde 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
| Object | Regel | Voorbeeld |
|---|---|---|
| Schema | kleine letters | practice, communication, support. |
| Tabel | PascalCase | ExerciseRuns, SystemMessages. |
| Kolom | PascalCase | CreatedAtUtc, IsActive. |
| Project | PascalCase met OefenHub. prefix | OefenHub.Practice. |
| DbContext | module + DbContext | PracticeDbContext. |
| Readmodel | betekenisvolle naam + ReadModel | GuardianResultSummaryReadModel. |
| Snapshotveld | betekenis + Snapshot waar nuttig | CategoryNameSnapshot. |
6.19 Technische kwaliteitsregels voor datamodelwijzigingen
Bij iedere datamodelwijziging moet worden gecontroleerd:
| Vraag | Verwachte 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:
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
| Punt | Verificatie / besluit |
|---|---|
| Cross-module FK-uitzonderingen | Vastleggen of er in de eerste implementatie toch harde FK’s over modulegrenzen nodig zijn. |
| Snapshotvelden per module | Per module controleren welke snapshots exact nodig zijn en waar anonimisering invloed heeft. |
| Persistent Reporting-schema | Vaststellen of Reporting eigen persistente tabellen nodig heeft of alleen tijdelijke exportoutput. |
| Live presence persistence | Bepalen welke online/live-state runtime mag blijven en welke persistent onder live moet worden opgeslagen. |
| TickerQ-schema | Verifiëren dat TickerQ-tabellen in schema scheduling geplaatst kunnen worden. |
| Readmodelmaterialisatie | Per readmodel bepalen of live query, cache, projection of materialized tabel nodig is. |
| ERD-synchronisatie | Controleren dat wijzigingen in dit Technisch Ontwerp-hoofdstuk geen afwijkende tabelwaarheid creëren naast database_informatie. |