Files
SluijsensandClaude Opus 5 8568ca43c6 Plans the Gitea deployment feature and refreshes the codebase analysis
Adds the AI-DLC inception record for deploying the CMS as a single .NET
application on hosting where no server configuration is possible.

The reverse-engineering artifacts were regenerated: the previous set
predated the Master module, the Slave host, the solution reorganisation
and single-host serving, all of which matter for deployment. Findings
were verified by running the build, both test suites and the linter
rather than inferred, which surfaced two facts the plan depends on:
the frontend lint gate currently fails (5 errors), and two transitive
packages carry high-severity advisories.

Records 24 functional requirements, 32 traced decisions and a
seven-unit decomposition whose ordering is load-bearing: durability
work must land before the first automated deploy, or the very first
deploy is the one that silently breaks master/slave trust.

Two conflicts found while designing and carried into the units:
- Both modules call AddDataProtection(), which runs after the host and
  would override a persistent key store while still passing any
  registration test.
- The availability gate runs before authentication, so its admin
  bypass cannot read HttpContext.User.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HHoJpxYXzHACSQguHrC5fw
2026-07-27 23:59:30 +02:00

17 KiB
Raw Permalink Blame History

Requirements Clarification Questions — Gitea Deployment Workflow

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 of uit je SlpSoftware-workflow kon opmaken, staat dat als context boven de vraag — dan hoef je alleen te bevestigen of te corrigeren.


A. Hosting en transport

Question 1

Context: de referentie-workflow uploadt via scp met sshpass naar een Raspberry Pi. Shared hosting zoals mijnhostingpartner.nl biedt doorgaans geen SSH, maar wel FTP/FTPS en soms Web Deploy (msdeploy). Dit bepaalt de hele deploy-stap.

Hoe komt de gepubliceerde .NET-applicatie op de productie-host terecht?

A) FTPS — FTP over TLS, meestal standaard beschikbaar op shared hosting B) Web Deploy / msdeploy — de MSBuild-native manier voor IIS-hosting, ondersteunt app_offline en incrementele sync C) SSH/SCP — zoals de referentie, alleen als de host SSH aanbiedt D) Ik weet nog niet wat de host ondersteunt — neem FTPS als uitgangspunt en documenteer hoe je overstapt X) Anders (beschrijf hieronder na de Answer:-tag)

Answer: X, Op de pi kan ik met FileZilla ook verbinden met SFTP. Is dat voldoende om FTP als uitgangspunt te nemen? Anders beginnen met opzetten zoals de referentie met SSH/SCP en later aanpassen naar FTPS als dat nodig is.

Question 2

Context: je hebt lokaal, test en productie. De referentie draait test én productie op dezelfde Raspberry Pi's.

Waar draait de testomgeving van de CMS?

A) Op dezelfde shared host als productie, als een tweede site/subdomein (bijv. test.<domein>) B) Op je eigen Raspberry Pi-infrastructuur (zoals de referentie), met een .NET runtime erop C) Op een andere shared-hostingaccount of -pakket X) Anders (beschrijf hieronder na de Answer:-tag)

Question 3

Context: de referentie gebruikt een zelf-gehoste Gitea Actions runner op Podman, waarbij container-based actions (appleboy/scp-action) faalden met een 409-fout — vandaar shell-stappen. De publish van deze CMS heeft bovendien zowel de .NET 10 SDK als Node + pnpm nodig.

Op welke runner draait deze workflow?

A) Dezelfde zelf-gehoste Podman-runner als de SlpSoftware-workflow — ik zorg dat .NET 10 SDK en Node/pnpm beschikbaar zijn (of laat de workflow ze installeren) B) Dezelfde runner, maar installeer de toolchain expliciet in de workflow met actions/setup-dotnet en pnpm/action-setup C) Een nieuwe/aparte runner speciaal voor .NET-builds X) Anders (beschrijf hieronder na de Answer:-tag)


B. De publieke website in wwwroot

Question 4

Belangrijk risico dat ik in de code vond: de publieke website van de klant staat in wwwroot/, en de admin-SPA in wwwroot/admin/. Een deploy die de hele wwwroot overschrijft of spiegelt, wist daarmee de website van de klant (die immers uit een andere workspace komt en niet in deze repo zit).

Hoe moet de deploy hiermee omgaan?

A) De CMS-deploy raakt wwwroot/ nooit behalve wwwroot/admin/ — de rest blijft staan, en de website-workspace deployt onafhankelijk zijn eigen bestanden in wwwroot/ B) De CMS-deploy overschrijft alles behalve een expliciete uitsluitingslijst, die ik in de workflow configureer C) De publieke website komt in een aparte submap (bijv. wwwroot/site/) zodat de scheiding fysiek duidelijker is — vereist een kleine wijziging in Program.cs X) Anders (beschrijf hieronder na de Answer:-tag)

Answer: C, noem de map "web" in plaats van "site", Dus dan krijgen we uiteindelijk 3 mappen in wwwroot: admin, web en eventueel een map voor de API (indien nodig).

Question 5

Wat moeten de instructies voor een website-workspace precies vastleggen? (Het bouwen/deployen van de website zelf blijft buiten scope — dit gaat om het contract waaraan zo'n workspace zich moet houden.)

A) Alleen het doelpad en de mapstructuur — waar de build-output heen moet en welke paden verboden zijn (admin/) B) Doelpad plus technische randvoorwaarden — routing/SPA-fallback-gedrag, verboden bestandsnamen, hoe je /api/v1 vanaf de website aanroept C) Doelpad, randvoorwaarden én een voorbeeld-deploystap (een YAML-snippet die een website-workspace kan overnemen in zijn eigen workflow) X) Anders (beschrijf hieronder na de Answer:-tag)


C. Workflow-opzet en gates

Question 6

Context: in de referentie draait de testdeploy automatisch bij een push/merge naar master, en productie alleen bij een handmatige workflow_dispatch met een deploy_production-vinkje — bewust, zodat niemand per ongeluk productie deployt.

Wil je diezelfde triggerstrategie hier?

A) Ja, identiek aan de referentie — PR's valideren, master deployt naar test, productie alleen expliciet via workflow_dispatch B) Ja, maar productie moet ook een handmatige goedkeuringsstap of aparte bevestiging hebben bovenop het vinkje C) Productie mag automatisch bij een tag/release (bijv. v1.2.3) in plaats van via een vinkje X) Anders (beschrijf hieronder na de Answer:-tag)

Question 7

Gemeten feit: pnpm run lint faalt nu met 5 errors en 1 warning (in AddCmsInstanceDialog.tsx, InviteUserDialog.tsx 2×, SettingsPage.tsx, SetStatusDialog.tsx). Alle 219 backend- en 213 frontend-tests slagen wél. Een lint-gate wordt dus meteen rood.

Hoe gaan we hiermee om?

A) Los de 5 lint-errors op als onderdeel van deze feature, en zet de lint-gate daarna blokkerend B) Zet de lint-gate blokkerend en laat de fixes over aan tech-debt-backlog — de workflow is dan pas groen ná die feature C) Neem lint op als niet-blokkerende stap (rapporteert, faalt de build niet) en maak hem later blokkerend X) Anders (beschrijf hieronder na de Answer:-tag)

Question 8

Gemeten feit: Microsoft.OpenApi 2.0.0 en System.Security.Cryptography.Xml 10.0.9 hebben high-severity advisories; beide komen transitief binnen.

Wil je een vulnerability-gate in de workflow?

A) Ja, blokkerend — en we pinnen de twee packages naar gepatchte versies als onderdeel van deze feature B) Ja, maar niet-blokkerend (rapporteert alleen), zodat de deploy niet vastloopt op transitieve advisories C) Nee, geen vulnerability-scan in deze workflow X) Anders (beschrijf hieronder na de Answer:-tag)

Question 9

Welke gates moeten er in de pipeline zitten vóór een deploy? (Meerdere letters mogen, bijv. A, B, C.)

A) Backend build (dotnet build -c Release) B) Backend tests (dotnet test) C) Frontend type-check + build (tsc -b && vite build) D) Frontend tests (vitest run) E) Frontend lint / format-check F) Code coverage-drempel (nu is er geen enkele drempel afgedwongen) X) Anders (beschrijf hieronder na de Answer:-tag)

Answer: A, B, C, D, E


D. Database en configuratie

Question 10

Gemeten feit: AvailabilityDbContext en MasterDbContext migreren zichzelf bij het opstarten, maar ApplicationDbContext (Identity) nooit. Een verse deploy start dus zonder Identity-tabellen tot iemand handmatig dotnet ef database update draait. Op shared hosting kun je vaak geen CLI-commando's op de server uitvoeren.

Hoe worden migraties in test en productie toegepast?

A) De pipeline genereert een idempotent SQL-script (dotnet ef migrations script --idempotent) als build-artifact, dat ik zelf uitvoer op de database — expliciet en controleerbaar B) De pipeline past migraties direct toe op de database vanuit de runner (vereist dat de runner de database kan bereiken) C) Laat ApplicationDbContext bij het opstarten automatisch migreren, net als de twee module-contexts — dan is deploy self-contained D) Combinatie: automatisch bij opstarten voor test, idempotent script voor productie X) Anders (beschrijf hieronder na de Answer:-tag)

Question 11

Gemeten feit: de admin-SPA eist VITE_API_BASE_URL als absolute URL (Zod-gevalideerd in config.ts). In het single-host model staat de API echter op dezelfde origin als /admin, dus dit is technisch onnodig — maar zolang het zo is, moet je per omgeving een aparte bundel bouwen.

Wat doen we hiermee?

A) Pas config.ts aan zodat de API-basis-URL leeg/relatief mag zijn en standaard same-origin is — dan is één bundel geldig voor test én productie B) Laat het zoals het is en bouw twee keer (aparte test- en productie-build), zoals de referentie doet voor VITE_APP_ENV C) Pas het aan naar same-origin, maar houd een optionele override-variabele voor uitzonderingsgevallen X) Anders (beschrijf hieronder na de Answer:-tag)

Answer: X, Het mag naar same-origin, maar de frontend kan ook een aparte test-build hebben net als de referentie website. Ook is het zo dat nu lokaal wel een url moet worden opgegeven. Als dat verder ook blijft werken hoeft de url variabele niet blokkerend te zijn voor een enkele bundel

Question 12

Gemeten feit: er is geen appsettings.Test.json en geen ASPNETCORE_ENVIRONMENT-waarde voor test. Productiegeheimen worden verwacht als environment-variabelen (ConnectionStrings__DefaultConnection, JwtSettings__Secret, etc.).

Hoe wordt de test/productie-configuratie geleverd?

A) Environment-variabelen op de host, per omgeving handmatig ingesteld — de workflow raakt ze niet B) De workflow schrijft ze bij deploy in een bestand (bijv. appsettings.Production.json) op basis van Gitea Secrets C) Environment-variabelen op de host voor geheimen, plus een nieuw appsettings.Test.json in de repo voor niet-geheime test-instellingen X) Anders (beschrijf hieronder na de Answer:-tag)

Question 13

Gemeten feit: Data Protection gebruikt de standaard bestandssysteem-key-ring zonder persistente store. Een redeploy die die map wist, maakt opgeslagen slave API keys onleesbaar — master↔slave-communicatie stopt dan tot instanties opnieuw worden toegevoegd. Dit staat al als waarschuwing in de README.

Nemen we dit mee in deze feature?

A) Ja — configureer een persistente key ring (PersistKeysToDbContext, gebruikt de bestaande database) zodat een redeploy veilig is B) Ja, maar alleen documenteren welke map bij een deploy niet overschreven mag worden — geen codewijziging C) Nee, buiten scope — apart oppakken X) Anders (beschrijf hieronder na de Answer:-tag)


E. Monitoring en observability

Question 14

Context: je gebruikt Sentry plus console-logging. De referentie heeft alleen een frontend (@sentry/react); hier is er ook een .NET-backend.

Waar komt Sentry?

A) Beide — Sentry.AspNetCore in de API én @sentry/react in de admin-SPA B) Alleen de backend — de admin-SPA is intern gebruik, daar volstaat console-logging C) Alleen de frontend, net als de referentie X) Anders (beschrijf hieronder na de Answer:-tag)

Question 15

Context: de referentie gebruikt één Sentry-project voor beide omgevingen en onderscheidt ze met een environment-tag.

Hoe richten we Sentry-projecten in voor de CMS?

A) Eén Sentry-project voor de CMS, met environment-tags voor test en productie (zoals de referentie) B) Aparte Sentry-projecten per omgeving C) Aparte Sentry-projecten voor backend en frontend, elk met environment-tags X) Anders (beschrijf hieronder na de Answer:-tag)

Question 16

Gemeten feit: het productie-loglevel staat op Warning en er is alleen de console-logger. Op shared hosting is een console vaak niet zichtbaar — logs zijn dan effectief nergens.

Wat is de logging-opzet in productie?

A) Console-logging blijft (voor lokaal/test) en Sentry vangt fouten op — dat is voldoende B) Console plus een logbestand op de host, met dagelijkse rotatie C) Console plus structured logging naar Sentry inclusief informatievere niveaus dan alleen exceptions X) Anders (beschrijf hieronder na de Answer:-tag)

Question 17

Context: AddHealthChecks() + MapHealthChecks("/health") kost geen package; .AddDbContextCheck<ApplicationDbContext>() kost er één. /health moet op de bypass-lijst van AvailabilityMiddleware, anders geeft de gate een 503 als een instantie is uitgezet.

Wat moet de health check controleren?

A) Alleen liveness — draait het proces? Geen database-aanroep, snelste en meest stabiele signaal voor UptimeRobot B) Liveness plus database-connectiviteit (AddDbContextCheck) C) Liveness, database én openstaande migraties — dan zie je ook een half-gedeployde staat D) Twee endpoints: /health voor liveness (voor UptimeRobot) en /health/ready met database en migraties (voor jezelf) X) Anders (beschrijf hieronder na de Answer:-tag)

Question 18

Wat moet UptimeRobot monitoren?

A) Alleen /health per omgeving B) /health plus de publieke website (/) — die wordt namelijk buiten de availability-gate om geserveerd C) /health, de publieke website en /admin X) Anders (beschrijf hieronder na de Answer:-tag)

Question 19

Context: de referentie heeft een zelf-gehoste Umami op analytics.slpsoftware.nl (Podman op de Pi), met per omgeving een eigen website-ID.

Hoe gebruiken we Umami hier?

A) Hergebruik de bestaande zelf-gehoste Umami — voeg alleen nieuwe website-entries toe voor de CMS-omgevingen B) Nieuwe, aparte Umami-instantie voor de CMS C) Hergebruik de bestaande instantie, maar dit is per-klant: elke CMS-installatie krijgt zijn eigen website-ID X) Anders (beschrijf hieronder na de Answer:-tag)

Question 20

Context: de admin-SPA is een intern beheerscherm; de publieke website komt uit een andere workspace.

Wat wordt er met Umami gemeten?

A) Alleen de publieke website — en de instructies leggen vast hoe een website-workspace het script meekrijgt B) Publieke website plus de admin-SPA (om te zien hoe beheerders het CMS gebruiken) C) Alleen de admin-SPA — de publieke website regelt zijn eigen analytics volledig zelf X) Anders (beschrijf hieronder na de Answer:-tag)


F. Rollback en betrouwbaarheid

Question 21

Context: de referentie rolt terug door een eerdere commit opnieuw te bouwen en te uploaden. Bij een .NET-app met database-migraties is dat riskanter, omdat een migratie niet zomaar terugdraait.

Wat is de rollback-strategie?

A) Opnieuw bouwen en deployen van een eerdere commit, en migraties bewust voorwaarts-compatibel houden (nooit destructief) B) Zoals A, plus de vorige publish-output bewaren op de host zodat je snel kunt terugzetten zonder te bouwen C) Zoals B, plus een database-backup vóór elke productie-deploy X) Anders (beschrijf hieronder na de Answer:-tag)

Question 22

Context: op IIS-hosting kun je met een app_offline.htm-bestand de app netjes stilleggen tijdens een deploy — zonder serverconfiguratie. Zonder dat kunnen bezoekers halve bestanden of vergrendelde DLL's tegenkomen.

Wil je downtime-beheersing tijdens de deploy?

A) Ja — plaats app_offline.htm vóór de upload en verwijder het erna B) Nee, korte downtime tijdens de upload is acceptabel C) Ja, en gebruik daarnaast de bestaande availability-functionaliteit om de instantie in onderhoudsmodus te zetten X) Anders (beschrijf hieronder na de Answer:-tag)


G. Workflow-extensies en fasering

Vraag: Beveiligingsextensies

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)

Vraag: Property-Based Testing Extensie

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)

Vraag: Operations-fase

Moet deze feature na Construction door de Operations-fase (deployment- en monitoring-opzet)?

Toelichting: voor deze feature is dat vermoedelijk het zwaartepunt — de deployment-instructies, monitoring-opzet en productie-readiness-checklist horen daar thuis.

A) Ja — draai de Operations-fase na Construction (deployment + monitoring setup) B) Nee — stop na Build and Test (deployment/monitoring vallen buiten scope voor deze feature) C) Nog niet zeker — vraag het me opnieuw na de Construction-fase X) Anders (beschrijf hieronder na de Answer:-tag)