diff --git a/CHANGELOG.md b/CHANGELOG.md index 30e1e2e..ca510c1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,7 +14,8 @@ Alle betekenisvolle wijzigingen worden hier bijgehouden. Het project volgt voorl ### Gewijzigd - De repository-README volgt nu de gebruikersreis van doel en dagelijkse workflow naar quickstart, configuratie, veiligheidsgrenzen, beheer en pas daarna architectuur en agentoverdracht. -- Vier actuele, compacte productbeelden documenteren dagoverzicht, vacatureverkenner, automatisering en het mobiele zoekprofiel in dark/light zonder externe runtime-assets. +- Negen actuele, compacte productbeelden vertellen nu de volledige gebruikersreis: dagoverzicht, vacatureverkenner, beslisanalyse, Skillsradar, werkgevers, sollicitaties, bronnen, automatisering en mobiel zoekprofiel. +- De README-galerij gebruikt taakgerichte captions, klikbare beelden, een consistente 1920×1080-desktopviewport en een gebalanceerde dark/light-compositie. - Het VacatureRadar-productlogo is hertekend als transparante vier-elementenradar zonder donkere tegel, rand of schaduw; login en sidebar gebruiken hetzelfde cleaner beeldmerk. - De sidebarfooter combineert radarstatus en een transparante, themabewuste ITWorx-credit; de dubbele demo-/accountidentiteit is verwijderd en blijft uitsluitend via het topbarmenu bereikbaar. - Widescreencontent schaalt nu gecontroleerd naar 2.200 px en op 4K naar 2.480 px, terwijl dashboardverhoudingen, korte viewports en mobiele layouts begrensd blijven. @@ -32,6 +33,7 @@ Alle betekenisvolle wijzigingen worden hier bijgehouden. Het project volgt voorl ### Hersteld +- De productieconfiguratiehelper voldoet opnieuw aan Ruff en de `.env`-bestandmodustest houdt rekening met Windows, waar POSIX-modusbits niet afdwingbaar zijn. - Publieke Nginx-hostnamen veroorzaken niet langer `DisallowedHost` wanneer `PUBLIC_BASE_URL` correct staat. - HTTPS-deployment gebruikt de externe poort in plaats van de interne applicatiepoort voor CSRF en publieke URL’s. - Interne healthchecks blijven bereikbaar bij `SECURE_SSL_REDIRECT=1`; productie-rate-limiting gebruikt een gedeelde Redis-cache. diff --git a/README.md b/README.md index 4c4fb54..d893058 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,10 @@ -# VacatureRadar +

+ VacatureRadar-logo +

-**Van vacature-overload naar een kleine, uitlegbare selectie die bij jou past.** +

VacatureRadar

+ +

Van vacature-overload naar een kleine, uitlegbare selectie die bij jou past.

VacatureRadar is een persoonlijke vacature-assistent voor België. De applicatie volgt toegestane werkgeversbronnen, ATS-pagina’s, feeds en vacaturemails, verwijdert dubbels en irrelevante resultaten en rangschikt de overblijvende kansen tegen jouw zoekprofiel. Jij behoudt altijd de controle: VacatureRadar helpt zoeken en opvolgen, maar solliciteert nooit automatisch. @@ -36,18 +40,65 @@ VacatureRadar is bedoeld voor één persoon of een eigen, afgeschermde installat | Bronnenbeheer | Veilige bronconfiguratie, gezondheid, handmatige import en mailboxkoppelingen | | Automatisering | Eerlijke 24-uursmetingen; niet-gemeten informatie blijft expliciet onbekend | -## Productbeelden +## Bekijk de volledige productflow -De beelden hieronder komen uit de lokale demo-omgeving. De getoonde cijfers zijn omgevingsdata, geen marketingclaims. +De beelden komen uit de lokale demo-omgeving. De getoonde cijfers zijn omgevingsdata, geen marketingclaims. Klik op een beeld voor de volledige resolutie. -| Vacatureverkenner | Automatisering | -|---|---| -| ![Vacatureverkenner met gerangschikte matches en detailanalyse](docs/screenshots/readme/matches-dark.png) | ![Automation center met verwerkingspipeline en brongezondheid](docs/screenshots/readme/automation-dark.png) | +### 1. Vind de relevante kansen + +De verkenner brengt zoeken, filters, gerangschikte resultaten en de belangrijkste matchcontext samen. Zo hoef je niet tussen lijst- en detailpagina’s te blijven wisselen.

- Mobiel zoekprofiel van VacatureRadar + Vacatureverkenner met gerangschikte matches en directe intelligence

+### 2. Begrijp waarom een vacature past + +Een analyse maakt score, datakwaliteit, beslissignalen, aandachtspunten en broninformatie afzonderlijk zichtbaar. Ervaring en senioriteitslabels worden als context getoond, niet als verborgen scorefactor. + +

+ Uitlegbare vacatureanalyse met scorecomponenten en besliscontext +

+ +### 3. Bouw markt- en werkgeversinzicht op + + + + + + + + + + +
Skillsradar
Vergelijk aantoonbare marktvraag met je profiel, zonder ontbrekende skills als afwijzingsregel te behandelen.
Werkgeversradar
Bekijk werkgevers, actieve IT-vacatures, bronnen en eerdere dossiers in één genormaliseerd overzicht.
Skillsradar met profieldekking en actuele marktvraagWerkgeversradar met vacature- en broninformatie
+ +### 4. Volg trajecten op en houd bronnen gezond + + + + + + + + + + +
Sollicitatiepipeline
Bewaar status, deadlines, notities en tijdlijn per dossier; de uiteindelijke sollicitatie blijft altijd handmatig.
Bronnenbeheer
Zie policyreview, laatste scans, volgende runs en brongezondheid zonder technische logs te moeten doorzoeken.
Sollicitatiepipeline met persoonlijke dossiersBronnenbeheer met policy- en gezondheidsstatus
+ +### 5. Controleer de radar — ook mobiel + + + + + + + + + + +
Automation center
Volg de echte verwerkingspipeline, bronruns en systeemstatus. Niet-gemeten runtime-informatie blijft expliciet onbekend.
Mobiel zoekprofiel
Controleer je persoonlijke radar en navigeer door de kernflow vanaf een smal scherm.
Automation center met pipeline en bronrunsMobiel zoekprofiel van VacatureRadar
+ ## Snel starten ### Optie 1 — lokale demo diff --git a/docs/ai/BACKLOG.yaml b/docs/ai/BACKLOG.yaml index a7dbbf3..eab3eac 100644 --- a/docs/ai/BACKLOG.yaml +++ b/docs/ai/BACKLOG.yaml @@ -1,6 +1,6 @@ schema_version: 1 project: VacatureRadar -updated_at: '2026-07-27' +updated_at: '2026-07-28' execution_policy: order: file-order, then first ready task whose dependencies are done no_product_questions: true @@ -2215,13 +2215,14 @@ tasks: summary: Maak de bestaande persoonlijke installatie veilig en reproduceerbaar bereikbaar achter Nginx Proxy Manager, herstel publieke host- en CSRF-configuratie en voorkom dat een gedeeld demoaccount persistente data wijzigt. acceptance_criteria: - - Eén publieke HTTPS-URL configureert hostvalidatie, CSRF, secure cookies, SSL-detectie en redirect zonder de interne - containerpoort in de externe origin op te nemen. + - Eén publieke HTTPS-URL configureert hostvalidatie, CSRF, secure cookies, SSL-detectie en redirect zonder de + interne containerpoort in de externe origin op te nemen. - Productie start fail-fast bij debugmodusgerelateerde onveiligheid, een zwakke secret, onveilige cookies, ontbrekende HTTPS-origin of een schrijfbare publieke demo. - Login- en importlimieten gebruiken in productie een gedeelde cache; forwarded client-IP’s worden alleen vanaf expliciet vertrouwde proxy-CIDR’s geaccepteerd. - - Het gastaccount is server-side alleen-lezen, heeft een begrensde sessie, kan afmelden en toont de beperking zichtbaar. + - Het gastaccount is server-side alleen-lezen, heeft een begrensde sessie, kan afmelden en toont de beperking + zichtbaar. - Unraid-envpad, Nginx Proxy Manager, healthchecks, noindex, heruitrol en terugdraaien zijn exact gedocumenteerd. verification: - PYTHONPATH=/mnt/data/vr_windows_site/site-packages pytest -q @@ -2244,3 +2245,41 @@ tasks: note: Publieke host/CSRF/HTTPS-configuratie, gedeelde Redis-rate-limiting, proxy-IPvertrouwen, cache-readiness, noindex en read-only gastdemo geïmplementeerd. 295 tests groen met 2 correcte Playwrightskips; Django check, migratiecheck, repositoryvalidatie, YAML-, syntax- en packagechecks groen. Live servervalidatie blijft extern. +- id: VR-226 + title: Verdiep de user-first README met een volledige productgalerij + status: done + priority: P1 + requirement_ids: + - NFR-006 + - NFR-008 + - NFR-009 + depends_on: + - VR-225 + summary: Maak de productpresentatie overtuigender met een logisch opgebouwde, actuele galerij die de volledige + gebruikersreis toont zonder de README traag, repetitief of marketingmatig te maken. + acceptance_criteria: + - De README bevat minstens acht actuele beelden die dashboard, zoeken/analyse, skills, sollicitatieopvolging, + profiel, bronnen, automatisering en mobiel gebruik als één samenhangende productreis tonen. + - Desktopbeelden gebruiken een consistente professionele viewport en rustige uitsnede; dark/light en mobiel zijn + doelbewust verdeeld, zonder overgangsoverlays, overflow, consolefouten, secrets of persoonlijke gegevens. + - De galerij heeft korte taakgerichte captions, een scanbare compositie en compacte lokale assets; duplicatieve + beelden of losse decoratieve screenshots worden verwijderd of vervangen. + - De eerder aangetroffen VR-225-baselinefouten in lint en platformafhankelijke bestandsmoduscontrole zijn hersteld; + repositoryvalidatie en de volledige kwaliteitsgate slagen. + verification: + - Browsercontrole van alle vastgelegde routes op desktop en mobiel in dark/light + - uv run pytest tests/unit/test_public_configuration.py + - python scripts/validate_repository.py + - ./scripts/codex_verify.sh + primary_paths: + - README.md + - docs/screenshots/readme/ + - scripts/configure_public_url.py + - tests/unit/test_public_configuration.py + - docs/quality/TRACEABILITY_MATRIX.md + - docs/ai/PROJECT_STATE.md + result: + completed_at: '2026-07-28' + note: README verdiept tot een klikbare user-first productreis met negen actuele beelden op 1920x1080 en 390x844 + in dark/light; alle routes zonder overflow of consolewaarschuwingen. VR-225-lint en Windows-modusassertie + hersteld; 296 tests groen, 2 skips en 83,44% dekking. diff --git a/docs/ai/PROJECT_STATE.md b/docs/ai/PROJECT_STATE.md index 508b6a3..70b1951 100644 --- a/docs/ai/PROJECT_STATE.md +++ b/docs/ai/PROJECT_STATE.md @@ -1,6 +1,6 @@ # Projectstatus -- Laatst bijgewerkt: 2026-07-27 +- Laatst bijgewerkt: 2026-07-28 - Repositoryversie: 0.3.12 productie- en reverse-proxyhardening - Uitvoeringsmodus: autonome backlog - Eerste uitvoerbare taak: controleer met `python scripts/backlog.py next` @@ -46,6 +46,13 @@ Het volledige scherm- en afwijkingsrapport staat in `docs/design/STITCH_INTEGRAT ## Laatste onderhoudsaudit +VR-226 op 2026-07-28: + +- README-presentatie verdiept van vier losse beelden naar een klikbare productreis met negen actuele screenshots: overzicht, zoeken, analyse, skills, werkgevers, sollicitaties, bronnen, automatisering en mobiel profiel; +- alle desktopbeelden opnieuw vastgelegd op 1920×1080, doelbewust verdeeld over dark/light en gecombineerd met 390×844 mobiel; geen overgangsoverlays, horizontale overflow, secrets of consolewaarschuwingen; +- de onrustige mobiele dashboardcapture is afgekeurd en verwijderd; de volledige galerij blijft lokaal en samen circa 1,1 MB; +- vier aangetroffen VR-225-lintproblemen en de ongeldige POSIX-modusassertie op Windows zijn hersteld; volledige gate groen met 296 geslaagde tests, 2 optionele skips en 83,44% branch-aware dekking. Volgende uitvoerbare taak: geen. + VR-224 op 2026-07-27: - README volledig herordend rond doelgroep, dagelijkse workflow, concrete productwaarde, veilige quickstart en eerste configuratie; architectuur, beheer en Codex-overdracht volgen pas daarna; diff --git a/docs/quality/TRACEABILITY_MATRIX.md b/docs/quality/TRACEABILITY_MATRIX.md index 8c21c8e..e254a22 100644 --- a/docs/quality/TRACEABILITY_MATRIX.md +++ b/docs/quality/TRACEABILITY_MATRIX.md @@ -61,9 +61,9 @@ Legenda: **I** = geïmplementeerd en getest in de huidige MVP; **P** = gedeeltel | NFR-003 | I/P | replay-, mail- en outboxtests; per-bronfouten | VR-103/112 | | NFR-004 | I | ScoreRun, provenance, skillvraag met expliciet veld-/tekstonderscheid en UI-copy | VR-109/208 uitgebreid evidence | | NFR-005 | I | domeinapps/services/adapters/ADRs | continue review | -| NFR-006 | I | offline pytest + coveragegate | VR-114 verbreedt e2e | +| NFR-006 | I | offline pytest + coveragegate, inclusief platformbewuste productieconfiguratietests | VR-114 e2e; `tests/unit/test_public_configuration.py`; VR-225/226 | | NFR-007 | P | `scripts/benchmark.py`, `tests/benchmark/test_benchmark.py` | VR-116 | -| NFR-008 | I | volledige negen-schermen-Stitch-cockpit, acht viewports, dark/light, toetsenborddrawer, premium visuele hiërarchie, zelfstandig VacatureRadar-productmerk, lokale ITWorx-ontwikkelaarscredit, toegankelijke interactieve radarillustratie en actuele user-first productdocumentatie | `tests/e2e/test_vr114_browser_and_accessibility.py`, `tests/integration/test_intelligence_views.py`, `tests/integration/test_views.py`, `artifacts/visual-validation/`, `docs/screenshots/readme/`, VR-209–224 | +| NFR-008 | I | volledige negen-schermen-Stitch-cockpit, acht viewports, dark/light, toetsenborddrawer, premium visuele hiërarchie, zelfstandig VacatureRadar-productmerk, lokale ITWorx-ontwikkelaarscredit, toegankelijke interactieve radarillustratie en actuele user-first productdocumentatie | `tests/e2e/test_vr114_browser_and_accessibility.py`, `tests/integration/test_intelligence_views.py`, `tests/integration/test_views.py`, `artifacts/visual-validation/`, negen beelden in `docs/screenshots/readme/`, VR-209–224/226 | | NFR-009 | I | lokale SQLite, configureerbare eigenaarbranding, Docker/Unraidconfig, publieke URL-helper, Nginx Proxy Manager-runbook, gevalideerde SSH-deployalias, release-smoke en restore | `tests/unit/test_deployment_configuration.py`, `tests/unit/test_public_configuration.py`, VR-117, VR-217/218/225 afgerond | | NFR-010 | I | `apps/sources/services/health.py`, `apps/sources/tasks.py`, `apps/core/views.py`, `config/settings.py` | `tests/integration/test_source_health.py` | VR-112 observability | @@ -113,3 +113,4 @@ Iedere backlogtaak die een requirement wijzigt, werkt in dezelfde commit deze ma - VR-224 maakt de repository-ingang user-first: de README volgt de dagelijkse productflow, bevat gecontroleerde lokale quickstarts en gebruikt vier actuele dark/light- en desktop/mobielscreenshots zonder secrets of externe assets. - VR-225 hardent de publieke installatie met `PUBLIC_BASE_URL`, exacte host/CSRF-afleiding, veilige proxy-HTTPS-detectie, vertrouwde client-IPchains, gedeelde Redis-rate-limiting, cache-readiness en een server-side alleen-lezen gastdemo. Bewijs staat in de productie-audit, Nginx-runbook en de settings-, network-, health-, auth- en deploymenttests. +- VR-226 verdiept de README tot een visuele productreis met negen actuele beelden op consistente desktop- en mobiele viewports. Dezelfde taak herstelt de VR-225-lintbaseline en maakt de POSIX-bestandsmodusassertie terecht platformafhankelijk. diff --git a/docs/screenshots/readme/applications-dark.png b/docs/screenshots/readme/applications-dark.png new file mode 100644 index 0000000..179902e Binary files /dev/null and b/docs/screenshots/readme/applications-dark.png differ diff --git a/docs/screenshots/readme/automation-dark.png b/docs/screenshots/readme/automation-dark.png index 6c31edd..ab54e34 100644 Binary files a/docs/screenshots/readme/automation-dark.png and b/docs/screenshots/readme/automation-dark.png differ diff --git a/docs/screenshots/readme/dashboard-light.png b/docs/screenshots/readme/dashboard-light.png index bf7903b..d475e22 100644 Binary files a/docs/screenshots/readme/dashboard-light.png and b/docs/screenshots/readme/dashboard-light.png differ diff --git a/docs/screenshots/readme/employers-light.png b/docs/screenshots/readme/employers-light.png new file mode 100644 index 0000000..e8e137f Binary files /dev/null and b/docs/screenshots/readme/employers-light.png differ diff --git a/docs/screenshots/readme/job-analysis-dark.png b/docs/screenshots/readme/job-analysis-dark.png new file mode 100644 index 0000000..0a0492d Binary files /dev/null and b/docs/screenshots/readme/job-analysis-dark.png differ diff --git a/docs/screenshots/readme/matches-dark.png b/docs/screenshots/readme/matches-dark.png index e461dea..661eef8 100644 Binary files a/docs/screenshots/readme/matches-dark.png and b/docs/screenshots/readme/matches-dark.png differ diff --git a/docs/screenshots/readme/profile-mobile-light.png b/docs/screenshots/readme/profile-mobile-light.png index 7970039..af2e97c 100644 Binary files a/docs/screenshots/readme/profile-mobile-light.png and b/docs/screenshots/readme/profile-mobile-light.png differ diff --git a/docs/screenshots/readme/skills-light.png b/docs/screenshots/readme/skills-light.png new file mode 100644 index 0000000..008e1d0 Binary files /dev/null and b/docs/screenshots/readme/skills-light.png differ diff --git a/docs/screenshots/readme/sources-light.png b/docs/screenshots/readme/sources-light.png new file mode 100644 index 0000000..4dddb85 Binary files /dev/null and b/docs/screenshots/readme/sources-light.png differ diff --git a/scripts/configure_public_url.py b/scripts/configure_public_url.py index 31b7441..b221826 100644 --- a/scripts/configure_public_url.py +++ b/scripts/configure_public_url.py @@ -16,11 +16,17 @@ def normalize_public_url(value: str) -> tuple[str, str]: raw = value.strip().rstrip("/") parsed = urlparse(raw) if parsed.scheme not in {"http", "https"} or not parsed.hostname: - raise ConfigurationError("Gebruik een volledige http(s)-URL, bijvoorbeeld https://jobs.example.be") + raise ConfigurationError( + "Gebruik een volledige http(s)-URL, bijvoorbeeld https://jobs.example.be" + ) if parsed.username or parsed.password or parsed.query or parsed.fragment: - raise ConfigurationError("De publieke URL mag geen credentials, query of fragment bevatten.") + raise ConfigurationError( + "De publieke URL mag geen credentials, query of fragment bevatten." + ) if parsed.path not in {"", "/"}: - raise ConfigurationError("De applicatie moet op de root van het domein gepubliceerd worden.") + raise ConfigurationError( + "De applicatie moet op de root van het domein gepubliceerd worden." + ) try: port = parsed.port except ValueError as exc: diff --git a/tests/unit/test_public_configuration.py b/tests/unit/test_public_configuration.py index 2ae6380..6475fca 100644 --- a/tests/unit/test_public_configuration.py +++ b/tests/unit/test_public_configuration.py @@ -43,6 +43,7 @@ def test_public_url_rejects_unsafe_or_unsupported_values(raw): with pytest.raises((ImproperlyConfigured, ConfigurationError)): normalize_public_base_url(raw) + def test_configure_public_url_updates_only_public_security_settings(tmp_path: Path): env_file = tmp_path / ".env" env_file.write_text( @@ -66,20 +67,22 @@ def test_configure_public_url_updates_only_public_security_settings(tmp_path: Pa assert "DJANGO_DEBUG=0" in content assert "vacatureradar.itworx.tech" in content assert ( - "DJANGO_CSRF_TRUSTED_ORIGINS=" - "http://192.168.10.150:1226,https://vacatureradar.itworx.tech" + "DJANGO_CSRF_TRUSTED_ORIGINS=http://192.168.10.150:1226,https://vacatureradar.itworx.tech" ) in content assert "CACHE_URL=redis://127.0.0.1:6379/1" in content assert "TRUSTED_PROXY_CIDRS=172.18.0.0/16" in content assert "DJANGO_SECRET_KEY=keep-this-secret" in content assert "POSTGRES_PASSWORD=keep-this-password" in content - assert env_file.stat().st_mode & 0o777 == 0o600 + if os.name != "nt": + assert env_file.stat().st_mode & 0o777 == 0o600 assert "DJANGO_SECRET_KEY" not in changed + def test_configure_public_url_rejects_plain_http(tmp_path: Path): with pytest.raises(ConfigurationError, match="HTTPS"): configure_env(tmp_path / ".env", "http://vacatureradar.example.be") + def test_public_base_url_populates_django_host_and_csrf_settings(): environment = os.environ.copy() environment.update( @@ -91,7 +94,7 @@ def test_public_base_url_populates_django_host_and_csrf_settings(): "SECURE_HSTS_SECONDS": "300", } ) - result = subprocess.run( + result = subprocess.run( # noqa: S603 - fixed interpreter and static assertion program [ sys.executable, "-c", @@ -111,9 +114,10 @@ def test_public_base_url_populates_django_host_and_csrf_settings(): capture_output=True, text=True, check=False, - ) # noqa: S603 - fixed interpreter and static assertion program + ) assert result.returncode == 0, result.stderr + def test_configure_public_url_is_idempotent(tmp_path: Path): env_file = tmp_path / ".env" env_file.write_text("DJANGO_ALLOWED_HOSTS=localhost\n", encoding="utf-8")