Pipeline di moderazione
Come Gemini, la quarantena e la revisione umana lavorano insieme per filtrare contenuti prima della pubblicazione.
Perché una pipeline a due fasi
I client non scrivono mai direttamente su poems. Ogni nuova poesia va in pendingPoems: uno staging invisibile al resto dell’app. Da lì una Cloud Function la consegna a Gemini 2.5 Flash e decide se promuoverla o metterla in quarantena. Stessa logica per commenti e foto profilo, con trigger diversi ma stesso contratto.
Separare staging e pubblicazione ha due vantaggi concreti: i client non conoscono l’esistenza di contenuti non approvati, e le Firestore rules possono proibire del tutto la scrittura diretta su poems.
Flusso di una poesia
client → pendingPoems/{id}
↓ onDocumentCreated
Gemini moderation
├─ approved → poems/{id} (moderationPassed: true)
│ ↓ sendNewPostNotification (follower push)
└─ blocked → quarantine + notifica autore ("contentHidden")
Il trigger sendNewPostNotification è anche lui su poems/{poemId}, ma controlla moderationPassed === true prima di procedere. Questo permette ai moderatori di forzare una pubblicazione manuale senza bypassare le notifiche.
Fail-open esplicito
Se Gemini non risponde — outage, quota, timeout — la poesia viene pubblicata comunque, ma marcata moderationDeferred: true con timestamp. Un utente non perde contenuto per problemi infrastrutturali non suoi; gli admin hanno un campo distinto da moderationPassed per eseguire un retry mirato, e i client più vecchi ignorano il flag aggiuntivo.
Il caso opposto — fail-safe — è riservato alle immagini: se una foto non può essere scaricata per essere analizzata, si blocca. Lasciar passare un’immagine non vista sarebbe più rischioso di perdere una pubblicazione.
Override moderatore
Il flag moderationOverride: true in pendingPoems segnala un’approvazione umana già avvenuta: la function salta la chiamata a Gemini e promuove direttamente. Serve per ripubblicare contenuti falsi-positivi senza pagare di nuovo la chiamata AI e senza rischiare un verdetto diverso alla seconda passata.
Commenti e foto profilo
- Commenti — stesso pattern: scritti in pending, valutati, promossi o eliminati. La notifica al destinatario parte solo dopo la promozione (
moderateCommentrimanda esplicitamente il triggersendCommentNotification). - Foto profilo — endpoint HTTP chiamato dal client subito dopo l’upload su Storage. Le funzioni scaricano i byte direttamente dal bucket e li passano a Gemini come
inlineData, senza URL pubblici intermedi. Esiste anche un triggermoderateLegacyProfilePhotosuusers/{uid}per intercettare cambi diretti al campophotoURLda client vecchi.
Revisione umana
L’admin panel e le segnalazioni utente si innestano nella stessa pipeline:
- Ogni evento di moderazione scrive un log consultabile dai moderatori.
notifyModerationOutcomeavvisa l’autore in-app quando il verdetto cambia (es. riabilitazione di contenuto prima bloccato).notifyModeratorsNewReportmanda un alert ai moderatori quando arriva una segnalazione utente.
Il risultato è un sistema in cui Gemini filtra il volume, e gli umani vedono solo i casi ambigui o segnalati.