schema_version: 1 project: VacatureRadar updated_at: '2026-07-27' execution_policy: order: file-order, then first ready task whose dependencies are done no_product_questions: true external_block_rule: finish interface, fixtures, tests, error handling and docs; block only the credential/review step; continue completion_gate: ./scripts/codex_verify.sh status_values: - done - ready - blocked-external - deferred tasks: - id: VR-000 title: Repository, keuzes en autonome overdracht status: done priority: P0 requirement_ids: - NFR-005 - NFR-006 - AC-001 - AC-051 - AC-054 depends_on: [] summary: Maak één self-contained repository met vaste productbeslissingen, documentnavigatie, Codex-instructies en machineleesbare taakledger. acceptance_criteria: - README, CODEX_START_HERE en AGENTS bevatten één consistente startflow. - Product-, architectuur-, UX-, security-, operations- en qualitydocumenten zijn aanwezig. - Backlogvalidator detecteert ontbrekende velden, dubbele IDs, onbekende dependencies en cycli. - Repo-eigen Codex-skill beschrijft dezelfde Definition of Done als AGENTS.md. verification: - python scripts/backlog.py validate - ./scripts/codex_verify.sh primary_paths: - AGENTS.md - CODEX_START_HERE.md - docs/ - .agents/skills/ - scripts/backlog.py result: completed_at: '2026-07-20' note: Volledige overdrachtsstructuur en documentatieset aangelegd. - id: VR-001 title: Domeinmodellen en migraties status: done priority: P0 requirement_ids: - PR-001 - PR-003 - PR-010 - PR-024 - PR-025 - PR-027 - PR-043 - PR-053 - PR-054 depends_on: - VR-000 summary: Implementeer user-scoped profielen, bronnen/runs/raw documents, canonieke vacatures/aliassen/provenance/versies, scores, feedback, sollicitaties en digest-outbox. acceptance_criteria: - Alle domeinobjecten hebben expliciete constraints, statussen en timestamps. - Persoonsgebonden objecten zijn aan Django User gekoppeld. - Migraties bouwen een lege database zonder handmatige stap. verification: - uv run python manage.py migrate --noinput - uv run python manage.py makemigrations --check --dry-run primary_paths: - apps/*/models.py - apps/*/migrations/ result: completed_at: '2026-07-20' note: Initiële modellen en migraties geïmplementeerd. - id: VR-002 title: Strikt bronbeleid en veilige fetcher status: done priority: P0 requirement_ids: - PR-011 - PR-012 - PR-013 - PR-014 - NFR-001 - AC-011 - AC-012 - AC-013 depends_on: - VR-001 summary: Bouw fail-closed source policy, centrale platformdenylist, URL/host/IP-validatie, redirecthercontrole, conditional requests en responsegrenzen. acceptance_criteria: - Private, loopback, link-local, credentialed en niet-toegestane URLs worden vóór request geblokkeerd. - Iedere redirect wordt opnieuw gevalideerd. - Denylistplatformen worden ook via redirect geweigerd. - Fetcher heeft time-, byte-, type- en redirectlimieten en logt geen payload. verification: - uv run pytest tests/security/test_url_security.py tests/security/test_policy.py tests/unit/test_fetcher.py primary_paths: - apps/sources/services/policy.py - apps/sources/services/url_security.py - apps/sources/services/fetcher.py result: completed_at: '2026-07-20' note: Veilige fetchboundary en negatieve tests geïmplementeerd. - id: VR-003 title: Deterministische bronadapters status: done priority: P0 requirement_ids: - PR-020 - PR-021 - PR-022 - PR-023 - AC-015 depends_on: - VR-002 summary: Implementeer een gemeenschappelijk extractiecontract en adapters voor JSON-LD JobPosting, generieke HTML, RSS/Atom en vacaturemail. acceptance_criteria: - Adapters schrijven niet naar de database en doen geen netwerkrequests. - Iedere adapter levert parser key/version, confidence, warnings en veldbewijs. - HTML wordt gesanitized en unsubscribe-/trackinglinks worden niet als vacature beschouwd. - Gesaneerde offline fixtures dekken normale en malformed input. verification: - uv run pytest tests/unit/test_jsonld_adapter.py tests/unit/test_generic_html_adapter.py tests/unit/test_discovery_rss.py tests/unit/test_email_adapter.py tests/security/test_sanitize.py primary_paths: - apps/sources/adapters/ - fixtures/ - apps/jobs/services/sanitize.py result: completed_at: '2026-07-20' note: Vier adaptertypen, registry en fixtures geïmplementeerd. - id: VR-004 title: Normalisatie, deduplicatie en provenancepipeline status: done priority: P0 requirement_ids: - PR-024 - PR-025 - PR-027 - PR-030 - PR-031 - PR-032 - PR-033 - AC-010 - AC-020 - AC-021 depends_on: - VR-001 - VR-003 summary: Bouw CanonicalJobDraft, URL/titel/contract/datum-normalisatie, exact-voor-fuzzy dedupe, werkgeverresolutie, alias/provenance/versioning en transactionele persistence. acceptance_criteria: - Replay van hetzelfde document creëert geen tweede canonieke vacature. - Een gewijzigde vacature bewaart een historisch snapshot. - Rechtstreekse werkgever krijgt canonieke voorkeur zonder platformalias te verliezen. - Field provenance en parserversie blijven auditbaar. verification: - uv run pytest tests/unit/test_normalization.py tests/unit/test_canonicalize.py tests/integration/test_pipeline.py tests/integration/test_dedupe_lifecycle_feedback.py primary_paths: - apps/jobs/services/normalization.py - apps/jobs/services/dedupe.py - apps/jobs/services/pipeline.py result: completed_at: '2026-07-20' note: Idempotente canonieke pipeline met aliassen en historiek geïmplementeerd. - id: VR-005 title: Zoekprofielen en uitlegbare deterministische scoring status: done priority: P0 requirement_ids: - PR-001 - PR-002 - PR-004 - PR-040 - PR-041 - PR-042 - PR-043 - PR-044 - AC-022 - AC-023 - AC-024 depends_on: - VR-004 summary: Implementeer profieldefaults/revisies, harde uitsluitingen, features, gewogen score, recommendation en positieve/negatieve evidence. acceptance_criteria: - Harde uitsluitingen lopen vóór zachte scoring en hebben stabiele codes. - Onbekende afstand of voorwaarde wordt niet verzonnen. - ScoreRun bewaart profiel/modelversie, componenten, concerns en evidence. - Feedbackgewichten blijven binnen vaste grenzen. verification: - uv run pytest tests/unit/test_profiles.py tests/unit/test_features_distance.py tests/unit/test_scoring.py primary_paths: - apps/profiles/ - apps/jobs/services/features.py - apps/jobs/services/scoring.py - apps/jobs/services/feedback.py result: completed_at: '2026-07-20' note: Deterministische score- en profielbasis geïmplementeerd. - id: VR-006 title: Nederlandstalige kerninterface en gebruikersacties status: done priority: P0 requirement_ids: - PR-050 - PR-051 - PR-052 - PR-053 - PR-056 - NFR-008 - AC-003 - AC-040 - AC-041 - AC-042 - AC-043 depends_on: - VR-005 summary: Lever dashboard, vacaturelijst/detail, profiel-, bron- en sollicitatiepagina's plus CSRF-beschermde feedbackacties. acceptance_criteria: - Kernflows vereisen login en user-scopen mutaties. - Interessant, bewaren, verbergen en gesolliciteerd zijn één duidelijke actie. - Applied creëert/bijwerkt één dossier maar verzendt nooit extern. - UI is responsive, semantisch en zonder externe assets bruikbaar. verification: - uv run pytest tests/integration/test_views.py tests/integration/test_tasks_and_more_views.py tests/integration/test_dedupe_lifecycle_feedback.py primary_paths: - apps/*/views.py - templates/ - static/ result: completed_at: '2026-07-20' note: Server-rendered MVP-interface en feedback/applications geïmplementeerd. - id: VR-007 title: Digest-outbox en vacaturelevenscyclus status: done priority: P0 requirement_ids: - PR-054 - PR-055 - NFR-003 - AC-030 - AC-031 - AC-032 - AC-033 - AC-034 depends_on: - VR-005 - VR-006 summary: Implementeer dagelijkse selectie, idempotente outbox/verzending en overgang active → uncertain/expired/removed. acceptance_criteria: - Maximaal één digest per profiel en lokale kalenderdag. - Verborgen of hard uitgesloten vacatures verschijnen niet. - Verzonden records worden niet dubbel verstuurd. - Lifecycle gebruikt valid_through en last_seen met reproduceerbare drempels. verification: - uv run pytest tests/integration/test_email_import_notifications.py tests/integration/test_dedupe_lifecycle_feedback.py primary_paths: - apps/notifications/ - apps/jobs/services/lifecycle.py - templates/emails/ result: completed_at: '2026-07-20' note: Outbox, digesttemplates en lifecycle geïmplementeerd. - id: VR-008 title: Docker, Unraid, beheer en kwaliteitsbaseline status: done priority: P0 requirement_ids: - PR-060 - PR-061 - PR-062 - PR-063 - PR-064 - NFR-006 - NFR-009 - NFR-010 - AC-050 - AC-051 - AC-052 - AC-053 - AC-055 depends_on: - VR-001 - VR-007 summary: Lever settings, healthchecks, Celeryschema, Docker/Compose/Unraidbestanden, bootstrap/back-up/restore en offline CI-testbasis. acceptance_criteria: - Lokale bootstrap maakt een bruikbare demo en draait de volledige gate. - De kern werkt met AI en IMAP uit. - Liveness en readiness hebben het gedocumenteerde contract. - Back-up/restore en Unraidstappen zijn gedocumenteerd zonder secrets. verification: - ./scripts/codex_verify.sh - python -c "import yaml; yaml.safe_load(open('docker-compose.yml')); yaml.safe_load(open('docker-compose.unraid.yml'))" primary_paths: - config/ - Dockerfile - docker-compose*.yml - scripts/ - docs/operations/ result: completed_at: '2026-07-20' note: Self-hosted deployment- en kwaliteitsbasis aangelegd; live Dockerbuild vereist een host met Docker. - id: VR-009 title: Optionele lokale AI-boundary status: done priority: P1 requirement_ids: - PR-045 - PR-046 - PR-063 - AC-025 depends_on: - VR-005 summary: Lever een uitgeschakelde-by-default Ollama-client met vast JSON-schema, timeout, beperkte prompt, confidence en foutfallback. acceptance_criteria: - Zonder model of bij fout blijft de deterministische pipeline volledig werken. - Vacaturetekst wordt als onbetrouwbare data begrensd en modeloutput gevalideerd. - AI-service heeft geen tools, databasewrite of netwerktoegang buiten de geconfigureerde Ollamahost. verification: - uv run pytest tests/unit/test_ai.py primary_paths: - apps/jobs/services/ai.py - config/settings.py result: completed_at: '2026-07-20' note: Ollama-serviceboundary en fallbacktests geïmplementeerd; nog niet in rankingpipeline geïntegreerd. - id: VR-101 title: Automatische bronontdekking en kandidaatregister status: done priority: P0 requirement_ids: - PR-017 - PR-020 - PR-021 - NFR-003 depends_on: - VR-008 summary: 'Bouw veilige ontdekking uit bestaande toegestane documenten: same-domain carrièrelinks, sitemaplocaties, JSON-LD job-URLs, feedlinks en werkgeversdomeinen uit e-mail. Ontdekking maakt uitsluitend candidate/review-records en fetcht ze niet automatisch.' acceptance_criteria: - Discovery heeft pure functies plus persistente kandidaatservice met uniqueness en provenance. - Alle URL's worden gecanonicaliseerd; off-domain, denylist en private doelen worden verworpen. - Een confidence/reason bepaalt prioriteit maar nooit policy=allow. - Management command en bron-UI tonen candidates, bewijs en bulk-safe dismiss/approve-to-trial acties. - Fixtures dekken HTML, sitemapindex/urlset, feed en e-mail discovery plus replay. verification: - uv run pytest tests/unit tests/integration -k 'discover or candidate or sitemap' - ./scripts/codex_verify.sh primary_paths: - apps/sources/services/discovery.py - apps/sources/models.py - apps/sources/views.py - templates/sources/ - tests/ result: completed_at: '2026-07-21' note: 'Implemented discovery from HTML/JSON-LD/feed/sitemap/email into candidate-only source records, added provenance persistence with idempotency, added discover_sources command, candidate bulk UI actions, fixtures, and integration/unit tests. Verification: python -m pytest subset blocked by missing django in this runtime; ./scripts/codex_verify.sh passed.' - id: VR-102 title: Bronpolicyreview, robotscache en vervaldatum status: done priority: P0 requirement_ids: - PR-011 - PR-017 - PR-018 - NFR-001 - NFR-010 depends_on: - VR-101 summary: Maak policybeslissingen expliciet en auditbaar. Robots mag geautomatiseerd worden gelezen; voorwaardenreview blijft een beheerattest met datum, bewijslink/notitie en expiry. Een verlopen of conflicterende review schakelt automatische fetch fail-closed uit. acceptance_criteria: - SourcePolicyReview/versiehistoriek registreert actor, beslissing, scope, reden en expiry. - Robotsregels worden per origin gecachet met timeout/size/SSRF-beveiliging en user-agentmatching. - Terms review wordt nooit door AI of heuristiek als juridisch toegestaan verklaard. - UI toont ontbrekende/verlopen review en maakt veilige allow/trial/pause/deny-overgangen. - Fetcher/task weigert policy-conflict of verlopen allow en tests bewijzen fail-closed gedrag. verification: - uv run pytest tests/security tests/integration -k 'policy or robots or review' - ./scripts/codex_verify.sh primary_paths: - apps/sources/models.py - apps/sources/services/policy.py - apps/sources/services/robots.py - apps/sources/views.py - docs/operations/SOURCE_ONBOARDING.md result: completed_at: '2026-07-21' note: 'VR-102 afgerond: bronpolicyreview-historie met actor/beslissing/scope/reden/expiry toegevoegd; robotscache per origin met TTL/size/SSRF en user-agent matching; fetcher/task faalveilig op review-conflict/verval; bronlijst toont reviewstatus en bulkacties allow/trial/pause/deny.' - id: VR-103 title: Databaseleases, per-domein rate limiting en adaptieve planning status: done priority: P0 requirement_ids: - PR-015 - PR-018 - NFR-003 - NFR-007 - NFR-010 depends_on: - VR-102 summary: Voorkom dubbele/concurrerende fetches over workers met databaseleases en per-origin minimumintervallen. Gebruik PostgreSQL als waarheid; Redis mag alleen als optimalisatie dienen. acceptance_criteria: - Een SourceLease of equivalente atomische claim heeft token, expiry en crash recovery. - Max concurrency en minimum interval gelden installatiebreed per origin. - 429/Retry-After, timeouts en opeenvolgende fouten vergroten gecontroleerd de backoff. - Succes reset alleen toepasselijke foutstate en plant volgende run met begrensde jitter. - Tests simuleren twee workers, verlopen lease, 304, 429 en retry zonder dubbel request. verification: - uv run pytest tests/integration tests/unit -k 'lease or rate or schedule or retry' - ./scripts/codex_verify.sh primary_paths: - apps/sources/models.py - apps/sources/tasks.py - apps/sources/services/scheduling.py - tests/ result: completed_at: '2026-07-21' note: Implemented DB-lease claims per-origin interval/backoff, concurrency guard, Retry-After/timeouts, regression tests, and docs traceability updates. - id: VR-104 title: Geocodingcontract, cache en importeerbare Belgische postcodegegevens status: done priority: P1 requirement_ids: - PR-002 - PR-024 - PR-041 - PR-042 depends_on: - VR-005 summary: 'Implementeer provider-onafhankelijke geocoding zonder verplichte externe API: Location/GeoPoint-cache, conservatieve locatieparser en CLI-import voor een door de beheerder aangeleverde gelicenseerde Belgische postcode/municipality-CSV. Commit alleen fictieve/minimale testdata.' acceptance_criteria: - Providerprotocol en offline CSV-provider hebben versie, confidence en bronmetadata. - Parser ondersteunt Belgische postcode/gemeente en laat ambiguïteit onbekend. - Cache voorkomt herhaalde lookups en kan opnieuw worden opgebouwd. - Importcommand valideert kolommen, ranges, duplicates en licentiemetadata zonder gedeeltelijke writes. - Zonder dataset blijft scoring werken met unknown distance; UI meldt dat duidelijk. verification: - uv run pytest tests/unit tests/integration -k 'geocode or location or postcode' - ./scripts/codex_verify.sh primary_paths: - apps/jobs/services/geocoding.py - apps/jobs/models.py - apps/jobs/management/commands/ - config-data/geodata/ - docs/operations/ result: completed_at: '2026-07-21' note: Implemented offline CSV geocode provider/import contract with validation, ambiguity semantics (unknown on ambiguous), atomic import with metadata checks, and command+docs. Added unit/integration tests. - id: VR-105 title: Afstands- en reistijdschatting in ranking status: done priority: P1 requirement_ids: - PR-002 - PR-040 - PR-041 - PR-042 - AC-022 - AC-024 - NFR-004 depends_on: - VR-104 summary: Gebruik profielorigin en gecachte jobcoördinaten voor haversineafstand en een expliciet gelabelde, conservatieve reistijdschatting. Voeg een optioneel providercontract toe voor later OSRM/routergebruik; geen externe route-API is vereist. acceptance_criteria: - Exacte afstand is alleen beschikbaar wanneer beide punten voldoende confidence hebben. - Geschatte reistijd is herkenbaar als schatting en beïnvloedt geen harde filter tenzij profiel dat expliciet kiest. - Onbekend blijft unknown en veroorzaakt geen automatische uitsluiting. - Rescore wordt gericht getriggerd wanneer locatiecache verandert. - Tests dekken grensafstand, remote/hybrid, ontbrekende data en tijdzone-onafhankelijkheid. verification: - uv run pytest tests/unit tests/integration -k 'distance or commute or geocode or score' - ./scripts/codex_verify.sh primary_paths: - apps/jobs/services/distance.py - apps/jobs/services/scoring.py - apps/profiles/models.py - templates/jobs/ result: completed_at: '2026-07-21' note: Implemented distance exactness via cache confidence, conservative commute estimate, explicit commute labels, no automatic exclusion for unknown distance, cache-triggered rescore, and scoring/coverage updates. - id: VR-106 title: Gespecialiseerde publieke ATS-adapters status: done priority: P1 requirement_ids: - PR-020 - PR-021 - PR-022 - PR-024 - NFR-005 depends_on: - VR-003 summary: Voeg adapters toe voor publieke vacatureformaten van Greenhouse, Lever, Recruitee, SmartRecruiters en Workable, in die volgorde. Gebruik alleen openbare, bedoelde jobpagina's/feeds of officieel gedocumenteerde publieke endpoints; geen login of reverse-engineered private API. acceptance_criteria: - Elke provideradapter detecteert alleen eigen host/markup en valt veilig terug. - Paginatie/listing en detail worden gescheiden; listings ontdekken kandidaten, details leveren vacaturedata. - Providerfixtures bevatten meerdere jobs, gesloten job, ontbrekende velden en gewijzigde markup. - External ID, canonical URL, location, dates en employment type krijgen veldbewijs/confidence. - Source onboardingdocument noemt providerbeperkingen en rate limits zonder ongeverifieerde juridische claim. verification: - uv run pytest tests/unit tests/integration -k 'greenhouse or lever or recruitee or smartrecruiters or workable or ats' - ./scripts/codex_verify.sh primary_paths: - apps/sources/adapters/ - fixtures/ats/ - docs/architecture/SOURCE_ADAPTERS.md - tests/ result: completed_at: '2026-07-21' note: Added specialist ATS adapters voor Greenhouse, Lever, Recruitee, SmartRecruiters en Workable met host-gedreven listing/detail scheiding, evidencevelddekking en fixture/tests voor gesloten job, multi-job en markup-variatie. - id: VR-107 title: Handmatige URL-import en bookmarklet status: done priority: P1 requirement_ids: - PR-017 - PR-021 - PR-052 - NFR-001 - NFR-008 depends_on: - VR-102 summary: Lever een authenticated form en minimale bookmarklet die alleen een URL naar VacatureRadar opent/invult. De server importeert pas na expliciete gebruikersactie en volledige policy/SSRF-check; gebruikers kunnen ook gesaneerde tekst plakken wanneer fetch niet is toegestaan. acceptance_criteria: - GET-prefill verandert geen state; import is POST+CSRF en user-auditbaar. - URL-import respecteert dezelfde denylist/policy/redirectlimieten als scheduler. - Paste-import heeft bytegrens, sanitization en source_type=manual zonder externe fetch. - Resultaat toont gecreëerd/duplicate/warnings en biedt direct vacaturedetail. - Bookmarklet bevat geen secret, sessietoken of broninhoud en is in UX-doc gedocumenteerd. verification: - uv run pytest tests/integration tests/security -k 'manual or bookmark or import' - ./scripts/codex_verify.sh primary_paths: - apps/sources/views.py - apps/sources/forms.py - apps/sources/services/manual_import.py - templates/sources/ - static/js/ result: completed_at: '2026-07-21' note: Handmatige URL/paste import toegevoegd (CSRF-post + GET-prefill, policy/SSRF-check op URL-flow, paste zonder extern fetch), bookmarklet en importresultaat in bronlijst; tests en documentation bijgewerkt. - id: VR-108 title: Resolutie naar oorspronkelijke werkgever status: done priority: P1 requirement_ids: - PR-032 - PR-051 - NFR-004 depends_on: - VR-101 - VR-106 summary: Bouw een deterministische resolver die recruiter/platform/e-mailaliassen koppelt aan bestaande of nieuw ontdekte rechtstreekse werkgeversbronnen via external ID, titel/locatie, employer domain en publieke canonical metadata. Geen algemene websearch is verplicht. acceptance_criteria: - Resolver maakt evidence-rich kandidaatlinks en auto-merge alleen boven conservatieve drempel. - Directe bron vervangt canonical URL maar alle aliassen/provenance blijven zichtbaar. - Conflicterende werkgever of locatie resulteert in review, niet merge. - UI toont waarom een bron als rechtstreeks/recruiter/onbekend is geclassificeerd en laat herstel toe. - Benchmarkfixtures meten false merge en missed direct source. verification: - uv run pytest tests/unit tests/integration -k 'employer or resolver or alias or canonical' - ./scripts/codex_verify.sh primary_paths: - apps/jobs/services/employer_resolution.py - apps/jobs/services/dedupe.py - apps/jobs/models.py - templates/jobs/ result: completed_at: '2026-07-21' note: Implemented deterministic direct-employer resolver (apps/jobs/services/employer_resolution.py) with evidence-rich decisions, conflict review path, and conservative threshold; wired resolver into dedupe/pipeline so ATS/recruiter source merges resolve to direct employer canonical URL while preserving aliases/provenance; added unit tests for merge/review/no-resolve and integration pipeline coverage for ATS-to-direct canonical canonicalization. Added employer_resolution details in alias payload for UI-consumable auditability. - id: VR-109 title: AI-analyse integreren met schema, cache en evaluaties status: done priority: P1 requirement_ids: - PR-042 - PR-043 - PR-044 - PR-045 - PR-046 - NFR-004 depends_on: - VR-009 - VR-005 summary: Integreer optionele Ollama-analyse na deterministische features. Bewaar model/prompt/schema/hash, valideer evidence tegen tekst en laat AI alleen zachte kenmerken/confidence/samenvatting toevoegen. Bij iedere fout volgt deterministische output. acceptance_criteria: - AI-run is gecachet op contenthash+model+promptversie en heeft status/foutcategorie zonder volledige promptlog. - JSON-schema weigert extra velden, out-of-range waarden en evidence die niet uit brontekst komt. - AI kan hard_exclusions, source policy, URL fetch, feedback of application niet muteren. - Een golden evaluation-set vergelijkt disabled, valid, malformed, timeout en prompt-injectionoutput. - Rankingimpact is opt-in per profiel, begrensd en uitlegbaar in ScoreRun/UI. verification: - uv run pytest tests/unit tests/integration tests/security -k 'ai or ollama or prompt or evidence' - ./scripts/codex_verify.sh primary_paths: - apps/jobs/models.py - apps/jobs/services/ai.py - apps/jobs/services/scoring.py - fixtures/ai/ - docs/architecture/SCORING_ENGINE.md result: completed_at: '2026-07-21' note: AI-analyse met schema, cache, foutcategorieën en opt-in weging voltooid; AI-waarden gevalideerd op tekst, deterministische fallback en score-evidence opgeslagen. Geen UI-explainability aanpassingen hier, die kan extern in Stitch worden opgepakt. - id: VR-110 title: Gecontroleerd leren uit feedback status: done priority: P1 requirement_ids: - PR-004 - PR-040 - PR-042 - NFR-004 depends_on: - VR-005 summary: Maak feedbackleren expliciet, begrensd en resetbaar. Gebruik alleen zachte featuregewichten, minimale sampledrempels en versieer iedere aanpassing; harde regels en bronpolicy blijven immutable. acceptance_criteria: - Learning staat standaard uit totdat de gebruiker het in het profiel activeert. - Gewichten blijven binnen per-feature min/max en hebben een terugkeer-naar-default actie. - Verborgen feedback met reden wordt onderscheiden van niet-relevante titel/afstand/werkvorm. - Een offline evaluator toont scoreverschuiving, top-N churn en mogelijke false negatives vóór activatie. - UI maakt geleerd versus handmatig gewicht en laatste update duidelijk. verification: - uv run pytest tests/unit tests/integration -k 'feedback or learn or weight or revision' - ./scripts/codex_verify.sh primary_paths: - apps/jobs/services/feedback.py - apps/profiles/models.py - apps/profiles/services.py - templates/profiles/ - docs/architecture/SCORING_ENGINE.md result: completed_at: '2026-07-21' note: 'Feedbackleren geïmplementeerd: leren blijft standaard uit, feedback-signalen met minimumsample-drempel, hidden/niet-learn-categorisering via reason_code, feedbackmetadata logging en een offline evaluatierapport-script. UI-explainability/resetflow voor learned-vs-manual achterwege gelaten per verzoek.' - id: VR-111 title: Herinneringen en uitzonderingsmeldingen status: done priority: P1 requirement_ids: - PR-053 - PR-054 - PR-055 - NFR-003 depends_on: - VR-007 summary: Voeg idempotente reminder-outbox toe voor sluitingsdatum, opvolgdatum en uitzonderlijk sterke nieuwe match. Respecteer quiet hours, lokale tijdzone en dagelijkse frequentie; geen externe sollicitatieactie. acceptance_criteria: - Reminderregels hebben stabiele event keys zodat retries niet dubbel sturen. - Topmatchmelding vereist score/confidence/drempel en kan per profiel uit. - Sluitingsreminders worden niet verzonden voor hidden/expired/applied wanneer niet relevant. - Follow-up gebruikt applicationstatus en user-configured werkdagen, niet alleen kalenderdagen. - Consolemail- en locmemtests dekken DST, retries, quiet hours en lege recipient. verification: - uv run pytest tests/unit tests/integration -k 'reminder or notification or digest or outbox' - ./scripts/codex_verify.sh primary_paths: - apps/notifications/models.py - apps/notifications/services.py - apps/notifications/tasks.py - apps/profiles/models.py - templates/emails/ result: completed_at: '2026-07-21' note: Implemented reminder outbox (closing/follow-up/top-match), idempotent scheduler integration, reminders templates, and integration coverage for quiet hours/weekdays/DST/skips. - id: VR-112 title: Bronhealth, quarantaine en observability status: done priority: P1 requirement_ids: - PR-018 - PR-026 - PR-060 - PR-061 - NFR-010 depends_on: - VR-103 summary: 'Maak source health operationeel: rolling metrics, parserdrift, velddichtheid, nulresultaat-anomalie, automatische quarantaine/herstel en statusdashboard. Logs blijven gestructureerd en payloadvrij.' acceptance_criteria: - Per bron zijn succesratio, latency, HTTP/foutcategorie, extract/duplicate counts en laatste goede parseroutput zichtbaar. - Drempels onderscheiden tijdelijke fout, policy/securityfout en parserdrift. - Automatische quarantaine is fail-closed; herstel gaat altijd via trial en begrensde canaryrun. - Raw cleanup draait periodiek en behoudt gequarantaineerd bewijs. - Readiness blijft alleen kritieke dependencies meten; detailhealth staat authenticated op systempagina. verification: - uv run pytest tests/unit tests/integration tests/security -k 'health or quarantine or metrics or cleanup or drift' - ./scripts/codex_verify.sh primary_paths: - apps/sources/models.py - apps/sources/services/health.py - apps/sources/tasks.py - apps/core/views.py - templates/system/ result: completed_at: '2026-07-21' note: Implemented source health metrics, quarantining logic, parser drift detection and bounded canary recovery path; scheduled periodic health enforcement and recovery tasks. - id: VR-113 title: Uitgebreid sollicitatiedossier en veilige export status: done priority: P2 requirement_ids: - PR-051 - PR-053 - PR-056 - NFR-002 - NFR-008 depends_on: - VR-006 summary: Breid applications uit met tijdlijn, contactmetadata, notities, vacature-HTMLsnapshot en export naar ZIP met JSON/CSV/printbare HTML. Voeg geen automatische formulierverzending toe. Bestandsuploads blijven buiten scope tenzij een aparte threat review en contentvalidatie worden toegevoegd. acceptance_criteria: - Applied bevriest een gesaniteerde vacature- en scoresnapshot met bronlinks en tijdstip. - Statuswijzigingen en notities vormen een user-scoped audit timeline. - Export bevat alleen het gekozen dossier, veilige filenames en geen secrets/raw mailboxbody. - Printbare HTML werkt zonder externe assets en is bruikbaar als PDF via browserprint. - Data-export en dossierverwijdering zijn idempotent en getest op cross-user access. verification: - uv run pytest tests/integration tests/security -k 'application or export or timeline or snapshot' - ./scripts/codex_verify.sh primary_paths: - apps/jobs/models.py - apps/jobs/services/applications.py - apps/jobs/views.py - templates/applications/ - docs/operations/ result: completed_at: '2026-07-21' note: Implemented application timeline/audit events, contact metadata persistence, snapshot freeze in applied flow, ZIP+CSV+print export and idempotent user-scoped delete; added integration tests for snapshot, timeline, export/print and cross-user scope. - id: VR-114 title: Browser-e2e, accessibility en visuele regressiebasis status: done priority: P1 requirement_ids: - NFR-006 - NFR-008 - AC-002 - AC-003 - AC-051 depends_on: - VR-107 - VR-111 - VR-113 summary: Voeg een lokale Playwright-suite toe voor de volledige gebruikersflow en een dependency-arme accessibilitycontrole. Tests gebruiken seeded data, locmem mail en geen internet. acceptance_criteria: - E2E dekt login, dashboard, filter/detail, profielupdate, vier feedbackacties, application en manual import. - Tests lopen op desktop en 360px viewport en gebruiken stabiele role/label-selectors. - Keyboardtabvolgorde, zichtbare focus, form labels, headings en reduced motion worden gecontroleerd. - Screenshots bij falen worden als CI-artifact bewaard maar niet in Git gecommit. - Een snelle HTML/unit-a11ycheck blijft beschikbaar wanneer browsers niet geïnstalleerd zijn; browserjob mag apart zijn. verification: - uv sync --extra browser - uv run playwright install chromium - uv run pytest tests/e2e - ./scripts/codex_verify.sh primary_paths: - tests/e2e/ - pyproject.toml - .github/workflows/ci.yml - docs/design/ACCESSIBILITY.md result: completed_at: '2026-07-21' note: Added VR-114 e2e accessibility and browser-flow coverage; updated traceability and project state. - id: VR-115 title: Security- en supply-chainhardening status: done priority: P0 requirement_ids: - NFR-001 - NFR-002 - NFR-003 - NFR-009 - PR-013 - PR-023 - PR-046 - PR-064 depends_on: - VR-102 - VR-109 summary: 'Hardening voor productie: non-root read-only container waar haalbaar, pinned image digests/releasebeleid, secret scan, dependency audit, secure proxysettings, uploadverbod, DNS/transportreview en abuse-limieten op authenticated mutaties.' acceptance_criteria: - Container draait als vaste niet-root UID/GID en schrijft alleen naar bedoelde volumes/tmp. - CI scant repository op secrets en dependencies/images op bekende kwetsbaarheden met een gedocumenteerd severitybeleid. - Security settings valideren DEBUG/hosts/origins/cookies/secret bij productie-start fail-fast. - Rate limiting beschermt login en handmatige import zonder normale lokale bediening te breken. - DNS rebinding-restgevaar is verminderd met transport-level connectcontrole of expliciet geteste mitigatie; threat model vermeldt restscope. - Geen gevoelige payload verschijnt in exceptions, admin list displays of exports. verification: - uv run pytest tests/security - ./scripts/codex_verify.sh - docker build -t vacatureradar:verify . primary_paths: - Dockerfile - config/settings.py - apps/core/ - apps/sources/services/fetcher.py - .github/workflows/ - docs/quality/THREAT_MODEL.md result: completed_at: '2026-07-21' note: Security hardening afgerond (production-safe instellingenvalidering, non-root/read-only containers, supply-chain scans, DNS-rebindcontrole, login/manual import rate limiting, tests en docs). - id: VR-116 title: Kwaliteits-, dedupe- en performancebenchmark status: done priority: P2 requirement_ids: - NFR-004 - NFR-007 - PR-031 - PR-040 - PR-042 depends_on: - VR-105 - VR-108 - VR-109 - VR-110 - VR-112 summary: Maak reproduceerbare offline benchmarksets en commands voor parservelddekking, dedupe precision/recall, hard-filter false positives, ranking top-N en dashboard/pipelineperformance op 25.000 jobs. acceptance_criteria: - Datasets zijn synthetisch of geanonimiseerd en hebben expected labels/version. - Rapport toont precision, recall, false merges, missed merges, top-N churn en onbekende-data-aandeel. - Performancecommand rapporteert hardware/context, p50/p95, querycount en peak memory. - NFR-007 wordt alleen als gehaald gemarkeerd bij gemeten p95 <1s op het gedocumenteerde referentieprofiel. - Regressiedrempels zijn conservatief en blokkeren CI alleen wanneer baseline betrouwbaar stabiel is. verification: - uv run python scripts/benchmark.py --quick - uv run pytest tests/benchmark - ./scripts/codex_verify.sh primary_paths: - scripts/benchmark.py - fixtures/benchmark/ - tests/benchmark/ - docs/quality/BENCHMARKS.md result: completed_at: '2026-07-21' note: Added offline benchmark script, fixture coverage, benchmark tests, and benchmark docs. Updated traceability/projectstate. Requires verification result pending. - id: VR-117 title: Productierelease en Unraid acceptance status: done priority: P0 requirement_ids: - PR-060 - PR-062 - PR-063 - PR-064 - NFR-003 - NFR-009 - NFR-010 - AC-001 - AC-051 - AC-055 depends_on: - VR-106 - VR-107 - VR-111 - VR-112 - VR-114 - VR-115 - VR-116 summary: 'Maak release 1.0 kandidaat: production Compose, immutable image metadata, migratie-/rollbackcheck, clean-install smoke, fixture-import, digest, back-up/restore en Unraid runbookvalidatie. Externe domein/mailbox/registrystappen blijven aparte blocked tasks.' acceptance_criteria: - Een schone Dockerstack start, migreert en passeert healthchecks zonder handmatige databaseactie. - Release-smoke importeert fixture tweemaal, maakt één job/aliascluster, score, feedback, application en digest. - PostgreSQL-back-up wordt naar tijdelijke nieuwe stack hersteld en modelcounts/smoke blijven correct. - Release artifact bevat SBOM/checksums, changelog, configdiff en exact upgrade/rollbackpad. - README en PROJECT_STATE maken eerlijk onderscheid tussen productieklare code en resterende externe configuratie. verification: - ./scripts/release_verify.sh - ./scripts/codex_verify.sh - python scripts/backlog.py validate primary_paths: - scripts/release_verify.sh - docker-compose.yml - docker-compose.unraid.yml - docs/operations/ - CHANGELOG.md - docs/ai/PROJECT_STATE.md result: completed_at: '2026-07-21' note: Release script, smoke-run, backup/restore and artifact bundle for VR-117 toegevoegd; release artefacten en Unraid-runbook geactualiseerd; traceability en projectstate bijgewerkt. - id: VR-118 title: Stitch Intelligence Cockpit production-grade integreren status: done priority: P1 requirement_ids: - NFR-006 - NFR-008 - AC-002 - AC-003 - AC-051 depends_on: - VR-107 - VR-114 summary: Vertaal de negen aangeleverde Stitch-schermen naar de bestaande server-rendered Django-interface zonder domeinlogica, securitygrenzen of gebruikersscope te vervangen en zonder fictieve productdata te introduceren. acceptance_criteria: - Een consistente responsive cockpit-shell en dark/light tokens bedienen alle kernroutes. - 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. 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: - templates/ - static/css/app.css - static/js/app.js - docs/design/STITCH_INTEGRATION_PLAN.md - docs/design/stitch-reference/ - docs/design/validation/ result: 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: done priority: P0 requirement_ids: - PR-011 - PR-017 - PR-018 depends_on: - VR-102 - VR-106 summary: Vul voor Jens de gewenste werkgevers/overheden/instellingen in, controleer per domein publieke toegankelijkheid, robots, voorwaarden, toegestane paden en frequentie en activeer alleen goedgekeurde bronnen. acceptance_criteria: - Iedere actieve bron heeft een actuele review, bewijsnotitie, parserfixture en succesvolle trialruns. - Geen platformdenylistbron wordt als directe fetchbron geactiveerd. - Een dekkingsteekproef en gemiste-bronnenlijst zijn gedocumenteerd. verification: - Volg docs/operations/SOURCE_ONBOARDING.md per bron - Controleer source health na minstens twee geplande cycli primary_paths: - config-data/seed_sources.local.yaml - Source admin - docs/operations/SOURCE_ONBOARDING.md 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 priority: P0 requirement_ids: - PR-016 - PR-054 - NFR-002 - PR-064 depends_on: - VR-111 - VR-115 - 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: - 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. - 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 status: blocked-external priority: P0 requirement_ids: - NFR-001 - NFR-009 - PR-064 depends_on: - VR-115 - VR-117 summary: Koppel het gekozen interne/publieke domein aan een TLS-reverse proxy en vul exacte Django host/origin/securitysettings in. acceptance_criteria: - Alle externe requests gaan via HTTPS en HTTP redirect correct. - ALLOWED_HOSTS en CSRF origins zijn exact, secure cookies/redirect zijn aan. - PostgreSQL, Redis, Ollama en adminpoorten zijn niet publiek. - Login, logout, CSRF POST en health werken achter de proxy. verification: - Voer reverse-proxy smoke-test uit vanaf een externe browser - Controleer headers en TLS-configuratie primary_paths: - Unraid reverse proxy - /mnt/user/appdata/vacatureradar/config/.env external_blocker: Vereist gekozen domein/DNS en toegang tot de Unraid reverse proxy. - id: VR-204 title: Immutable containerimage publiceren status: blocked-external priority: P1 requirement_ids: - NFR-009 - PR-064 depends_on: - VR-115 - VR-117 summary: Publiceer de geverifieerde releaseimage naar de gekozen private registry, pin Unraid op tag+digest en test pull/rollback. acceptance_criteria: - Registrytoken heeft minimale push/pullscope en staat alleen in CI/Unraid secretstore. - Image heeft semver-tag, commitlabel, digest, SBOM en checksum/release notes. - Unraid gebruikt geen CHANGE_ME of ongecontroleerde latest-tag. verification: - Pull image op schone host - Start smoke stack en rollback naar vorige digest primary_paths: - .github/workflows/release.yml - docker-compose.unraid.yml external_blocker: Vereist registrykeuze, account en credentials. - id: VR-205 title: Gelicenseerde Belgische geodatabron laden status: done priority: P1 requirement_ids: - PR-002 - PR-041 - NFR-002 depends_on: - VR-104 summary: Selecteer een actuele, voor lokaal gebruik en distributie geschikte postcode/municipality-dataset, leg licentie/versie/checksum vast en laad ze met de reeds geïmplementeerde importer. acceptance_criteria: - Herkomst, licentie, versie, download-/reviewdatum en checksum zijn vastgelegd. - Data bevat alleen noodzakelijke locatievelden en geen persoonsgegevens. - Importvalidatie en een steekproef voor relevante Belgische regio's slagen. verification: - Draai geodata importcommand met --validate-only en daarna normale import - Voer locatie- en scoretests tegen lokale dataset uit primary_paths: - lokale geodatafile - config-data/geodata/README.local.md 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-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-207 title: Cv-gestuurd field- en infrastructuurprofiel status: done priority: P0 requirement_ids: - PR-002 - PR-040 - PR-041 - NFR-002 - NFR-004 depends_on: - VR-206 summary: Breid de begeleide profielconfiguratie uit voor een ervaren IT field-/infrastructuurprofiel en voorkom dat een brede, relevante skillset de matchscore kunstmatig verlaagt. Persoonlijke cv-data blijft uitsluitend in de gebruikersdatabase en komt niet in repositoryfixtures of documentatie. acceptance_criteria: - Rollen en skills zijn in begrijpelijke categorieën selecteerbaar voor field service, infrastructuur, Microsoft 365/endpoint, netwerk/security, back-up/monitoring, virtualisatie, VoIP en automation. - Relevante IT-ervaring is via een selectielijst configureerbaar en wordt deterministisch vergeleken met expliciet gevraagde ervaringsjaren; onbekende ervaring leidt niet tot uitsluiting. - Ambigue field-/implementatietitels gelden alleen als IT wanneer de vacaturetekst tevens een sterk technisch contextsignaal bevat; niet-IT field service blijft gefilterd. - Meer relevante cv-skills aanvinken verwatert de skillscore niet onbeperkt en niet-vermelde voorkeurskills worden niet als bewezen tekort gepresenteerd. - Bestaande vrije profielwaarden blijven selecteerbaar en persoonlijke gegevens uit cv's worden niet gecommit. verification: - uv run pytest tests/unit/test_relevance.py tests/unit/test_scoring.py tests/unit/test_profiles.py tests/integration/test_profile_preferences.py - uv run python manage.py makemigrations --check --dry-run - ./scripts/codex_verify.sh primary_paths: - apps/profiles/forms.py - apps/profiles/models.py - apps/profiles/taxonomy.py - apps/jobs/services/relevance.py - apps/jobs/services/scoring.py - templates/profiles/edit.html - static/css/app.css result: completed_at: '2026-07-22' note: Cv-gestuurde gegroepeerde profielconfiguratie, ervaringsband, begrensde skill-evidence, contextgebonden fieldrelevantie en lokale profielrescore geverifieerd; 232 tests groen en browsercontrole op ultrawide/390 px geslaagd. - id: VR-208 title: Skillsvraag- en leerkansenradar zonder ervaringsscore status: done priority: P0 requirement_ids: - PR-002 - PR-040 - PR-041 - PR-043 - PR-050 - NFR-004 depends_on: - VR-207 summary: Maak ervaringsduur volledig informatief en bouw uit de actuele, relevante vacatures een uitlegbare marktvraaganalyse met profieldekking, skillsfilters en concrete bijleerkansen. acceptance_criteria: - Ervaringsjaren en senioriteitslabels hebben geen invloed op score, aanbeveling of harde uitsluiting; de profielwaarde is uitsluitend informatieve context en bestaande senioriteitsgewichten worden veilig genegeerd en opgeruimd. - De analyse gebruikt alleen actieve IT-vacatures die voor het actieve profiel niet hard uitgesloten zijn en blijft strikt gebruikersgescopeerd. - Een deterministische, uitbreidbare skillcatalogus toont per technologie of capability in hoeveel vacatures een expliciet tekstsignaal voorkomt en onderscheidt profieldekking van mogelijke leer-/bijscholingskansen. - Het profiel biedt extra relevante skills als gegroepeerde checkboxes; de inzichtspagina biedt categorie- en dekkingsfilters en links naar de onderliggende vacatures. - Feiten, tekstinferenties en onbekende gegevens zijn in de Nederlandstalige UI duidelijk onderscheiden; lege toestanden en layouts werken van 320 tot 2560 px zonder horizontale paginaoverflow. verification: - uv run pytest tests/unit/test_scoring.py tests/unit/test_skill_demand.py tests/integration/test_skill_insights.py tests/integration/test_profile_preferences.py - uv run python manage.py makemigrations --check --dry-run - ./scripts/codex_verify.sh - Browsercontrole op 2560x1440, 1440x900 en 390x844 primary_paths: - apps/jobs/services/scoring.py - apps/jobs/services/skill_demand.py - apps/jobs/views.py - apps/profiles/taxonomy.py - templates/jobs/skill_insights.html - static/css/app.css - docs/architecture/SCORING_ENGINE.md result: completed_at: '2026-07-22' note: Ervarings- en senioriteitsinvloed uit score en learning verwijderd; gebruikersgescopeerde Skillsradar met actuele bronselectie, vraagbewijs, profieldekking, leerkansen, uitgebreide skillfilters en 2560/1440/390-browsercontrole voltooid. - id: VR-209 title: Stitch frontendcontract, audit en cockpit-shell status: done priority: P0 requirement_ids: - PR-040 - PR-050 - PR-051 - NFR-004 - NFR-008 depends_on: - VR-208 summary: Leg de volledige negen-schermenaudit en fidelitymatrix vast en vervang het globale design system, de shell, navigatie en generieke browserstates door de Stitch Intelligence Cockpit. acceptance_criteria: - Contract en integratieplan bevatten alle negen schermen, afmetingen, componenten, route/data-mapping, fidelitydoelen, responsive/accessibilityrisico's en legacy-opruiming. - De enige productieshell gebruikt de lokale Stitch-tokens, compacte navigatie, contextbar, mobile drawer, skiplink, focusstaten en echte statusdata zonder externe runtimeassets. - Login, meldingen, lege toestanden en generieke foutstates gebruiken dezelfde visuele taal en blijven zonder JavaScript bruikbaar. verification: - uv run pytest tests/integration/test_views.py tests/e2e/test_vr114_browser_and_accessibility.py - uv run ruff check . primary_paths: - docs/design/STITCH_FRONTEND_CONTRACT.md - docs/design/STITCH_INTEGRATION_PLAN.md - templates/base.html - static/css/app.css - static/js/app.js result: completed_at: '2026-07-22' note: Volledige negen-schermenaudit, fidelitymatrix, bindend frontendcontract en nieuwe lokale Stitch-cockpit-shell met gesplitst design system, mobile navigatie en generieke foutstates; relevante tests groen. - id: VR-210 title: Stitch dashboard en vacature-intelligence status: done priority: P0 requirement_ids: - PR-040 - PR-041 - PR-050 - NFR-004 depends_on: - VR-209 summary: Vervang dashboard, vacatureverkenner en detail door de echte Stitch-composities met database-aggregaties, uitlegbare scores, provenance en veilige acties. acceptance_criteria: - Dashboard toont echte dag-, match-, filter-, duplicaat-, sollicitatie-, activiteit- en brongezondheidsdata met beste matches als dominante feed. - De explorer heeft serverfilters, actieve chips, paginering en een brede master/detailcompositie die querystring en browser-back behoudt. - Het detail toont scorebewijs, inhoud, provenance, versies, duplicaten, sollicitatiestatus en een responsive actiedock; ervaring telt nergens als scorefactor en externe links blijven veilig. verification: - uv run pytest tests/integration/test_views.py tests/unit/test_scoring.py tests/unit/test_relevance.py primary_paths: - apps/core/views.py - apps/jobs/views.py - apps/jobs/services/cockpit.py - templates/dashboard/today.html - templates/jobs/list.html - templates/jobs/detail.html result: completed_at: '2026-07-22' note: Dashboard, vacatureverkenner en detail volledig naar Stitch-composities vervangen met echte cockpitaggregaties, laatste profielscore, master/detailselectie, provenance, versies, duplicaten en veilige acties; relevante scoring/relevance/viewtests groen. - id: VR-211 title: Stitch pipeline, radarprofiel en brongezondheid status: done priority: P0 requirement_ids: - PR-002 - PR-050 - PR-051 - NFR-004 depends_on: - VR-210 summary: Vervang sollicitaties, zoekprofiel en bronnen door de functionele Stitch-pipeline, radarconfigurator en source-healthinterface. acceptance_criteria: - Sollicitaties bieden kanban en lijstfallback, gebruikersgescopeerde POST-statuswijziging, deadlines, contact- en timelinecontext. - Het zoekprofiel groepeert echte selecties, toont revisie-informatie en een server-rendered preview uit de laatste echte match. - Bronnen tonen policy, runs, fout/succes, volgende planning, parser, tellingen, retry en bestaande beveiligde import-/mailboxflows. verification: - uv run pytest tests/integration/test_applications.py tests/integration/test_profile_preferences.py tests/integration/test_sources_manual_import.py tests/integration/test_source_health.py primary_paths: - apps/jobs/views.py - apps/profiles/views.py - apps/sources/views.py - templates/applications - templates/profiles - templates/sources/list.html result: completed_at: '2026-07-22' note: Stitch-kanban met gescopeerde auditbare status-POST, dossiereditor en tijdlijn; gegroepeerde radarconfigurator met echte scorepreview/revisies; health-first bronnenconsole met policy/runbewijs, retry, mailbox- en importflows. Relevante tests groen. - id: VR-212 title: Stitch automation, activiteit en werkgeversintelligence status: done priority: P0 requirement_ids: - PR-040 - PR-050 - PR-051 - NFR-002 - NFR-004 depends_on: - VR-211 summary: Bouw de ontbrekende activiteit- en werkgeversroutes en vervang systeemstatus door een echte afgeleide automationcockpit. acceptance_criteria: - Automation toont echte pipeline-, run-, score-, notificatie-, scheduling-, database- en configuratiestatus en labelt niet-beschikbare infrastructuur eerlijk. - Activiteit combineert betrouwbare, gebruikersgescopeerde gebeurtenissen in een filterbare, gelinkte en gepagineerde tijdlijn. - Werkgevers index/detail aggregeren echte werkgever-, vacature-, score-, bron- en sollicitatiedata zonder CRM- of marktclaims te verzinnen. verification: - uv run pytest tests/integration/test_intelligence_views.py tests/integration/test_views.py primary_paths: - apps/jobs/services/activity.py - apps/jobs/services/employer_intelligence.py - apps/jobs/views.py - apps/jobs/urls.py - apps/core/views.py - templates/activity - templates/employers - templates/system/status.html result: completed_at: '2026-07-22' note: Echte automationcockpit met 24u-pipeline en eerlijke runtimeconfiguratie; gepagineerde/filterbare activiteitreadservice; werkgeversindex/detail met vacature-, score-, bron- en dossieraggregaties. Nieuwe routes, templates en scope-tests groen. - id: VR-213 title: Stitch responsive validatie en legacyverwijdering status: done priority: P0 requirement_ids: - NFR-004 - NFR-008 - NFR-009 depends_on: - VR-212 summary: Rond de high-fidelity replacement af met browsermatrix, accessibility, elf screenshots, legacy-audit, documentatie en volledige regressiegate. acceptance_criteria: - Alle negen schermen en kernflows zijn visueel en functioneel gecontroleerd tussen 360 en 1440 px, met aanvullende ultrawidecontrole en schone browserconsole. - Elf verplichte validatiescreenshots bestaan; majeure afwijkingen, accessibility- en querybevindingen staan in het eindrapport. - Oude visuele selectors, dode partials/JS en parallelle shellmarkup zijn verwijderd; de Stitch-frontend is de enige normale productiefrontend. - De volledige verificatiegate slaagt en backlog, projectstatus, traceability, README en changelog zijn bijgewerkt. verification: - ./scripts/codex_verify.sh - Browsermatrix 1440x900, 1280x800, 1024x768, 768x1024, 390x844 en 360x800 primary_paths: - static/css/app.css - static/js/app.js - tests/e2e - artifacts/visual-validation - docs/design/STITCH_INTEGRATION_REPORT.md result: completed_at: '2026-07-22' note: Alle negen Stitch-schermen zijn browsergevalideerd van 360 tot 2560 px; elf screenshots, accessibility-/legacy-/queryaudit en documentatie afgerond. Volledige gate groen met 248 tests, 2 optionele skips en 84,40% coverage. - id: VR-214 title: Herstel het Unraid Dockerman-containericoon status: done priority: P1 requirement_ids: - NFR-009 depends_on: - VR-213 summary: Vervang de fragiele runtime-SVG voor de Dockerman-tegel door een lokale rasterasset en dek het volledige Unraid-label- en packagingcontract af. acceptance_criteria: - Dockerman verwijst via de gepubliceerde webpoort naar een lokale PNG die door collectstatic in de image wordt opgenomen. - De browserfavicon blijft lokaal en ongewijzigd beschikbaar. - Een regressietest controleert de exacte WebUI- en icoonlabels, PNG-signatuur en verwachte afmetingen. - Het Unraid-runbook beschrijft het cachegedrag en de veilige refreshstap. verification: - uv run pytest tests/unit/test_deployment_configuration.py tests/integration/test_views.py - ./scripts/codex_verify.sh primary_paths: - docker-compose.unraid.yml - static/img/vacatureradar-docker.png - tests/unit/test_deployment_configuration.py - docs/operations/UNRAID_DEPLOYMENT.md result: completed_at: '2026-07-25' note: Dockerman-icoon vervangen door lokale 256x256 PNG via exact Unraid-poortlabel; URL, PNG-signatuur en afmetingen regressiegedekt. Volledige gate groen met 264 tests en 83,47% dekking. Live Unraid-image sha256:799825df1a343b6bee43695850454a5fdc977b5af3366077e6ac6aaeeb94f6f9 gebouwd en gerecreate; container healthy, readiness/liveness groen en PNG via LAN HTTP 200 (7111 bytes). - id: VR-215 title: Corrigeer Dockermans server-side icoondownload status: done priority: P1 requirement_ids: - NFR-009 depends_on: - VR-214 summary: Gebruik voor het Dockerman-icoon een concrete server-side URL omdat Unraid placeholders alleen voor WebUI-links vervangt en niet voor icoondownloads. acceptance_criteria: - Het icoonlabel bevat geen IP- of poortplaceholder en is vanaf de Unraid-host bereikbaar. - Dockerman maakt `VacatureRadar-icon.png` in zijn eigen icooncache aan. - De Docker-tegel gebruikt de gecachte PNG terwijl WebUI-poortsubstitutie behouden blijft. - De regressietest en het Unraid-runbook leggen dit onderscheid vast. verification: - uv run pytest tests/unit/test_deployment_configuration.py - Live Unraid-recreate, cachecontrole en HTTP-smoke - ./scripts/codex_verify.sh primary_paths: - docker-compose.unraid.yml - tests/unit/test_deployment_configuration.py - docs/operations/UNRAID_DEPLOYMENT.md result: completed_at: '2026-07-25' note: Dockerman gebruikt nu concrete server-side loopback-URL zonder placeholders; live Unraid-container healthy, HTTP-smoke groen, persistente en RAM-cache bevatten geldige 256x256 PNG en docker.json verwijst naar VacatureRadar-icon.png. Gericht 5 tests en volledige gate groen met 264 tests en 83,44% dekking. - id: VR-216 title: Premium UX-verfijning met rustige visuele hiërarchie status: done priority: P1 requirement_ids: - NFR-004 - NFR-008 - NFR-009 depends_on: - VR-215 summary: Verfijn de bestaande Stitch-interface naar een premium, rustige cockpit met minder visuele ruis, selectiever kleurgebruik en sterkere informatiehiërarchie zonder server-rendered flows te wijzigen. acceptance_criteria: - Donker en licht thema gebruiken gelaagde oppervlakken, zachtere scheidingen en cyan alleen voor primaire signalen en acties; navigatie en labels gebruiken leesbare humane typografie. - Dashboard, verkenner, detail, pipeline en profiel hebben een herkenbare eigen compositie met consistente componenten, zonder nepdata of dode bediening. - Mobiele KPI's staan compact boven de vouw, filters blijven bruikbaar en de pipeline scrolt intern zonder pagina-overflow tussen 360 en 1440 px. - Browsercontrole op 390 en 1280 px dekt donker en licht thema, kernflows en een schone console. verification: - uv run pytest tests/e2e/test_vr114_browser_and_accessibility.py tests/integration/test_views.py - ./scripts/codex_verify.sh - Browsermatrix 390x844 en 1280x800 in donker en licht thema primary_paths: - static/css - templates/dashboard/today.html - templates/jobs/list.html - templates/applications/list.html - templates/profiles/list.html - docs/design/STITCH_INTEGRATION_REPORT.md result: completed_at: '2026-07-25' note: Premium calm-intelligence-laag voor dark/light, compacte mobiele KPI's, responsieve filtercommandobar, intern scrollende pipeline en breed profiel. Bestaande login-CSP-fout opgelost met lokale externe JS. Browsermatrix 390/1280 zonder overflow en schone console; volledige gate groen met 264 tests, 2 optionele skips en 83,44% dekking. - id: VR-217 title: Borg Unraid-authenticatie en voeg interactieve radarillustraties toe status: done priority: P1 requirement_ids: - NFR-008 - NFR-009 depends_on: - VR-216 summary: Maak het bestaande SSH-deploymentprofiel expliciet en voeg een lokale, toegankelijke interactieve radarillustratie toe op inhoudelijk passende cockpitstates zonder echte data of kernflows te vervangen. acceptance_criteria: - Deploymentdocumentatie en helper valideren de geconfigureerde Unraid-hostalias en falen met een concrete herstelmelding wanneer de verkeerde SSH-identiteit wordt gekozen. - Een herbruikbare lokale radarillustratie versterkt profiel- en lege radarstates met pointer-/focusrespons en bevat geen externe asset, fictieve metric of betekenisdragende informatie. - De illustratie degradeert zonder JavaScript, respecteert prefers-reduced-motion en blijft verborgen voor hulptechnologie; kernacties en tekst blijven zelfstandig bruikbaar. - Browsercontrole op 390 en 1280 px in donker en licht thema toont geen overflow, consolefout of concurrerende visuele hiërarchie; de live Unraid-container is na deployment healthy. verification: - uv run pytest tests/unit/test_deployment_configuration.py tests/e2e/test_vr114_browser_and_accessibility.py - Browsermatrix 390x844 en 1280x800 in donker en licht thema - Live SSH-, containerhealth- en HTTP-smoke via de geconfigureerde hostalias - ./scripts/codex_verify.sh primary_paths: - scripts/deploy_unraid.ps1 - docs/operations/UNRAID_DEPLOYMENT.md - templates/components/radar_illustration.html - templates/profiles/list.html - static/css/premium.css - static/js/app.js result: completed_at: '2026-07-26' note: Unraid-authenticatie hersteld via gevalideerde hostalias unraid-itworx met root en dedicated sleutel; fail-fast deployhelper toegevoegd. Interactieve lokale SVG-radar met pointerparallax, dark/light en reduced-motionfallback toegevoegd. Browsermatrix 390/1280 zonder overflow of consolefouten; 265 tests groen. Live image sha256:4d30e01e778777d5a2cde4339a9b2ad006edb25cae387293737420152d65069d healthy en readiness/CSS/JS HTTP 200. - id: VR-218 title: Personaliseer merkidentiteit en verfijn de globale UX status: done priority: P1 requirement_ids: - NFR-004 - NFR-008 - NFR-009 depends_on: - VR-217 summary: Vervang het generieke favicon door een herkenbaar radarsymbool, voeg configureerbare eigenaarssignatuur toe en verfijn shell, oriëntatie, navigatie en micro-interacties tot een coherente persoonlijke premiumervaring. acceptance_criteria: - Favicon en hoofdlogo delen één scherp, lokaal en op 16 px herkenbaar radarsymbool met passende light/dark browsermetadata en zonder externe assets. - De shell en authenticatieschermen tonen VacatureRadar als product en een configureerbare eigenaarssignatuur met veilige standaardwaarde Jens; deze branding wordt niet uit gebruikersdata of nepdata afgeleid. - De topbar geeft compacte paginaoriëntatie, navigatie-/zoekinteracties hebben duidelijkere focus- en hoverstates en mobiele bruikbaarheid blijft intact zonder extra bediening of JavaScriptafhankelijkheid. - Browsercontrole op dashboard, verkenner, profiel en login bij 390 en 1280 px in donker en licht thema toont geen overflow, consolefout of onduidelijke hiërarchie; live container en assets zijn healthy na deployment. verification: - uv run pytest tests/e2e/test_vr114_browser_and_accessibility.py tests/integration/test_auth_login.py tests/integration/test_views.py - Browsermatrix 390x844 en 1280x800 in donker en licht thema - Live favicon-, logo-, readiness- en containerhealth-smoke - ./scripts/codex_verify.sh primary_paths: - apps/core/context_processors.py - static/favicon.svg - static/img/vacatureradar-logo.svg - templates/base.html - templates/registration - static/css/premium.css - static/css/auth.css result: completed_at: '2026-07-26' note: Persoonlijke Jens-branding, vernieuwd radarbeeldmerk en favicon, contextuele bovenbalk en verfijnde navigatie/zoekfocus zijn regressiegedekt, responsief in de browser gevalideerd en live uitgerold als healthy image sha256:5f25f00c9b7efb166587901ff39b02c56c98fb9946ddef0a4546a22f18dc0802. - id: VR-219 title: Herstel ultrawide uitlijning en versterk persoonlijke merklock-up status: done priority: P1 requirement_ids: - NFR-004 - NFR-008 depends_on: - VR-218 summary: Breng de cockpit op brede schermen terug naar één voorspelbaar horizontaal grid en maak de persoonlijke Jens-signatuur tot een herkenbaar onderdeel van de productbranding in plaats van losse metadata. acceptance_criteria: - Header, filters, hoofdpanelen en onderliggende secties delen op desktop en ultrawide hetzelfde startpunt en dezelfde contentbreedte; er ontstaat geen grote toevallige lege linkerkolom. - Verkenner en automatisering benutten 1920- en 3840-pixelbreedtes evenwichtig zonder uitgerekte leesregels, losgekoppelde panelen of documentoverflow. - Sidebar en bovenbalk tonen één consistente VacatureRadar-by-Jens-merklock-up; authenticatie en mobiele shell behouden dezelfde eigenaarssignatuur zonder gebruikersnaam als merk te presenteren. - Browsercontrole op 390, 1280, 1920 en 3840 px bevestigt consistente ankers, bruikbare paneelverhoudingen, schone console en intacte toetsenbord-/mobiele flows. verification: - Browsermatrix dashboard, verkenner, automatisering en login op 390/1280/1920/3840 px - uv run pytest tests/integration/test_auth_login.py tests/integration/test_views.py - ./scripts/codex_verify.sh primary_paths: - templates/base.html - static/css/layout.css - static/css/premium.css - static/css/responsive.css result: completed_at: '2026-07-26' note: Ultrawide hoofdsecties delen één links verankerd 2800px-grid; explorer- en automationverhoudingen zijn begrensd en Personal intelligence by Jens is de consistente lock-up. Browsermatrix 390/1280/1920/3840 schoon; 267 tests groen; live image sha256:86836f82cc543a7adb414e47b9667e9123bb9ceba10d629a53086273aaaae03f healthy met readiness en asset-smokes. - id: VR-220 title: Integreer de officiële ITWorx-merkidentiteit status: done priority: P1 requirement_ids: - NFR-004 - NFR-008 - NFR-009 depends_on: - VR-219 summary: Vervang de tijdelijke tekstuele Jens-branding door de door de eigenaar aangeleverde officiële ITWorx.tech-wordmark en cloud-check-identiteit, met VacatureRadar herkenbaar als product binnen dat merk. acceptance_criteria: - Sidebar, login en herstelpagina's gebruiken de transparante officiële ITWorx.tech-wordmark uit het aangeleverde asset pack; VacatureRadar blijft duidelijk als productnaam aanwezig. - Browserfavicon en app-/Dockericoon gebruiken de officiële cloud-check-symboliek in een compacte transparante, lokaal gehoste en voor klein formaat geoptimaliseerde variant. - Merkassets hebben betekenisvolle alt-/toegankelijkheidslabels, laden zonder externe runtimebron en blijven scherp en leesbaar in donker/licht thema en op mobiel. - Browsercontrole op login, dashboard en verkenner bij 390, 1280 en 1920 px toont correcte assets, geen overflow of consolefouten; de live container levert brandingassets en readiness met HTTP 200. verification: - Controleer afmetingen, transparantie en bestandsgrootte van de afgeleide merkassets - uv run pytest tests/integration/test_auth_login.py tests/integration/test_views.py tests/unit/test_deployment_configuration.py - Browsermatrix 390/1280/1920 voor login, dashboard en verkenner - Live asset-, favicon-, readiness- en containerhealth-smoke - ./scripts/codex_verify.sh primary_paths: - static/img/itworx-wordmark.png - static/img/itworx-app-icon.png - static/img/vacatureradar-docker.png - templates/base.html - templates/registration - static/css/premium.css - static/css/auth.css result: completed_at: '2026-07-26' note: Officiële aangeleverde ITWorx.tech-wordmark geïntegreerd in sidebar, topbar, login en herstel; cloud-check exact afgeleid voor 512px favicon/app-icon en 256px Dockermanicoon. Browsermatrix 390/1280/1920 schoon, 267 tests groen en live image sha256:daf34407813b37cdf2d0fc65a482ded65375f89eedd3f0144a8c0ce206d41565 healthy met readiness/PNG-smokes. - id: VR-221 title: Scheid appmerk van ontwikkelaarsbranding status: done priority: P1 requirement_ids: - NFR-004 - NFR-008 - NFR-009 depends_on: - VR-220 summary: Herstel VacatureRadar als zelfstandig productmerk met een nieuw professioneel radarlogo en favicon, en plaats de aangeleverde ITWorx.tech-identiteit uitsluitend als subtiele ontwikkelaarscredit. acceptance_criteria: - VacatureRadar gebruikt een zelfstandig, vectorvriendelijk beeldmerk dat radar, detectie en een gevonden kans combineert, scherp blijft op 16 px en visueel niet met het ITWorx-cloud-check-logo concurreert. - Sidebar, login, favicon en Dockerman tonen het VacatureRadar-productmerk; ITWorx.tech staat alleen op geschikte secundaire plaatsen als `Ontwikkeld door ITWorx.tech`. - De ontwikkelaarscredit gebruikt de officiële aangeleverde ITWorx-wordmark lokaal en blijft ondergeschikt, toegankelijk en leesbaar in donker/licht thema en op mobiel. - Browsercontrole op login, dashboard en verkenner bij 390, 1280 en 1920 px toont correcte merkhiërarchie, geladen assets, geen overflow of consolefouten; live container en alle assets zijn healthy. verification: - Inspecteer VacatureRadar-SVG op viewBox, elementeenvoud en klein-formaat-signatuur - uv run pytest tests/integration/test_auth_login.py tests/integration/test_views.py tests/unit/test_deployment_configuration.py - Browsermatrix 390/1280/1920 voor login, dashboard en verkenner - Live logo-, favicon-, ontwikkelaarswordmark-, readiness- en containerhealth-smoke - ./scripts/codex_verify.sh primary_paths: - static/favicon.svg - static/img/vacatureradar-logo.svg - static/img/vacatureradar-docker.png - static/img/itworx-wordmark.png - templates/base.html - templates/registration - static/css/premium.css - static/css/auth.css result: completed_at: '2026-07-26' note: VacatureRadar heeft een zelfstandig professioneel open-radar-logo, SVG-favicon en 256px Dockermanicoon; officiële ITWorx.tech-wordmark staat alleen als Ontwikkeld door-credit. Twee beeldconcepten verkend, finale geometrie handmatig als vijf-elementen-SVG gebouwd. Browsermatrix 390/1280/1920 schoon, 267 tests groen en live image sha256:4184aeff33759b7a205637b0a0333b751b599141fe691a61965d2f1c56ca984a healthy met alle asset-smokes. - id: VR-222 title: Voer een integrale premium visuele audit en herstelroadmap uit status: done priority: P1 requirement_ids: - NFR-004 - NFR-008 - NFR-009 depends_on: - VR-221 summary: Audit de volledige cockpit als één designsysteem en herstel merkhiërarchie, uitlijning, informatiedichtheid, interactiedoelen, responsief gedrag en motion tot een consistente premium productervaring. acceptance_criteria: - Een gedateerd auditrapport bevat geprioriteerde bevindingen, concreet gevolg, herstelactie en volledige roadmap voor alle hoofdschermen, login en herstel. - Topbar en hoofdcontent delen voorspelbare horizontale ankers; dashboard en activiteit zijn aantoonbaar compacter zonder echte informatie te verbergen of controles onbruikbaar te maken. - VacatureRadar blijft het enige primaire appmerk; ITWorx.tech staat uitsluitend als subtiele ontwikkelaarscredit en geen concept- of chroma-keybeeld wordt als productasset geleverd. - Controls, focus, reduced motion, dark/light en 390/768/1280/1440/1920/3840 px zijn gecontroleerd zonder overflow, consolefouten of regressie in de server-rendered kernflow. - De live container is healthy en levert het finale logo, favicon en de relevante CSS met HTTP 200. verification: - Browsermatrix voor alle hoofdschermen plus login in dark/light en 390/768/1280/1440/1920/3840 px - uv run pytest tests/integration/test_auth_login.py tests/integration/test_views.py - ./scripts/codex_verify.sh - Live readiness-, containerhealth- en assetsmokes primary_paths: - docs/design/VISUAL_AUDIT_2026-07-26.md - templates/base.html - templates/dashboard/today.html - templates/activity/list.html - static/css/premium.css - static/css/pages.css - static/css/responsive.css result: completed_at: '2026-07-26' note: 'Integrale audit en roadmap uitgevoerd: gedeeld contentframe, vijf dashboardmatches, compacte activiteit, subtiele ITWorx-credit, grotere klikdoelen, reduced-motion, CSS-cacheversies en herstelde mobiele login. Browsermatrix 50 checks plus light/login schoon; 268 tests groen, 2 skips, 83,45% dekking. Live image sha256:7e1688db80241813a04e27038ef5e4afb64748868b6a97e353346f077be50b70 healthy; readiness en assets HTTP 200.' - id: VR-223 title: Verfijn transparant productlogo en professionele widescreenshell status: done priority: P1 requirement_ids: - NFR-004 - NFR-008 - NFR-009 depends_on: - VR-222 summary: Herstel de resterende merk- en shellfrictie uit de gebruikersscreenshot met een transparant cleaner productlogo, één rustige sidebarfooter zonder dubbele accountidentiteit en beter benutte widescreenruimte. acceptance_criteria: - Het VacatureRadar-logo heeft geen donkere tegelachtergrond en blijft als eenvoudige vector scherp en herkenbaar op dark/light, login, sidebar en klein formaat; favicon en Dockerman blijven doelgeschikt. - De sidebar toont onderaan één samenhangende status-/ontwikkelaarszone en herhaalt de demo- of accountidentiteit niet; accountacties blijven bereikbaar via het bestaande topbarmenu. - De cockpit benut 1920, 2560 en 3840 px evenwichtiger zonder uitgerekte leesregels, losstaande topbaracties of horizontale documentoverflow; mobiel en laptop blijven intact. - Een gerichte vervolgcheck identificeert en herstelt bijkomende zichtbare shellproblemen, inclusief light/dark, korte viewport en toetsenbord-/interactiestates. - De live container is healthy en levert logo, favicon, CSS en readiness met HTTP 200. verification: - Browsermatrix dashboard, verkenner, automatisering, login op 390/1280/1920/2560/3840 px en korte sidebarviewport - uv run pytest tests/integration/test_auth_login.py tests/integration/test_views.py tests/unit/test_deployment_configuration.py - ./scripts/codex_verify.sh - Live readiness-, containerhealth- en assetsmokes primary_paths: - static/img/vacatureradar-logo.svg - static/css/layout.css - static/css/premium.css - static/css/responsive.css - templates/base.html result: completed_at: '2026-07-27' note: Transparant vier-elementenlogo zonder donkere tegel; één compacte sidebarfooter zonder dubbele accountidentiteit; monochrome dark-mode ITWorx-credit en widescreenframes van 2200/2480 px. Browsermatrix 18 shellchecks plus dark/light/login schoon; volledige gate tweemaal groen met 268 tests, 2 skips en 83,45% dekking. Live image sha256:ea9e61a1febca59eb906bfdebcd9fd2b2c2b000189a8772f4abf09012722e921 healthy; readiness en assets HTTP 200. - id: VR-301 title: Multi-tenant SaaS, teams en billing status: deferred priority: P3 requirement_ids: - NFR-005 depends_on: - VR-117 summary: Niet nodig voor de persoonlijke installatie. Alleen heroverwegen bij een apart productbesluit met tenantisolatie, privacy, support en billingarchitectuur. acceptance_criteria: - Nieuwe productbeslissing en ADR vereist vóór implementatie. verification: - Niet uitvoeren binnen huidige scope. primary_paths: - docs/product/SCOPE_AND_NON_GOALS.md - id: VR-224 title: Maak de repository-README functioneel en user-first met actuele screenshots status: done priority: P1 requirement_ids: - NFR-008 - NFR-009 depends_on: - VR-223 summary: Herbouw de repository-ingang rond het gebruikersprobleem, de dagelijkse workflow en een veilige quickstart, ondersteund door compacte actuele productbeelden uit de echte server-rendered cockpit. acceptance_criteria: - De README begint bij doel, doelgroep en dagelijkse gebruikersflow; installatie, beheer, architectuur en agentoverdracht volgen in een duidelijke progressieve volgorde zonder bestaande essentiële informatie te verliezen. - Minstens vier actuele screenshots tonen verschillende functionele hoofdschermen, desktop en mobiel en dark/light; ze bevatten geen secrets of persoonlijke gegevens en zijn lokaal, geoptimaliseerd en correct gelinkt. - Quickstarts, poorten, lokale credentials, veiligheidsgrenzen en operationele documentatielinks zijn aantoonbaar correct en maken duidelijk wat demo-, ontwikkel- en productiegebruik betekent. - README-links en repositorydocumentatie valideren, de beelden zijn visueel gecontroleerd zonder overflow of consolefouten en de volledige kwaliteitsgate slaagt. verification: - Browsercontrole van de vastgelegde routes en viewports - python scripts/validate_repository.py - ./scripts/codex_verify.sh primary_paths: - README.md - docs/screenshots/readme/ - docs/quality/TRACEABILITY_MATRIX.md - docs/ai/PROJECT_STATE.md result: completed_at: '2026-07-27' note: User-first README met gecontroleerde quickstarts en vier actuele dark/light desktop-/mobielscreenshots; browsermatrix zonder overflow of consolewaarschuwingen, repositoryvalidatie groen en volledige gate met 268 tests, 2 skips en 83,48% dekking. - id: VR-302 title: Automatisch sollicitaties invullen of versturen status: deferred priority: P3 requirement_ids: - PR-056 - AC-043 depends_on: - VR-117 summary: Expliciet niet bouwen. Menselijke eindcontrole en verzending via het oorspronkelijke kanaal blijven een vaste veiligheidsgrens. acceptance_criteria: - Er bestaat geen submitendpoint, browserbot of taak die extern solliciteert. verification: - Codezoekreview op submit/auto-apply; ADR-0006 blijft accepted. primary_paths: - docs/architecture/adrs/0006-no-automatic-applications.md - id: VR-303 title: Publieke mobiele app en algemene externe API status: deferred priority: P3 requirement_ids: - NFR-005 - NFR-009 depends_on: - VR-117 summary: Server-rendered single-user UI voldoet. Alleen uitvoeren bij concrete integratiebehoefte, met auth/scopes/versioning en een nieuwe ADR. acceptance_criteria: - Geen externe API-oppervlakte toevoegen zonder consumer en threat model. verification: - Niet uitvoeren binnen huidige scope. primary_paths: - docs/api/openapi.yaml - docs/architecture/adrs/0008-server-rendered-design.md - id: VR-225 title: Hard publieke reverse-proxydeployment en gasttoegang uit status: done priority: P0 requirement_ids: - NFR-001 - NFR-006 - NFR-009 depends_on: - VR-224 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. - 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. - Unraid-envpad, Nginx Proxy Manager, healthchecks, noindex, heruitrol en terugdraaien zijn exact gedocumenteerd. verification: - PYTHONPATH=/mnt/data/vr_windows_site/site-packages pytest -q - python manage.py check - python manage.py makemigrations --check --dry-run - python scripts/validate_repository.py - bash -n scripts/deploy_docker.sh scripts/entrypoint.sh scripts/unraid_aio_entrypoint.sh - Live Nginx-, TLS-, CSRF-, Dockerhealth- en restore-smoke op de doelserver primary_paths: - config/settings.py - apps/core/middleware.py - apps/core/network.py - apps/core/health.py - scripts/configure_public_url.py - docker-compose.unraid.yml - docs/operations/NGINX_PROXY_MANAGER.md - docs/quality/PRODUCTION_AUDIT_2026-07-27.md result: completed_at: '2026-07-27' 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.