1117 lines
42 KiB
YAML
1117 lines
42 KiB
YAML
schema_version: 1
|
|
project: VacatureRadar
|
|
updated_at: '2026-07-21'
|
|
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-201
|
|
title: Concrete live-bronnen inventariseren en juridisch/operationeel reviewen
|
|
status: blocked-external
|
|
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
|
|
external_blocker: Vereist persoonlijke werkgeverskeuzes en een actuele menselijke bronvoorwaardenreview. Commit
|
|
lokale bronlijst niet wanneer die persoonlijke informatie bevat.
|
|
- 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
|
|
summary: Configureer een dedicated vacaturemailbox, app-password en digestrecipient; test read-only import en
|
|
mailverzending zonder credentials in Git/logs.
|
|
acceptance_criteria:
|
|
- IMAP gebruikt TLS, dedicated mailbox en mark-seen standaard uit tijdens acceptatie.
|
|
- Dezelfde live testmail importeert idempotent.
|
|
- SMTP verstuurt één testdigest en outboxstatus klopt.
|
|
- Credentials zijn geroteerbaar en alleen in productie-secretstore/.env aanwezig.
|
|
verification:
|
|
- Volg Unraid mailboxchecklist
|
|
- Inspecteer logs op afwezigheid van secret/payload
|
|
primary_paths:
|
|
- /mnt/user/appdata/vacatureradar/config/.env
|
|
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: blocked-external
|
|
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
|
|
external_blocker: Vereist een actuele datasetkeuze/licentiecheck; bulkdata hoort niet automatisch in de project-ZIP.
|
|
- 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-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
|