Modération

difuzio met en attente certains messages et certaines demandes d'abonnement dans une file de modération (moderation_queue), et suspend automatiquement les listes dont la réputation se dégrade (kill-switch). Cette page décrit ces deux mécanismes et les leviers réellement disponibles dans la version actuelle.

La file de modération

Le pipeline de traitement des posts et le flux d'abonnement alimentent la file. Un élément est mis en attente (held) pour l'une de ces raisons (moderation_queue.reason) :

  • policy_moderated : la politique de la liste est moderated (tout passe en modération).
  • non_member : un non-abonné poste sur une liste réservée aux membres.
  • first_post : premier post d'un nouvel abonné (si la modération du premier post est activée).
  • auth_downgrade : l'authentification du message s'est dégradée par rapport à ce qui est attendu.
  • dmarc_inbound : échec DMARC entrant sur un domaine auteur en politique stricte (p=reject), pour une liste en politique open ou members.
  • command_suspect : une commande par email douteuse.
  • list_suspended : la liste est suspendue (kill-switch), les posts sont retenus.

Deux raisons supplémentaires (size_exceeded, spam_suspect) sont réservées pour une évolution ultérieure ; aucun chemin ne les émet dans la version actuelle.

Expiration automatique

Les éléments retenus expirent automatiquement au-delà de leur fenêtre : une tâche périodique du worker passe les éléments trop anciens à l'état expired (de même pour les demandes d'abonnement en attente). Aucun message n'est donc retenu indéfiniment.

Agir sur la file

La file se pilote en CLI et en API REST. En CLI :

difuzio moderation list    --domain lists.example.org --list announce
difuzio moderation approve --domain lists.example.org --list announce --id <id>
difuzio moderation reject  --domain lists.example.org --list announce --id <id> --note "raison"

moderation list affiche les éléments retenus (id, type, raison, date). approve et reject agissent indifféremment sur un post retenu ou une demande d'abonnement (le type est résolu automatiquement par l'identifiant). L'approbation d'un post le relâche immédiatement vers le fan-out ; l'approbation d'un abonnement crée l'abonné. Les décisions sont idempotentes (une seconde décision sur le même élément renvoie "déjà décidé").

En API REST (permission moderate) :

GET  /api/v1/domains/{domaine}/lists/{liste}/moderation/messages
GET  /api/v1/domains/{domaine}/lists/{liste}/moderation/subscriptions
POST .../moderation/messages/{id}/approve | /reject
POST .../moderation/subscriptions/{id}/approve | /reject

Les éléments non traités expirent toujours automatiquement au-delà de leur fenêtre (filet de sécurité).

Kill-switch de réputation

Indépendamment de la file, difuzio surveille la réputation de chaque liste et suspend son envoi quand les signaux deviennent mauvais. L'évaluation tourne en continu comme tâche périodique du worker (difuzio:killswitch).

Seuils

Sur une fenêtre glissante (reputation.window_days, 7 jours par défaut) et au-delà d'un plancher de volume (reputation.min_sent, 500 messages par défaut) :

  • taux de plaintes supérieur à complaint_rate_suspend (0,3 % par défaut) : suspension de l'envoi, raison complaint_rate ;
  • taux de rebonds durs supérieur à hard_bounce_rate_suspend (5 % par défaut) : suspension, raison bounce_rate ;
  • taux de plaintes supérieur à complaint_rate_warn (0,1 % par défaut) : alerte seulement, pas de suspension.

En deçà de min_sent messages sur la fenêtre, aucune suspension n'est déclenchée (plancher anti-bruit, pour ne pas pénaliser une petite liste sur quelques incidents).

Effet d'une suspension

Une liste suspendue (lists.send_suspended) cesse d'émettre ; les nouveaux posts sont retenus avec la raison list_suspended. La raison de suspension est enregistrée (complaint_rate, bounce_rate, ou manual).

Suspendre ou lever une suspension

La suspension et la réactivation manuelles d'une liste se font en CLI :

difuzio list-suspend --domain lists.example.org --list announce --note "raison"
difuzio list-resume  --domain lists.example.org --list announce

list-suspend pose une suspension manuelle (raison manual) ; list-resume efface la suspension (manuelle ou automatique). Ne lever une suspension qu'après avoir corrigé la cause : une réactivation prématurée fait replonger la réputation. Voir Délivrabilité pour le traitement des rebonds et des plaintes.