Skip to main content

Logging, audit, securitylogging en technische foutafhandeling

19.1 Doel van dit hoofdstuk

Dit hoofdstuk beschrijft hoe OefenHub technische logging, domeinhistorie, auditinformatie, securitygerelateerde logging, foutcorrelatie en veilige foutafhandeling technisch inricht.

De uitwerking sluit aan op de middel-zware modulaire monoliet uit het Technisch Ontwerp. Logging en audit worden niet als één generieke centrale module behandeld, maar worden verdeeld over de laag of module die eigenaar is van de brongebeurtenis. Security wordt evenmin als apart project gemodelleerd in de basisarchitectuur; securityconfiguratie en securitylogging worden expliciet uitgewerkt binnen Web, Infrastructure, Identity, Authorization, Scheduling en de relevante domeinmodules.

Dit hoofdstuk gaat over technische inrichting. Nieuwe functionele rechten, bewaartermijnen, gebruikerslabels of schermgedrag ontstaan hier niet zelfstandig. Wanneer tijdens implementatie blijkt dat functionele eisen ontbreken of wijzigen, moet dat worden teruggelegd in Functioneel Ontwerp, Software Requirements Specification, database-informatie of schermdocumentatie.

19.2 Afbakening

OnderwerpIn dit hoofdstukNiet in dit hoofdstuk
Technische loggingLogstructuur, logniveaus, correlation, foutregistratie, privacygrenzenConcrete hostingprovider of commerciële observability-tool als bindende keuze
Audit en domeinhistorieTechnische verwerking en eigenaarschapNieuwe auditfunctionaliteit of nieuwe gebruikersrechten
SecurityloggingAccess denied, verdachte patronen, pipeline- en autorisatie-eventsEen apart OefenHub.Security project
FoutafhandelingException boundaries, veilige foutrespons, foutpagina's, loggingNieuwe UX-teksten buiten bestaande scherm- en popupdocumentatie
Jobs en retriesCorrelation, foutregistratie en herleidbaarheid vanuit jobsVolledige TickerQ-inrichting; zie Technisch Ontwerp: background jobs, TickerQ en periodieke verwerking
Beheer en operatieHerleidbaarheid, monitoringinput en failed-state analyseBackup/restore en operationele procedures; zie Technisch Ontwerp: beheerbeleid, monitoring, backup, restore en operatie
Privacy en retentieLoggingbeperkingen en gevoelige dataDefinitieve retentie- en anonimiseringregels; zie Technisch Ontwerp: privacy, retentie, anonimisering en gegevensbescherming

19.3 Ontwerpprincipes

PrincipeRegel
Logging is ondersteunendLogs ondersteunen beheer, diagnose, securityanalyse en reconstructie, maar vervangen geen domeinhistorie of brondata.
Domein blijft eigenaarDomeinspecifieke audit en historie worden opgeslagen bij de module die eigenaar is van de bronmutatie.
Geen centrale auditmoduleEr komt geen generiek OefenHub.Audit project in de basis. Audit/historie is domeingericht.
Geen apart securityprojectEr komt geen generiek OefenHub.Security project in de basis. Security wordt verdeeld over Web, Infrastructure, Identity, Authorization en domeinspecifieke logging.
Gestructureerd loggenLogs worden als gestructureerde velden geschreven en niet als alleen vrije tekst.
Correlation verplichtRequest-, workflow- en jobgerelateerde logs moeten met correlation-identifiers herleidbaar zijn.
Privacy by designLogs bevatten geen credentials, tokens, wachtwoorden, volledige antwoordpayloads, ruwe exportinhoud of onnodige persoonsgegevens.
Veilige foutresponsGebruikers krijgen veilige, generieke foutinformatie. Technische details blijven in logs.
Retry is begrensdRetrybare fouten worden niet eindeloos herhaald en eindigen beheerbaar in een foutstatus.
Bij twijfel beperkenWanneer onzeker is of informatie gevoelig is, wordt deze niet gelogd of alleen als veilige samenvatting vastgelegd.

19.4 Begrippen en onderscheid

BegripBetekenisVoorbeelden
Technische logOperationele registratie voor diagnose en beheer.Exception, requestduur, failed job attempt, dependency failure.
DomeinhistorieFunctionele historie binnen één domeinmodule.TicketHistory, CategoryHistory, ExerciseHistory, RelationshipEvents.
ManagementlogAuditlaag voor beheerhandelingen.Beheerder wijzigt categorie, popup, template of accountstatus.
SecurityloggingRegistratie van securityrelevante gebeurtenissen.Access denied, ongeldige rolcontext, verdachte routepoging, mislukte autorisatiecontrole.
CorrelationTechnische herleidbaarheid over request, workflow, job en modulegrenzen.CorrelationId, RequestId, JobId, WorkflowId.
FoutafhandelingVertaling van technische fouten naar veilige respons, popup of foutpagina.403, 404, 500, validatiefout, reconnect-fout.

19.5 Eigenaarschap per logtype

LogtypeEigenaarPersistente opslagToelichting
Request-/pipeline-logOefenHub.Web / hostingLoggingproviderBevat requestpad, statuscode, duur en correlation. Geen bodyinhoud.
Applicatie-exceptionModule waar exception ontstaat of boundary waar afgehandeldLoggingproviderExceptiondetails worden intern gelogd, maar niet aan gebruiker getoond.
DomeinhistorieBetreffende domeinmoduleModule-eigen schemaBijvoorbeeld support.TicketHistory of relationships.RelationshipEvents.
BeheeractieOefenHub.Admin of beheercontext-eigenaaradmin schema waar van toepassingBijvoorbeeld ManagementLogEntries.
Autorisatie/security-eventOefenHub.Authorization, OefenHub.Identity of domeineigenaarLoggingprovider en eventueel module-eigen tabelGeen apart security schema in de basis.
Joblifecycle-logOefenHub.Schedulingscheduling schema en loggingproviderPogingen, fouten, retrystatus en technische lifecycle.
Live-meekijk-auditOefenHub.LiveMonitoringlive schemaLiveViewAudit is domeinaudit, geen generieke auditlaag.
PDF/export-foutOefenHub.Reporting of aanroepende moduleLoggingprovider; tijdelijke output niet als logGeen PDF-inhoud of volledige exportpayload in logs.

19.6 Geen apart audit- of securityproject

19.6.1 Audit

Audit wordt in OefenHub niet ingericht als één centraal project met één generiek datamodel. Veel auditinformatie heeft domeinbetekenis en moet naast de brondata staan zodat reconstructie en beheeranalyse inhoudelijk begrijpelijk blijven.

Voorbeelden:

DomeinAudit-/historietypeReden voor domeineigenaarschap
RelatiesRelationshipEventsAcceptatie, afwijzing, ontkoppeling en verloop hebben relatiedomeinbetekenis.
CatalogusCategoryHistory, ExerciseHistoryWijzigingen moeten gekoppeld blijven aan categorie-, oefening- en modulecontext.
SupportTicketHistory, TicketClosures, TicketReopenRequestsTicketlifecycle vereist eigen status- en sluitlogica.
Live meekijkenLiveViewAuditStart/einde van meekijksessies hoort bij live-monitoring en autorisatiecontext.
AdminManagementLogEntriesBeheerhandelingen hebben beheercontext en objectcontext nodig.

Een generieke auditmodule wordt alleen via een toekomstig Technisch Ontwerp-besluit overwogen wanneer aantoonbaar domeinoverstijgende auditgegevens ontstaan die niet logisch bij een bestaande module kunnen worden opgeslagen.

19.6.2 Security

Security wordt wel volledig beschreven en ingericht, maar niet als apart project gemodelleerd. De reden is dat de meeste securitymaatregelen onderdeel zijn van bestaande technische boundaries:

SecurityonderwerpTechnische plek
Rate limitingOefenHub.Web middleware/pipelineconfiguratie.
HSTSOefenHub.Web middleware/pipelineconfiguratie.
CSPOefenHub.Web response-headerconfiguratie.
Security headersOefenHub.Web via middleware of extension methods.
SecretsEnvironment/configuration binding in OefenHub.Web en OefenHub.Infrastructure.
Identity-providerkoppelingOefenHub.Identity.
Rolcontext en policiesOefenHub.Authorization.
Verdachte toegangspogingenPipeline, Authorization en domeinboundary-logs.
Access deniedAuthorization en moduleboundary waar de weigering ontstaat.

Wanneer securityconfiguratie in een toekomstige uitbreiding groot genoeg wordt voor organisatorische afscheiding, kan zij via een expliciet Technisch Ontwerp-besluit worden ondergebracht in een apart infrastructuur- of securityproject. Dat is geen uitgangspunt voor de eerste Technisch Ontwerp-baseline.

19.7 Loggingarchitectuur

OefenHub gebruikt de .NET loggingabstractie als technische basis. Modulecode logt via ILogger<T> of een module-eigen logginginterface wanneer dat nodig is voor testbaarheid of domeinspecifieke verrijking. De concrete loggingbaseline voor de V1.0-architectuur is Serilog met Seq als centrale logviewer. Hosting en infrastructuur configureren Serilog, sinks, verrijking en Seq-koppeling; domeinmodules kiezen geen concrete loggingprovider rechtstreeks.

19.7.1 Logroutes

BronRouteOpmerking
Web requestMiddleware/pipeline naar loggingproviderInclusief correlation en statuscode.
Blazor component/pageAlleen technische UI-fouten en lifecyclefoutenGeen businesslogica in Web.
Module serviceILogger<T> binnen moduleGeen directe dependency op concrete loggingprovider.
JobuitvoeringOefenHub.Scheduling plus uitvoerend domeinZelfde correlation doorgeven.
Infrastructure adapterAdapter-specifieke loggingBijvoorbeeld storage, mail/provider, identity-providercommunicatie.
Exception boundaryCentrale exception middleware of workflowboundaryTechnische details intern; veilige respons extern.

19.7.2 Serilog en Seq

Voor gestructureerde technische logging geldt Serilog als concrete loggingproviderbaseline. Seq wordt gebruikt als centrale viewer voor doorzoekbare loganalyse in development, test, acceptatie en productie, voor zover dit past binnen het beheer- en privacybeleid van de omgeving.

Regels:

  • Applicatie- en modulecode blijft loggen via ILogger<T> of afgesproken module-eigen abstractions.
  • Serilog wordt centraal geconfigureerd in Web/Infrastructure, inclusief enrichers voor correlation, omgeving, applicatieversie en relevante technische context.
  • Seq is een operationele viewer en geen functionele bron van waarheid.
  • Seq mag geen secrets, tokens, volledige oefenpayloads, vrije berichtinhoud, volledige PDF-inhoud of onnodige persoonsgegevens bevatten.
  • Per omgeving worden logniveau, sinkconfiguratie, opslag, retentie en toegang afgestemd met het beheer- en privacybeleid.

19.7.2.1 Serilog-/Seq-configuratiebaseline

De V1.0-baseline gebruikt een lichte Serilog-/Seq-inrichting die past bij een niet-kritieke, middelgrote applicatie. De inrichting is bedoeld voor diagnose, foutanalyse en securitymonitoring, niet voor functionele rapportage of langdurige persoonsdataopslag.

OnderdeelBaselineToelichting
Configuratiebronappsettings + environment overrides + secretsmechanisme waar nodigLoggingconfiguratie wordt centraal gebonden; modulecode configureert Serilog of Seq niet rechtstreeks.
Minimumniveau developmentDebug of InformationTrace alleen tijdelijk en lokaal.
Minimumniveau test/acceptatieInformationFrameworkruis, zoals Microsoft en System, standaard op Warning.
Minimumniveau productieInformationDebug/Verbose in productie alleen tijdelijk, begrensd en met expliciete aanleiding.
Sinks developmentConsole en lokale Seq waar beschikbaarLokale Aspire-inrichting mag Seq starten voor ontwikkelaars.
Sinks test/acceptatie/productieConsole/runtime-logstream en SeqSeq is intern/beheerd toegankelijk; publieke toegang is niet toegestaan.
VerrijkingCorrelationId, RequestId, omgeving, applicatieversie, machine/container, rolcontext indien beschikbaarGeen volledige persoonsgegevens of inhoudelijke payloads opnemen.
Scrubbing/maskingTokens, cookies, secrets, connectionstrings, vrije berichtinhoud, PDF-inhoud, volledige oefenpayloads en onnodige persoonsgegevens verwijderen of maskerenScrubbing gebeurt vóór verzending naar Seq of permanente opslag.
ExportAlleen incidentgericht en beheerdLogexport is geen reguliere rapportagefunctie en mag geen ongecontroleerde persoonsgegevens bevatten.

19.7.2.2 Logretentie

Logretentie is kort en doelgericht. De volgende termijnen zijn de V1.0-baseline, tenzij een omgeving strenger moet zijn door hosting-, privacy- of opslagbeleid.

LogcategorieRetentie V1.0Toelichting
Development lokaalBest effort, maximaal 7 dagenLokale ontwikkellogs mogen zonder historisch behoud worden opgeschoond.
Test en acceptatie14 dagenGenoeg voor regressieanalyse rond testcycli.
Productie Debug/Verbose192 uur (8 dagen)Alleen wanneer tijdelijk ingeschakeld.
Productie reguliere technische logs120 dagenVoor incidentanalyse, foutpatronen en operationele diagnose.
Productie securityrelevante technische logs360 dagenBijvoorbeeld access-deniedpatronen, rate-limit hits en verdachte routepatronen.
Critical incidentselectieMaximaal 720 dagen na expliciete incidentregistratieAlleen beperkte, gemotiveerde selectie; geen generieke verlenging van alle logs.

Seq-retentie wordt ingericht met een klein aantal retentiepolicies, bijvoorbeeld voor Debug/Verbose, niet-productie en productie-events. Als opslag of privacybeleid kortere termijnen vereist, gaan die voor.

19.7.3 Logniveaus

NiveauGebruik
TraceAlleen lokaal of zeer gericht tijdelijk onderzoek. Niet standaard in productie.
DebugOntwikkel- en testdiagnose. Niet structureel voor productieanalyse.
InformationNormale technische lifecycle-events met operationele waarde.
WarningAfwijkende maar herstelbare situaties, geweigerde toegang, retrybare fouten, onverwachte lege technische toestand.
ErrorMislukte actie, failed job, exception die gebruikersactie of verwerking verhindert.
CriticalErnstige verstoring, dataconsistentierisico, securityincident of niet-beschikbare kerncomponent.

Gebruik van Information wordt beperkt tot gebeurtenissen die nuttig zijn voor diagnose of beheer. Elk veelvoorkomend pad mag niet onnodig ruis veroorzaken.

19.8 Verplichte logvelden

Niet ieder logrecord heeft alle velden, maar de volgende velden zijn het standaardvocabulaire voor gestructureerde logs.

VeldVerplicht wanneerToelichting
CorrelationIdAltijd wanneer beschikbaarKoppelt request, workflow, job en modulelogs.
RequestIdHTTP-/Blazor-requestTechnische requestherleiding.
UserIdIngelogde gebruiker bekendAlleen interne id, geen naam of e-mail tenzij functioneel noodzakelijk en toegestaan.
RoleContextActieve rolcontext relevantBijvoorbeeld Student, Teacher, Guardian, Admin.
ModuleNameModulelogNaam van de module die logt.
ActionNameService-, workflow- of jobactieTechnisch herkenbare actie.
EntityTypeObjectcontext relevantBijvoorbeeld Ticket, ExerciseRun, RelationshipInvitation.
EntityIdObjectcontext relevantAlleen id; geen volledige payload.
JobIdJobuitvoeringTickerQ/jobidentifier.
JobTypeJobuitvoeringFunctionele jobsoort.
AttemptNumberRetrybare jobactiePogingnummer.
WorkflowIdCross-module workflowHerleidt meerdere moduleacties binnen één workflow.
ErrorCodeBekende foutsoortStabiele technische code indien beschikbaar.
ExceptionTypeException gelogdType zonder gevoelige exceptiondata in message te forceren.
ElapsedMsPerformance relevantDuur van request, query, export of jobactie.

19.8.1 Taal van technische logging

Technische logevents, operation names, exceptioncategorieën, eventnamen, propertynamen en vaste logmessage-templates worden in het Engels vastgelegd. Dit houdt logs consistent met code, libraries, infrastructuur, dashboards en externe technische tooling.

Gebruikersgerichte foutmeldingen, popupteksten, beheerlabels en functionele schermteksten blijven Nederlandstalig en worden niet rechtstreeks uit technische logmessages afgeleid. Vrije gebruikersinvoer wordt niet vertaald of verrijkt voor logging; waar logging nodig is, worden alleen veilige identifiers, statuswaarden en correlationgegevens vastgelegd.

19.9 Correlation en herleidbaarheid

Correlation is verplicht voor technische reconstructie over modulegrenzen heen. Eén gebruikersactie kan meerdere modulecalls, databaseacties, jobs, systeemberichten en readmodelupdates veroorzaken. Zonder gedeelde correlation ontstaat geen betrouwbare analyseketen.

19.9.1 Correlation-hiërarchie

IdentifierDoelVoorbeeld
CorrelationIdOverkoepelende keten voor request/workflow/job.Loginflow, ticket sluiten, oefening delen.
RequestIdSpecifiek HTTP-request of serverinteractie.Eén Blazor-serverrequest of endpointcall.
WorkflowIdFunctionele cross-module workflow.Ticket doorzetten naar docent.
JobIdTechnische background job.Verlopen uitnodigingen verwerken.
DomainEventIdDomeinevent of pending action.RelationshipInvitationCreated.

Wanneer een request een job aanmaakt, wordt de actieve CorrelationId meegegeven aan de jobpayload of jobmetadata. Wanneer de job wordt uitgevoerd, gebruikt zij dezelfde correlation als parent en voegt zij JobId en AttemptNumber toe.

19.9.2 Voorbeeldketen

HTTP request: gebruiker sluit melding
CorrelationId = c-123
RequestId = r-456

Support module:
TicketClosure aangemaakt
TicketHistory geschreven
CorrelationId = c-123

Scheduling:
Job aangemaakt voor vervolgcommunicatie
JobId = j-789
Parent CorrelationId = c-123

Later jobuitvoering:
JobId = j-789
AttemptNumber = 1
Communication contract aangeroepen
SystemMessage aangemaakt
CorrelationId = c-123

19.10 Privacy en verboden loginhoud

Logs mogen niet uitgroeien tot een tweede datalaag met gevoelige inhoud. OefenHub logt daarom geen inhoud die niet nodig is voor technische analyse.

Niet loggenReden
WachtwoordenCredentialgeheim.
Access tokens, refresh tokens, id tokensTokenmisbruik voorkomen.
Keycloak-/identity-providercredentialsExterne identity-data blijft buiten OefenHub-loginhoud.
Volledige antwoordpayloads van oefeningenLeerlinggegevens en inhoudelijke oefendata.
Volledige JSON/base64-modulepayloadsKunnen antwoorden, timing en oefeninhoud bevatten.
Volledige privéberichtinhoudCommunicatieprivacy.
Volledige ticketbeschrijvingen in technische logsKan persoonsgegevens of gevoelige context bevatten.
PDF-inhoud of exportbestandenExportdata hoort niet in logs.
Browsercookies of volledige headersKunnen tokens of identifiers bevatten.
Volledige request bodiesTe groot en privacygevoelig.
Stacktraces richting gebruikerAlleen intern loggen.

Wel toegestaan zijn veilige samenvattingen, ids, statuscodes, aantallen, technische foutcodes en gehashte of gemaskeerde waarden wanneer dat functioneel noodzakelijk is.

19.11 Domeinhistorie en audit

Domeinhistorie is niet hetzelfde als technische logging. Domeinhistorie is functionele bron voor reconstructie binnen een domein en moet daarom transactioneel worden behandeld volgens de regels van dat domein.

19.11.1 Domeinhistorie binnen dezelfde transactie

Wanneer een historyrecord nodig is om een bronmutatie achteraf functioneel te reconstrueren, wordt het historyrecord in dezelfde domeintransactie opgeslagen als de bronmutatie.

Voorbeelden:

MutatieHistory/auditTransactiebeleid
Ticket formeel sluitenTicketClosures en TicketHistoryAtomair binnen support.
Categorie migrerenCategory migration/historyAtomair binnen catalog of expliciet gemotiveerde workflow.
Relatie accepterenRelationshipEventsAtomair binnen relationships.
Live meekijken startenLiveViewAudit startrecordAtomair met startregistratie binnen live.
Beheerder wijzigt popupManagementLogEntryAtomair met beheerwijziging binnen admin.

19.11.2 Domeinhistorie niet vervangen door logs

Een technisch logrecord zoals "ticket closed" is onvoldoende als formele historie. De bron van reconstructie blijft het domeinrecord, bijvoorbeeld TicketClosures of TicketHistory. Logs helpen alleen bij technische diagnose.

19.12 Securitylogging

Securitylogging registreert gebeurtenissen die relevant zijn voor beveiliging, autorisatie, misbruikdetectie en forensische analyse. De registratie mag geen gevoelige payload lekken.

19.12.1 Securityevents

EventBronLoggingniveauPersistente domeinopslag
Toegang geweigerd door policyAuthorization of moduleboundaryWarningStandaard alleen technische logging.
Ongeldige rolcontextAuthorizationWarningStandaard alleen technische logging.
Niet-actief account probeert toegangIdentityWarningAlleen persistente identity/accountregistratie wanneer dit nodig is voor accountlifecycle of beheeractie.
Routeparameter probeert andere gebruiker te openenModuleboundaryWarningStandaard alleen technische logging; domeinhistorie alleen wanneer het domein dit functioneel nodig heeft.
Repeated access denied patroonWeb/AuthorizationWarning/Error afhankelijk van patroonOperationele securitymonitoring in Seq; geen generieke securityeventtabel.
Verdachte job- of beheeractieScheduling/AdminWarning/ErrorJobhistory of managementlog wanneer de actie al binnen dat domein bronhoudend geregistreerd moet worden.
Misconfiguratie security headersWeb startup/healthcheckErrorTechnische logging.

19.12.1.1 Persistentiebaseline voor securityevents

Voor V1.0 komt er geen generieke security-schema, geen centrale SecurityEvents-tabel en geen algemene securityeventbron naast technische logging. Securityevents blijven standaard in Serilog/Seq, met korte en privacybewuste retentie.

Persistente opslag is alleen toegestaan wanneer één van deze situaties geldt:

  • het event is functioneel onderdeel van domeinhistorie, zoals relatie-, support-, beheer- of live-meekijkhistorie;
  • het event is nodig voor een concrete account-, beheer- of joblifecycle;
  • een toekomstig Functioneel Ontwerp-, Software Requirements Specification- of privacybesluit maakt langdurige registratie verplicht;
  • een securityincident vereist een tijdelijke, gemotiveerde incidentregistratie buiten de generieke loggingstroom.

Voorbeelden:

SituatieV1.0-opslagReden
Een ouder/voogd krijgt geen toegang tot een kindresultaatTechnische access-deniedlogGeen functionele bronmutatie.
Een beheerder wijzigt een popup of templateManagementLogEntry naast technische logBeheeractie is functionele audit.
Live meekijken wordt gestartLiveViewAudit naast technische logLive-meekijken heeft domeinauditwaarde.
TickerQ-dashboardtoegang wordt geweigerdTechnische securitylogGeen apart domeinrecord nodig.
Repeated access denied vanaf dezelfde bronSeq/securitymonitoring + rate limitingPatroonanalyse zonder centrale securityeventtabel.

GuardianAccessDenied blijft een access-denied/security-event en wordt niet als brondata, readmodel of duurzaam domeinobject behandeld, tenzij een later besluit dit expliciet wijzigt.

19.12.2 Access denied zonder datalek

Bij autorisatiefouten wordt gelogd dat een poging is geweigerd, maar niet welke gevoelige data de gebruiker probeerde te bekijken.

Veilig:

Access denied for EntityType=ExerciseRun, EntityId=<id>, UserId=<id>, RoleContext=Guardian, Reason=MissingActiveGuardianRelationship

Niet veilig:

Access denied for run of child Sanne de Vries, exercise answers were ...

19.12.3 Verantwoordelijkheid

ComponentVerantwoordelijkheid
OefenHub.WebPipeline-events, requeststatussen, headers, rate limiting, HSTS/CSP-configuratie.
OefenHub.IdentityAccountstatus, provisioningfouten, externe logincontext zonder credentials/tokens.
OefenHub.AuthorizationPolicy failures, rolcontextfouten, server-side contextcontrole.
DomeinmoduleDomeinspecifieke weigering, bijvoorbeeld ontbrekende ouderrelatie of docentcontext.
OefenHub.SchedulingSecurityrelevante job- en dashboardtoegang, mislukte jobuitvoeringen.

19.13 Technische foutafhandeling

Foutafhandeling gebeurt op meerdere boundaries. Elke boundary heeft een eigen taak: technisch loggen, functioneel veilig afhandelen en de gebruiker niet onnodig technische details tonen.

19.13.1 Foutboundaries

BoundaryVoorbeeldenGedrag
Web middlewareOnverwachte exception, 500Log exception met correlation; toon generieke foutpagina.
Blazor component/pageRenderfout, formulieractie faaltToon veilige melding of popupkey; log technisch detail.
Module serviceDomeinvalidatie, inconsistentieGeef typed result/exception terug; log alleen waar nuttig.
Workflow boundaryCross-module actie faaltRollback of failed-status volgens workflowbeleid; log correlation.
Job boundaryRetrybare fout, definitieve jobfoutRegistreer attempt, error en retry/final failed-state.
Infrastructure adapterExterne dependency faaltLog providerfout zonder secrets; geef veilige fout terug.

19.14 Foutcategorieën

CategorieVoorbeeldGebruikersresponsLogging
ValidatiefoutOngeldige invoer, ontbrekend verplicht veldFormulierfeedback of popupkeyMeestal geen Error-log; eventueel Information/Warning bij misbruikpatroon.
AutorisatiefoutGeen actieve relatie, verkeerde rolcontext403 of veilige toegang-geweigerdafhandelingWarning met correlation, geen gevoelige inhoud.
Niet gevondenObject bestaat niet of niet zichtbaar404 of veilige niet-beschikbaarafhandelingInformation/Warning afhankelijk van context.
ConflictStatus gewijzigd, dubbele uitnodiging, concurrencyVeilige conflictmeldingWarning met object- en statuscontext.
Technische foutDatabase/infra/exceptionGenerieke foutpagina of popupkeyError met exception intern.
SecurityincidentHerhaald misbruik, verdachte routepatronenGeneriek blokkeren of rate limitWarning/Error/Critical afhankelijk van ernst.

19.15 40x- en 50x-afhandeling

StatusBetekenisTechnische behandeling
400Ongeldige request of invoerGeen technische details tonen; validatiefouten waar mogelijk functioneel teruggeven.
401Niet ingelogd of sessie ongeldigVeilige login-/sessieroute; geen identity-providerdetails tonen.
403Wel ingelogd, geen toegangLog access denied zonder payload; toon veilige toegang-geweigerdcontext.
404Niet gevonden of niet zichtbaarGeen onderscheid lekken tussen niet bestaan en geen toegang wanneer privacy dat vereist.
409Conflict of concurrencyGebruiker veilig informeren dat context is gewijzigd.
429Rate limitGenerieke melding; log patroon op Warning.
500Onverwachte serverfoutCorrelation loggen; generieke foutpagina.
503Tijdelijke onbeschikbaarheidGenerieke beschikbaarheidsmelding; monitoring/logging.

Gebruikers zien geen stacktrace, SQL-fout, connectionstring, table name, token, route-internal of module-internal naam wanneer dat niet functioneel bedoeld is.

19.16 Typed results en exceptions

Modulecontracten geven bij voorkeur typed results terug voor verwachte fouttoestanden. Exceptions zijn bedoeld voor onverwachte technische fouten of invariantschendingen.

SituatieVoorkeur
Verwachte validatiefoutTyped result met foutcode.
Verwachte autorisatie-afwijzingTyped result of domain-specific denied result.
Niet gevonden binnen toegestane contextTyped result.
Concurrency conflictTyped result of specifieke exception die boundary vertaalt.
Onmogelijke domeintoestandDomain exception met veilige code.
Database/providerfoutException loggen op technische boundary.

Typed results bevatten stabiele foutcodes zodat Web kan bepalen welke popupkey, foutpagina of formulierfeedback gebruikt wordt zonder technische details te tonen.

19.17 Logging in cross-module workflows

Cross-module workflows worden door de functionele eigenaar gecoördineerd. Logging moet aantonen welke module welke stap heeft uitgevoerd en waar een eventuele fout is ontstaan.

19.17.1 Workflowlogvelden

VeldDoel
WorkflowNameTechnische naam, bijvoorbeeld ForwardTicketToTeacher.
WorkflowIdUnieke uitvoering van de workflow.
WorkflowOwnerModuleModule die functioneel eigenaar is.
StepNameStap binnen de workflow.
StepOwnerModuleModule die de stap uitvoert.
TransactionBoundaryIndicatie of stap onderdeel is van atomair gedeelte.
RollbackRequiredAlleen voor workflows die compensatie of rollbackbeleid hebben.
ResultStatusSucceeded, Failed, Retried, Skipped, Compensated.

19.17.2 Voorbeeld

WorkflowName=ForwardTicketToTeacher
WorkflowOwnerModule=Support
StepName=CloseTicket
StepOwnerModule=Support
CorrelationId=c-123
WorkflowId=w-456
ResultStatus=Succeeded

StepName=CreatePrivateMessageOnBehalfOfUser
StepOwnerModule=Communication
CorrelationId=c-123
WorkflowId=w-456
ResultStatus=Failed
ErrorCode=Communication.ThreadCreationFailed

Wanneer een workflow atomair moet zijn, mag een gedeeltelijk succesvolle toestand niet worden gecommit. Wanneer een workflow bewust retrybare vervolgacties gebruikt, moet een failed vervolgactie beheerbaar zichtbaar blijven.

19.18 Logging in background jobs

Background jobs vallen onder OefenHub.Scheduling voor technische lifecycle, maar de domeinactie blijft eigendom van de uitvoerende module.

19.18.1 Joblogvelden

VeldDoel
JobIdUnieke jobidentifier.
JobTypeFunctionele jobsoort.
AttemptNumberPogingnummer.
MaxAttemptsMaximaal aantal pogingen.
NextRetryAtUtcVolgende retry wanneer van toepassing.
TriggeredByModuleModule die job heeft aangemaakt.
ExecutingModuleModule waarvan contract wordt aangeroepen.
CorrelationIdHerleidbaarheid naar oorspronkelijke request of workflow.
PayloadReferenceVeilige verwijzing naar payload, niet de volledige payload als die gevoelig is.
LastErrorCodeStabiele foutcode.
LastErrorMessageVeilige technische samenvatting.

19.18.2 Failed jobs

Een job die na maximaal aantal pogingen faalt, blijft beheerbaar herleidbaar. De fout mag niet verdwijnen in alleen technische logging. Minimale informatie:

InformatieDoel
JobtypeWeten welke verwerking faalde.
CorrelationIdTerugvinden van oorspronkelijke actie.
PogingenVaststellen of retrybeleid werkte.
Laatste foutDiagnose zonder gevoelige payload.
Betrokken moduleWeten wie inhoudelijk eigenaar is.
TijdstippenAnalyse van timing en incidenten.

19.19 Databasefouten en EF Core

Databasefouten worden op repository-/DbContext-boundary of serviceboundary gevangen waar zij technisch zinvol vertaald kunnen worden. Ruwe SQL, connectionstrings of providerdetails worden niet aan gebruikers getoond.

FoutBehandeling
Concurrency conflictVertalen naar conflictresultaat of veilige foutcode.
Unique constraint violationVertalen naar bekende domein-/validatiefout wanneer verwacht.
Foreign key violation binnen moduleError; duidt meestal op bug of race condition.
Soft link naar ontbrekend objectDomein bepaalt veilige niet-beschikbaarafhandeling.
Migration/startupfoutCritical/Error bij applicatiestart of deploymentcontrole.
TimeoutError/Warning afhankelijk van impact; querycontext zonder payload loggen.

Omdat cross-module hard FK's niet standaard worden gebruikt, moeten soft-linkfouten bewust in applicatielogica worden afgehandeld. Een ontbrekende soft-linked bron mag niet leiden tot lekken van technische details.

19.20 Logging van persoonsgegevens

Persoonsgegevens mogen alleen worden gelogd wanneer dat noodzakelijk is voor beheer of securityanalyse en niet anders kan. De voorkeur gaat uit naar interne id's, geanonimiseerde waarden of momentopnames die al volgens het datamodel zijn toegestaan.

GegevenLoggingbeleid
UserIdToegestaan als interne identifier.
NaamAlleen indien noodzakelijk voor beheerlog/audit en toegestaan door domeinregels.
E-mailadresVermijden; eventueel gemaskeerd of gehasht voor provisioninganalyse.
IP-adresAlleen waar security/technische analyse dit rechtvaardigt; retentie beperken.
UserAgentToegestaan in technische snapshot/securitycontext; niet onbeperkt bewaren.
Kind-/leerlingnaamNiet loggen bij autorisatiefouten waar toegang ontbreekt.
Antwoorden/oefeninhoudNiet in technische logs.

Definitieve bewaartermijnen en anonimisering vallen onder Technisch Ontwerp: privacy, retentie, anonimisering en gegevensbescherming.

19.21 Beheerlogging

Beheeracties worden niet alleen technisch gelogd, maar waar functioneel nodig ook vastgelegd in beheer- of domeinhistorie.

Voorbeelden:

BeheeractieFunctionele opslagTechnische log
Categorie wijzigenCategory historyInformation met actor/object/correlation.
Categorie migrerenCategory migration/historyInformation/Error bij workflowstappen.
Popup wijzigenManagementLogEntry of popup historyInformation met veldwijziging zonder onnodige payload.
Accountstatus aanpassenAccount lifecycle logWarning/Information afhankelijk van actie.
Docentondersteuning uitvoerenDomeineigen support/auditInformation met supportcontext.
Failed job opnieuw startenScheduling jobhistoryWarning/Information met JobId.

Beheerlogs moeten actor, rolcontext, objecttype, objectid, actie en tijdstip kunnen herleiden. Vrije toelichting wordt alleen opgeslagen waar het functionele domein dit vereist.

19.22 Foutrespons in Web

OefenHub.Web vertaalt technische uitkomsten naar veilige UI-respons.

BronWeb-afhandeling
Typed validation resultFormulierfeedback.
Typed access denied result403/veilige toegang-geweigerdafhandeling.
Typed not found result404 of niet-beschikbaarcontext.
Known domain conflictVeilige melding dat gegevens zijn gewijzigd.
Unknown exceptionGenerieke foutpagina of popup, correlation intern.
Job failed asyncNiet direct tonen tenzij gebruiker nog in context wacht; beheerbaar loggen.

Web mag foutafhandeling samenstellen, maar mag geen module-interne gegevens of technische exceptiondetails aan de gebruiker tonen.

19.23 Foutafhandeling tijdens actieve oefenrun

Tijdens een actieve oefenrun gelden aanvullende grenzen omdat afleiding en dataverlies voorkomen moeten worden.

SituatieBehandeling
Antwoord opslaan faaltGebruiker veilig informeren dat opslaan niet is gelukt; geen stilzwijgende voortgang.
SignalR-update faaltOefenvoortgang blijft server-side bron; live-kijkers krijgen reconnect/einde volgens live-regels.
Badge/notificatie-update faaltNiet zichtbaar maken tijdens oefening; na de oefening opnieuw beoordelen.
Onverwachte foutGeen antwoordpayload loggen; correlation gebruiken.

19.24 Foutafhandeling bij PDF/export

PDF-export gebruikt historische runcontext en snapshots, maar logt geen PDF-inhoud.

FoutBehandeling
Run niet toegankelijkAutorisatie-afhandeling zonder gedeeltelijke data.
Run niet gevondenNiet-beschikbaarafhandeling.
Module-rendering faaltError met module-id/name, geen vraagpayload.
Tijdelijk bestand faaltError met export-id/correlation, geen PDF-inhoud.
Cleanup faaltRetrybare jobfout via scheduling.

19.25 Monitoringinput

Dit hoofdstuk definieert log- en foutinformatie die door monitoring gebruikt kan worden. Het is niet de volledige monitoringinrichting.

Minimale monitoringbronnen:

BronSignaal
Web request logsFoutpercentages, response times, 40x/50x-patronen.
Module error logsDomein- of infrastructuurfouten.
Scheduling jobstatusFailed jobs, retry storm, langdurige verwerking.
SecurityloggingAccess denied pieken, rate-limit hits, verdachte routepatronen.
DatabasefoutenTimeouts, migration issues, concurrencyconflicten.
PDF/exportfoutenRenderingproblemen of bestandsopslagproblemen.

Operationele dashboards en alerting worden uitgewerkt in Technisch Ontwerp: beheerbeleid, monitoring, backup, restore en operatie.

19.26 Teststrategie voor logging en foutafhandeling

Logging zelf hoeft niet in iedere unittest exact te worden gevalideerd, maar kritieke foutpaden en securitygrenzen moeten wel testbaar zijn.

TesttypeDoel
Unit testsTyped results, validatiefouten, domeinexceptions en foutcodes.
Module integration testsDatabasefouten, concurrency en history/audit binnen module.
Workflow testsAtomair of retrybaar gedrag bij cross-module fouten.
Job testsRetrybeleid, failed-state, idempotentie en correlationdoorgifte.
Security testsAccess denied, geen datalek in respons, rolcontextcontrole.
Architecture testsGeen directe toegang tot interne entities/DbContexts over modulegrenzen.
Logging tests gerichtControleren dat verboden payloads niet worden gelogd in kritieke paden.

19.27 Implementatiechecklist

Bij iedere nieuwe module, workflow of technisch component moet minimaal worden gecontroleerd:

  • Welke logevents zijn nodig voor beheer en diagnose?
  • Welke domeinhistorie is functioneel bronhoudend?
  • Welke fouttoestanden zijn verwacht en krijgen typed results?
  • Welke fouttoestanden zijn onverwacht en worden als exception gelogd?
  • Welke correlation-identifiers moeten worden doorgegeven?
  • Worden credentials, tokens, payloads en persoonsgegevens vermeden?
  • Is access denied veilig zonder datalek?
  • Is retry begrensd en beheerbaar?
  • Is een failed job of workflow achteraf herleidbaar?
  • Is duidelijk welke module eigenaar is van de foutafhandeling?
  • Is de foutrespons naar de gebruiker veilig en consistent?
  • Zijn retentie en anonimisering afgestemd met het privacyhoofdstuk?

19.28 Implementatieverificaties

PuntToelichtingEigenaar vervolguitwerking
Serilog/Seq-inrichtingInrichting toetsen aan de vastgelegde Serilog-/Seq-configuratiebaseline, inclusief sinks, enrichers, Seq-koppeling, toegang en exportbeperking.Infrastructuur/operatie.
Correlation middlewareUitwerken hoe CorrelationId wordt aangemaakt, doorgegeven en hergebruikt.Web/Infrastructure.
TickerQ-logkoppelingControleren hoe TickerQ job-id, schema, dashboard en loggingmetadata beschikbaar maakt.Scheduling.
Security headersCSP/HSTS/headerconfiguratie toetsen aan de vastgelegde baseline.Web/securityconfiguratie.
Persistent securityeventsToetsen dat securityevents standaard in technische logs blijven en alleen domeineigen persistent worden wanneer hoofdstuk 19 dit toestaat.Identity/Authorization/domeinmodules.
Retentie logsSeq-/logretentie controleren tegen de vastgelegde termijnen per omgeving en logcategorie.Privacy/operatie.
Beheerinterface failed jobsBepalen welke jobfouten via interne TickerQ-interface of beheerpagina zichtbaar worden.Scheduling/Admin.

19.x OIDC remote failure handling

OIDC remote failures zoals Correlation failed worden als security-/auth-flowfouten behandeld en mogen niet als Developer Exception bij gebruikers terechtkomen. De authenticationlaag handelt remote failures centraal af, logt technische context met OefenHub correlation-id en toont alleen een veilige gebruikersmelding.

De handler mag geen callback zonder geldige OIDC state/correlation als succesvolle login accepteren. De oplossing moet gebruikersvriendelijk zijn voor meerdere tabs of apparaten: een venster zonder geldige correlation-context krijgt uitleg om opnieuw te starten of verder te gaan in het venster waar login wel is afgerond.