Files
slp-modular-cms/src/SlpModularCms.Api
SluijsensandClaude Opus 5 8e79a72340 Makes the application say what it is doing and when it fails
U4. Console logging plus Sentry, a same-origin tunnel so ad blockers cannot
silence browser errors, Umami on the admin SPA, and six security events that
alert rules can actually be built on.

The correlation id is the W3C trace id from the ambient Activity, enabled by
one line of ActivityTrackingOptions so every entry from every category carries
it without touching a call site. It propagates across the master/slave
boundary via traceparent, which TraceIdentifier cannot do at all, and it is
the same value ProblemDetails already returns to the browser.

The security events use source-generated LoggerMessage with constant
templates. Sentry groups log events by message, so interpolating an email
address would give every address its own issue and "more than 20 failed
logins in five minutes" could never fire — the events would arrive, be
visible, be tagged, and the alerting would silently be impossible. A test
asserts the rendered message is identical across argument values.

Scrubbing happens in-process, before transmission, and covers Set-Cookie as
well as Cookie: the login response issues the refreshToken there, so
scrubbing only the request side would protect nothing. Transactions are
scrubbed too, because they carry request data and are the channel nobody
thinks of.

The tunnel derives its destination from the DSN once at startup and reads
nothing from the request, which is what separates a tunnel from a
server-side request forgery primitive. Size is capped by a bounded read
rather than by trusting Content-Length, and the endpoint is rate limited.

Two things found along the way. Zod 4's url() hands the value to the URL
constructor, which accepts any scheme — so the existing frontend validation
would have accepted the exact "htp://" typo BR-U4-24 names, and the SPA
would have called a nonexistent origin. Now constrained to http(s). And the
new appsettings comments are verified against the real configuration
provider, because the failure mode if it rejected them is both hosts
refusing to start after a release switch.

One deviation. IAdminTokenValidator was meant to gain a reason-reporting
overload; implemented that way, a substitute returning false by default
silently inverted the access decision while both methods compiled. Two
methods whose difference is invisible at the call site is the defect, so it
is now a single Validate returning AdminTokenResult.

Touches two files from already-committed units: DatabaseMigrationExtensions
(U2) gains a flush before the rethrow, or the one Critical event in the
system dies with the process; AdminTokenValidator (U1) classifies why a
bypass was refused.

Build 0 errors; 366 backend tests pass, up from 315, and 237 frontend tests,
up from 213. tsc clean, eslint clean on every changed file.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HHoJpxYXzHACSQguHrC5fw
2026-07-28 11:25:54 +02:00
..
2026-06-15 17:00:16 +02:00
2026-06-15 17:00:16 +02:00

SlpModularCms.Api

AIDLC Context

Als ontwikkelaar wil ik een modulaire CMS API bouwen. Deze API zal een raamwerk hebben met veelgebruikte functionaliteiten en gebruikersbeheer. Het doel is dat ik deze API kan gebruiken voor klanten om websites en applicaties te bouwen. Elke klant kan andere wensen hebben, maar per branch of type website zullen er altijd functionaliteiten zijn die hetzelfde zijn. Extra functionaliteiten moeten dus met modules worden geïmplementeerd, zodat ze eenvoudig kunnen worden toegevoegd of verwijderd. Om mijzelf in te dekken wil ik iets inbouwen zodat ik modules op afstand kan uitzetten of dat ik de CMS kan blokkeren in het geval dat een klant zich niet aan de afspraak houd zoals een betaling niet doen of andere dingen.

Dit betekent dat er standaard iets moet worden ingebouwd dat de API een controle uitvoert met een call naar een zogenoemde "master"-API om te controleren of alles nog beschikbaar is. Misschien moet het zelfs bij de master worden opgeslagen in de database én bij de client zelf. De "master"-API moet een module krijgen waarin alles wordt opgeslagen en waarin de API kan controleren of de klant nog toegang heeft tot de CMS, maar deze module mag later pas. Voor de MVP wil ik het raamwerk hebben met authenticatie, authorisatie en gebruikersbeheer voor gebruikers.

Zodra dat staat kan er gekeken worden naar een simpele eerste module.

Daarna kan de module voor de "master"-API worden geïmplementeerd waar ook de connectie tussen "master"- en client-API moet worden bedacht. Hier kan later over worden nagedacht, maar den kaan iets als client-secret pairs.