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
+160
View File
@@ -0,0 +1,160 @@
# Bron- en adapterarchitectuur
## 1. Adaptercontract
Iedere adapter implementeert conceptueel:
```python
class SourceAdapter(Protocol):
parser_key: str
parser_version: str
def extract(self, content: str, *, url: str) -> ExtractionResult: ...
```
`ExtractionResult` bevat:
- `jobs: list[ExtractedJob]`;
- stabiele parser key/version;
- confidence 0..1;
- machine-/mensleesbare warnings.
Adapters:
- doen geen netwerkrequests;
- schrijven niet naar ORM;
- voeren geen scoring of bronpolicy uit;
- werken deterministisch op aangeleverde fixtures;
- bewaren alleen beperkte raw payload voor debugging;
- leveren evidence per belangrijk veld.
## 2. Parservolgorde
Voor HTML:
1. JSON-LD `JobPosting`;
2. gespecialiseerde adapter op expliciete source parser key;
3. generieke HTML-fallback;
4. geen vacature wanneer minimumvelden ontbreken.
Voor XML/feed:
1. RSS/Atom;
2. sitemapdiscovery (backlog);
3. geen generieke HTMLparser.
Voor e-mail:
1. MIME decode zonder attachments;
2. linkextractie met unsubscribe/privacyfilter;
3. platformalias bewaren;
4. oorspronkelijke werkgever proberen te resolveren in een aparte begrensde taak.
## 3. Minimumvelden
Een jobdraft is verwerkbaar wanneer minstens aanwezig:
- titel;
- HTTP(S)-URL of stabiele externe identiteit.
Employer, locatie en beschrijving mogen tijdelijk ontbreken, maar verlagen confidence. Een generieke pagina zonder herkenbare titel wordt niet als job opgeslagen.
## 4. Confidence
Richtwaarden:
| Methode | Baseline |
|---|---:|
| JSON-LD geldig individueel JobPosting | 0,95 |
| gespecialiseerde publieke ATS-adapter | 0,90 |
| RSS/Atom | 0,82 |
| vacaturemailanchor | 0,650,75 |
| generieke HTMLselectors | 0,450,75 |
Fieldconfidence en extractionconfidence zijn gescheiden. Een perfecte titel maakt een ontbrekende werkgever niet betrouwbaar.
## 5. Nieuwe adapter toevoegen
1. Maak `apps/sources/adapters/<naam>.py`.
2. Geef vaste parser key en semverachtige version.
3. Parse alleen de aangeleverde content.
4. Maak geanonimiseerde fixture onder `fixtures/`.
5. Test happy path, ontbrekende velden, gewijzigd markup en malafide HTML.
6. Registreer uitsluitend voor een expliciete source/parserdetectie.
7. Documenteer bronbeleid, rate limit en canonical URL-gedrag.
8. Voeg traceability toe.
## 6. ATS-strategie
Gespecialiseerde adapters mogen publieke HTML of publieke, documenteerbare endpoints gebruiken wanneer:
- geen login/token nodig is;
- bronpolicy `allow` is;
- gebruiksvoorwaarden/robots zijn beoordeeld;
- het endpoint rechtstreeks vacatures van de werkgever publiceert;
- rate limiting en identifiers stabiel zijn;
- fallback naar HTML mogelijk is.
Een endpoint mag technisch JSON zijn zonder een commerciële platform-API-integratie te vormen. De policybeslissing blijft per bron vereist.
## 7. Bronpromotie
```text
candidate
-> policy/robots/terms review
-> trial (kleine frequentie, parserconfidence meten)
-> active (voldoende succesvolle runs)
-> quarantined (policy, security of herhaalde parsefout)
-> trial/active na expliciet herstel
```
Automatische promotie naar `active` vereist minimaal:
- meerdere succesvolle runs;
- geen private/deny redirect;
- voldoende extractieconfidence;
- geen onverwachte volumepiek;
- policy nog geldig.
Juridische voorwaarden mogen niet door een taalmodel als definitief toegestaan worden verklaard.
## 8. Rate limiting
Per eTLD+1/domein:
- concurrency standaard 1;
- minimum interval standaard 30 seconden;
- respecteer `Retry-After`;
- conditionele GET met ETag/Last-Modified;
- exponentiële backoff bij fout;
- geen retry op policyblokkade;
- adaptieve lagere frequentie bij stabiele, zelden wijzigende bron.
## 9. Parserdrift
Bronhealth detecteert:
- leeg resultaat waar eerder vacatures waren;
- sterke daling in velddichtheid/confidence;
- nieuwe foutstatus/contenttype;
- wijziging in jobvolume;
- ontbrekende title/URL;
- veel nieuwe canonical keys door URLtrackingwijziging.
Automatisch herstel mag veilige selectorvarianten proberen, maar nieuwe logica moet eerst op opgeslagen fixture/snapshot draaien. Geen live agressieve exploratie.
## Publieke ATS-providers (VR-106)
| Provider | Hostherkenning | Parserbenadering | Opmerking | Rate limit (advies) |
|---|---|---|---|---|
| Greenhouse | `*.greenhouse.io`, `*.boards.greenhouse.io` | gespecialiseerd endpoint/JSON + detailstructuren | gebruik alleen publieke boardpagina's/feeds, geen private/persoonlijke endpoints | 15 requests/min met conditional request indien beschikbaar |
| Lever | `jobs.lever.co` | gespecialiseerd JSON/HTML listing+detail | alleen publieke postings, geen recruiter login flow | 60 requests/min per domein |
| Recruitee | `*.recruitee.com` | gespecialiseerd listing+detail parser | parse alleen door werkgever geïntendeerde publieke vacature-URLs | 60 requests/min per domein |
| SmartRecruiters | `*.smartrecruiters.com` | gespecialiseerd listing+detail parser | geen interne API-auth nodig; stop bij CAPTCHA/anti-bot | 30 requests/min per domein |
| Workable | `apply.workable.com` | gespecialiseerd listing+detail parser | alleen publieke vacaturepagina/JSON; geen private endpoints | 30 requests/min per domein |
Voor elke provider-adapter:
- `supports()` kijkt eerst op host/marker om andere pagina's niet te matchen;
- listingpayloads produceren kandidaten zonder fetch van detail;
- detailpayloads vullen een enkele vacaturestructuur;
- elke veldafklaring krijgt veld-evidence met method-labels en confidence.