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
8.0 KiB
Requirements Clarification Questions — Ronde 2
Je antwoorden waren grotendeels eenduidig. Vier punten hebben opheldering nodig: één directe vraag van jou, twee combinaties van antwoorden die technisch niet samen kunnen, en één gevolg van je keuze voor blokkerende beveiligingsregels.
1. SFTP is niet FTPS — jouw vraag beantwoord
Je vroeg bij Question 1: "Op de pi kan ik met FileZilla ook verbinden met SFTP. Is dat voldoende om FTP als uitgangspunt te nemen?"
Nee, en gelukkig maakt dat je keuze eenvoudiger. Ondanks de vergelijkbare namen zijn het losstaande protocollen:
- SFTP = SSH File Transfer Protocol. Draait volledig binnen een SSH-verbinding op poort 22. Dat FileZilla via SFTP verbindt, betekent dus dat SSH werkt op de Pi — en
scpgebruikt exact dezelfde SSH-verbinding. De referentie-aanpak werkt daar dus zonder aanpassing. - FTPS = FTP met TLS-versleuteling. Een compleet ander protocol op andere poorten, met een eigen server (vsftpd, IIS FTP). Dat SFTP werkt zegt hier niets over.
Kortom: voor de Pi is SSH/SCP het juiste antwoord, niet FTPS. FTPS is alleen relevant als productie op shared hosting komt, want daar is SSH doorgaans afwezig.
Daarmee blijft de echte vraag open: jouw antwoord op Question 1 ging over de Pi, maar de vraag ging over productie. Question 2 zegt dat de test-omgeving op de Pi draait. De commit-message van 3885703 noemt shared hosting (mijnhostingpartner.nl) als reden voor de single-host-opzet.
Clarification Question 1
Waar draait de productie-omgeving van deze CMS?
A) Ook op je eigen Pi-infrastructuur — dan is SSH/SCP goed voor beide omgevingen en is FTPS voorlopig nergens nodig B) Op shared hosting (mijnhostingpartner.nl) — dan bouwen we test via SSH/SCP naar de Pi én productie via FTPS, twee verschillende transportmechanismen in dezelfde workflow C) Voorlopig op de Pi, maar shared hosting is het einddoel — bouw nu SSH/SCP en zet het transport zo op dat FTPS er later naast kan zonder de workflow te herstructureren D) Nog onbekend — bouw alleen de test-deploy (SSH/SCP) en documenteer productie als open punt X) Anders (beschrijf hieronder na de Answer:-tag)
2. Één bundel versus omgevingstags — die twee kunnen niet samen
Bij Question 11 gaf je aan dat same-origin mag, dat lokaal een expliciete URL moet blijven werken, en dat de URL-variabele geen enkele bundel in de weg hoeft te staan. Dat kan ik prima bouwen (same-origin standaard + optionele override).
Maar je andere antwoorden maken één bundel alsnog onmogelijk:
- Question 14/15 = Sentry in de admin-SPA, met een
environment-tag om test en productie te scheiden - Question 20 = Umami ook op de admin-SPA, en Umami gebruikt per omgeving een eigen website-ID
Vite-variabelen worden op build-time in de bundel gebakken. Eén dist/ kan dus niet tegelijk environment: test en environment: production zijn, en niet twee verschillende Umami-website-ID's bevatten. Dit is exact de reden dat je referentie-workflow een aparte build-production-job heeft.
Clarification Question 2
Hoe lossen we dit op?
A) Accepteer twee builds, precies zoals de referentie — een test-build en een productie-build met eigen Vite-variabelen. Same-origin voor de API-URL blijft alsnog nuttig (minder configuratie, geen fout mogelijk), maar levert geen enkele bundel op B) Maak de omgevingsconfiguratie runtime in plaats van build-time — de API levert Sentry-DSN, environment en Umami-website-ID uit zijn eigen configuratie, en de SPA haalt dat bij het opstarten op. Eén bundel geldig voor alle omgevingen, maar wel nieuw werk (endpoint + laadmoment in de SPA) C) Twee builds nu (optie A), met runtime-configuratie (optie B) als later te overwegen verbetering X) Anders (beschrijf hieronder na de Answer:-tag)
3. app_offline.htm werkt niet op de Pi
Bij Question 22 koos je app_offline.htm vóór de upload plaatsen en erna weghalen. Dat is een prima techniek — maar het is een functie van de ASP.NET Core Module in IIS: IIS ziet dat bestand, stopt de app en serveert het als reactie op elk verzoek.
Op de Pi (Question 2 = B) draait je app als Kestrel-proces, waarschijnlijk achter nginx en beheerd door systemd. Daar heeft app_offline.htm geen enkel effect — het bestand wordt gewoon genegeerd, en de upload overschrijft DLL's van een draaiend proces, wat op Linux tot halve of vastgelopen requests leidt.
Er is bovendien een tweede reden waarom dit aandacht nodig heeft: de publieke website in wwwroot/web/ wordt statisch geserveerd. Bij een nette stop is die dus óók onbereikbaar tijdens de deploy, terwijl die website niets met de CMS-deploy te maken heeft.
Clarification Question 3
Hoe regelen we downtime-beheersing per omgeving?
A) Per omgeving de passende techniek: op de Pi het systemd-proces stoppen vóór de upload en erna starten; op IIS-hosting app_offline.htm. De workflow kiest op basis van de omgeving
B) Alleen de Pi-aanpak nu (proces stoppen/starten), en app_offline.htm toevoegen zodra er daadwerkelijk IIS-hosting is
C) Deploy naar een tijdelijke map en wissel dan van map (atomaire switch) — kortste downtime, en de publieke website blijft continu bereikbaar
X) Anders (beschrijf hieronder na de Answer:-tag)
4. Blokkerende beveiligingsregels raken meer dan de workflow
Je koos voor het afdwingen van alle beveiligingsregels als blokkerende vereisten. Voor de pipeline zelf sluit dat mooi aan op je andere keuzes (vulnerability-gate blokkerend, lockfile aanwezig, geen hardcoded secrets, rate limiting bestaat al).
Twee regels vragen echter werk in de applicatie dat nu volledig ontbreekt, en ze zijn blokkerend — dus ik moet weten of je ze binnen deze feature wilt of expliciet wilt uitstellen:
- SECURITY-04 — HTTP-securityheaders. De app zet er nu geen enkele: geen
Content-Security-Policy,Strict-Transport-Security,X-Content-Type-Options,X-Frame-OptionsofReferrer-Policy. Normaal regel je die in nginx of IIS, maar jouw uitgangspunt is juist dat serverconfiguratie niet mogelijk is — dus horen ze in middleware in de app thuis. Let op: een CSP raakt ook de publieke website die uit een andere workspace komt, want die wordt door hetzelfde proces geserveerd. Umami en Sentry hebben daarnaast expliciete CSP-uitzonderingen nodig. - SECURITY-14 — alerting en logretentie. Vereist alerting op authenticatiefouten en autorisatieschendingen, plus minimaal 90 dagen logretentie. Question 16 koos structured logging naar Sentry; Sentry's gratis plan bewaart events standaard 30 dagen, dus 90 dagen is daarmee niet haalbaar zonder een betaald plan of een tweede bestemming.
Clarification Question 4
Wat doen we met deze twee regels?
A) Beide binnen deze feature: securityheaders-middleware bouwen (inclusief CSP-uitzonderingen voor Umami/Sentry), en alerting via Sentry-alertregels — met de logretentie gedocumenteerd als bewuste afwijking op wat Sentry's plan biedt B) Alleen SECURITY-04 (securityheaders) binnen deze feature; SECURITY-14 vastleggen als gedocumenteerde afwijking, omdat volledige alerting en 90-daagse retentie een aparte beslissing over kosten is C) Beide vastleggen als gedocumenteerde afwijking en later oppakken — deze feature blijft strikt de deployment-workflow plus health check X) Anders (beschrijf hieronder na de Answer:-tag)
Clarification Question 5
Als er securityheaders komen (Question 4 = A of B): hoe strikt mag de Content-Security-Policy zijn, gegeven dat hetzelfde proces een publieke website serveert die jij niet in deze repo beheert?
A) Strikt (default-src 'self' plus expliciete uitzonderingen voor Umami en Sentry) en de website-instructies leggen vast waar een website-workspace zich aan moet houden
B) Strikt voor /admin en /api, ruimer voor de publieke website — een website-bouwer wordt dan niet beperkt door een CSP die hij niet kent
C) Alleen rapporterend beginnen (Content-Security-Policy-Report-Only) zodat niets stilletjes breekt, en later afdwingen
X) Anders (beschrijf hieronder na de Answer:-tag)