feat: release regional radar and mailbox integrations
deploy / deploy (push) Canceled after 0s

This commit is contained in:
Jens
2026-07-22 05:12:07 +02:00
parent 598d3ec18a
commit 551d0f46c2
131 changed files with 6209 additions and 336 deletions
+357 -12
View File
@@ -1,6 +1,6 @@
schema_version: 1
project: VacatureRadar
updated_at: '2026-07-21'
updated_at: '2026-07-22'
execution_policy:
order: file-order, then first ready task whose dependencies are done
no_product_questions: true
@@ -961,7 +961,8 @@ tasks:
- Dashboard, vacatures, detail, pipeline, profiel, bronnen, systeem en login gebruiken echte backenddata en acties.
- Externe auto-apply, nepmetrics, onbewezen werkgeverinzichten en onbetrouwbare activiteitenfeeds zijn niet overgenomen.
- Zes doelviewports hebben één h1, geen horizontale overflow en werkende mobiele navigatie.
- Stitch-bronnen, integratieplan, screenshots en verificatierapport zijn traceerbaar maar niet onderdeel van de productiecontainer.
- Stitch-bronnen, integratieplan, screenshots en verificatierapport zijn traceerbaar maar niet onderdeel van de
productiecontainer.
verification:
- uv run pytest tests/e2e tests/integration/test_views.py tests/integration/test_tasks_and_more_views.py
- ./scripts/codex_verify.sh
@@ -977,9 +978,341 @@ tasks:
completed_at: '2026-07-21'
note: Stitch-visuele taal geïntegreerd in CSP-veilige Django-templates; dark/light, responsive shell, pipeline,
broninteracties en browservalidatie toegevoegd zonder functionele scope-uitbreiding of fictieve data.
- id: VR-119
title: Stitch-schermcompositie dominant doorvoeren
status: done
priority: P0
requirement_ids:
- PR-050
- PR-051
- NFR-008
depends_on:
- VR-118
summary: Herwerk de cockpit na productfeedback zodat de aangeleverde Stitch-frontend niet alleen de visuele tokens
maar ook de schermcompositie, informatiedichtheid en interactiehiërarchie bepaalt, met behoud van echte Django-data,
toegankelijke server-rendered flows en alle bestaande veiligheidsgrenzen.
acceptance_criteria:
- De gedeelde shell, utilitybar en navigatie volgen aantoonbaar de Stitch-compositie op desktop en mobiel.
- Dashboard, vacatureoverzicht en detail nemen de primaire Stitch-layouts vrijwel volledig over met uitsluitend
aantoonbare databasevelden en bestaande veilige acties.
- Pipeline, profiel, bronnen, systeem en login gebruiken dezelfde dichte cockpit-hiërarchie en componentvormen.
- Lege, fout- en een-itemtoestanden behouden de bedoelde compositie zonder grote onverklaarde lege vlakken.
- Zes doelviewports hebben één h1, geen pagina-brede horizontale overflow en werkende toetsenbordnavigatie.
- Geen auto-apply, externe assets, fictieve metrics of onbewezen intelligence wordt toegevoegd.
verification:
- uv run pytest tests/e2e tests/integration/test_views.py tests/integration/test_tasks_and_more_views.py
- ./scripts/codex_verify.sh
- Browsercontrole op 1440x900, 1280x800, 1024x768, 768x1024, 390x844 en 360x800
primary_paths:
- apps/core/context_processors.py
- apps/core/views.py
- apps/jobs/views.py
- templates/
- static/css/app.css
- static/js/app.js
- docs/design/STITCH_INTEGRATION_PLAN.md
- docs/design/validation/
result:
completed_at: '2026-07-21'
note: Stitch-schermcompositie dominant doorgevoerd in shell, dashboard, vacaturefeed/detail, pipeline, profieleditor,
bronnen en systeem; geverifieerd met 146 tests, 82,02% coverage en browsermatrix op zes viewports, dark/light
en mobiele navigatie.
- id: VR-120
title: Begeleid zoekprofiel en functionele livebronnen opleveren
status: done
priority: P0
requirement_ids:
- PR-001
- PR-002
- PR-005
- PR-011
- PR-017
- PR-018
- PR-022
depends_on:
- VR-119
summary: Verwerk de functionele productfeedback door thuislocatie tot postcode te vereenvoudigen, technische JSON-invoer
door selectielijsten en checkboxes te vervangen en minimaal twee actuele publieke werkgeversfeeds end-to-end
te valideren.
acceptance_criteria:
- Het profiel vraagt alleen een viercijferige thuispostcode en leidt gemeente/coördinaten af wanneer lokale geodata
eenduidig beschikbaar is.
- Functietitels, skills, contractvormen, werkmodellen en regio's zijn begeleide keuzevelden die bestaande waarden
veilig behouden.
- Minimaal twee echte werkgeverfeeds hebben een actuele policyreview, parserfixtures en twee succesvolle livecycli.
- Demobronnen zijn niet zichtbaar in het normale bronoverzicht en actuele vacatures stromen door naar ranking.
- Profiel-, adapter-, pipeline-, view- en browsertests plus de volledige verificatiegate slagen.
verification:
- uv run pytest tests/integration/test_profile_preferences.py tests/integration/test_seed_sources.py tests/integration/test_pipeline.py
tests/unit/test_ats_adapters.py
- Volg docs/operations/SOURCE_ONBOARDING.md en controleer twee livecycli per geactiveerde bron
- ./scripts/codex_verify.sh
primary_paths:
- apps/profiles/
- templates/profiles/
- apps/sources/
- config-data/seed_sources.yaml
- docs/operations/SOURCE_ONBOARDING.md
result:
completed_at: '2026-07-21'
note: Postcode-only profiel, begeleide checkboxkeuzes, gereviewde VITO- en Deliverect-feeds met twee livecycli,
employeridentiteit, broninventaris en robotsredirecthardening; 155 tests geslaagd, 2 optioneel overgeslagen,
82,94% coverage en volledige codex_verify-gate groen.
- id: VR-121
title: Regionale werkgevers- en platformalertdekking uitbreiden
status: done
priority: P0
requirement_ids:
- PR-011
- PR-012
- PR-017
- PR-018
- PR-032
depends_on:
- VR-120
summary: Breid de livebroncatalogus uit met publieke werkgeversfeeds in Limburg en aangrenzende Belgische werkregio's,
maak gedeelde ATS-hosts first-class en documenteer de veilige alertingress voor VDAB en Indeed.
acceptance_criteria:
- Minimaal acht bijkomende publieke bronnen hebben een actuele policyreview, parserdekking en twee succesvolle
livecycli voordat ze actief worden.
- De catalogus bevat aantoonbaar regionale dekking voor Hasselt/Genk en aanvullende IT-werkgevers in Brussel,
Gent of Leuven.
- Meerdere werkgevers op één publieke ATS-host kunnen naast elkaar bestaan zonder bronrecords te overschrijven.
- Corda Campus-vacaturekaarten worden deterministisch uitgelezen en off-domain links worden verworpen.
- Indeed en VDAB worden uitsluitend via officiële vacaturealerts/mailimport of handmatige import gebruikt en blijven
op de directe-fetchdenylist.
verification:
- uv run pytest tests/unit/test_regional_adapters.py tests/unit/test_ats_adapters.py tests/unit/test_source_models.py
tests/integration/test_seed_sources.py
- Voer twee livecycli uit voor iedere nieuwe bron en controleer source health, parserwarnings en inventaristelling
- ./scripts/codex_verify.sh
primary_paths:
- apps/sources/
- config-data/seed_sources.yaml
- fixtures/pages/corda-campus-jobs.html
- fixtures/ats/smartrecruiters-public-postings.json
- docs/operations/LIVE_SOURCE_CATALOG.md
result:
completed_at: '2026-07-21'
note: Acht extra gereviewde livebronnen, gedeelde ATS-hostidentiteit, Corda-adapter en veilige VDAB/Indeed-alertingress
toegevoegd; twee livecycli per bron, 159 tests, 82,91% coverage en in-app-browsercontrole geslaagd.
- id: VR-122
title: Dagelijkse officiële VDAB-ingang operationaliseren
status: done
priority: P0
requirement_ids:
- PR-012
- PR-016
- PR-018
- PR-064
depends_on:
- VR-121
summary: Verwerk officiële VDAB-jobalerts eenmaal per dag via de bestaande dedicated mailbox, met herkenbare provenance,
begrensde verwerking en een duidelijke route naar de contractueel toegankelijke VDAB Vacature API.
acceptance_criteria:
- De IMAP-ingang draait standaard eenmaal per dag op een configureerbaar tijdstip en blijft idempotent bij replay.
- VDAB-alertmails worden als VDAB-provenance herkend en vacatures stromen zonder automatische linkfetch door de
bestaande normalisatie-, dedupe- en rankingpipeline.
- De mailboxpoll is begrensd op aantal en berichtgrootte; oversized of onleesbare berichten stoppen de batch niet.
- De bronpagina toont de dagelijkse planning, configuratiestatus, laatste VDAB-import en het onderscheid tussen
jobalertingang en de officiële API waarvoor VDAB-goedkeuring vereist is.
- Directe VDAB-scraping, platformlogin en niet-goedgekeurde API-toegang blijven geblokkeerd en dit is getest en
operationeel gedocumenteerd.
verification:
- uv run pytest tests/unit/test_email_adapter.py tests/integration/test_email_import_notifications.py tests/integration/test_tasks_and_more_views.py
- ./scripts/codex_verify.sh
primary_paths:
- apps/sources/adapters/email_alert.py
- apps/sources/services/email_import.py
- apps/sources/services/imap_import.py
- apps/sources/tasks.py
- config/settings.py
- templates/sources/list.html
- docs/architecture/adrs/0005-email-alerts-as-platform-ingress.md
result:
completed_at: '2026-07-21'
note: Dagelijkse configureerbare VDAB-jobalertimport met expliciete provenance, begrensde foutgeisoleerde IMAP-poll,
beveiligde handmatige inplanning en heldere officiele API-route; 164 tests, 2 optioneel overgeslagen, 83,55%
coverage en desktop/390px Codex-browsercontrole groen.
- id: VR-123
title: Platformmailboxen veilig in de UI koppelen en frequent synchroniseren
status: done
priority: P0
requirement_ids:
- PR-012
- PR-016
- PR-018
- PR-064
depends_on:
- VR-122
summary: Vervang de globale dagelijkse IMAP-configuratie door gebruikersgescopeerde mailboxkoppelingen per vacatureplatform,
met versleutelde app-wachtwoorden en een eigen frequent synchronisatie-interval.
acceptance_criteria:
- Een ingelogde gebruiker kan voor VDAB en Indeed afzonderlijk een Gmail-, Outlook- of aangepaste IMAP-mailbox
koppelen, wijzigen, pauzeren en direct laten synchroniseren.
- App-wachtwoorden worden met een afzonderlijke roteerbare sleutel versleuteld opgeslagen, nooit teruggetoond
en nooit in logs of taakresultaten opgenomen.
- Iedere mailbox heeft een interval van 5 tot 360 minuten; de scheduler plant alleen verschuldigde actieve mailboxen
en is concurrency- en replayveilig.
- Mailimport bewaart mailbox- en platformprovenance, is per mailbox idempotent en laat een fout in één mailbox
de andere mailboxen niet blokkeren.
- Alle mutaties zijn login-, user-scope- en CSRF-beveiligd; negatieve tests dekken cross-user toegang, ontbrekende
encryptiesleutel, ongeldige host/poort en secretlekken.
- Bronpagina, runbook, threat model, configuratie en migratiedocumentatie zijn bijgewerkt; directe platformfetch
en platformlogin blijven uitgesloten.
verification:
- uv run pytest tests/unit/test_mailbox_credentials.py tests/integration/test_mailbox_connections.py tests/integration/test_email_import_notifications.py
- uv run python manage.py makemigrations --check --dry-run
- ./scripts/codex_verify.sh
primary_paths:
- apps/sources/models.py
- apps/sources/forms.py
- apps/sources/services/mailbox_connections.py
- apps/sources/services/imap_import.py
- apps/sources/tasks.py
- apps/sources/views.py
- templates/sources/list.html
- config/settings.py
result:
completed_at: '2026-07-22'
note: 'Per-platform VDAB/Indeed-mailboxen met versleutelde app-wachtwoorden, intervallen van 5-360 minuten,
leases, user-scoped UI, securitytests en documentatie; volledige gate: 178 passed, 2 skipped, 83.56%.'
- id: VR-124
title: LinkedIn en Belgische jobboards via veilige jobalertmail toevoegen
status: done
priority: P0
requirement_ids:
- PR-012
- PR-016
- PR-021
- NFR-001
- NFR-003
depends_on:
- VR-123
summary: Breid de platformmailboxingang uit met LinkedIn, ictjob.be, Jobat, StepStone, EuroBrussels en BrusselsJobs
en beperk iedere parserrun tot vacaturelinks van het expliciet gekozen jobboard.
acceptance_criteria:
- De mailbox-UI biedt naast VDAB en Indeed ook LinkedIn, ictjob.be, Jobat, StepStone, EuroBrussels en BrusselsJobs
met een actuele officiele jobalertlink en dezelfde afzonderlijke mailbox-, interval-, pauze- en syncflow.
- Gesaneerde fixtures en adaptertests bewijzen per nieuw platform titel-, link- en provenance-extractie zonder
live netwerkcall.
- Een platformgebonden mail importeert alleen HTTPS-vacaturelinks op het verwachte jobboarddomein; externe, tracking-,
account-, privacy- en uitschrijflinks worden genegeerd.
- Mailboxrecords, bronprovenance, idempotentie, user scoping, encryptie, leases en foutisolatie blijven voor alle
platformkeuzes behouden.
- Bronbeleid, catalogus, threat model, onboarding, traceability en UI-copy vermelden dat directe platformlogin
en jobboardscraping uitgesloten blijven.
verification:
- uv run pytest tests/unit/test_email_adapter.py tests/integration/test_email_import_notifications.py tests/integration/test_mailbox_connections.py
- uv run python manage.py makemigrations --check --dry-run
- ./scripts/codex_verify.sh
primary_paths:
- apps/sources/models.py
- apps/sources/adapters/email_alert.py
- apps/sources/services/email_import.py
- templates/sources/list.html
- fixtures/emails/
- docs/operations/LIVE_SOURCE_CATALOG.md
result:
completed_at: '2026-07-22'
note: LinkedIn, ictjob.be, Jobat, StepStone, EuroBrussels en BrusselsJobs toegevoegd aan platformmailboxen;
domeingebonden HTTPS-parser, zes fixtures, denylist, UI en docs; 192 passed, 2 skipped, 83.61%, desktop/390px
browser groen.
- id: VR-125
title: Brusselse dekking vervangen door regionale werkgevers en Belgische jobplatformen
status: done
priority: P0
requirement_ids:
- PR-011
- PR-012
- PR-017
- PR-018
- PR-021
- NFR-001
- NFR-003
depends_on:
- VR-124
summary: Verwijder de expliciete Brusselse jobboards en werkgevers uit de actieve radar, voeg brede Belgische
jobalertplatformen toe en activeer veilige publieke vacaturelijsten van werkgevers rond Hasselt-Genk.
acceptance_criteria:
- EuroBrussels en BrusselsJobs zijn niet meer configureerbaar of actief; bestaande koppelingen worden veilig uitgeschakeld
en verborgen zonder historische provenance te verwijderen.
- Careerjet, Randstad en Robert Half zijn beschikbaar via hun officiele e-mailalerts en blijven op de directe-fetchdenylist.
- Werkgeversbronnen buiten de regionale scope worden gedeactiveerd en verborgen; bestaande vacaturehistoriek blijft
bewaard.
- Minstens vier lokale werkgeverspagina's uit de kern Hasselt-Genk worden met host- en padgebonden adapters, gesaneerde
fixtures, actuele bronreview en twee succesvolle livecycli toegevoegd.
- Tot een thuispostcode is ingevuld, vermeldt de catalogus expliciet dat Hasselt-Genk als omkeerbaar centrum voor
de 40-km-selectie is gebruikt; ranking blijft de exacte profielafstand toepassen zodra die bekend is.
- Bronbeleid, threat model, onboarding, traceability en gebruikerscopy blijven duidelijk over e-mailingress, robots,
SSRF, off-domain afwijzing en het verbod op platformlogin en scraping.
verification:
- .venv/Scripts/python.exe -m pytest tests/unit/test_regional_adapters.py tests/unit/test_email_adapter.py tests/integration/test_seed_sources.py
tests/integration/test_email_import_notifications.py
- .venv/Scripts/python.exe manage.py makemigrations --check --dry-run
- ./scripts/codex_verify.sh
primary_paths:
- apps/sources/adapters/regional.py
- apps/sources/platforms.py
- apps/sources/management/commands/seed_sources.py
- config-data/seed_sources.yaml
- fixtures/pages/
- fixtures/emails/
- docs/operations/LIVE_SOURCE_CATALOG.md
result:
completed_at: '2026-07-22'
note: Brusselse mailboxen en zeven buitenregionale bronnen veilig geretired; Careerjet, Randstad en Robert Half
toegevoegd; ACA, Xplore, UHasselt, PXL en ZOL na host/padreview en twee livecycli actief; 200 passed, 2 skipped,
83.90%, browser desktop/390px groen.
- id: VR-126
title: Werkgeversradar herankeren op postcode 2400 Mol
status: done
priority: P0
requirement_ids:
- PR-002
- PR-011
- PR-017
- PR-018
- PR-021
- NFR-001
- NFR-003
depends_on:
- VR-125
summary: Vervang de tijdelijke Hasselt-Genk-aanname door postcode 2400 Mol en voeg veilige publieke vacaturelijsten
toe van relevante werkgevers binnen ongeveer 40 km, met nadruk op infrastructuur-, systeem- en netwerkfuncties.
acceptance_criteria:
- De actieve profielruntime bewaart postcode 2400 en een maximale afstand van 40 km; ontbrekende gelicenseerde
coördinatendata blijft expliciet zichtbaar als extern restpunt en wordt niet stil ingevuld.
- De broncatalogus en UI noemen Mol als centrum en maken onderscheid tussen geografisch gereviewde bronnen en
exacte vacatureafstand die pas na geocoding kan worden berekend.
- Minstens vijf werkgevers uit Mol, Geel, Westerlo of Turnhout met regelmatig gepubliceerde eigen vacatures worden
host- en padgebonden toegevoegd, inclusief relevante IT-/infrastructuurwerkgevers.
- Iedere nieuwe bron heeft een gesaneerde fixture, positieve adaptertest, off-domain/route-negatie en minstens
twee geslaagde livecycli zonder parserwarnings voor activering.
- Bestaande regionale bronnen blijven alleen actief wanneer hun primaire vestiging of vacaturelocatie indicatief
binnen 40 km van Mol valt; historische vacatures en provenance worden bij retirement behouden.
- Bronbeleid, threat model, livecatalogus, onboarding, traceability en gebruikerscopy documenteren robots-, SSRF-,
sanitization- en locatiegrenzen; login, sollicitatie-endpoints en platformscraping blijven uitgesloten.
verification:
- .venv/Scripts/python.exe -m pytest tests/unit/test_regional_adapters.py tests/integration/test_seed_sources.py
tests/integration/test_profile_preferences.py tests/security/test_policy.py
- .venv/Scripts/python.exe manage.py makemigrations --check --dry-run
- ./scripts/codex_verify.sh
primary_paths:
- apps/sources/adapters/regional.py
- apps/sources/management/commands/seed_sources.py
- config-data/seed_sources.yaml
- fixtures/pages/
- templates/sources/list.html
- docs/operations/LIVE_SOURCE_CATALOG.md
result:
completed_at: '2026-07-22'
note: Profielruntime op postcode 2400 en 40 km gezet; SCK CEN, Cipal Schaubroeck, VanRoey, NTX en Thomas More
met fail-closed Mol-regioadapter, fixtures, docs en twee livecycli geactiveerd; 206 passed, 2 skipped, 84.12%,
browser desktop/360px groen.
- id: VR-201
title: Concrete live-bronnen inventariseren en juridisch/operationeel reviewen
status: blocked-external
status: done
priority: P0
requirement_ids:
- PR-011
@@ -1001,8 +1334,11 @@ tasks:
- config-data/seed_sources.local.yaml
- Source admin
- docs/operations/SOURCE_ONBOARDING.md
external_blocker: Vereist persoonlijke werkgeverskeuzes en een actuele menselijke bronvoorwaardenreview. Commit
lokale bronlijst niet wanneer die persoonlijke informatie bevat.
result:
completed_at: '2026-07-22'
note: Gemeente Mol en zeven Kempen-werkgevers na actuele menselijke review, fail-closed fixtures/tests en twee
livecycli geactiveerd; twaalf interessante regionale werkgevers als niet-scanbare waaklijst toegevoegd; TLS
gebruikt strikt de gepinde certifi-bundel zonder bypass.
- id: VR-202
title: Live IMAP- en SMTP-credentials configureren
status: blocked-external
@@ -1015,18 +1351,23 @@ tasks:
depends_on:
- VR-111
- VR-115
summary: Configureer een dedicated vacaturemailbox, app-password en digestrecipient; test read-only import en
mailverzending zonder credentials in Git/logs.
- VR-123
- VR-124
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:
- IMAP gebruikt TLS, dedicated mailbox en mark-seen standaard uit tijdens acceptatie.
- Dezelfde live testmail importeert idempotent.
- Iedere platformmailbox gebruikt TLS, een dedicated account/app-wachtwoord en read-only mailboxselectie.
- Dezelfde live testmail importeert per mailbox idempotent en alle geconfigureerde intervallen worden door de
scheduler gerespecteerd.
- SMTP verstuurt één testdigest en outboxstatus klopt.
- Credentials zijn geroteerbaar en alleen in productie-secretstore/.env aanwezig.
- De encryptiesleutel staat alleen in de productie-secretstore/.env; app-wachtwoorden zijn als ciphertext in de
database aanwezig 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.
- id: VR-203
title: Productiedomein, TLS en reverse proxy activeren
@@ -1078,7 +1419,7 @@ tasks:
external_blocker: Vereist registrykeuze, account en credentials.
- id: VR-205
title: Gelicenseerde Belgische geodatabron laden
status: blocked-external
status: done
priority: P1
requirement_ids:
- PR-002
@@ -1098,7 +1439,11 @@ tasks:
primary_paths:
- lokale geodatafile
- config-data/geodata/README.local.md
external_blocker: Vereist een actuele datasetkeuze/licentiecheck; bulkdata hoort niet automatisch in de project-ZIP.
result:
completed_at: '2026-07-22'
note: GeoNames België postcodedataset 2026-04-03 onder CC BY 4.0 gereviewd, checksums vastgelegd, 2781 unieke
rijen gevalideerd en 5562 lookuprecords geïmporteerd; 2400 Mol opgelost naar 51.1919, 5.1166 en actieve profielscores
herberekend.
- id: VR-301
title: Multi-tenant SaaS, teams en billing
status: deferred