Adds SlpModularCms.Api.SlpSoftware and extracts shared CmsHost composition
Continuous Integration / config (pull_request) Successful in 11s
Continuous Integration / changes (pull_request) Successful in 21s
Continuous Integration / backend-build (pull_request) Successful in 6m10s
Continuous Integration / vulnerability-scan (pull_request) Successful in 4m59s
Continuous Integration / frontend-prepare (pull_request) Successful in 1m27s
Continuous Integration / backend-test (pull_request) Failing after 7m48s
Continuous Integration / frontend-build (pull_request) Successful in 2m5s
Continuous Integration / frontend-test (pull_request) Successful in 4m24s
Continuous Integration / frontend-lint (pull_request) Successful in 2m0s
Continuous Integration / publish-test (pull_request) Skipped
Continuous Integration / publish-production (pull_request) Skipped
Continuous Integration / deploy-test (pull_request) Skipped
Continuous Integration / deploy-production (pull_request) Skipped

Unit 1 of the slpsoftware-api feature (FR-1/FR-2/FR-3): a new Client project
in the Clients solution folder, intended to eventually become the deployed
API for test.slpsoftware.nl/slpsoftware.nl, hosting the same four modules as
SlpModularCms.Api plus a future Offerings module.

- Extracts SlpModularCms.Api/Program.cs's hosting-pipeline composition into
  SlpModularCms.Core.Hosting.CmsHost (ConfigureServices/ConfigurePipeline),
  shared by both Client projects so they cannot drift apart
- Moves StaticContentExtensions.cs + WebsitePlaceholder.html from Api into
  Core, since CmsHost cannot live in Api but Core cannot depend on Api
- Adds SlpModularCms.Api.SlpSoftware with its own isolated local dev database
  and dev ports (5286/7223, distinct from Api's and Api.Slave's)
- Adds SlpModularCms.Api.Tests with WebApplicationFactory-based pipeline
  regression tests (security headers, health check, SPA fallback, rate
  limiting), scoped to Api per NFR Design
- Adds a frontend dev:slpsoftware pnpm script mirroring dev:slave
- Fixes GlobalExceptionHandler logging routine 401s (e.g. an expired/missing
  refresh token) as unhandled errors -- pre-existing, unrelated to this
  feature's own scope, found while testing the new instance

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FWyStNL2ZsjrS7FLd7xvvN
This commit is contained in:
2026-08-02 01:28:39 +02:00
co-authored by Claude Sonnet 5
parent dcc82cdf62
commit fa389e42ee
51 changed files with 3119 additions and 127 deletions
@@ -0,0 +1,166 @@
# Requirements Clarification Questions — SlpSoftware Production API
Vul je keuze in achter elke `[Answer]:`-tag. Kies de laatste optie (`Anders`) als niets past en beschrijf dan je voorkeur.
Waar ik iets al uit de code, de solution-structuur of de externe handoff-doc kon opmaken, staat dat als context boven de vraag — dan hoef je vaak alleen te bevestigen of te corrigeren.
---
## A. Verhouding tussen `SlpModularCms.Api` en de nieuwe `SlpModularCms.Api.SlpSoftware`
### Question 1
**Context**: ik heb de `.sln` nagekeken. De **Clients**-solution folder bestaat al, maar bevat momenteel **nul projecten** — hij staat leeg te wachten. `SlpModularCms.Api` en `SlpModularCms.Api.Slave` zitten vandaag allebei onder **Application** (samen met `Core` en de `Modules`-submap), precies zoals `CLAUDE.md` het beschrijft: "Development versions of the applications". M.a.w.: de structuur is al voorbereid op precies deze feature.
Klopt mijn lezing dat `SlpModularCms.Api.SlpSoftware` het **eerste** project wordt dat ooit in Clients komt, en dat `SlpModularCms.Api` gewoon blijft staan waar hij staat (Application, ongewijzigde rol als dev-host)?
A) Ja — klopt precies zo
B) Nee — `SlpModularCms.Api` moet zelf verplaatst/hernoemd worden naar Clients in plaats van een apart nieuw project
X) Anders (beschrijf hieronder na de [Answer]:-tag)
[Answer]: A
### Question 2
**Context**: `SlpModularCms.Api` host vandaag vier modules: Core, Identity, Availability en Master (zie `Program.cs` / module-orchestrator). De admin-CMS (login, content-beheer) heeft dus sowieso auth (Identity) en de bestaande availability-gate nodig.
Moet `SlpModularCms.Api.SlpSoftware` dezelfde vier modules hosten (Core + Identity + Availability + Master) plus de nieuwe module, of ontbreekt er iets bewust?
A) Ja — zelfde vier modules + de nieuwe module
B) Nee, er moet iets weg of anders (beschrijf hieronder)
X) Anders (beschrijf hieronder na de [Answer]:-tag)
[Answer]: A
### Question 3
**Context**: `SlpModularCms.Api/Program.cs` bevat inmiddels een flinke samengestelde pipeline (static content + SPA-fallback voor `/admin` én `wwwroot/web/`, health checks, security headers/CSP, rate limiting, Sentry, Data Protection, startup-migraties, module-orchestrator) — grotendeels gebouwd tijdens de `gitea-deployment-workflow`-feature. Als `SlpModularCms.Api.SlpSoftware` straks hetzelfde moet doen, kan dat op twee manieren.
Hoe wil je omgaan met deze hosting-/pipeline-code tussen de twee Client-projecten?
A) Extraheer de gedeelde samenstelling naar een herbruikbare methode in `SlpModularCms.Core` (bijv. iets als `CmsHost.Configure(...)`), zodat beide `Program.cs`-bestanden dun blijven en niet uit elkaar kunnen groeien — kost wat refactorwerk nu, maar voorkomt duplicatie en drift
B) Dupliceer `Program.cs` gewoon naar het nieuwe project (sneller nu, maar toekomstige pipeline-wijzigingen moeten dan op twee plekken worden doorgevoerd)
X) Anders (beschrijf hieronder na de [Answer]:-tag)
[Answer]: A
---
## B. Scope van de nieuwe module (op basis van `packages-api-handoff.md`)
### Question 4
**Context**: de handoff-doc in de andere workspace vraagt letterlijk alleen om een publieke, unauthenticated `GET /api/v1/packages` — geen mutatie-endpoints, "CMS authoring is out of scope for the marketing site itself" staat er expliciet bij. Maar de hele reden dat dit een CMS-endpoint wordt (in plaats van hardcoded blijven) is dat de content beheerbaar moet zijn.
Wat moet deze feature opleveren voor het **beheren** van package-content?
A) Alleen de publieke `GET`-endpoint + geseede content (exact zoals de handoff vraagt) — CRUD/admin-UI voor packages is een latere, aparte feature
B) Ook admin-CRUD nu meenemen (aanmaken/bewerken/verwijderen/herordenen van packages via de admin-SPA), zodat er direct een reden is dat dit "CMS-beheerd" is
X) Anders (beschrijf hieronder na de [Answer]:-tag)
[Answer]: B
### Question 5
**Context**: de handoff-doc noemt `content.ts` (in de andere workspace) als bron van de drie huidige, live pakketten (`pakket_01` Landingspagina, `pakket_02` Website, `pakket_03` Maatwerk) en zegt expliciet: gebruik dat bestand als seed-data zodat de site niet verandert zodra het endpoint live gaat.
Moet deze feature die drie pakketten automatisch seeden (bijv. via een EF-migratie of startup-seed), of is handmatige invoer later acceptabel?
A) Automatisch seeden met de exacte waarden uit de handoff-doc (ik geef de drie teksten door / je leest ze uit de referentie-workspace)
B) Niet automatisch seeden — content komt er later handmatig in
X) Anders (beschrijf hieronder na de [Answer]:-tag)
[Answer]: x, ik doe het zelf, maar wil wel beginnen met de waarden die nu worden gebruikt dus dat moet wel ergens vast worden gelegd/worden behouden.
### Question 6
**Context**: de handoff-doc noemt als open item dat er een nginx `location /api/v1/ { proxy_pass ... }` moet worden toegevoegd, omdat die workspace er vanuit gaat dat de Pi's vandaag alleen statische bestanden serveren. Maar in **dit** repo (zie `WEBSITE_WORKSPACE.md` en de — grotendeels al gemergde — `gitea-deployment-workflow`-feature) wordt de site (`wwwroot/web/`) al same-origin door **dezelfde** Client-API geserveerd die ook `/api/v1` en `/admin` bedient; er is dus al geen aparte nginx-proxy voor de API nodig zodra die Client-API de gedeployde host is.
Klopt mijn lezing dat dit "open item" uit de externe handoff-doc bij ons al is opgelost door de bestaande architectuur, zodra `SlpModularCms.Api.SlpSoftware` de gedeployde host wordt — en dat er dus geen extra nginx-wijziging nodig is?
A) Ja, klopt — geen extra nginx-config nodig, zolang de juiste Client-API wordt gedeployed
B) Nee, er zit een addertje onder het gras (beschrijf hieronder)
X) Anders / weet ik niet zeker — laten we dit samen checken tegen de echte nginx-config op de Pi
[Answer]: A
---
## C. Deploy-retarget en levenscyclus van `SlpModularCms.Api`
### Question 7
**Context**: je zei dat `Api.SlpSoftware` "uiteindelijk" de gedeployde API moet worden — dat klinkt alsof het omzetten van de CI/CD-pipeline (`.gitea/workflows/deploy-scp.yaml`, `continuous_integration.yaml`, en `deployment-instructions.md` — allemaal eigendom van de `gitea-deployment-workflow`-feature, momenteel gericht op `SlpModularCms.Api`) niet per se in déze feature hoeft te zitten.
Hoort het daadwerkelijk omzetten van de CI/CD-pipeline naar `Api.SlpSoftware` bij deze feature (Operations-fase), of is dat expliciet een latere, aparte stap?
A) Ja, neem de CI/CD-omzetting mee in de Operations-fase van déze feature (uitbreiden op de bestaande pipeline, niet dupliceren)
B) Nee — deze feature levert alleen het nieuwe project + de nieuwe module op; de omzetting van de pipeline is een aparte, latere feature
X) Anders (beschrijf hieronder na de [Answer]:-tag)
[Answer]: A
### Question 8
Moet `SlpModularCms.Api` (de huidige dev-host) op termijn verdwijnen zodra `Api.SlpSoftware` bewezen in productie draait, of blijft hij net als `Api.Slave` gewoon permanent bestaan als lokale dev-tool?
A) `SlpModularCms.Api` blijft permanent bestaan als lokale dev-host (zelfde rol als vandaag, geen verwijdering gepland)
B) `SlpModularCms.Api` is op termijn kandidaat om verwijderd te worden — noteer dit als toekomstige tech debt, niet nu oppakken
X) Anders (beschrijf hieronder na de [Answer]:-tag)
[Answer]: A
---
## D. Naming en techniek van de nieuwe module
### Question 9
Hoe moet de nieuwe module heten? Op basis van de scope (package/pricing-kaarten voor de marketingsite) stel ik `SlpModularCms.Modules.Packages` voor.
A) `SlpModularCms.Modules.Packages` (aanbevolen — beschrijft het domein, niet de specifieke site)
B) `SlpModularCms.Modules.SlpSoftware` (koppelt de module aan de site zelf i.p.v. aan het domeinconcept)
X) Anders (geef zelf een naam op na de [Answer]:-tag)
[Answer]: A, al lijkt het me iets te generiek. Als je de naam leest zou hetr zomaar kunnen zijn dat ik het in de toekomst lees als andere packages. als een soort library module. Het is een dienst of service die je ermee moet aanleveren. Het is nu voor SlpSoftware, maar later wil ik het ook kunnen hergebruiken voor bijvoorbeeld een klant die fotografie doet en fotoshoot verkoopt. Dan wil ik deze module kunnen hergebruiken. Kan je eventueel nog wat andere suggesties doen?
### Question 10
**Context**: `Availability` en `Master` hebben allebei hun eigen `DbContext` (module-isolatie is het bestaande patroon), draaiend op MariaDB via EF Core.
Moet de nieuwe module z'n eigen `DbContext` krijgen (zelfde isolatie-patroon), of past het beter bij een bestaande context?
A) Eigen `DbContext` (bijv. `PackagesDbContext`), consistent met Availability/Master
B) Hergebruik een bestaande `DbContext` (geef aan welke)
X) Anders (beschrijf hieronder na de [Answer]:-tag)
[Answer]: A
---
## E. Beveiligingsextensie (standaardvraag van de workflow)
### Question 11
Moeten de beveiligingsregels als harde vereisten worden afgedwongen voor dit project?
A) Ja — dwing alle BEVEILIGINGSREGELS af als blokkerende vereisten (aanbevolen voor productietoepassingen)
B) Nee — sla alle BEVEILIGINGSREGELS over (geschikt voor PoC's, prototypes en experimentele projecten)
X) Anders (beschrijf hieronder na de [Answer]:-tag)
[Answer]: A
## F. Property-Based Testing-extensie (standaardvraag van de workflow)
### Question 12
Moeten de property-based testing (PBT) regels worden afgedwongen voor dit project?
A) Ja — dwing alle PBT-regels af als blokkerende vereisten (aanbevolen voor projecten met bedrijfslogica, datatransformaties, serialisatie of stateful componenten)
B) Gedeeltelijk — dwing PBT-regels alleen af voor pure functies en serialisatie round-trips (geschikt voor projecten met beperkte algoritmische complexiteit)
C) Nee — sla alle PBT-regels over (geschikt voor eenvoudige CRUD-applicaties, UI-only projecten of dunne integratielagen zonder significante bedrijfslogica)
X) Anders (beschrijf hieronder na de [Answer]:-tag)
[Answer]: C
## G. Operations-fase (standaardvraag van de workflow)
### Question 13
Moet deze feature na Construction ook door de Operations-fase (deployment- en monitoring-setup)?
**Let op**: dit bepaalt alleen of de Operations-fase van déze feature draait — Question 7 hierboven bepaalt of die Operations-fase ook echt de CI/CD-pipeline omzet naar `Api.SlpSoftware`, of alleen bijvoorbeeld lokale/documentatie-stappen bevat.
A) Ja — draai de Operations-fase na Construction
B) Nee — stop na Build and Test (deployment/monitoring vallen buiten scope voor deze feature)
C) Weet ik nog niet — vraag het me nogmaals na de Construction-fase
X) Anders (beschrijf hieronder na de [Answer]:-tag)
[Answer]: A