This commit is contained in:
@@ -1444,6 +1444,50 @@ tasks:
|
||||
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-206
|
||||
title: Premium Stitch-cockpit en deterministische IT-focus
|
||||
status: done
|
||||
priority: P0
|
||||
requirement_ids:
|
||||
- PR-040
|
||||
- PR-050
|
||||
- PR-051
|
||||
- NFR-004
|
||||
- NFR-008
|
||||
depends_on:
|
||||
- VR-119
|
||||
- VR-120
|
||||
- VR-205
|
||||
summary: Audit de volledige gebruikersflow in code en browser, voorkom dat niet-IT-vacatures de dagelijkse radar
|
||||
vervuilen en benut de Stitch-compositie veel dominanter op mobiel, desktop en widescreen.
|
||||
acceptance_criteria:
|
||||
- Een deterministische en uitlegbare IT-relevantieregel heeft voorrang op scoring en AI; niet-IT-vacatures zijn
|
||||
standaard afwezig uit Vandaag en de vacaturefeed maar blijven via een expliciete archiefkeuze inspecteerbaar.
|
||||
- De vacaturefeed gebruikt echte score-evidence, bruikbare relevantie-/match-/sorteerfilters en toont standaard
|
||||
de meest relevante IT-kansen in plaats van louter de nieuwste bronrecords.
|
||||
- Dashboard, vacaturelijst en vacaturedetail nemen de bruikbare Stitch-panelhiërarchie, informatiedichtheid en
|
||||
actiepatronen over zonder fictieve metrics, quick-apply of externe frontendafhankelijkheden.
|
||||
- De shell en kernlayouts schalen inhoudelijk tussen 320 en 2560 px; widescreen voegt bruikbare kolommen/panelen
|
||||
toe en laat de inhoud niet op een smalle 1280px-strook staan.
|
||||
- Focus, headings, labels, lege toestanden, dark/light contrast, mobiele navigatie en reduced motion blijven toegankelijk;
|
||||
kernroutes hebben geen horizontale paginaoverflow of browserconsolefouten.
|
||||
verification:
|
||||
- uv run pytest tests/unit/test_relevance.py tests/unit/test_scoring.py tests/integration/test_views.py tests/e2e/test_vr114_browser_and_accessibility.py
|
||||
- ./scripts/codex_verify.sh
|
||||
- Browsermatrix op 2560x1440, 1920x1080, 1440x900, 1024x768, 390x844 en 320x800
|
||||
primary_paths:
|
||||
- apps/jobs/services/relevance.py
|
||||
- apps/jobs/services/scoring.py
|
||||
- apps/jobs/views.py
|
||||
- templates/dashboard/today.html
|
||||
- templates/jobs/list.html
|
||||
- templates/jobs/detail.html
|
||||
- static/css/app.css
|
||||
- docs/design/STITCH_INTEGRATION_PLAN.md
|
||||
result:
|
||||
completed_at: '2026-07-22'
|
||||
note: 'Volledige code- en browseraudit: deterministische IT-focus, laatste gebruikersscore, premium Stitch-feed/detail
|
||||
en adaptieve 320-2560px-layout; 225 tests groen en browsermatrix geslaagd.'
|
||||
- id: VR-301
|
||||
title: Multi-tenant SaaS, teams en billing
|
||||
status: deferred
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Projectstatus
|
||||
|
||||
- Laatst bijgewerkt: 2026-07-22
|
||||
- Repositoryversie: 0.2.10 Kempen-werkgeversradar en GeoNames
|
||||
- Repositoryversie: 0.2.11 premium IT-radar en ultrawide Stitch-cockpit
|
||||
- Uitvoeringsmodus: autonome backlog
|
||||
- Eerste uitvoerbare taak: controleer met `python scripts/backlog.py next`
|
||||
|
||||
@@ -131,6 +131,15 @@ VR-201/VR-205-herverificatie op 2026-07-22:
|
||||
- de fetcher valideert het werkelijk verbonden publieke peer-IP, zodat legitieme CDN-rotatie van DAF en Xplore Group veilig wordt ondersteund;
|
||||
- taakledger bevat 44 taken: 38 `done`, 3 `blocked-external`, 3 `deferred` en 0 `ready`.
|
||||
|
||||
VR-206-herverificatie op 2026-07-22:
|
||||
|
||||
- 225 geslaagde tests en 2 optioneel overgeslagen pytest-Playwrightvarianten; HTML/a11y-fallback geslaagd;
|
||||
- 84,53% branch-aware codedekking; Ruff, Django system check, migratiecontrole, taakledger en repositoryvalidatie geslaagd via `scripts/codex_verify.sh`;
|
||||
- de standaardradar gebruikt een deterministische titelgestuurde IT-grens en laat verborgen/hard uitgesloten matches weg, met expliciete archiefopties voor volledige inspectie;
|
||||
- de lokale auditinventaris telt 336 actieve records: 108 aantoonbare IT-titels, 228 gefilterde niet-IT-records en 102 kaarten in de persoonlijke radarselectie;
|
||||
- de Stitch-cockpit benut maximaal 2240 px met tweekoloms matchfeeds op ultrawide; de zes kernroutes zijn handmatig gecontroleerd op 320, 390, 1024, 1440, 1920 en 2560 px zonder horizontale paginaoverflow;
|
||||
- dark/light, gelabelde velden, mobiele drawer, score-/confidencecopy, archieffilters en inline bewaren zijn in de geïntegreerde browser gecontroleerd.
|
||||
|
||||
## Deploymentstatus
|
||||
|
||||
- `main` is via de bestaande Gitea-SSH-sleutel naar `NuklearRabbit/VacatureRadar` gepusht.
|
||||
@@ -141,6 +150,13 @@ VR-201/VR-205-herverificatie op 2026-07-22:
|
||||
|
||||
## Laatste uitgevoerde backlogtaak
|
||||
|
||||
- 2026-07-22: `VR-206` voltooid.
|
||||
- Niet-IT-vacatures en commercieel/recruitmentmisleidende IT-titels zijn standaard uit Vandaag en de vacaturefeed verwijderd zonder bronhistoriek te wissen.
|
||||
- Matchsortering, radar-/archieffilters, score-evidence en gebruikersgescopeerde dashboardscores maken de dagelijkse selectie beslisbaar.
|
||||
- De Stitch-dominante shell, feeds, details en context-rails schalen van 320 tot 2560 px en gebruiken op ultrawide twee resultaatkolommen.
|
||||
- Een open redirect in feedbackterugkeer, 320 px bronoverflow en de ontbrekende faviconfallback zijn als auditbevindingen mee opgelost.
|
||||
- Volgende taak: geen uitvoerbare `ready` taak; `VR-202`, `VR-203` en `VR-204` blijven `blocked-external`.
|
||||
|
||||
- 2026-07-22: `VR-201` en `VR-205` voltooid.
|
||||
- De officiële GeoNames-postcodedataset lost postcode 2400 op naar Mol en levert indicatieve postcodecentrumafstanden; licentie, versie, reviewdatum en twee SHA-256-checksums zijn vastgelegd.
|
||||
- Gemeente Mol, Ziekenhuis Geel, lokaal bestuur Geel, Stad Turnhout, Group Renotec, Ravago, Sanofi Geel en DAF Trucks Westerlo zijn na fixtures, negatieve routechecks en twee livecycli actief.
|
||||
|
||||
@@ -52,11 +52,12 @@ mag in een afgeschermde browsercontext uitvallen zonder de bediening te breken.
|
||||
## 4. Spacing en layout
|
||||
|
||||
- 4/8px-gebaseerde schaal;
|
||||
- contentcontainer maximaal 1600px zodat de cockpit op brede schermen bruikbaar blijft;
|
||||
- contentcontainer maximaal 2240px; vanaf 1850px gebruikt de cockpit extra resultaatkolommen en
|
||||
contextpanelen in plaats van alleen langere tekstregels;
|
||||
- kaarten met consistente padding 20–24px desktop, 16px mobiel;
|
||||
- minimaal 44×44px touch targets voor primaire interactie;
|
||||
- vaste zijbalk van 272px boven 900px, toegankelijke uitschuifnavigatie daaronder;
|
||||
- grids breken onder 1180px, 900px en 680px logisch af;
|
||||
- grids breken rond 1850px, 1350px, 1180px, 900px en 680px logisch af;
|
||||
- vaste/sticky elementen mogen content niet bedekken.
|
||||
|
||||
## 5. Componenten
|
||||
|
||||
@@ -19,6 +19,17 @@ Na productfeedback is de integratie aangescherpt: Stitch bepaalt nu niet alleen
|
||||
|
||||
De bedoelde “circa 90% Stitch” slaat hiermee op overgenomen visuele structuur en interactiehiërarchie, niet op het kopiëren van fictieve content, externe assets, auto-apply of routes waarvoor het domeinmodel geen betrouwbare data bezit.
|
||||
|
||||
## VR-206: premium radar en ultrawide compositie
|
||||
|
||||
De volledige audit maakt de Stitch-compositie ook functioneel dominant. De vacaturefeed start met
|
||||
een brede commandofilter, toont beslisbare score-evidence en krijgt op breed desktop een vaste
|
||||
radarcontext. Vanaf 1850 px worden matchfeeds tweekoloms; de shell benut maximaal 2240 px in plaats
|
||||
van de vroegere 1280 px. Op mobiel worden filters, sectiekoppen en acties lineair gestapeld.
|
||||
|
||||
De visuele hiërarchie is gekoppeld aan een deterministische IT-grens: niet-IT en hard uitgesloten
|
||||
matches zijn standaard afwezig. Het volledige archief en verborgen scores blijven expliciet
|
||||
inspecteerbaar, zodat premium rust niet ten koste gaat van auditbaarheid.
|
||||
|
||||
## Visuele richting
|
||||
|
||||
- Donkere cockpit als standaard: diep marineblauw, tonale panelen, fijne slate-randen, signaalcyaan voor primaire interactie, emerald voor aantoonbaar gezonde status en koraal/amber voor fouten of aandacht.
|
||||
@@ -58,7 +69,7 @@ De bedoelde “circa 90% Stitch” slaat hiermee op overgenomen visuele structuu
|
||||
|
||||
## Responsive en toegankelijkheid
|
||||
|
||||
- Validatiebreedtes: 1440×900, 1280×800, 1024×768, 768×1024, 390×844 en 360×800.
|
||||
- Validatiebreedtes: 2560×1440, 1920×1080, 1440×900, 1024×768, 390×844 en 320×800.
|
||||
- Eén `h1` per pagina, semantische landmarks, zichtbare focus, toetsenbordbediening, 44px touchdoelen waar praktisch, tekstlabels naast statuskleur en een robuuste skiplink.
|
||||
- Tabellen schakelen op smalle schermen naar kaartachtige rijen of blijven gecontroleerd horizontaal scrolbaar wanneer kolomvergelijking essentieel is.
|
||||
- Animatie is subtiel en volledig uitgeschakeld bij `prefers-reduced-motion`.
|
||||
|
||||
@@ -56,6 +56,8 @@ Regels:
|
||||
Filters:
|
||||
|
||||
- vrije tekst;
|
||||
- relevantiefocus: standaard aantoonbare IT-titels, met expliciet volledig bronarchief;
|
||||
- radarselectie: standaard geen harde uitsluitingen of verborgen score, met aparte inspectiefilters;
|
||||
- status;
|
||||
- recommendation/scoreband;
|
||||
- werkvorm;
|
||||
@@ -65,6 +67,10 @@ Filters:
|
||||
|
||||
Desktop gebruikt een compacte filterbalk; mobiel een disclosurepanel. Filters blijven in querystring zodat bookmarks en back navigation werken.
|
||||
|
||||
De standaardvolgorde is persoonlijke matchscore, niet importtijd. Niet-IT-inhoud wordt niet
|
||||
verwijderd: ze blijft uitsluitend via `Volledig archief` bereikbaar. Een beschrijvingshit alleen
|
||||
mag nooit een niet-IT-titel promoveren.
|
||||
|
||||
Tabel of kaarten kiezen op breedte. Geen horizontale scroll voor kernvelden.
|
||||
|
||||
## 5. Vacaturedetail
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
# VR-206 volledige UX-, logica- en browseraudit
|
||||
|
||||
Datum: 2026-07-22
|
||||
|
||||
## Uitgangssituatie
|
||||
|
||||
De productiecontrole toonde 242 actieve vacatures. De standaardlijst sorteerde hoofdzakelijk op
|
||||
`first_seen` en liet elke actieve vacature zien. Daardoor stonden onder meer facilitaire techniek,
|
||||
logopedie, vroedkunde en niet-IT-onderzoek tussen de persoonlijke IT-resultaten. Op 2560 px bleef
|
||||
de inhoud bovendien op ongeveer 1280 px begrensd, waardoor de Stitch-cockpit een brede lege zone
|
||||
overliet.
|
||||
|
||||
## Bevindingen en oplossing
|
||||
|
||||
| Prioriteit | Bevinding | Oplossing |
|
||||
| --- | --- | --- |
|
||||
| P0 | Niet-IT-vacatures bereikten Vandaag en de standaardfeed. | Titelgestuurde, deterministische IT-classificatie vóór score/AI; niet-IT blijft alleen in het expliciete volledige archief. |
|
||||
| P0 | Vandaag gebruikte niet overal de laatste gebruikersgescopeerde score en open dossiercijfers waren niet volledig gebruikersgescopeerd. | Laatste score per vacature/profiel via subquery; profiel, scores en dossiers zijn aan de aangemelde gebruiker gebonden. |
|
||||
| P1 | Verborgen/hard uitgesloten IT-vacatures stonden hoog door hun ruwe score. | Nieuwe standaardkeuze `Radarselectie` laat verborgen resultaten weg; `Verborgen` en `Alle IT-scores` blijven bewuste inspectiekeuzes. |
|
||||
| P1 | De lijst sorteerde op bronrecency in plaats van persoonlijke besliswaarde. | Standaard matchscore aflopend, met alternatieven voor nieuwste en sluitingsdatum. |
|
||||
| P1 | Stitch werd visueel gebruikt, maar ultrawide bleef een smalle strook. | Adaptieve contentbreedte tot 2240 px, tweekoloms feeds vanaf 1850 px en context-/actierails op breed desktop. |
|
||||
| P1 | Vacaturekaarten boden weinig scorebewijs. | Score, datakwaliteit, eerste pluspunt, eerste aandachtspunt, status, werkmodel en directe actie staan in de feed. |
|
||||
| P2 | Confidencewaarden wisselden tussen breuken en percentages. | Alle dagelijkse score- en extractiekwaliteit wordt als percentage getoond. |
|
||||
| P2 | Inline feedback accepteerde een willekeurige `next`-URL. | Terugkeer alleen naar dezelfde host, met negatieve regressietest. |
|
||||
| P2 | De bronpagina liep op 320 px uit door statuschips naast lange sectiekoppen. | Sectiekoppen stapelen onder 680 px; de 320 px matrix heeft geen horizontale overflow. |
|
||||
| P2 | Sommige browsers vroegen `/favicon.ico` en kregen een 404. | Lokale permanente fallback naar het bestaande SVG-favicon. |
|
||||
|
||||
## Relevantieregel
|
||||
|
||||
De classifier is bewust conservatief en titelgestuurd. Een beschrijving die toevallig “digitale
|
||||
systemen” vermeldt, maakt een zorg- of facilitaire functie niet relevant. Duidelijke IT-families
|
||||
zoals infrastructuur, netwerk, cloud, security, software, data, applicatiebeheer en workplace
|
||||
worden toegelaten. Commerciële of recruitmentcontext die IT-woorden bevat, wordt expliciet
|
||||
afgewezen. Dezelfde regexcontracten worden in Python en in de databasequery gebruikt.
|
||||
|
||||
Op de lokale auditdataset met 336 actieve records bleven 108 titelmatig aantoonbare IT-vacatures
|
||||
over en werden 228 niet-IT-records uit de standaardfocus gehouden. Na uitsluiting van verborgen
|
||||
matches bevatte de persoonlijke radarselectie 102 kaarten. Het volledige archief blijft 336
|
||||
records bevatten: er wordt geen bronhistoriek gewist.
|
||||
|
||||
## Stitch-vertaling
|
||||
|
||||
- Dashboard: KPI-strip, beslisbare matchfeed en vaste radar-/actierail.
|
||||
- Vacaturelijst: brede commandofilter, compacte evidencekaarten, scorehiërarchie en radarcontext.
|
||||
- Detail: scorehero, intelligence-strip, bronhistorie en menselijke actierail.
|
||||
- Shell: vaste desktopnavigatie, compacte utilitybar, lokale iconen en mobiele drawer.
|
||||
- Ultrawide: twee inhoudskolommen plus context; geen kunstmatig uitgerekte tekstregels of fictieve grafieken.
|
||||
|
||||
Alle cijfers en signalen komen uit de database. Quick apply, automatische sollicitatie,
|
||||
platformloginbots, fictieve trendgrafieken en externe frontendassets blijven bewust afwezig.
|
||||
|
||||
## Browsermatrix
|
||||
|
||||
Handmatig gecontroleerd in de geïntegreerde browser op 320×800, 390×844, 1024×768, 1440×900,
|
||||
1920×1080 en 2560×1440. De zes kernroutes (`/`, `/jobs/`, `/jobs/applications/`, `/profiles/`,
|
||||
`/sources/`, `/system/`) hebben één `h1`, gelabelde formuliervelden en geen horizontale
|
||||
paginaoverflow. De vacaturefeed schakelt van één kolom naar twee kolommen op ultrawide en gebruikt
|
||||
daar 2240 px van de beschikbare ruimte. Mobiele navigatie opent en sluit met correcte
|
||||
`aria-expanded`-status.
|
||||
|
||||
## Resterend operationeel punt
|
||||
|
||||
Na deployment moet de bestaande productie-inventaris opnieuw gescoord worden zodat opgeslagen
|
||||
score-evidence eveneens het nieuwe `it_relevance`-blok bevat. De viewfilter werkt onmiddellijk en
|
||||
onafhankelijk daarvan; het herscoren verbetert de uitleg en blijvende `hidden`-status.
|
||||
@@ -80,6 +80,7 @@ Django/Celery
|
||||
| T-38 | Cross-user mailboxbeheer, dubbele polls of IMAP naar private host | credentialmisbruik, duplicaten, toegang tot interne diensten | alle views scopen op gebruiker en vereisen CSRF; unieke user+platformkoppeling; transactionele lease; hostvorm en publieke DNS/IP-validatie vóór TLS-IMAP | `tests/integration/test_mailbox_connections.py`, `tests/unit/test_mailbox_credentials.py`, `apps/sources/services/imap_import.py`, `VR-123` |
|
||||
| T-39 | Mol-/Kempenbron vermengt een andere werkgever, campus of vestiging | foutieve afstand, phishing of buitenregionale resultaten | exacte HTTPS-host/pad/GUID-routes; same-host details; expliciete plaatsfilters voor regionale en gedeelde lijsten; postcodecentra blijven als benadering herkenbaar; waaklijstbronnen worden niet gescand | `tests/unit/test_regional_adapters.py`, `tests/integration/test_tasks_and_more_views.py`, `VR-126/201` |
|
||||
| T-40 | Verouderde lokale CA-store of ongeldige serverketen lokt een TLS-bypass uit | onderschepte vacature- of mailboxdata en credentialdiefstal | expliciet gepinde `certifi`-CA-bundel voor HTTP, robots en IMAP; hostnaamcontrole en `CERT_REQUIRED`; nooit `verify=False`; dependency- en negatieve TLS-tests bij update | `tests/unit/test_tls.py`, `tests/security/test_robots.py`, `apps/sources/services/tls.py`, `VR-201` |
|
||||
| T-41 | Gemodificeerde `next`-parameter na vacaturefeedback | open redirect naar phishingdomein na een geldige gebruikersactie | terugkeer-URL moet dezelfde host en het actuele HTTPS-beleid respecteren; anders veilige detailfallback | `tests/integration/test_tasks_and_more_views.py`, `VR-206` |
|
||||
|
||||
## Misbruikscenario's
|
||||
|
||||
|
||||
@@ -32,14 +32,14 @@ Legenda: **I** = geïmplementeerd en getest in de huidige MVP; **P** = gedeeltel
|
||||
| PR-031 | I | conservatieve fuzzy dedupe | `tests/unit/test_dedupe_lifecycle_feedback.py`, `scripts/benchmark.py`, `tests/benchmark/test_benchmark.py` | VR-116 benchmark |
|
||||
| PR-032 | I | direct-sourcepreferentie/alias | pipeline- en dedupetests | VR-108 resolver |
|
||||
| PR-033 | I | canonical constraints/transacties | replaytests | — |
|
||||
| PR-040 | I | features/scoring | scoringtests | — |
|
||||
| PR-040 | I | features/scoring + deterministische IT-relevantie vóór AI | `tests/unit/test_scoring.py`, `tests/unit/test_relevance.py`, viewtests | VR-206 |
|
||||
| PR-041 | I | scorecomponenten | `tests/unit/test_features_distance.py`, `tests/unit/test_scoring.py` | VR-105 afgerond |
|
||||
| PR-042 | I | unknown/confidencegedrag | `tests/unit/test_features_distance.py`, `tests/unit/test_scoring.py` | VR-105 |
|
||||
| PR-043 | I | `ScoreRun` | pipeline/scoringtests | — |
|
||||
| PR-044 | I | profiel/modelversievelden | scoring/profiletests | VR-109 promptversie |
|
||||
| PR-045 | I | optionele Ollamaservice/fallback | `test_ai.py` | VR-109 |
|
||||
| PR-046 | I | geen tools + guardrails | AI/securitytests | VR-109/115 evaluaties |
|
||||
| PR-050 | I | dashboard view/template + Stitch-dominante cockpitshell/feed/rail | viewtests, VR-119 browsermatrix | VR-114/118/119 e2e/a11y |
|
||||
| PR-050 | I | dashboard/list views + Stitch-dominante cockpitshell/feed/rail en ultrawide compositie | viewtests, VR-119/206 browsermatrix | VR-114/118/119/206 e2e/a11y |
|
||||
| PR-051 | I | detailview/template/provenance + scorehero/intelligence-strip | viewtests, VR-119 screenshots | VR-114/118/119 |
|
||||
| PR-052 | I | feedbackendpoint/UI | feedback/viewtests | — |
|
||||
| PR-053 | I | applicationmodel/serviceflow | `tests/integration/test_dedupe_lifecycle_feedback.py`, `tests/integration/test_applications.py` | VR-113 uitgebreid dossier |
|
||||
@@ -98,5 +98,5 @@ Iedere backlogtaak die een requirement wijzigt, werkt in dezelfde commit deze ma
|
||||
- VR-126 herankert profiel en broncatalogus op postcode 2400 Mol en 40 km. De host-, pad- en locatiefilters voor SCK CEN, Cipal Schaubroeck, VanRoey, NTX en Thomas More worden gedekt door regionale adaptertests, source-viewtests, live bronruns en de bijgewerkte threat T-39.
|
||||
- VR-201 activeert Gemeente Mol en zeven bijkomende Kempen-werkgevers na menselijke voorwaardenreview, fixtures, fail-closed locatie-/routefilters en twee livecycli. Twaalf interessante werkgevers zonder stabiele actieve ingang staan afzonderlijk en niet-scanbaar op de UI-waaklijst. Bewijs staat in de livecatalogus, seeddata, `KempenEmployerAdapter`, bronruns en adapter-/seed-/viewtests.
|
||||
- VR-205 laadt de officiële Belgische GeoNames-postcodedataset 2026-04-03 onder CC BY 4.0, documenteert bron- en afgeleide checksums en lost 2400 Mol op naar het benaderende postcodecentrum. Bewijs staat in `config-data/geodata/README.local.md`, het importlog, geocodingtests en de opnieuw berekende profiel-vacaturescores.
|
||||
|
||||
- VR-206 voegt een titelgestuurde IT-relevantiegrens vóór scoring/AI toe, maakt de persoonlijke radarselectie de standaard en benut Stitch-panelen dynamisch tot 2560 px. Bewijs staat in `apps/jobs/services/relevance.py`, de score-/viewtests en `docs/design/validation/VR-206_AUDIT.md`.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user