Records the functional design for the two remaining application units, before any of their code exists. Security headers have to come from the application, because relying on nginx or IIS configuration is exactly what this deployment model rules out. Strict applies to /admin, /api/v1 and /health; a relaxed policy applies to the public website, which this repository does not author. The strict policy needs style-src 'unsafe-inline'. That is not a shortcut: Radix positions dropdowns and dialogs with inline style attributes recalculated per click and scroll position, and CSP nonces apply only to style elements, never to style attributes. No nonce- or hash-based variant leaves the admin UI working. The exception is bounded to styles — script-src stays closed, which is where XSS actually lives. The website's policy is enforcing rather than absent, so every HTML-serving path carries a CSP and no exception has to be recorded. It still blocks external script origins, so it remains a real boundary. HSTS is skipped in development: browsers remember it per host and localhost is shared with unrelated projects. Every other header applies locally, so a CSP violation surfaces while developing. For observability, browser error reports tunnel through the API rather than going to Sentry directly. Ad blockers block Sentry domains, which loses errors precisely for the users most likely to have browser oddities. The tunnel forwards only to the host derived from the configured DSN — a caller-supplied destination would turn an anonymous endpoint into a request-forgery primitive. Two consequences of the chosen options are recorded rather than left implicit: Enabling SendDefaultPii attaches request headers, and this application carries two standing credentials in them. Besides the refreshToken cookie, X-Master-Api-Key would have been sent to a third party on every error raised during a master/slave call. The scrub list removes the whole Cookie header, Authorization, X-Master-Api-Key and the request body. Console logging at Information plus structured logging to Sentry would, taken literally, mean one Sentry event per request — exhausting the free plan within hours and burying real errors in request noise. The thresholds are split: console keeps Information, Sentry takes warnings and above as events with Information as breadcrumbs, so every event arrives carrying the trail that led to it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HHoJpxYXzHACSQguHrC5fw
5.1 KiB
Functional Design Questions — U4 Observability Integration
Vul je keuze in achter elke [Answer]:-tag. Kies de laatste optie (Anders) als niets past.
Question 1 — Gaan Sentry-meldingen direct of via een tunnel?
Context: in je SlpSoftware-workflow loopt Sentry via een tunnel: de browser stuurt fouten naar een pad op je eigen domein (/sentry-tunnel), dat ze doorstuurt naar Sentry. Dat is daar gedaan omdat adblockers verzoeken naar Sentry-domeinen blokkeren met ERR_BLOCKED_BY_CLIENT — waardoor je juist bij de gebruikers met een adblocker geen fouten meer ziet.
Dat probleem geldt hier net zo goed. Een tunnel heeft bovendien een neveneffect dat hier goed uitkomt: alle verkeer blijft same-origin, dus connect-src 'self' volstaat en de CSP van U3 heeft geen externe Sentry-origin nodig.
Nadeel: de tunnel moet ergens draaien. In jouw referentie doet nginx dat; hier kan het geen serverconfiguratie zijn, dus zou de .NET-app het zelf moeten doorsturen.
A) Tunnel via de API — een endpoint in de app stuurt de Sentry-envelope door. Werkt met adblockers, houdt de CSP eenvoudig, en vereist geen serverconfiguratie. Wel nieuwe code die uitgaand verkeer doet B) Direct naar Sentry, en de Sentry-ingest-origin in de CSP toestaan — eenvoudiger, geen extra endpoint, maar fouten van gebruikers met een adblocker komen niet aan C) Direct nu, tunnel als vervolgpunt als blijkt dat er te veel gemist wordt X) Anders (beschrijf hieronder na de Answer:-tag)
Question 2 — Mag Sentry gebruikersgegevens meesturen?
Context: Sentry.AspNetCore heeft een instelling SendDefaultPii. Staat die aan, dan stuurt Sentry bij elke fout ook het IP-adres, de gebruikersnaam en request-headers mee — inclusief cookies. In deze applicatie zit in die cookies de refreshToken.
Standaard staat de instelling uit. SECURITY-03 verbiedt expliciet het loggen van secrets en PII.
A) Uit laten — geen PII, geen cookies, geen IP. Fouten bevatten dan alleen de technische context, wat voor diagnose vrijwel altijd genoeg is
B) Aan, maar met een filter dat de refreshToken-cookie en de Authorization-header verwijdert — meer context bij een fout, met het gevoelige eruit gehaald
C) Aan zonder filter — maximale context
X) Anders (beschrijf hieronder na de Answer:-tag)
Question 3 — Welk logniveau in productie?
Context: appsettings.json staat nu op Warning. Dat betekent dat een normale productie-run vrijwel niets logt — geen opstartmeldingen, geen module-discovery, geen migratie-uitkomst. Juist die drie zijn na een deploy het interessantst, en ModuleOrchestrator logt op Information dat hij modules gevonden heeft (bij falen logt hij een waarschuwing, maar hij stopt niet).
Je koos structured logging naar Sentry op niveaus verder dan alleen exceptions (Q16 = C).
A) Information als standaard in productie, met Microsoft.AspNetCore op Warning — dan zie je opstart, modules en migraties, zonder request-ruis
B) Warning behouden en de belangrijke opstartmeldingen expliciet naar Warning tillen — minimale logvolume, maar dan staat "alles ging goed" als waarschuwing in het log
C) Information voor alles, inclusief het framework — meeste inzicht, meeste volume
X) Anders (beschrijf hieronder na de Answer:-tag)
Question 4 — Welke gebeurtenissen zijn het waard om op te alarmeren?
Context: SECURITY-14 vraagt alerting op authenticatiefouten en autorisatieschendingen. De applicatie moet die dus eerst als gebeurtenis uitsturen voordat je er in Sentry een alertregel op kunt zetten.
Kandidaten die deze applicatie kan onderscheiden. Meerdere letters mogen (bijv. A, B, D).
A) Mislukte logins — meerdere achter elkaar duidt op een aanval of een vergeten wachtwoord
B) Geweigerde autorisatie op een beveiligd endpoint — iemand probeert iets waarvoor hij geen rechten heeft
C) Een geweigerde master-API-key op /api/v1/master/* of /api/v1/SlaveStatus — dat betekent óf een aanvaller, óf een echt probleem met de key ring
D) Een geweigerde admin-bypass op de availability-gate — sinds de FR-24-fix betekent dit iemand die het met een ongeldig token probeerde
E) Rate limiting die aanslaat op de login-endpoints
F) Migratiefouten bij het opstarten — geen beveiligingsgebeurtenis, maar wel iets waarvan je direct wilt weten
X) Anders (beschrijf hieronder na de Answer:-tag)
Answer:A, B, C, D, E, F
Question 5 — Umami op de admin-SPA: altijd, of respecteren wat de browser vraagt?
Context: je koos Umami op zowel de publieke website als de admin-SPA (Q20 = B). De admin-SPA is een intern beheerscherm, en de gebruikers daarvan zijn jouw klanten en hun medewerkers — herkenbare, kleine groepen.
Umami is privacyvriendelijk (geen cookies, geen persoonsgegevens), dus dit is geen juridische vraag maar een keuze over verwachtingen.
A) Altijd meten in test en productie, nooit lokaal — eenvoudig en consistent
B) Altijd meten, maar de Do Not Track-voorkeur van de browser respecteren en dan niets laden
C) Alleen de publieke website meten en de admin-SPA overslaan, in afwijking van Q20 — beheerders worden dan niet gemeten
X) Anders (beschrijf hieronder na de Answer:-tag)