Files
VacatureRadar/docs/operations/RUNBOOK.md
T
Jens 67be350283
deploy / deploy (push) Canceled after 0s
Harden live mail OAuth and immutable releases
2026-07-30 02:00:09 +02:00

7.1 KiB

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:
celery -A config inspect ping
celery -A config inspect active
celery -A config inspect reserved
  1. Kijk naar timeouts, policyblokkades en retryloops.
  2. 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.
  • Microsoft 365 gebruikt uitsluitend app-only OAuth. Configureer M365_TENANT_ID, M365_CLIENT_ID, M365_CLIENT_SECRET, M365_MAILBOX_USER en EMAIL_BACKEND=apps.notifications.backends.Microsoft365OAuthEmailBackend. Verleen alleen IMAP.AccessAsApp en SMTP.SendAsApp, admin consent en mailboxscope; Basic Auth en Microsoft 365-app-wachtwoorden worden niet ondersteund.
  • 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:

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.