4.4 KiB
Datamodel
Entity-relatiemodel
erDiagram
USER ||--o{ SEARCH_PROFILE : owns
SEARCH_PROFILE ||--o{ PROFILE_REVISION : versions
SEARCH_PROFILE ||--o{ SCORE_RUN : evaluates
SEARCH_PROFILE ||--o{ DIGEST_OUTBOX : receives
SOURCE ||--o{ SOURCE_RUN : executes
SOURCE ||--o{ RAW_DOCUMENT : retrieves
SOURCE_RUN ||--o{ RAW_DOCUMENT : produces
RAW_DOCUMENT ||--o{ JOB_SOURCE_ALIAS : evidences
RAW_DOCUMENT ||--o| EMAIL_MESSAGE_RECORD : wraps
EMPLOYER ||--o{ JOB_POSTING : publishes
JOB_POSTING ||--o{ JOB_SOURCE_ALIAS : aliases
JOB_POSTING ||--o{ FIELD_PROVENANCE : fields
JOB_SOURCE_ALIAS ||--o{ FIELD_PROVENANCE : proves
JOB_POSTING ||--o{ JOB_VERSION : versions
JOB_POSTING ||--o{ SCORE_RUN : scored
JOB_POSTING ||--o{ FEEDBACK : receives
JOB_POSTING ||--o{ APPLICATION : tracked
USER ||--o{ FEEDBACK : gives
USER ||--o{ APPLICATION : owns
Entiteiten
SearchProfile
Bevat harde/soft voorkeuren, locatie, drempels, digesttijd en version. De JSON-velden blijven schematisch gedocumenteerd in docs/api/INTERNAL_CONTRACTS.md en gevalideerd in service/formcode.
Belangrijke invarianten:
- unieke naam per user;
- recommendation threshold ≤ top threshold;
- gewichten numeriek, niet-negatief en met positieve som;
- coördinaten binnen bereik;
- precies één actief profiel per user via
activate()-serviceflow.
Source
Bronregister met source_type, status en onafhankelijk policy.
Status betekent operationele toestand; policy betekent toestemming:
candidate— ontdekt, niet actief;trial— beperkte proefcontrole;active— normaal gepland;quarantined— automatisch/manual geïsoleerd;paused/disabled— niet plannen;allow/review/deny— netwerktoegangsbesluit.
Een deny-bron mag niet active zijn.
RawDocument
Tijdelijke immutable-ish fetchsnapshot. Bevat alleen begrensde tekstbody, headers op allowlist, hash, parserresultaat en retentie. Quarantaine verhindert cleanup tot inspectie.
Employer
Genormaliseerde werkgever/recruiteridentiteit. Uniek op normalized name + domain. is_direct_employer en is_recruiter zijn confidencegedreven kenmerken, geen juridisch oordeel.
JobPosting
Canonieke vacature met UUID, canonical key, content hash, status en genormaliseerde velden. De canonical key wordt uit external ID/URL of fallbackidentiteit afgeleid. De exacte key is uniek; fuzzy matching is alleen een kandidaatbeslissing.
Statusflow:
new -> active -> uncertain -> removed
\-> expired
active/uncertain -> duplicate/quarantined (beheerflow)
JobSourceAlias
Verbindt alle bronvermeldingen met één canonieke vacature. Bewaart externe ID, bronURL, parser, confidence en beperkte payload. De alias is het anker voor veldprovenance.
FieldProvenance
Per veld: extractiemethode, confidence, evidenceexcerpt en parserversie. Evidence is begrensd en mag geen geheime mailinhoud bevatten.
JobVersion
Snapshot per unieke contenthash. Bij inhoudswijziging wordt de vorige toestand bewaard; de huidige toestand krijgt eveneens een versie.
ScoreRun
Append-only score voor één job + profielversie. Bevat componentbijdragen, confidence, recommendation, redenen en evidence. Meerdere runs maken algoritme- en profielvergelijking mogelijk.
Feedback
Append-only useractie. Geen laatste-statekolom; views kunnen de laatste actie afleiden. Hierdoor blijft correctiehistorie behouden.
Application
Eén dossier per user/job. snapshot bewaart wat de gebruiker zag toen hij solliciteerde. document_manifest bevat alleen metadata/paden, geen willekeurige externe URL-executie.
DigestOutbox
Idempotente meldingseenheid met unieke dedupe key. Statusovergangen: pending → sent/failed; skipped bij ontbrekende recipient/configuratie.
Indexstrategie
Bestaand:
- job title + region;
- job status + valid_through;
- alias source + external ID;
- alias canonical URL;
- source + raw contenthash;
- profile + score descending + created_at;
- bron next_run_at en healthdatums.
Toekomstig bij meetbare noodzaak:
- trigram/index voor fuzzy title/employer (PostgreSQL);
- partial index op actieve vacatures;
- latest score materialisatie;
- JSON GIN uitsluitend voor werkelijk bevraagde keys.
Migratiebeleid
- schemawijzigingen via Django migrations;
- destructieve wijzigingen in twee fasen;
- grote backfills chunked en restartable;
- productieback-up vóór migratie;
- migratiecheck in CI;
- rollback of forward-fix expliciet in taskplan.