Skip to main content

3. Docentstructuur en leerlingtoegang

Deze sectie beschrijft de door docenten ingerichte niveaustructuur, samenwerking tussen docenten op niveau-laag, eigendomsoverdracht van niveaus en de autorisatie van leerlingen tot die structuur.

3.1 TeacherLevels

TabelnaamCategorieDoel / verantwoordelijkheidGerelateerde tabellen
TeacherLevelsDocentstructuurDoor een docent aangemaakte niveaus met vrije naamgeving en één actuele eigenaar.Users, TeacherLevelCollaborators, TeacherLevelOwnershipTransfers, TeacherLevelCategories, TeacherStudentLevelAccess
VeldnaamTypeDefaultPKFKVerwijst naarUniqueNullableIndexOpmerking
Iduniqueidentifier-JN-JNJPrimaire sleutel. GUID wordt in de applicatiecode gegenereerd; geen database-default.
OwnerTeacherUserIduniqueidentifier-NNUsers.IdNNJDocent die op dit moment eigenaar is van het niveau. Soft link naar Users.Id; geen harde database-FK vanwege modulegrens.
Namenvarchar(150)-NN-NNJVrije naamgeving, bijvoorbeeld Groep 7 of Klas 2026 - Groep 7.
Descriptionnvarchar(500)nullNN-NJNOptionele beschrijving.
IsActivebit1NN-NNJMaakt niveau actief of historisch.
CreatedAtUtcdatetime2sysutcdatetime()NN-NNNAanmaakmoment.
UpdatedAtUtcdatetime2sysutcdatetime()NN-NNNLaatste wijziging.

Validaties / constraints

  • Naam hoeft niet globaal uniek te zijn.

Business rules

  • Een niveau behoort altijd aan precies één docent als actuele eigenaar.
  • Een niveau kan daarnaast één of meerdere actieve collaborators hebben.
  • Een leerling kan pas toegang krijgen tot een niveau via een actieve docent-leerlingrelatie.
  • Wanneer de actuele eigenaar van een niveau het account verwijdert of geanonimiseerd wordt, mag geen verweesd actief niveau overblijven. Zonder actieve collaborators wordt het niveau gedeactiveerd; met actieve collaborators moet eigenaarschap eerst gecontroleerd worden overgedragen.

Lifecycle / gedrag

  • Niveaus worden gedeactiveerd in plaats van verwijderd wanneer historie behouden moet blijven.
  • Eigenaarschap kan worden overgedragen; de actuele eigenaar wordt dan in deze tabel aangepast.
  • Bij accountverwijdering van de eigenaar geldt aanvullend: bij precies één actieve collaborator mag automatische overdracht plaatsvinden; bij meerdere actieve collaborators moet de opvolgende eigenaar expliciet door de eigenaar of een beheerder worden gekozen.

Designkeuzes

  • Niveau is bewust docent-specifiek en niet leerling-specifiek.
  • Samenwerking en eigendomsoverdracht worden in aparte tabellen vastgelegd zodat eigenaarschap, samenwerking en leerlingtoegang logisch gescheiden blijven.

Foreign keys op databaseniveau

  • Harde foreign keys op databaseniveau: niet van toepassing binnen deze tabel.

Functionele / logische verwijzingen zonder harde FK

  • OwnerTeacherUserId is een soft link naar Users.Id. De eigenaar wordt applicatief gevalideerd via het identity-/autorisatiedomein; er wordt geen harde database-FK naar Users gelegd.

FK + snapshot

  • FK + snapshot: niet van toepassing binnen deze tabel.

3.2 TeacherLevelCollaborators

TabelnaamCategorieDoel / verantwoordelijkheidGerelateerde tabellen
TeacherLevelCollaboratorsDocentstructuurActieve samenwerking van extra docenten op een bestaand niveau.TeacherLevels, Users, UserRelationships
VeldnaamTypeDefaultPKFKVerwijst naarUniqueNullableIndexOpmerking
Iduniqueidentifier-JN-JNJPrimaire sleutel. GUID wordt in de applicatiecode gegenereerd; geen database-default.
TeacherLevelIduniqueidentifier-NJTeacherLevels.IdNNJNiveau waarop wordt samengewerkt.
CollaboratorTeacherUserIduniqueidentifier-NNUsers.IdNNJDocent die als collaborator op dit niveau mag meewerken. Soft link naar Users.Id; geen harde database-FK vanwege modulegrens.
GrantedAtUtcdatetime2sysutcdatetime()NN-NNNMoment waarop de samenwerking is toegekend.
GrantedByUserIduniqueidentifier-NNUsers.IdNNNGebruiker die de samenwerking heeft toegekend. Soft link naar Users.Id; geen harde database-FK vanwege modulegrens.
RevokedAtUtcdatetime2nullNN-NJNMoment waarop de samenwerking is ingetrokken.
RevokedByUserIduniqueidentifiernullNNUsers.IdNJNGebruiker die de samenwerking heeft ingetrokken. Soft link naar Users.Id; geen harde database-FK vanwege modulegrens.
IsActivebit1NN-NNJActieve samenwerking op dit niveau.

Validaties / constraints

  • Actieve combinatie TeacherLevelId + CollaboratorTeacherUserId is uniek.
  • De actuele eigenaar van het niveau mag niet als collaborator van hetzelfde niveau voorkomen.

Business rules

  • Een collaborator mag alleen worden gekoppeld wanneer tussen eigenaar en collaborator een actieve TeacherTeacher-relatie bestaat.
  • De actieve TeacherTeacher-relatie is een voorwaarde voor het aangaan van nieuwe collaboration, maar niet de technische drager van bestaand niveau-bewerkrecht. Een reeds bestaand collaboratorrecord blijft dus zelfstandig geldig totdat dit expliciet op niveau-laag wordt ingetrokken.
  • Een record in deze tabel geeft bewerkrecht op het betreffende niveau.
  • In beheercontext worden eerst de al actieve collaborators getoond, alfabetisch op naam, en daaronder de nog beschikbare docenten, eveneens alfabetisch op naam.
  • Een beheerder mag in uitzonderingssituaties een nieuwe collaborator forceren; daarbij wordt zo nodig eerst een docent-docentrelatie vastgelegd en daarna direct een collaboratorrecord aangemaakt zonder acceptatiestap door de nieuwe docent.

Lifecycle / gedrag

  • Samenwerking op niveau wordt ingetrokken via RevokedAtUtc/RevokedByUserId en niet hard verwijderd.
  • Bij eigendomsoverdracht blijft de oude eigenaar standaard collaborator.
  • Het beëindigen van een algemene TeacherTeacher-relatie trekt bestaande collaboratorrecords niet automatisch in. Intrekking van niveau-samenwerking vereist een expliciete actie op het collaboratorrecord of een afgeleide beheerflow zoals eigendomsoverdracht of accountverwijdering.
  • Wanneer een beheerder een collaborator forceert, moet deze actie auditbaar zijn en ontvangt de oorspronkelijk geselecteerde docent hierover een systeembericht.

Designkeuzes

  • Samenwerking op niveau is bewust los gemodelleerd van de algemene docent-docent relatie. Daardoor geeft de relatie alleen het algemene samenwerkingsverband aan en bepaalt deze tabel de concrete samenwerking op niveau-laag.

Foreign keys op databaseniveau

  • Harde foreign keys op databaseniveau: TeacherLevelId -> TeacherLevels.Id.

Functionele / logische verwijzingen zonder harde FK

  • CollaboratorTeacherUserId, GrantedByUserId en RevokedByUserId zijn soft links naar Users.Id. De gebruikerscontext wordt applicatief gevalideerd via identity-/autorisatiecontracten; er worden geen harde database-FK's naar Users gelegd.

FK + snapshot

  • FK + snapshot: niet van toepassing binnen deze tabel.

3.3 TeacherLevelOwnershipTransfers

TabelnaamCategorieDoel / verantwoordelijkheidGerelateerde tabellen
TeacherLevelOwnershipTransfersDocentstructuurHistorie van overdracht van eigenaarschap van een niveau tussen docenten.TeacherLevels, TeacherLevelCollaborators, Users
VeldnaamTypeDefaultPKFKVerwijst naarUniqueNullableIndexOpmerking
Iduniqueidentifier-JN-JNJPrimaire sleutel. GUID wordt in de applicatiecode gegenereerd; geen database-default.
TeacherLevelIduniqueidentifier-NJTeacherLevels.IdNNJNiveau waarvan eigenaarschap is overgedragen.
PreviousOwnerTeacherUserIduniqueidentifier-NNUsers.IdNNJDocent die vóór de overdracht eigenaar was. Soft link naar Users.Id; geen harde database-FK vanwege modulegrens.
NewOwnerTeacherUserIduniqueidentifier-NNUsers.IdNNJDocent die na de overdracht eigenaar is geworden. Soft link naar Users.Id; geen harde database-FK vanwege modulegrens.
TransferredAtUtcdatetime2sysutcdatetime()NN-NNNMoment van overdracht.
TransferredByUserIduniqueidentifier-NNUsers.IdNNNGebruiker die de overdracht heeft uitgevoerd; dit is de huidige eigenaar of een beheerder. Soft link naar Users.Id; geen harde database-FK vanwege modulegrens.
Reasonnvarchar(1000)-NN-NNNVerplichte toelichting op de overdracht.

Validaties / constraints

  • NewOwnerTeacherUserId moet op het moment van overdracht een actieve collaborator van het niveau zijn.
  • PreviousOwnerTeacherUserId en NewOwnerTeacherUserId mogen niet gelijk zijn.

Business rules

  • Eigenaarschap kan alleen worden overgedragen door de huidige eigenaar of een beheerder. Bij iedere overdracht is een reden verplicht.
  • Na overdracht wordt de nieuwe eigenaar actuele eigenaar van het niveau.
  • De oude eigenaar blijft standaard collaborator.
  • In de beheerinterface mag eigenaarschap uitsluitend worden overgezet naar een reeds actieve collaborator; als er nog geen collaborator beschikbaar is, moet eerst collaboration op dat niveau worden toegevoegd.
  • Bij accountverwijdering van de actuele eigenaar blijft dezelfde regel gelden: automatische of geforceerde overdracht mag alleen naar een docent die op dat moment al actieve collaborator van het niveau is.

Lifecycle / gedrag

  • Iedere overdracht levert één historisch record op en overschrijft niet eerdere overdrachten.
  • De nieuwe eigenaar hoort daarna niet meer als actieve collaborator op hetzelfde niveau voor te komen.

Designkeuzes

  • Eigendomsoverdracht is apart gemodelleerd om volledige audittrail, onderbouwing en latere reconstructie van eigenaarschap te behouden.

Foreign keys op databaseniveau

  • Harde foreign keys op databaseniveau: TeacherLevelId -> TeacherLevels.Id.

Functionele / logische verwijzingen zonder harde FK

  • PreviousOwnerTeacherUserId, NewOwnerTeacherUserId en TransferredByUserId zijn soft links naar Users.Id. De overdrachtshistorie blijft daardoor domein-eigen vastgelegd zonder harde database-afhankelijkheid op het identity-domein.

FK + snapshot

  • FK + snapshot: niet van toepassing binnen deze tabel.

3.4 Categories

TabelnaamCategorieDoel / verantwoordelijkheidGerelateerde tabellen
CategoriesCentrale onderwijsinhoudCentrale categorie-identiteit die door meerdere docentniveaus kan worden hergebruikt. Bevat naam, visuele presentatie en auditinformatie.TeacherLevelCategories, CategoryHistory
VeldnaamTypeDefaultPKFKVerwijst naarUniqueNullableIndexOpmerking
Iduniqueidentifier-JN-JNJPrimaire sleutel. GUID wordt in de applicatiecode gegenereerd; geen database-default.
Namenvarchar(150)-NN-JNJCentrale categorienaam. Wordt gedeeld gebruikt over docentniveaus heen.
IconKeynvarchar(100)-NN-NNNVaste sleutel naar de gekozen categorie-icoonset.
ColorHexnvarchar(7)-NN-NNNCentrale kleurwaarde in hex-formaat, bijvoorbeeld #4A90E2.
CreatedByUserIduniqueidentifier-NNUsers.IdNNJGebruiker die de categorie oorspronkelijk heeft aangemaakt. Soft link naar Users.Id; geen harde database-FK vanwege modulegrens.
CreatedAtUtcdatetime2sysutcdatetime()NN-NNNAanmaakmoment.
UpdatedByUserIduniqueidentifier-NNUsers.IdNJNGebruiker die de laatste inhoudelijke wijziging heeft uitgevoerd. Soft link naar Users.Id; geen harde database-FK vanwege modulegrens.
UpdatedAtUtcdatetime2sysutcdatetime()NN-NNNLaatste wijzigmoment.
IsDeletedbit0NN-NNJSoft delete voor beheerbare opschoning zonder historieverlies.

Validaties / constraints

  • Name is uniek binnen actieve records.
  • IconKey en ColorHex zijn verplicht.
  • ColorHex moet een geldig hex-kleurformaat hebben.

Business rules

  • Categories bevat de centrale identiteit van een categorie: naam, kleur en icoon.
  • Deze identiteit kan door meerdere docenten en docentniveaus worden hergebruikt en mag daarom niet vrij per docentcontext afwijken.
  • Een beheerder kan een categorie hernoemen, deactiveren, soft deleten of migreren naar een andere bestaande centrale categorie wanneer dubbele of semantisch overlappende categorieën zijn ontstaan.

Lifecycle / gedrag

  • Beheer kan naam, kleur en icoon wijzigen wanneer daar een geldige reden voor is.
  • Dergelijke wijzigingen moeten herleidbaar zijn omdat ze meerdere docentcontexten en leerlingweergaven kunnen beïnvloeden.
  • Na migratie blijft een broncategorie historisch bestaan, maar mag deze niet langer nieuw gekozen of gekoppeld worden door docenten.

Designkeuzes

  • Kleur en icoon worden bewust centraal op Categories vastgelegd. Hiermee blijft voor alle gebruikers die dezelfde categorie gebruiken één consistente semantische en visuele identiteit behouden.

Foreign keys op databaseniveau

  • Harde foreign keys op databaseniveau: niet van toepassing binnen deze tabel.

Functionele / logische verwijzingen zonder harde FK

  • CreatedByUserId en UpdatedByUserId zijn soft links naar Users.Id; er worden geen harde database-FK's naar het identity-domein gelegd.
  • IconKey functioneert als code-, enum- of sleutelwaarde en verwijst bewust niet via een harde foreign key. ColorHex bevat een inhoudelijke of technische contextwaarde en is daarom logische samenhang zonder harde foreign key.

FK + snapshot

  • FK + snapshot: niet van toepassing binnen deze tabel.

3.5 CategoryHistory

TabelnaamCategorieDoel / verantwoordelijkheidGerelateerde tabellen
CategoryHistoryAudit en historieVastleggen van beheerwijzigingen op centrale categorieën zodat altijd herleidbaar is wie, wanneer, wat en waarom heeft aangepast.Categories, Users
VeldnaamTypeDefaultPKFKVerwijst naarUniqueNullableIndexOpmerking
Iduniqueidentifier-JN-JNJPrimaire sleutel. GUID wordt in de applicatiecode gegenereerd; geen database-default.
CategoryIduniqueidentifier-NJCategories.IdNNJCategorie waarop de wijziging betrekking heeft.
ActionTypenvarchar(50)-NN-NNJGesloten domein, bijvoorbeeld CREATE, UPDATE_NAME, UPDATE_COLOR, UPDATE_ICON, SOFT_DELETE, RESTORE.
OldValuenvarchar(max)-NN-NJNVorige waarde voor de betreffende wijziging, indien van toepassing.
NewValuenvarchar(max)-NN-NJNNieuwe waarde voor de betreffende wijziging, indien van toepassing.
Reasonnvarchar(500)-NN-NNNVerplichte reden van de wijziging.
ChangedByUserIduniqueidentifier-NNUsers.IdNNJBeheerder die de wijziging heeft uitgevoerd. Soft link naar Users.Id; geen harde database-FK vanwege modulegrens.
ChangedAtUtcdatetime2sysutcdatetime()NN-NNNMoment waarop de wijziging is vastgelegd.

Validaties / constraints

  • ActionType gebruikt een gesloten vaste waardeset in code en database.
  • ChangedByUserId en ChangedAtUtc zijn verplicht.
  • Per inhoudelijke wijziging wordt een afzonderlijk historyrecord vastgelegd.

Business rules

  • Alleen beheerwijzigingen op centrale categorie-identiteit worden hier vastgelegd.
  • Door specifieke ActionType-waarden te gebruiken is FieldName niet nodig; OldValue en NewValue zijn voldoende voor reconstructie.
  • Bij een migratie moet CategoryHistory zowel op de broncategorie als op de doelcategorie een entry ontvangen, zodat later in een eventuele UI zichtbaar blijft dat een beheerder een migratie heeft uitgevoerd.

Lifecycle / gedrag

  • CategoryHistory is append-only en wordt niet aangepast of verwijderd door reguliere functionele processen.
  • De tabel ondersteunt reconstructie, impactanalyse en navraag wanneer een categorie later wordt aangepast, gedeactiveerd of gemigreerd.

Designkeuzes

  • Er is bewust geen aparte CategoryActionTypes-tabel opgenomen.
  • De set actiecodes is klein, stabiel en alleen wijzigbaar bij code- of datamodelaanpassingen.
  • Voor migraties worden expliciete bron- en doelactiecodes gebruikt, zodat zonder extra JSON-detailveld duidelijk blijft welke zijde van de migratie in een historyregel wordt beschreven.

Foreign keys op databaseniveau

  • Harde foreign keys op databaseniveau: CategoryId -> Categories.Id.

Functionele / logische verwijzingen zonder harde FK

  • ChangedByUserId is een soft link naar Users.Id; er wordt geen harde database-FK naar het identity-domein gelegd.
  • ActionType functioneert als code-, enum- of sleutelwaarde en verwijst bewust niet via een harde foreign key.

FK + snapshot

  • FK + snapshot: niet van toepassing binnen deze tabel.

3.5.1 CategoryMigrations

TabelnaamCategorieDoel / verantwoordelijkheidGerelateerde tabellen
CategoryMigrationsAudit en historieRegistreert migraties van een broncategorie naar een bestaande doelcategorie, inclusief actor, moment en reden.Categories, Users, CategoryHistory, TeacherLevelCategories, TeacherLevelCategoryExercises
VeldnaamTypeDefaultPKFKVerwijst naarUniqueNullableIndexOpmerking
Iduniqueidentifier-JN-JNJPrimaire sleutel. GUID wordt in de applicatiecode gegenereerd; geen database-default.
SourceCategoryIduniqueidentifier-NJCategories.IdNNJBroncategorie die gemigreerd wordt.
TargetCategoryIduniqueidentifier-NJCategories.IdNNJBestaande doelcategorie waarnaar gemigreerd wordt.
MigratedByUserIduniqueidentifier-NNUsers.IdNNJBeheerder die de migratie uitvoerde. Soft link naar Users.Id; geen harde database-FK vanwege modulegrens.
MigratedAtUtcdatetime2sysutcdatetime()NN-NNJMoment waarop de migratie administratief is vastgelegd.
Reasonnvarchar(1000)-NN-NNNVerplichte reden van de migratie.

Validaties / constraints

  • SourceCategoryId en TargetCategoryId moeten verschillend zijn en beide naar actieve of historisch bekende categorieën verwijzen.
  • Een broncategorie mag niet meerdere keren naar verschillende doelcategorieën tegelijk gemigreerd worden.

Business rules

  • Een categoriemigratie zet alle relevante koppelingen naar docentniveaus en de onderliggende oefenkoppelingen van de broncategorie over naar de doelcategorie. Daarbij moet expliciet gecontroleerd worden op reeds bestaande doelkoppelingen en reeds bestaande oefenkoppelingen onder de doelcategorie; dubbele records mogen niet blind worden aangemaakt.
  • Bestaande historische ExerciseRuns worden door een categoriemigratie niet aangepast en behouden hun oorspronkelijke CategoryId-context.

Lifecycle / gedrag

  • Na een succesvolle migratie blijft de broncategorie historisch bestaan, maar nieuwe koppelingen naar die broncategorie zijn niet meer toegestaan.
  • De migratie zelf wordt append-only vastgelegd en niet aangepast of verwijderd door reguliere processen.
  • Dit geldt ook voor runs die later vanuit geschiedenis gedeeld worden.

Designkeuzes

  • Een aparte migratietabel houdt bron, doel, actor en reden compact en eenduidig vast, terwijl CategoryHistory leesbare historyregels per bron- en doelcategorie blijft bieden.

Foreign keys op databaseniveau

  • Harde foreign keys op databaseniveau: SourceCategoryId -> Categories.Id; TargetCategoryId -> Categories.Id.

Functionele / logische verwijzingen zonder harde FK

  • MigratedByUserId is een soft link naar Users.Id; er wordt geen harde database-FK naar het identity-domein gelegd.

FK + snapshot

  • FK + snapshot: niet van toepassing binnen deze tabel.

3.6 TeacherLevelCategories

TabelnaamCategorieDoel / verantwoordelijkheidGerelateerde tabellen
TeacherLevelCategoriesDocentstructuurKoppeling van centrale categorieën aan een docentniveau.TeacherLevels, Categories
VeldnaamTypeDefaultPKFKVerwijst naarUniqueNullableIndexOpmerking
Iduniqueidentifier-JN-JNJPrimaire sleutel. GUID wordt in de applicatiecode gegenereerd; geen database-default.
TeacherLevelIduniqueidentifier-NJTeacherLevels.IdNNJBepaalt bij welk docentniveau de categorie hoort.
CategoryIduniqueidentifier-NJCategories.IdNNJGeselecteerde categorie uit het centrale model.
SortOrderint0NN-NNNVolgorde binnen het niveau.
IsActivebit1NN-NNJPerformancevlag voor leerlingquery's. Wordt automatisch bijgewerkt op basis van actieve onderliggende items binnen dit docentniveau; docenten wijzigen deze waarde niet handmatig.
CreatedAtUtcdatetime2sysutcdatetime()NN-NNNAanmaakmoment.

Validaties / constraints

  • Actieve combinatie TeacherLevelId + CategoryId is uniek.
  • IsActive wordt niet handmatig door docenten aangepast maar automatisch afgeleid uit de actuele onderliggende niveau-items.

Business rules

  • Een docent kan per niveau één of meerdere categorieën opnemen.
  • SortOrder is puur presentatielogica.
  • IsActive fungeert als afgeleide operationele vlag en staat op true zolang binnen deze niveau-categorie minimaal één relevante onderliggende oefenkoppeling of oefening actief is.

Lifecycle / gedrag

  • Delen van de structuur worden gedeactiveerd in plaats van verwijderd wanneer resultatenhistorie behouden moet blijven.
  • Als de laatste relevante actieve onderliggende inhoud binnen een docentniveau vervalt, kan de koppeling automatisch op inactief worden gezet.

Designkeuzes

  • TeacherLevelCategories bevat alleen de koppeling tussen docentniveau en centrale categorie-identiteit plus contextspecifieke ordening en actieve status.
  • Naam, kleur en icoon horen bewust bij Categories en niet bij deze koppeltabel.

Foreign keys op databaseniveau

  • Harde foreign keys op databaseniveau: TeacherLevelId -> TeacherLevels.Id; CategoryId -> Categories.Id.

Functionele / logische verwijzingen zonder harde FK

  • Buiten de expliciete foreign keys bevat deze tabel geen afzonderlijke functionele verwijzingen die als harde foreign key gemodelleerd hoeven te worden; overige velden zijn inhouds-, status- of auditwaarden.

FK + snapshot

  • FK + snapshot: niet van toepassing binnen deze tabel.

3.7 TeacherLevelCategoryExercises

TabelnaamCategorieDoel / verantwoordelijkheidGerelateerde tabellen
TeacherLevelCategoryExercisesDocentstructuurConcrete oefeningen binnen een docentniveau-categorie.TeacherLevelCategories, Exercises
VeldnaamTypeDefaultPKFKVerwijst naarUniqueNullableIndexOpmerking
Iduniqueidentifier-JN-JNJPrimaire sleutel. GUID wordt in de applicatiecode gegenereerd; geen database-default.
TeacherLevelCategoryIduniqueidentifier-NJTeacherLevelCategories.IdNNJBepaalt binnen welke niveau-categorie het item valt.
ExerciseIduniqueidentifier-NJExercises.IdNNJVerwijzing naar de concrete oefening die binnen deze categorie beschikbaar wordt gemaakt.
SortOrderint0NN-NNNVolgorde binnen de categorie.
IsActivebit1NN-NNJMaakt item actief of historisch.
CreatedAtUtcdatetime2sysutcdatetime()NN-NNNAanmaakmoment.

Validaties / constraints

  • ExerciseId is verplicht.
  • Eventuele aanvullende uniqueness-regels moeten voorkomen dat dezelfde oefening dubbel actief wordt gekoppeld binnen exact dezelfde niveau-categorie-context.

Business rules

  • Een docent kan binnen een categorie één of meerdere oefeningen koppelen.
  • Een extra groeperingslaag onder oefeningen wordt op dit moment niet toegepast.
  • De koppeltabel bepaalt binnen welke niveau-categorie een concrete oefening beschikbaar is en in welke volgorde deze wordt getoond.

Lifecycle / gedrag

  • Koppelingen worden gedeactiveerd in plaats van verwijderd wanneer gekoppelde resultaten of historie behouden moeten blijven.
  • Een inactieve koppeling haalt de oefening uit de zichtbare niveau-categorie zonder onderliggende historie te verliezen.

Designkeuzes

  • De koppeltabel tussen niveau-categorie en oefening houdt structuur, volgorde en contextuele activatie los van de oefening zelf. Daardoor kan de oefening een eigen lifecycle en audittrail houden, terwijl de plaatsing binnen een niveau afzonderlijk bestuurbaar blijft.

Foreign keys op databaseniveau

  • Harde foreign keys op databaseniveau: TeacherLevelCategoryId -> TeacherLevelCategories.Id; ExerciseId -> Exercises.Id.

Functionele / logische verwijzingen zonder harde FK

  • Buiten de expliciete foreign keys bevat deze tabel geen afzonderlijke functionele verwijzingen die als harde foreign key gemodelleerd hoeven te worden; overige velden zijn inhouds-, status- of auditwaarden.

FK + snapshot

  • FK + snapshot: niet van toepassing binnen deze tabel.

3.8 Exercises

TabelnaamCategorieDoel / verantwoordelijkheidGerelateerde tabellen
ExercisesDocentstructuurConcrete, door een docent geconfigureerde oefening op basis van precies één technische module, inclusief opgeslagen configuratiepayload en eigen lifecycle.ExerciseModules, TeacherLevelCategoryExercises, ExerciseRuns, ExerciseHistory, Users
VeldnaamTypeDefaultPKFKVerwijst naarUniqueNullableIndexOpmerking
Iduniqueidentifier-JN-JNJPrimaire sleutel. GUID wordt in de applicatiecode gegenereerd; geen database-default.
Namenvarchar(150)-NN-NNJDoor docent gekozen naam van de oefening.
IconKeynvarchar(100)-NN-NNNDoor docent gekozen icoon voor deze oefening.
ExerciseModuleIduniqueidentifier-NJExerciseModules.IdNNJTechnische moduleversie waarop deze oefening gebaseerd is.
ParentExerciseIduniqueidentifiernullNJExercises.IdNJJOptionele verwijzing naar de bron-oefening wanneer deze oefening als kopie of afgeleide variant is aangemaakt.
ModuleConfigurationJsonBase64nvarchar(max)-NN-NNNModulespecifieke configuratiepayload, opgeslagen als JSON in base64-vorm.
IsActivebit0NN-NNJStatus van de oefening zelf: 0 = in onderhoud, 1 = actief en regulier inzetbaar.
CreatedByUserIduniqueidentifier-NNUsers.IdNNJGebruiker die de oefening oorspronkelijk heeft aangemaakt. Soft link naar Users.Id; geen harde database-FK vanwege modulegrens.
CreatedAtUtcdatetime2sysutcdatetime()NN-NNNAanmaakmoment.
UpdatedByUserIduniqueidentifiernullNNUsers.IdNJJGebruiker die de laatste wijziging heeft uitgevoerd. Soft link naar Users.Id; geen harde database-FK vanwege modulegrens.
UpdatedAtUtcdatetime2sysutcdatetime()NN-NNNLaatste wijzigmoment.

Validaties / constraints

  • ExerciseModuleId en ModuleConfigurationJsonBase64 zijn verplicht.
  • ParentExerciseId mag niet naar hetzelfde record verwijzen.
  • Een oefening verwijst altijd naar precies één record in ExerciseModules, terwijl één moduleversie door meerdere oefeningen gebruikt kan worden.

Business rules

  • Een oefening is de concrete opgeslagen configuratie van een technische module.
  • Nieuwe oefeningen starten standaard in onderhoud (IsActive = 0).
  • Zodra de docent de oefening afrondt en activeert kan deze in een niveau-categoriecontext gebruikt worden.
  • Bij een modulemigratie wordt de oefening als bronobject aangepast voor toekomstig gebruik; de actie kan productiebreed of docentgericht worden uitgevoerd.
  • Voor gecontroleerd testen wordt geen fijnmaziger selectie dan docentniveau afgedwongen in de UI.

Lifecycle / gedrag

  • Oefeningen worden in principe niet hard verwijderd.
  • Historie, samenwerking tussen collaborators en afgeleide kopieën maken het wenselijk om oefeningen te deactiveren of administratief uit te faseren.
  • Bij migratie naar een andere technische module blijven bestaande resultaten functioneel intact en moet delen vanuit historie blijven werken; oude technische modules mogen daarom pas na een overbruggingsperiode en gecontroleerde opschoning verwijderd worden.

Designkeuzes

  • De configuratiepayload blijft bewust als JSON in base64 opgeslagen omdat iedere technische module een eigen configuratie-DTO en eigen antwoord-/vraagstructuur kan hebben.
  • De configuratiepayload bevat binnen de module-specifieke JSON minimaal een moduleherleidbare sleutel en schema-aanduiding, zoals moduleKey en schemaVersion, zodat de technische module oude configuratievormen gecontroleerd kan interpreteren. Dit introduceert geen extra databasekolommen; de herleidbaarheid hoort bij de payload zelf.
  • Tegelijk wordt uitgegaan van uitbreidbare payloads volgens het open/closed principe, bijvoorbeeld door toekomstige extra configuratie-ingangen nullable toe te voegen zodat bestaande configuraties blijven werken.

Foreign keys op databaseniveau

  • Harde foreign keys op databaseniveau: ExerciseModuleId -> ExerciseModules.Id; ParentExerciseId -> Exercises.Id.

Functionele / logische verwijzingen zonder harde FK

  • CreatedByUserId en UpdatedByUserId zijn soft links naar Users.Id; er worden geen harde database-FK's naar het identity-domein gelegd.
  • IconKey functioneert als code-, enum- of sleutelwaarde en verwijst bewust niet via een harde foreign key. ModuleConfigurationJsonBase64 bevat vrije of modulespecifieke payload en is bewust niet relationeel uitgesplitst naar harde foreign keys.

FK + snapshot

  • FK + snapshot: niet van toepassing binnen deze tabel.

3.9 ExerciseHistory

TabelnaamCategorieDoel / verantwoordelijkheidGerelateerde tabellen
ExerciseHistoryAudit en historieAppend-only audittrail van wijzigingen op oefeningen, inclusief configuratie-items, oude en nieuwe waardes en actorinformatie.Exercises, Users
VeldnaamTypeDefaultPKFKVerwijst naarUniqueNullableIndexOpmerking
Iduniqueidentifier-JN-JNJPrimaire sleutel. GUID wordt in de applicatiecode gegenereerd; geen database-default.
ExerciseIduniqueidentifier-NJExercises.IdNNJOefening waarop de wijziging betrekking heeft.
ActionTypenvarchar(50)-NN-NNJGesloten domeinwaarde die het soort wijziging benoemt.
ConfigItemnvarchar(200)nullNN-NJJUnieke verwijzing naar het configuratie-item dat door de technische module als gewijzigd is aangeleverd.
OldValuenvarchar(max)nullNN-NJNVorige exacte waarde vóór de wijziging.
NewValuenvarchar(max)nullNN-NJNNieuwe exacte waarde na de wijziging.
ChangedByUserIduniqueidentifier-NNUsers.IdNNJGebruiker die de wijziging uitvoerde. Soft link naar Users.Id; geen harde database-FK vanwege modulegrens.
ChangedAtUtcdatetime2sysutcdatetime()NN-NNJMoment waarop de wijziging is vastgelegd.

Validaties / constraints

  • ActionType gebruikt een gesloten vaste waardeset in code en database.
  • ChangedByUserId en ChangedAtUtc zijn verplicht.
  • ConfigItem mag leeg blijven voor acties op recordniveau zoals create, copy_from_parent of update_is_active, maar is verplicht zodra een concreet configuratie-item wordt gewijzigd.

Business rules

  • ExerciseHistory registreert wie wat wanneer heeft aangepast aan een oefening.
  • Dit is essentieel omdat meerdere docenten als collaborator aan hetzelfde niveau en daarmee aan dezelfde oefeningen kunnen werken.
  • Ook modulemigraties van een oefening moeten hier zichtbaar worden gemaakt via een expliciete action type, zodat later te reconstrueren is dat een beheerder de oefening technisch heeft overgezet.

Lifecycle / gedrag

  • ExerciseHistory is append-only en wordt niet aangepast of verwijderd door reguliere functionele processen.
  • Een gecombineerde wijziging levert meerdere historyrecords op, zodat per aspect zichtbaar blijft wat wanneer veranderd is.
  • Voor een modulemigratie is een aparte action type verplicht; JSON-details zijn daarvoor niet nodig.

Designkeuzes

  • ConfigItem wordt bewust door de technische module aangeleverd, omdat alleen de module zelf eenduidig weet welk configuratieonderdeel gewijzigd is.
  • Hierdoor blijft de auditlog leesbaar, ook bij sterk modulespecifieke instellingen.
  • Voor modulemigraties blijft ConfigItem leeg en wordt de betekenis volledig gedragen door de action type en de aparte migratietabel.

Foreign keys op databaseniveau

  • Harde foreign keys op databaseniveau: ExerciseId -> Exercises.Id.

Functionele / logische verwijzingen zonder harde FK

  • ChangedByUserId is een soft link naar Users.Id; er wordt geen harde database-FK naar het identity-domein gelegd.
  • ActionType functioneert als code-, enum- of sleutelwaarde en verwijst bewust niet via een harde foreign key.

FK + snapshot

  • FK + snapshot: niet van toepassing binnen deze tabel.

3.10 ExerciseModules

TabelnaamCategorieDoel / verantwoordelijkheidGerelateerde tabellen
ExerciseModulesTechnische modulesDoor beheer vrijgegeven technische oefenmodules waar oefeningen expliciet naar verwijzen. Bevat de vertaallaag tussen weergavenaam, code-referentie en versie, plus activatie- en testzichtbaarheid.Exercises, ExerciseRuns, Users
VeldnaamTypeDefaultPKFKVerwijst naarUniqueNullableIndexOpmerking
Iduniqueidentifier-JN-JNJPrimaire sleutel van de technische moduleversie. GUID wordt in de applicatiecode gegenereerd; geen database-default.
DisplayNamenvarchar(150)-NN-NNJLeesbare naam die in selectielijsten voor docenten wordt getoond.
CodeReferencenvarchar(200)-NN-NNJTechnische referentie waarmee via strategy pattern de juiste module-implementatie wordt gevonden.
Versionnvarchar(50)-NN-NNJDoor beheer vastgelegde versiereferentie, bijvoorbeeld 1.2 of 2.0-preview.
IsActivebit1NN-NNJBepaalt of deze moduleversie regulier beschikbaar is voor gebruik in nieuwe oefeningen.
IsVisibleForTestingbit0NN-NNJBepaalt of deze moduleversie zichtbaar mag zijn voor docenten met de rol TestDocent, ook wanneer de versie nog niet regulier actief is.
CreatedByUserIduniqueidentifier-NNUsers.IdNNJBeheerder die deze moduleversie heeft geregistreerd of vrijgegeven. Soft link naar Users.Id; geen harde database-FK vanwege modulegrens.
CreatedAtUtcdatetime2sysutcdatetime()NN-NNNAanmaakmoment.
UpdatedByUserIduniqueidentifiernullNNUsers.IdNJNBeheerder die de laatste wijziging heeft uitgevoerd. Soft link naar Users.Id; geen harde database-FK vanwege modulegrens.
UpdatedAtUtcdatetime2sysutcdatetime()NN-NNNLaatste wijzigmoment.

Validaties / constraints

  • De combinatie CodeReference + Version is uniek.
  • Een moduleversie kan tegelijk actief, inactief of uitsluitend zichtbaar voor testdoeleinden zijn, maar de precieze zichtbaarheid voor docenten volgt altijd uit combinatie van de modulevlaggen en de roltoekenning van de gebruiker.

Business rules

  • Een oefening verwijst expliciet naar precies één record in ExerciseModules. Hierdoor ligt per oefening en per run vast welke technische moduleversie verantwoordelijk is voor beschrijving, configuratie en generatie.
  • Een beheerder moet oefeningen kunnen migreren van een oude naar een nieuwe beschikbare technische module; dit kan productiebreed of beperkt tot alle oefeningen van één geselecteerde docent die die module gebruiken.
  • De vlag IsVisibleForTesting mag functioneel onafhankelijk van IsActive worden beheerd.
  • Een technische module mag pas inactief worden gemaakt wanneer er geen records meer bestaan in Exercises waarbij Exercises.ExerciseModuleId naar deze module verwijst.

Lifecycle / gedrag

  • Beheer registreert handmatig de DisplayName, CodeReference en Version van een moduleversie. Reguliere docenten zien alleen actieve moduleversies; docenten met de rol TestDocent mogen desgewenst ook testzichtbare versies configureren of testen. Bij het registreren van een moduleversie moet via de strategy-interface een eenvoudige connectiviteitstest mogelijk zijn, zodat typefouten of foutieve technische koppelingen vroeg ontdekt worden. Het afzonderlijk wijzigen van testzichtbaarheid mag de productieve inzetbaarheid van een module niet impliciet wijzigen.

Designkeuzes

  • Er is bewust geen aparte extra autorisatielaag voor testmodules geïntroduceerd. De combinatie van de bestaande rollenstructuur, de rol TestDocent en de vlag IsVisibleForTesting houdt het model klein. Migratie tussen moduleversies wordt bewust als beheerderactie toegestaan zonder harde database- of codevalidatie op backwards compatibility; dit is een geaccepteerd beheerrisico zolang downgrade of herstel mogelijk blijft.

Foreign keys op databaseniveau

  • Harde foreign keys op databaseniveau: niet van toepassing binnen deze tabel.

Functionele / logische verwijzingen zonder harde FK

  • CreatedByUserId en UpdatedByUserId zijn soft links naar Users.Id; er worden geen harde database-FK's naar het identity-domein gelegd.
  • CodeReference functioneert als code-, enum- of sleutelwaarde en verwijst bewust niet via een harde foreign key.

FK + snapshot

  • FK + snapshot: niet van toepassing binnen deze tabel.

3.10.1 ExerciseModuleMigrations

TabelnaamCategorieDoel / verantwoordelijkheidGerelateerde tabellen
ExerciseModuleMigrationsAudit en historieRegistreert migraties van oefeningen van een bronmodule naar een doelmodule, inclusief scope, actor, moment en module-naamsnapshots.Exercises, ExerciseModules, Users, ExerciseHistory
VeldnaamTypeDefaultPKFKVerwijst naarUniqueNullableIndexOpmerking
Iduniqueidentifier-JN-JNJPrimaire sleutel. GUID wordt in de applicatiecode gegenereerd; geen database-default.
ExerciseIduniqueidentifiernullNJExercises.IdNJJOptioneel gevuld wanneer de migratie administratief wordt vastgelegd voor één specifieke oefening als afzonderlijke proef- of testmigratie vóór bredere uitrol. Dit veld introduceert geen extra bulk-scope naast Global en PerTeacher, maar markeert een concrete enkelvoudige migratiehandeling.
SourceExerciseModuleIduniqueidentifier-NJExerciseModules.IdNNJBronmodule van waaruit gemigreerd wordt.
TargetExerciseModuleIduniqueidentifier-NJExerciseModules.IdNNJDoelmodule waarnaar gemigreerd wordt.
SourceExerciseModuleNameSnapshotnvarchar(200)-NN-NNNNaam- en versiesnapshot van de bronmodule ten tijde van de migratie.
TargetExerciseModuleNameSnapshotnvarchar(200)-NN-NNNNaam- en versiesnapshot van de doelmodule ten tijde van de migratie.
ScopeTypenvarchar(30)-NN-NNJFunctionele scope van de migratie, bijvoorbeeld Global of PerTeacher.
TeacherUserIduniqueidentifiernullNNUsers.IdNJJOptioneel gevulde docent wanneer de migratie alleen alle oefeningen van één docent raakt. Soft link naar Users.Id; geen harde database-FK vanwege modulegrens.
MigratedByUserIduniqueidentifier-NNUsers.IdNNJBeheerder die de migratie uitvoerde. Soft link naar Users.Id; geen harde database-FK vanwege modulegrens.
MigratedAtUtcdatetime2sysutcdatetime()NN-NNJMoment waarop de migratie administratief is vastgelegd.
Reasonnvarchar(1000)-NN-NNNVerplichte toelichting of aanleiding voor de migratie.

Validaties / constraints

  • SourceExerciseModuleId en TargetExerciseModuleId moeten verschillend zijn en naar beschikbare of historisch bekende moduleversies verwijzen.
  • TeacherUserId is verplicht wanneer ScopeType = PerTeacher en moet leeg blijven bij ScopeType = Global.

Business rules

  • Een migratie kan productiebreed worden uitgevoerd voor alle oefeningen die een bronmodule gebruiken, of beperkt blijven tot alle relevante oefeningen van één geselecteerde docent.
  • Fijnmaziger selectie dan docentniveau wordt functioneel niet afgedwongen.
  • Het uitgangspunt is dat backwards compatibility vooraf getest is; dit risico wordt niet hard in code of database afgevangen.

Lifecycle / gedrag

  • Bestaande resultaten en geschiedenis blijven functioneel intact na migratie.
  • Oude technische modules mogen na een overbruggingsperiode en gecontroleerde opschoning verwijderd worden; de naam- en versiesnapshots in deze tabel zorgen dat auditinformatie leesbaar blijft.

Designkeuzes

  • Een aparte migratietabel legt bronmodule, doelmodule, scope en actor compact vast.
  • ExerciseHistory blijft daarnaast de leesbare audittrail op oefeningniveau, met een expliciete action type voor modulemigratie.

Foreign keys op databaseniveau

  • Harde foreign keys op databaseniveau: ExerciseId -> Exercises.Id; SourceExerciseModuleId -> ExerciseModules.Id; TargetExerciseModuleId -> ExerciseModules.Id.

Functionele / logische verwijzingen zonder harde FK

  • TeacherUserId en MigratedByUserId zijn soft links naar Users.Id; er worden geen harde database-FK's naar het identity-domein gelegd.
  • ScopeType functioneert als code-, enum- of sleutelwaarde en verwijst bewust niet via een harde foreign key.

FK + snapshot

  • FK + snapshot: niet van toepassing binnen deze tabel.

3.11 LiveViewAudit

TabelnaamCategorieDoel / verantwoordelijkheidGerelateerde tabellen
LiveViewAuditAudit en historieAudittrail van live meekijksessies, inclusief wie meekijkt, vanuit welke rol, bij welke gebruiker en bij welke oefenrun.Users, Roles, ExerciseRuns
VeldnaamTypeDefaultPKFKVerwijst naarUniqueNullableIndexOpmerking
Iduniqueidentifier-JN-JNJPrimaire sleutel. GUID wordt in de applicatiecode gegenereerd; geen database-default.
ViewerUserIduniqueidentifier-NNUsers.IdNNJGebruiker die de meekijksessie startte. Soft link naar Users.Id; geen harde database-FK vanwege modulegrens.
ViewerRoleIduniqueidentifier-NNRoles.IdNNJRol waarmee de meekijksessie is gestart. Soft link naar Roles.Id; geen harde database-FK vanwege modulegrens. Rolnaam wordt vastgelegd in ViewerRoleNameSnapshot.
ViewerRoleNameSnapshotnvarchar(100)-NN-NNNSnapshot van de rolnaam / context op het moment van meekijken, zodat audit leesbaar blijft als rolnamen later wijzigen.
ObservedUserIduniqueidentifier-NNUsers.IdNNJGebruiker die tijdens de sessie is bekeken. Soft link naar Users.Id; geen harde database-FK vanwege modulegrens.
ExerciseRunIduniqueidentifier-NNExerciseRuns.IdNNJOefenrun waarop de meekijksessie betrekking had. Soft link naar ExerciseRuns.Id; geen harde database-FK vanwege modulegrens. De oefenrun en run-snapshots blijven bron voor inhoudelijke context.
StartedAtUtcdatetime2-NN-NNJStartmoment van de meekijksessie.
EndedAtUtcdatetime2-NN-NJJEindmoment van de meekijksessie. Mag leeg blijven zolang de sessie nog actief is of onvolledig is afgesloten.

Validaties / constraints

  • ViewerUserId, ViewerRoleId, ObservedUserId, ExerciseRunId en StartedAtUtc zijn verplicht.
  • EndedAtUtc moet gelijk aan of later dan StartedAtUtc zijn wanneer het veld gevuld is.

Business rules

  • LiveViewAudit registreert auditbaar wie, vanuit welke rol, bij welke gebruiker en bij welke oefenrun live heeft meegekeken.
  • Dit ondersteunt privacy, navraag, beveiligingscontrole en reconstructie van meekijksessies.
  • Meerdere gelijktijdige meekijkers zijn toegestaan, waaronder combinaties van meerdere ouders/voogden en meerdere docenten bij dezelfde actieve oefensessie.

Lifecycle / gedrag

  • Iedere meekijksessie levert één auditrecord op.
  • De sessie wordt bij start geopend met StartedAtUtc en bij afsluiten of timeout aangevuld met EndedAtUtc.
  • Live meekijken verloopt via SignalR. Bij tijdelijk verbindingsverlies wordt een beperkt retrymechanisme toegepast; wanneer de verbinding daarna niet herstelt, wordt de sessie functioneel als verbroken behandeld.
  • Records worden niet hard verwijderd door reguliere functionele processen.
  • De sessie eindigt functioneel wanneer de leerling de actieve oefensessie afsluit of wanneer de verbinding definitief wordt verbroken.

Designkeuzes

  • Het starten van een ouder-/voogd-live-meekijksessie maakt altijd precies één LiveViewAudit-record aan; online-overzicht en beschikbaarheidsbepaling doen dat niet.
  • Beëindigen van een live-meekijksessie is idempotent: wanneer EndedAtUtc al gevuld is, wordt geen tweede beëindiging geregistreerd en wordt de oefenrun niet geraakt.
  • Verbindingsverlies, logout, run-einde of weg navigeren beëindigen de auditbare live sessie zonder antwoord-, score-, voortgangs- of runstatusmutatie.
  • Browse-modus en terugkeren naar live zijn lokale UI-state en krijgen geen eigen databasekolommen.
  • ViewerRoleNameSnapshot wordt bewust naast ViewerRoleId vastgelegd zodat auditregels begrijpelijk blijven wanneer rolnamen of roltoewijzingen later wijzigen.
  • De auditlaag registreert de meekijksessie zelf en niet de afzonderlijke realtime updates; de actuele inhoud wordt tijdens de sessie via SignalR vanuit de lopende run ontsloten.
  • De audit legt sessies vast en niet elk afzonderlijk live event of iedere schermrefresh.

Foreign keys op databaseniveau

  • Harde foreign keys op databaseniveau: niet van toepassing binnen deze tabel.

Functionele / logische verwijzingen zonder harde FK

  • ViewerUserId en ObservedUserId zijn soft links naar Users.Id; er worden geen harde database-FK's naar het identity-domein gelegd.
  • ViewerRoleId is een soft link naar Roles.Id; rolcontext wordt daarnaast vastgelegd in ViewerRoleNameSnapshot.
  • ExerciseRunId is een soft link naar ExerciseRuns.Id; de live-audit verwijst functioneel naar de oefenrun zonder harde database-FK naar het practice-domein.

Soft link + snapshot

  • ViewerRoleId + ViewerRoleNameSnapshot leggen de rolcontext historisch leesbaar vast zonder harde database-FK.
  • De inhoudelijke runcontext blijft beschikbaar via de soft link naar ExerciseRuns.Id en de run-snapshots in het practice-domein.

3.12 TeacherStudentLevelAccess

TabelnaamCategorieDoel / verantwoordelijkheidGerelateerde tabellen
TeacherStudentLevelAccessAutorisatieToegang van een leerling tot een of meer niveaus van een docent.UserRelationships, TeacherLevels, Users
VeldnaamTypeDefaultPKFKVerwijst naarUniqueNullableIndexOpmerking
Iduniqueidentifier-JN-JNJPrimaire sleutel. GUID wordt in de applicatiecode gegenereerd; geen database-default.
TeacherStudentRelationshipIduniqueidentifier-NNUserRelationships.IdNNJActieve docent-leerlingrelatie waarop de toegang rust. Soft link naar UserRelationships.Id; geen harde database-FK vanwege modulegrens.
TeacherLevelIduniqueidentifier-NNTeacherLevels.IdNNJNiveau waarvoor toegang wordt verleend. Soft link naar TeacherLevels.Id; geen harde database-FK omdat niveau-autorisatie in het autorisatiedomein ligt en het niveau in het catalogusdomein.
StudentUserIduniqueidentifier-NNUsers.IdNNJLeerling met toegang tot het niveau. Soft link naar Users.Id; geen harde database-FK vanwege modulegrens.
GrantedAtUtcdatetime2sysutcdatetime()NN-NNNMoment van autoriseren.
GrantedByUserIduniqueidentifier-NNUsers.IdNNNGebruiker die toegang heeft verleend. Soft link naar Users.Id; geen harde database-FK vanwege modulegrens.
IsActivebit1NN-NNJActieve toegang tot het niveau.
RevokedAtUtcdatetime2nullNN-NJNMoment van intrekken.
RevokedByUserIduniqueidentifiernullNNUsers.IdNJNGebruiker die toegang heeft ingetrokken. Soft link naar Users.Id; geen harde database-FK vanwege modulegrens.
RevocationReasonnvarchar(500)nullNN-NJNOptionele toelichting op intrekken.

Validaties / constraints

  • Actieve combinatie TeacherStudentRelationshipId + TeacherLevelId + StudentUserId is uniek.
  • TeacherLevel moet eigendom zijn van de docentzijde van de relatie.

Business rules

  • Een leerling kan toegang hebben tot meerdere niveaus van dezelfde docent én van meerdere docenten.
  • Een leerling kan tussen geautoriseerde niveaus wisselen in het profiel of op de frontpage.
  • Collaborators op een niveau krijgen hierdoor geen leerlingtoegang; daarvoor blijft een expliciete docent-leerlingrelatie nodig.
  • Vanuit beheer kan een leerling alleen aan een niveau worden toegevoegd wanneer tussen de betreffende docent en leerling al een actieve docent-leerlingrelatie bestaat.
  • Deze autorisatieflow zet dus geen nieuwe relatie-uitnodiging of acceptatieproces op, maar kent uitsluitend niveau-toegang toe binnen een reeds bestaande relatiecontext.

Lifecycle / gedrag

  • Bij beëindiging van een docent-leerlingrelatie worden alle actieve toegangen die aan die relatie gekoppeld zijn ingetrokken.
  • Wanneer een beheerder vanuit ondersteuning niveau-toegang toevoegt of intrekt, moet deze actie auditbaar zijn en voorzien worden van een reden.

Designkeuzes

  • Autorisatie is bewust los gemodelleerd van de relatietabel.
  • Daardoor blijft de relatie een pure koppeling en blijft niveau-toegang uitbreidbaar.

Foreign keys op databaseniveau

  • Harde foreign keys op databaseniveau: niet van toepassing binnen deze tabel.

Functionele / logische verwijzingen zonder harde FK

  • TeacherStudentRelationshipId is een soft link naar UserRelationships.Id; de actieve relatie wordt applicatief gevalideerd via het relatiedomein.
  • TeacherLevelId is een soft link naar TeacherLevels.Id; het niveau blijft eigendom van het catalogusdomein.
  • StudentUserId, GrantedByUserId en RevokedByUserId zijn soft links naar Users.Id; er worden geen harde database-FK's naar het identity-domein gelegd.

FK + snapshot

  • FK + snapshot: niet van toepassing binnen deze tabel.

3.13 Profiel- en meldingencontext binnen docentstructuur

3.13.1 Geselecteerd niveau in gebruikersprofiel

  • UserSettings.SelectedTeacherLevelId verwijst naar een docentniveau dat voor de gebruiker functioneel toegankelijk moet zijn.
  • Voor leerlingen wordt de toegestane set bepaald door actieve TeacherStudentLevelAccess-records en de onderliggende actieve docent-leerlingrelatie.
  • Het kiezen van een niveau in het profiel maakt geen nieuw TeacherStudentLevelAccess-record aan.
  • Wanneer een eerder geselecteerd niveau later niet meer toegankelijk is, moet de applicatie de actieve niveaucontext opnieuw bepalen of de gebruiker opnieuw laten kiezen.
  • Een verplichte niveaukeuze mag niet worden opgeslagen wanneer de gekozen waarde niet meer toegankelijk of niet meer actief is.

3.13.2 Doorzetten van meldingen naar docent

  • Wanneer een melding naar een docent wordt doorgezet, moet de geselecteerde docent functioneel passen binnen de actuele context van de melding en de gebruiker.
  • De doorzetactie maakt geen nieuwe docent-leerlingtoegang aan en wijzigt geen TeacherStudentLevelAccess.
  • Eventuele privécommunicatie die door de doorzetactie ontstaat, gebruikt het communicatiedomein en niet de niveau-autorisatietabellen als opslaglocatie.

3.14 Account-lifecycle binnen docentstructuur

3.14.1 Accountverwijdering en docentniveau-eigenaarschap

Wanneer een docent het eigen account verwijdert of wanneer het account wordt geanonimiseerd, mag niveau-eigenaarschap niet onbepaald achterblijven. Voor niveaus waarvan de gebruiker actuele eigenaar is gelden de volgende regels:

  • zonder actieve collaborator wordt het niveau historisch of inactief gemaakt;
  • met precies één actieve collaborator wordt eigenaarschap automatisch aan die collaborator overgedragen;
  • met meerdere actieve collaborators moet vóór definitieve selfservice-verwijdering een geldige opvolgende eigenaar worden gekozen.

De opvolger moet altijd een actieve collaborator op het betreffende niveau zijn. Eigendomsoverdracht door accountverwijdering moet auditbaar blijven en mag geen nieuwe docent-leerlingrelaties of niveauautorisaties aanmaken.

3.14.2 Afhankelijke toegang na anonimisering

Leerling-, docent-, ouder-/voogd- en collaborator-toegang die afhankelijk was van het verwijderde account wordt beëindigd of niet langer toegepast volgens de bestaande domeinregels. Historische eigendomsoverdrachten, afgeronde oefenruns en auditrecords blijven reconstructeerbaar onder geanonimiseerde identiteit wanneer dat functioneel nodig is.

Actieve live-meekijksessies waarbij het geanonimiseerde account betrokken is, worden beëindigd. De bestaande LiveViewAudit-informatie blijft historisch beschikbaar en wordt waar nodig voorzien van een eindmoment.

3.15 Beheerder- en ouder-/voogdcontext binnen docentstructuur

OnderwerpAanscherping
DocentondersteuningBeheerder-docentondersteuning werkt als supportcontext boven bestaande docentstructuren. De beheerder selecteert eerst één docentcontext en inspecteert daarna niveaus, categorieën, oefeningen, leerlingen, collaborators, eigenaarschap en geschiedenis.
Geen duplicatie centraal beheerDocentondersteuning vervangt geen centraal categoriebeheer en geen centraal modulebeheer. Categorie-identiteit, modulemetadata en modulemigratie blijven in de daarvoor bedoelde beheerdomeinen.
Leerlingtoegang corrigerenEen beheerder mag binnen docentondersteuning leerlingtoegang op niveau corrigeren wanneer de geldige docentcontext en relatie-/autorisatievoorwaarden server-side zijn vastgesteld.
CollaboratorcorrectieCollaborators kunnen door beheer worden toegevoegd of verwijderd binnen een expliciete supportflow. Collaboratorrechten blijven beperkt tot onderwijsinhoud binnen het niveau en geven geen leerling-, resultaat- of live-meekijktoegang.
Eigenaarschapsoverdracht door beheerderEigenaarschapsoverdracht vanuit beheer volgt dezelfde kernregel als de docentflow: alleen een actieve collaborator kan nieuwe eigenaar worden en een reden is verplicht.
Ouder-/voogdinzageEen ouder/voogd ziet resultaten en geschiedenis van alle niveaus van gekoppelde kinderen. Deze inzage is onafhankelijk van de docent die de oefening oorspronkelijk heeft aangeboden.
Ouder-/voogd live meekijkenOuder-/voogd-live-meekijken gebruikt dezelfde opgeslagen voortgangsbron als docent-live-meekijken, maar de autorisatiegrens is de actieve ouder-/voogdrelatie met het kind.