Initial deploy setup
deploy / deploy (push) Canceled after 0s

This commit is contained in:
Jens
2026-07-21 14:00:00 +02:00
commit b8091e59bd
285 changed files with 27854 additions and 0 deletions
+133
View File
@@ -0,0 +1,133 @@
# Datamodel
## Entity-relatiemodel
```mermaid
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:
```text
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.