# 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. Zet `IMAP_ENABLED=0` om lockout of herhaalde fouten te beperken. 2. Controleer host, poort, TLS, mailboxnaam en app-password. 3. Verifieer dat de mailbox niet is hernoemd en het account niet is vergrendeld. 4. Test eerst read-only met `IMAP_MARK_SEEN=0`. 5. Een reeds verwerkte mail is idempotent via message identity; verwijder geen `EmailMessageRecord` om opnieuw te proberen zonder analyse. ## 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.