131 lines
6.8 KiB
Markdown
131 lines
6.8 KiB
Markdown
# Operationeel runbook
|
|
|
|
## Dagelijkse controle
|
|
|
|
Controleer bij voorkeur automatisch en minstens wekelijks handmatig:
|
|
|
|
- `/health/ready/` is 200;
|
|
- web, worker, scheduler, PostgreSQL en Redis zijn actief;
|
|
- vrije ruimte op database-, media-, log- en back-upvolume;
|
|
- bronnen in `quarantined`, `paused` of met oplopende `failure_count`;
|
|
- `DigestOutbox` met status `failed` of langdurig `pending`;
|
|
- meest recente geslaagde back-up en laatste hersteltest;
|
|
- onverwachte login- of policyfouten in logs.
|
|
|
|
## Incidentprioriteiten
|
|
|
|
| Niveau | Voorbeeld | Eerste actie |
|
|
|---|---|---|
|
|
| P1 | datalek, secret gepubliceerd, ongeautoriseerde netwerkfetch | stop web/worker/scheduler, isoleer netwerk, roteer secrets |
|
|
| P2 | database niet beschikbaar, imports corrupt, herhaalde mail | stop schrijvende processen, behoud bewijs, maak snapshot |
|
|
| P3 | één adapter kapot, digest vertraagd, bron in quarantaine | pauzeer bron/functie, herstel met fixture en test |
|
|
| P4 | copy/layout/probleem zonder datarisico | registreer backlogtaak en plan normale release |
|
|
|
|
## Web niet ready
|
|
|
|
1. Controleer liveness. Faalt die ook, inspecteer webcontainer/proces en poortbinding.
|
|
2. Bij `database=error:*`: controleer PostgreSQL-status, disk, credentials en netwerknaam.
|
|
3. Test vanuit webcontainer of DNS `postgres` resolveert en poort 5432 bereikbaar is.
|
|
4. Draai geen migraties herhaald blind; lees eerst de laatste stacktrace.
|
|
5. Herstart alleen de falende laag. Een volledige stackrestart kan diagnostiek wissen.
|
|
|
|
## Worker verwerkt niets
|
|
|
|
1. Controleer Redis en `CELERY_BROKER_URL`.
|
|
2. Controleer workerqueues `high,default,low`.
|
|
3. Inspecteer actieve en gereserveerde taken:
|
|
|
|
```bash
|
|
celery -A config inspect ping
|
|
celery -A config inspect active
|
|
celery -A config inspect reserved
|
|
```
|
|
|
|
4. Kijk naar timeouts, policyblokkades en retryloops.
|
|
5. Start niet meerdere schedulers; dat kan dubbele planning veroorzaken, ook al zijn imports idempotent.
|
|
|
|
## Bron faalt of gaat in quarantaine
|
|
|
|
1. Laat quarantaine staan; forceer geen fetch.
|
|
2. Lees alleen categorie, status, URL-host en beperkte foutmelding in `SourceRun`.
|
|
3. Controleer of het domein, redirectdoel, robots-/voorwaardenstatus of contenttype veranderde.
|
|
4. Download geen pagina met een onbeveiligde shellopdracht vanaf de productiehost.
|
|
5. Reproduceer met een gesaneerde fixture in een ontwikkelomgeving.
|
|
6. Werk parser/policy en securitytests bij.
|
|
7. Zet bron pas terug op `trial`, voer één begrensde run uit en promoveer daarna eventueel naar `active`.
|
|
|
|
## IMAP-import stopt
|
|
|
|
1. Pauzeer alleen de falende platformmailbox op de bronpagina; andere mailboxen blijven werken.
|
|
2. Controleer provider, publieke IMAP-host, poort 993, mailboxmap, account en app-wachtwoord.
|
|
3. Verifieer dat `MAILBOX_CREDENTIAL_KEYS` aanwezig is en dat bij een rotatie de oude sleutel nog achter de nieuwe staat.
|
|
4. Verifieer dat de mailbox niet is hernoemd en het account niet is vergrendeld.
|
|
5. Alle polls selecteren de mailbox read-only; een reeds verwerkte mail is per mailbox idempotent via message identity.
|
|
6. Controleer het gekozen interval en `next_poll_at`; de scheduler zoekt iedere vijf minuten naar verschuldigde koppelingen.
|
|
7. Controleer `IMAP_MAX_MESSAGES_PER_POLL` en `IMAP_MAX_MESSAGE_BYTES`. Vergroot die niet om een onverwacht groot of verdacht bericht blind te verwerken.
|
|
8. Controleer bij een leeg resultaat of het jobboardmailformaat nog gelabelde HTTPS-vacaturelinks op het gekozen platformdomein bevat; versoepel de domeinfilter niet zonder fixture en securitytest.
|
|
9. Activeer de mailbox opnieuw, kies **Nu synchroniseren** en controleer `last_success_at`. Verwijder geen `EmailMessageRecord` om zonder analyse te herhalen.
|
|
|
|
## Mailboxsleutel roteren
|
|
|
|
1. Maak een nieuwe Fernet-sleutel en zet die als eerste in `MAILBOX_CREDENTIAL_KEYS`; behoud de oude sleutel erachter.
|
|
2. Herstart web, worker en scheduler zodat alle processen dezelfde sleutellijst gebruiken.
|
|
3. Draai `python manage.py rotate_mailbox_credentials`.
|
|
4. Synchroniseer één mailbox en controleer dat geen ciphertext, app-wachtwoord of volledige mailpayload in logs staat.
|
|
5. Verwijder daarna de oude sleutel en herstart opnieuw.
|
|
|
|
## Digest ontbreekt of dubbel
|
|
|
|
- Controleer actief profiel, digesttijd/zone en `DIGEST_RECIPIENT`.
|
|
- Controleer `DigestOutbox` op datum en status.
|
|
- Bij SMTP-fout: corrigeer configuratie en retry dezelfde outbox gecontroleerd.
|
|
- Maak geen tweede outboxrecord handmatig; uniciteit per profiel/datum is de duplicaatbarrière.
|
|
- Een lege digest is toegestaan wanneer geen vacature boven de ingestelde drempel valt.
|
|
|
|
## Verdachte of kwaadaardige vacature-inhoud
|
|
|
|
1. Open de originele bron niet automatisch in een ingelogde browser.
|
|
2. Zet bij twijfel het raw document op `quarantined` zodat retentie het bewijs niet wist.
|
|
3. Controleer opgeslagen gesaniteerde tekst en veldherkomst.
|
|
4. Voeg de payload als geanonimiseerde fixture toe wanneer een parser/sanitizerfout bestaat.
|
|
5. Laat AI-output nooit een commando, URL-fetch of configuratiemutatie veroorzaken.
|
|
|
|
## Sollicitatiedossier exporteren en opschonen
|
|
|
|
1. Open de sollicitatielijst in een ingelogde gebruiker-sessie en ga naar het dossier.
|
|
2. Controleer dat de timeline alleen mutaties voor dat dossier bevat (status, notities, contact, snapshot).
|
|
3. Exporteer met het dossier-exportendpoint om een zip met `application.json`, `timeline.csv`, `application_print.html` te controleren.
|
|
4. Controleer het zipbestand lokaal op:
|
|
- correcte dossier-ID;
|
|
- geen raw e-mailbody of bron-payload;
|
|
- geen externe assets of scriptrequests in HTML.
|
|
5. Verwijderen mag alleen op gebruikersniveau (`delete` endpoint); herhaalde delete-aanroepen moeten zonder fout uitkomen.
|
|
|
|
## Schijfruimte laag
|
|
|
|
1. Stop scheduler en worker wanneer de database- of PostgreSQL-volume kritiek vol is.
|
|
2. Controleer oude back-ups, containerlogs, raw-documentretentie en Ollama-modellen.
|
|
3. Verwijder nooit willekeurig PostgreSQL-bestanden.
|
|
4. Laat `cleanup_raw_documents` alleen niet-gequarantaineerde verlopen documenten opruimen.
|
|
5. Vergroot volume of herstel rotatie, start daarna database, web, worker en scheduler in die volgorde.
|
|
|
|
## Secret vermoedelijk gelekt
|
|
|
|
1. Stop externe toegang en disable betrokken account/token.
|
|
2. Roteer Django secret, adminwachtwoord, database-, SMTP-, IMAP- en registrycredentials voor zover betrokken.
|
|
3. Trek oude sessies in door sessies te verwijderen of het secret te wijzigen.
|
|
4. Controleer logs en source-runs op misbruik, zonder gevoelige payload verder te kopiëren.
|
|
5. Maak een incidentnotitie met exacte tijden, scope, rotaties en herstelvalidatie.
|
|
|
|
## Herstelvalidatie
|
|
|
|
Na ieder incident:
|
|
|
|
```bash
|
|
python manage.py check
|
|
python manage.py migrate --plan
|
|
python manage.py shell -c "from apps.core.health import readiness; print(readiness())"
|
|
```
|
|
|
|
Controleer daarna login, één fixture-import, scoreberekening, bronlijst, sollicitatielijst en mailbackend. Start live polling pas nadat deze controles slagen.
|