Harden live mail OAuth and immutable releases
deploy / deploy (push) Canceled after 0s

This commit is contained in:
Jens
2026-07-30 02:00:09 +02:00
parent 1397f085bd
commit 67be350283
23 changed files with 429 additions and 20 deletions
+13 -6
View File
@@ -1356,22 +1356,25 @@ tasks:
summary: Configureer de gewenste afzonderlijke platformmailboxen via de beveiligde UI, de Fernet-secretkey en
digestrecipient; test read-only import en mailverzending zonder credentials in Git/logs.
acceptance_criteria:
- Iedere platformmailbox gebruikt TLS, een dedicated account/app-wachtwoord en read-only mailboxselectie.
- Iedere platformmailbox gebruikt TLS, een dedicated alias en read-only mailboxselectie; Microsoft 365 gebruikt
app-only OAuth/XOAUTH2 en geen Basic Auth of app-wachtwoord.
- Dezelfde live testmail importeert per mailbox idempotent en alle geconfigureerde intervallen worden door de
scheduler gerespecteerd.
- SMTP verstuurt één testdigest en outboxstatus klopt.
- De encryptiesleutel staat alleen in de productie-secretstore/.env; app-wachtwoorden zijn als ciphertext in de
database aanwezig en sleutelrotatie is live getest.
- OAuth-clientcredentials en de encryptiesleutel staan alleen in de productie-secretstore/.env; eventuele
Gmail/custom-app-wachtwoorden zijn als ciphertext opgeslagen en sleutelrotatie is live getest.
verification:
- Volg Unraid mailboxchecklist
- Inspecteer logs op afwezigheid van secret/payload
primary_paths:
- /mnt/user/appdata/vacatureradar/config/.env
- Bronnen -> Platformmailboxen
external_blocker: Vereist mailbox-/SMTP-account en app-password van de gebruiker.
external_blocker: De dedicated productie-alias, Entra-appregistratie, admin consent en Exchange-mailboxscope zijn
op 2026-07-30 live ingericht; resterend zijn de productie-uitrol en echte platformalertmails voor de
import-/digestproef.
- id: VR-203
title: Productiedomein, TLS en reverse proxy activeren
status: blocked-external
status: done
priority: P0
requirement_ids:
- NFR-001
@@ -1393,7 +1396,11 @@ tasks:
primary_paths:
- Unraid reverse proxy
- /mnt/user/appdata/vacatureradar/config/.env
external_blocker: Vereist gekozen domein/DNS en toegang tot de Unraid reverse proxy.
result:
completed_at: '2026-07-29'
note: Publiek domein, HTTP-naar-HTTPS, TLS/securityheaders, DEBUG=False, secure cookies, CSRF-gastlogin, kernroutes
en readiness live bewezen in docs/audit/FINAL_ACCEPTANCE.md op 2026-07-29; interne diensten zijn uitsluitend
containerintern bereikbaar.
- id: VR-204
title: Immutable containerimage publiceren
status: blocked-external
+38 -3
View File
@@ -30,7 +30,37 @@ Productieoplevering 0.3.14 op 2026-07-29:
- de pre-releasecustomdump, media en composeconfig staan checksum-geldig onder `/mnt/user/appdata/VacatureRadar/backups/release-0.3.14-20260729T164500Z`; rollbackimage `vacatureradar:rollback-0.3.13` wijst naar `sha256:34aef8853f77a3f311b119bd67d9f1160a97fd4a21e62c9776222be289bf3b88`;
- productie is healthy zonder restarts, versie 0.3.14 is publiek zichtbaar, alle gastkernroutes antwoorden 200 en een echte importsmoke creëerde één job binnen een transactie waarna rollback expliciet bevestigd werd.
Volgende uitvoerbare taak: geen na afronding van VR-228. Alleen de bestaande optionele externe identity- en mailboxacties blijven open.
Volgende uitvoerbare taak: geen na afronding van VR-228. Alleen de optionele
mailbox-/identityconfiguratie (`VR-202`) en publicatie naar een externe private
registry (`VR-204`) blijven extern geblokkeerd.
## Laatste risicohardening
Live mailboxvoorbereiding op 2026-07-30:
- Exchange Online bevestigde dat de dedicated VacatureRadar-alias aan de productie-mailbox is toegevoegd;
- de alias is niet primair gemaakt en bestaande adressen zijn ongewijzigd gebleven;
- de Entra-appregistratie, admin consent en Exchange-mailboxscope zijn live ingericht
met app-only OAuth; tijdelijke bootstraprechten en de bootstrap-app zijn na afloop verwijderd;
- `VR-202` resteert alleen nog op de productie-uitrol en echte platformalert-/digestproeven;
Basic Auth wordt niet geactiveerd;
- de volledige lokale gate is groen met 324 tests, 0 failures, 0 skips en 84,05%
branch-aware dekking.
Risicohardening op 2026-07-29:
- de productiefetcher blokkeert nu fail-closed wanneer de HTTP-transportlaag het
werkelijk verbonden peer-IP niet beschikbaar stelt; ieder niet-publiek peer-IP
bleef al geblokkeerd;
- alleen expliciet geïnjecteerde test/custom clients mogen nog de begrensde
DNS-overlapfallback gebruiken; een negatieve regressietest dekt de
productiegrens;
- `VR-203` is administratief afgerond op basis van het bestaande live bewijs in
`docs/audit/FINAL_ACCEPTANCE.md`: publieke HTTP→HTTPS, TLS/securityheaders,
veilige cookies, CSRF-gastlogin, kernroutes en readiness zijn aantoonbaar
geslaagd;
- verificatie: Ruff groen, 8 gerichte fetchertests geslaagd en de volledige gate
groen met 319 tests, 0 failures, 0 skips en 84,21% branch-aware dekking.
Productieoplevering 0.3.13 op 2026-07-29:
@@ -554,13 +584,18 @@ Deze blokkeren onafhankelijke code niet:
- verdere persoonlijke werkgevers-/bronnenkeuze en actuele menselijke review buiten de actieve VITO-/Deliverect-startercatalogus;
- live IMAP/SMTP-account en app-password;
- Unraid-domein, DNS, TLS en reverse proxy;
- containerregistry en credentials;
- actieve/voor deze repository geregistreerde Gitea Actions-runner;
## Bekende verificatiebeperking van de aangeleverde basis
De Pythonapplicatie, Dockerimage en PostgreSQL/Redis/Unraid-stack zijn geverifieerd. De optionele pytest-Playwrightvarianten vallen lokaal terug op de HTML/a11y-probe; VR-119 is aanvullend met de geïntegreerde browser op alle kernroutes uitgevoerd, VR-120 op het begeleide profiel en de live vacaturefeed en VR-124 op de acht platformmailboxen en alertkaarten. Een publieke HTTPS-smoke blijft afhankelijk van domein-, DNS- en reverse-proxyconfiguratie.
De Pythonapplicatie, Dockerimage en PostgreSQL/Redis/Unraid-stack zijn
geverifieerd. De verplichte Playwright-gate draait lokaal met Chromium; VR-119 is
aanvullend met de geïntegreerde browser op alle kernroutes uitgevoerd, VR-120 op
het begeleide profiel en de live vacaturefeed en VR-124 op de acht
platformmailboxen en alertkaarten. Publieke HTTPS, proxyheaders en de gastflow
zijn op 2026-07-29 live geaccepteerd en vastgelegd in
`docs/audit/FINAL_ACCEPTANCE.md`.
## Hervatten
+5
View File
@@ -77,6 +77,11 @@ celery -A config inspect reserved
## Digest ontbreekt of dubbel
- Controleer actief profiel, digesttijd/zone en `DIGEST_RECIPIENT`.
- Microsoft 365 gebruikt uitsluitend app-only OAuth. Configureer `M365_TENANT_ID`,
`M365_CLIENT_ID`, `M365_CLIENT_SECRET`, `M365_MAILBOX_USER` en
`EMAIL_BACKEND=apps.notifications.backends.Microsoft365OAuthEmailBackend`.
Verleen alleen `IMAP.AccessAsApp` en `SMTP.SendAsApp`, admin consent en mailboxscope;
Basic Auth en Microsoft 365-app-wachtwoorden worden niet ondersteund.
- Controleer `DigestOutbox` op datum en status.
- Bij SMTP-fout: corrigeer configuratie en retry dezelfde outbox gecontroleerd.
- Maak geen tweede outboxrecord handmatig; uniciteit per profiel/datum is de duplicaatbarrière.
+3 -1
View File
@@ -164,7 +164,9 @@ IMAP_MAX_MESSAGES_PER_POLL=200
IMAP_MAX_MESSAGE_BYTES=1000000
```
Herstart web, worker en scheduler. Open daarna **Bronnen → Platformmailboxen** en koppel ieder gewenst platform afzonderlijk: VDAB, Indeed, LinkedIn, ictjob.be, Jobat, StepStone, Careerjet, Randstad of Robert Half. Kies Gmail, Outlook / Microsoft 365 of een aangepaste publieke IMAP-host, gebruik een app-wachtwoord en laat `INBOX` geselecteerd tenzij de alert naar een aparte map wordt gefilterd. De scheduler controleert iedere vijf minuten welke mailbox volgens haar eigen interval verschuldigd is.
Herstart web, worker en scheduler. Open daarna **Bronnen → Platformmailboxen** en koppel ieder gewenst platform afzonderlijk: VDAB, Indeed, LinkedIn, ictjob.be, Jobat, StepStone, Careerjet, Randstad of Robert Half. Gmail en aangepaste publieke IMAP-hosts gebruiken een app-wachtwoord. Outlook / Microsoft 365 gebruikt centraal app-only OAuth via de vier `M365_*`-waarden en `EMAIL_BACKEND=apps.notifications.backends.Microsoft365OAuthEmailBackend`; geef de Entra-app alleen `IMAP.AccessAsApp` en `SMTP.SendAsApp` en beperk de Exchange-serviceprincipal tot de bedoelde mailbox. Laat `INBOX` geselecteerd tenzij de alert naar een aparte map wordt gefilterd. De scheduler controleert iedere vijf minuten welke mailbox volgens haar eigen interval verschuldigd is.
Voor een immutable registryrelease zet je `VACATURERADAR_IMAGE=gitea.itworx.tech/jens/vacatureradar:<versie>@sha256:<digest>` en start je met `docker compose -f docker-compose.unraid.yml up -d --no-build`.
Voor sleutelrotatie zet je `nieuwe-sleutel,oude-sleutel` in `MAILBOX_CREDENTIAL_KEYS`, herstart je de processen en draai je:
+9 -1
View File
@@ -115,7 +115,10 @@ Een wijziging aan netwerk, mail, AI, rendering, auth, exports of uploads vereist
## Resterende risico's
- De fetcher controleert het werkelijk verbonden peer-IP wanneer httpcore dat exposeert. Een custom transport dat geen peerinformatie aanbiedt valt terug op DNS-set-overlap; volledige IP-pinning blijft een aanvullend egress-hardeningniveau.
- De productiefetcher blokkeert fail-closed wanneer httpcore het werkelijk verbonden
peer-IP niet exposeert en weigert ieder niet-publiek peer-IP. Alleen een expliciet
geïnjecteerde test/custom client mag terugvallen op DNS-set-overlap; die clientgrens
mag daarom niet voor productie-fetches worden gebruikt.
- Brute-force of herhaalde foutieve mutatiepogingen blijven mogelijk, maar zijn in productie begrensd via gedeelde Redis-rate-limiting en blokkades op login/manual-import. Correcte individuele client-IPherkenning vereist het exacte proxy-CIDR.
- Bronvoorwaarden vereisen menselijke/externe review per domein; automatisering kan dat niet juridisch beslissen.
- Fuzzy dedupe en featureheuristieken kunnen inhoudelijk verkeerd zijn; provenance, feedback en benchmarkevaluaties beperken maar elimineren dit niet.
@@ -150,3 +153,8 @@ Een wijziging aan netwerk, mail, AI, rendering, auth, exports of uploads vereist
- Impact: herhaalde herstarts van dezelfde bron veroorzaken extra belasting
- Mitigatie: cooldown plus metadataflag voor eenmalige canary, en trialstatus met beperkte runtrigger
- Verificatie: `tests/integration/test_source_health.py`
# Microsoft 365 OAuth
- Exchange Online gebruikt app-only XOAUTH2; Basic Auth en app-wachtwoorden zijn uitgesloten.
- Client secrets leven alleen in de productie-secretstore en tokenfouten bevatten geen token of secret.
- De serviceprincipal krijgt uitsluitend IMAP/SMTP-toegang tot de bedoelde mailbox; IMAP-selectie blijft read-only.