Plan - Migration Formulaires vers Cloudflare D1 & Email Routing
Plan d’Exécution — Persistance D1 & Alertes Email Routing
Section titled “Plan d’Exécution — Persistance D1 & Alertes Email Routing”- Date : 2026-10-29
- Statut : Proposé (En attente de validation)
- Références :
- Dépôts / Modules concernés :
amn-services/submission-processor(Consumer Queue, D1 & Email Sending)amn-services/form-handler(Producer Queue)- Base de données Cloudflare D1 (
amn-submissions-dev/amn-submissions-prod) - Configuration CI/CD GitHub Actions (
.github/workflows/deploy-submission-processor.yml,redeploy-secrets.yml)
1. Objectifs du Projet
Section titled “1. Objectifs du Projet”- Remplacement de Sanity par Cloudflare D1 :
- Les soumissions de formulaires (contact et newsletter) ne sont plus archivées dans Sanity CMS.
- Création et initialisation d’une table SQL
submissionsdans Cloudflare D1. - Suppression de
@sanity/clientet des tokens/secrets Sanity du workersubmission-processor.
- Notification d’alerte par email native (Contact) :
- Pour chaque soumission de type
contact, envoyer automatiquement un email de notification formaté (HTML et texte) à l’adresse de l’organisation (env.NOTIFICATION_EMAIL_TO) via le service natif Cloudflare Email Routing / Email Sending (env.EMAIL.send()).
- Pour chaque soumission de type
- Maintien intégral de la logique Loops (Newsletter) :
- Conserver la logique asynchrone d’enregistrement des abonnés newsletter vers Loops (Form Endpoint Double Opt-In et REST API fallback).
- Stricte conformité de sécurité :
- Aucun secret ou ID en clair dans
wrangler.json. - Bindings et variables gérés via
.dev.vars(local), Cloudflare Secrets (remote) et GitHub Actions Secrets (CI/CD).
- Aucun secret ou ID en clair dans
2. Découpage par Phases
Section titled “2. Découpage par Phases”Phase 1 : Schéma SQL & Provisioning de la Base Cloudflare D1
Section titled “Phase 1 : Schéma SQL & Provisioning de la Base Cloudflare D1”- 1.1. Création du fichier
schema.sql:CREATE TABLE IF NOT EXISTS submissions (id TEXT PRIMARY KEY,type TEXT NOT NULL,name TEXT,email TEXT NOT NULL,message TEXT,source TEXT,submitted_at TEXT NOT NULL); - 1.2. Provisioning des bases D1 sur Cloudflare :
- Création de la base dev :
npx wrangler d1 create amn-submissions-dev. - Application du schéma en local :
npx wrangler d1 execute amn-submissions-dev --local --file=./schema.sql. - Application du schéma sur Cloudflare :
npx wrangler d1 execute amn-submissions-dev --remote --file=./schema.sql.
- Création de la base dev :
- 1.3. Configuration des bindings dans
wrangler.json:- Déclarer le bloc
d1_databasesavec le bindingDB. - Déclarer le bloc
send_emailavec le bindingEMAIL.
- Déclarer le bloc
Phase 2 : Refactorisation du Worker submission-processor
Section titled “Phase 2 : Refactorisation du Worker submission-processor”- 2.1. Nettoyage des dépendances Sanity :
- Désinstaller
@sanity/client(pnpm remove @sanity/client). - Installer les utilitaires d’emails légers (
pnpm add mimetextpour la composition MIME).
- Désinstaller
- 2.2. Mise à jour de l’interface
Env(src/index.ts) :export interface Env {ENVIRONMENT: string;DB: D1Database;EMAIL?: SendEmail;NOTIFICATION_EMAIL_TO?: string;NOTIFICATION_EMAIL_FROM?: string;LOOPS_API_KEY?: string;LOOPS_FORM_ID?: string;LOOPS_MAILING_LIST_ID?: string;LOOPS_USER_GROUP?: string;LOOPS_DEFAULT_SOURCE?: string;} - 2.3. Mise à jour de
fetch()(/healthet/test-direct) :- Dans
/health: remplacer les indicateurs Sanity par l’état du bindingdatabaseConfigured: Boolean(env.DB)etemailConfigured: Boolean(env.EMAIL). - Dans
/test-direct: remplacer la mutationsanityClient.create()par une insertion SQL préparée dansenv.DB.
- Dans
- 2.4. Mise à jour du gestionnaire de Queue (
queue()) :- Étape 1 (Persistance D1) : Exécuter
INSERT INTO submissionspour chaque message du lot. - Étape 2 (Alerte Email) : Si
submission.type === 'contact'et sienv.EMAILest disponible, construire le courriel MIME et l’expédier viaenv.EMAIL.send(). - Étape 3 (Synchronisation Loops) : Si
submission.type === 'newsletter', exécuterregisterLoopsContact()(inchangé).
- Étape 1 (Persistance D1) : Exécuter
Phase 3 : Vérification et Alignement du Worker form-handler
Section titled “Phase 3 : Vérification et Alignement du Worker form-handler”- 3.1. Revue du schéma Zod et de l’interface
Env:- Vérifier que
form-handlerreste strictement focalisé sur la validation et l’envoi dansSUBMISSIONS_QUEUE. - S’assurer qu’aucune dépendance Sanity résiduelle n’existe dans ce Worker.
- Vérifier que
Phase 4 : Mise à jour des Secrets & Workflows CI/CD
Section titled “Phase 4 : Mise à jour des Secrets & Workflows CI/CD”- 4.1. Configuration de
.dev.vars:- Retirer
SANITY_PROJECT_ID,SANITY_DATASET,SANITY_API_WRITE_TOKEN. - Ajouter
NOTIFICATION_EMAIL_TO=andsinus.ai@gmail.com. - Ajouter
NOTIFICATION_EMAIL_FROM=hello@amn-mail-dev.lasommedesrosees.com.
- Retirer
- 4.2. Configuration des secrets Cloudflare & GitHub Actions :
- Injecter
NOTIFICATION_EMAIL_TOetNOTIFICATION_EMAIL_FROMviawrangler secret put. - Mettre à jour
.github/workflows/deploy-submission-processor.ymletredeploy-secrets.ymlpour purger les étapes Sanity et injecter les nouvelles variables d’alerte email.
- Injecter
Phase 5 : Recette & Validation de Bout en Bout
Section titled “Phase 5 : Recette & Validation de Bout en Bout”- 5.1. Test unitaire SQL D1 :
- Vérifier l’insertion et la sélection dans la table
submissionsviawrangler d1 execute.
- Vérifier l’insertion et la sélection dans la table
- 5.2. Test d’une soumission Contact :
- Soumettre un formulaire de contact depuis
amn-blogou via curl surform-handler. - Vérifier la création de la ligne dans D1 (
type: 'contact'). - Vérifier la réception de l’email d’alerte dans la boîte de destination
NOTIFICATION_EMAIL_TO(andsinus.ai@gmail.com).
- Soumettre un formulaire de contact depuis
- 5.3. Test d’une soumission Newsletter :
- Soumettre une inscription depuis le prefooter.
- Vérifier la création de la ligne dans D1 (
type: 'newsletter'). - Vérifier le déclenchement de l’email Double Opt-In dans Loops.
3. Critères d’Acceptation (Definition of Done)
Section titled “3. Critères d’Acceptation (Definition of Done)”- Le fichier
schema.sqlest présent à la racine desubmission-processoret la tablesubmissionsest active dans D1. -
@sanity/clientest complètement retiré desubmission-processor. - Toutes les soumissions (contact et newsletter) sont stockées dans D1.
- Tout contact soumis génère un email d’alerte à l’adresse de l’entreprise via Cloudflare Email Routing (
andsinus.ai@gmail.com). - Les newsletters continuent d’être synchronisées dans Loops sans régression.
- Aucun secret en clair dans
wrangler.jsonet build TypeScript sans erreur (pnpm exec tsc --noEmitcode 0).