Ajoute deux entrées au menu d’administration. Les campagnes s’affichent dans un tableau vide honnête. Les statistiques disent clairement qu’aucune mesure n’est encore branchée, sans afficher de zéro trompeur.
296 lines
33 KiB
Markdown
296 lines
33 KiB
Markdown
# Memento — Plan administration : marketing, statistiques et offres Stripe
|
||
|
||
Date : 6 septembre 2026.
|
||
Statut : plan en cours. M1 livré le 6 septembre 2026 (navigation et pages de travail). Aucun envoi, aucun coupon, aucun chiffre inventé.
|
||
Demande : examiner l'administration et préparer un plan détaillé avant toute implémentation.
|
||
Périmètre de cette session : lectures du code, consultation de documentation officielle, observation locale de `/admin` et `/admin/billing`, rédaction de ce document. Aucun courriel envoyé, aucun coupon créé, aucune donnée modifiée.
|
||
|
||
## 1. Objectif et décisions proposées
|
||
|
||
Permettre à un administrateur de préparer des courriels de relance ou de présentation de Memento, choisir leurs destinataires, joindre une offre commerciale réellement applicable dans Stripe, vérifier le message, envoyer une campagne et mesurer son résultat.
|
||
|
||
Ajouter deux entrées à l'administration :
|
||
- **Marketing** : campagnes, audiences, modèles de courriel, offres et préférences d'envoi.
|
||
- **Statistiques** : revenus, abonnements, activité produit et résultats des campagnes.
|
||
|
||
Conserver **Facturation & quotas** comme référence pour les tarifs, les identifiants de prix et les limites IA. Les offres ne constituent pas un deuxième catalogue tarifaire.
|
||
|
||
Proposition de première version : campagnes manuelles, brouillons assistés par IA, test obligatoire, réductions en pourcentage, destinataires déjà inscrits et autorisés à recevoir de la prospection. Ajouter ensuite les montants fixes et les relances planifiées. Aucune séquence automatique active par défaut.
|
||
|
||
### Références fournies
|
||
|
||
Les deux captures de l'utilisateur représentent une autre application. Elles expriment des capacités souhaitées, pas une consigne de copier ses chiffres, sa marque ou ses activités.
|
||
- Capture marketing : génération IA, audience, réduction, sujet, contenu, aperçu, test et historique.
|
||
- Capture statistiques : période, revenus, abonnements et usage.
|
||
- Fichiers source des captures : `/home/devparsa/.codex/attachments/d3ab1333-8c84-4124-af46-d4dd77f73aab/codex-clipboard-04125874-6e48-421f-970c-ffc9b3641a13.png` et `/home/devparsa/.codex/attachments/3147e261-0b19-4103-a242-8d1ad26e2720/codex-clipboard-b9c36100-7ca2-4c48-83f2-00255b6e710c.png`.
|
||
|
||
Ne pas reprendre « traductions », « liste d'attente » ou d'autres fonctions sans équivalent confirmé dans Memento. Préférer une interface de travail structurée à une accumulation de grandes cartes vides.
|
||
|
||
## 2. État actuel vérifié
|
||
|
||
| Élément | Présent | Conséquence |
|
||
| --- | --- | --- |
|
||
| Navigation admin | `memento-note/components/admin-sidebar.tsx` : accueil, utilisateurs, IA, facturation, publications, paramètres | Ajouter deux destinations sans réorganiser toute l'administration |
|
||
| Accueil admin | `app/(admin)/admin/page.tsx` : utilisateurs, notes, carnets, agents, abonnements et usage | Garder cette synthèse ; fournir les analyses détaillées dans Statistiques |
|
||
| Facturation | `app/(admin)/admin/billing/`, `app/actions/admin-billing.ts` | Réutiliser configuration métier en base et contrôles administrateur |
|
||
| Paiement abonnement | `app/api/billing/create-checkout/route.ts` | `allow_promotion_codes: true` existe dans les deux modes de paiement ; pas de parcours de campagne dans cette route |
|
||
| Stripe | `lib/stripe.ts` ; version API déclarée `2026-04-22.dahlia` | Vérifier les types de la version installée avant d'écrire les paramètres de coupons |
|
||
| Notifications Stripe | `app/api/billing/webhook/route.ts` | Gère notamment abonnement, fin d'essai et échec de paiement ; compléter le journal financier et la déduplication si absents |
|
||
| Courriels | `lib/mail.ts` : Resend et SMTP, identifiant de message, repli automatique entre fournisseurs | Ne pas utiliser le repli aveugle pour les campagnes : un délai dépassé peut masquer un envoi déjà accepté |
|
||
| Rappel d'essai | `lib/billing/trial-reminder-email.ts` | Éviter les doublons avec les futures relances |
|
||
| Données | `User`, `Subscription`, `UsageLog`, `AiConsentLog`, `AuditLog` dans `prisma/schema.prisma` | Étendre les modèles existants avec migrations additives |
|
||
| Historique d'usage | `UsageLog` agrège par utilisateur, fonction et période | Insuffisant pour reconstruire honnêtement un usage quotidien historique |
|
||
| Consentement marketing | Non identifié dans les modèles examinés | Ne pas assimiler consentement IA, compte vérifié ou abonnement à un consentement marketing |
|
||
| Dernière activité et langue marketing | Pas de champs dédiés identifiés sur `User` | Définir des sources fiables avant les segments « inactifs » et les envois multilingues |
|
||
|
||
Les valeurs vues localement ne décrivent pas la production. Ne pas présenter les compteurs locaux comme chiffres commerciaux.
|
||
L'accueil actuel transforme certaines erreurs de lecture en zéro : ne pas reproduire ce comportement dans les nouvelles statistiques.
|
||
|
||
## 3. Parcours et composition des écrans
|
||
|
||
### 3.1 Marketing : liste des campagnes
|
||
|
||
Route proposée : `/admin/marketing`.
|
||
Tableau avec nom interne, objectif, audience, langue, offre associée, état, date prévue, acceptés par le fournisseur, délivrés et conversions payées.
|
||
Actions : créer, reprendre un brouillon, dupliquer, consulter les résultats, suspendre les messages restants. Pagination et filtres d'état.
|
||
Une duplication crée un nouveau brouillon et exige un nouveau test ; elle ne déclenche aucun envoi.
|
||
|
||
### 3.2 Préparation d'une campagne
|
||
|
||
Route : `/admin/marketing/campaigns/[id]`.
|
||
Parcours en quatre étapes, brouillon sauvegardé entre les étapes :
|
||
1. **Objectif et destinataires** : nouveauté produit, découverte d'une fonction, fin d'essai commerciale, retour après inactivité, réabonnement, fidélisation. Définition d'audience et exclusions chiffrées.
|
||
2. **Message et offre** : sujet, texte d'aperçu de boîte mail, contenu, bouton principal, éventuelle réduction. Éditeur visuel adapté au courriel ; code HTML dans une vue avancée, pas comme outil principal.
|
||
3. **Aperçu et test** : ordinateur/téléphone, version texte, valeurs de personnalisation fictives, conditions de réduction et pied de page réel. Adresse de test explicite. Test obligatoire pour chaque variante linguistique finale.
|
||
4. **Validation et envoi** : nombre final, différences depuis la préparation, exclusions, coût d'envoi si connu, échéance de l'offre, résumé de consentement. Commande finale explicite, puis progression et annulation des envois non commencés.
|
||
|
||
L'IA propose un brouillon, jamais un envoi. Une correction de sujet, contenu, offre, liens, modèle, expéditeur ou langue invalide le test correspondant.
|
||
L'audience est revue au moment de l'envoi ; un changement de taille important doit être visible avant confirmation.
|
||
Éviter les cartes imbriquées et les longs formulaires entièrement ouverts. Aides contextuelles, sauvegarde visible et messages d'erreur au bon champ.
|
||
|
||
### 3.3 Audiences
|
||
|
||
Audiences de départ : comptes autorisés à recevoir des annonces ; utilisateurs BASIC ; essais en cours/fin prochaine ; abonnés payants par formule et périodicité ; anciens abonnés ; langue connue.
|
||
La présence d'un compte Stripe ne prouve pas un abonnement payant. Distinguer utilisateurs inscrits, abonnés à la communication et abonnés payants dans les libellés.
|
||
|
||
Les segments « inactifs depuis N jours » exigent une mesure d'activité humaine documentée. `User.updatedAt`, les notes créées par des agents et les accès automatiques ne sont pas de bons substituts à une dernière visite.
|
||
Exclusions : désabonnement marketing, absence de base d'envoi autorisée, plainte, adresse définitivement invalide, compte supprimé, adresse non vérifiée selon politique retenue, plafonnement de fréquence, destinataire incompatible avec l'offre.
|
||
Afficher les raisons et les nombres, avec détails accessibles uniquement aux administrateurs autorisés. Pas d'import arbitraire de fichiers d'adresses dans la première version.
|
||
|
||
### 3.4 Génération assistée
|
||
|
||
Champs : objectif, consignes, langue, ton, offre facultative. Fournisseur et modèle issus du catalogue serveur vivant, sélection avancée si utile.
|
||
Contexte autorisé : description validée de Memento, fonctions réellement livrées, tarifs du catalogue, essai de 7 jours, conditions exactes de l'offre.
|
||
Interdit : lire le contenu privé des notes pour cibler un message ; inventer des chiffres, témoignages, promesses ou conditions commerciales.
|
||
Produire une structure validée : sujet, aperçu, blocs de texte, bouton, mentions de l'offre. Générer ensuite le HTML avec un modèle maîtrisé et une version texte.
|
||
Échapper les personnalisations, limiter taille et liens, neutraliser scripts/événements HTML, isoler l'aperçu. Les consignes saisies ne peuvent pas déclencher d'outil d'envoi ou de création Stripe.
|
||
Créer une fonction IA dédiée `marketing_email` dans le mécanisme existant d'entitlements et réservation atomique ; quota administratif configurable dans Facturation. Réserver avant l'appel, sans remboursement automatique sur échec, et notifier le compteur d'usage. Ne pas facturer silencieusement les destinataires.
|
||
|
||
## 4. Offres et coupons Stripe
|
||
|
||
### 4.1 Modèle métier
|
||
|
||
Un **coupon Stripe** définit la réduction. Un **code promotionnel Stripe** la distribue avec ses restrictions. Une **offre Memento** relie campagne, conditions, coupon/code et suivi.
|
||
Ne pas créer une remise uniquement dans le courriel ou le navigateur.
|
||
|
||
Champs de l'offre : nom interne, réduction en pourcentage ou montant/devise, formules admissibles, mensualité/annualité, date limite d'activation avec fuseau affiché, durée d'application, maximum d'utilisations, bénéficiaires et état de synchronisation.
|
||
Séparer clairement **date limite pour profiter de l'offre** et **durée de la réduction après activation**.
|
||
Montants en unités monétaires entières, pas en nombres flottants. Une offre publiée est versionnée ; on ne modifie pas rétroactivement les conditions des messages déjà envoyés.
|
||
|
||
### 4.2 Offre de départ recommandée
|
||
|
||
« 20 % de réduction sur la prochaine facture mensuelle admissible du forfait Pro », réservée à une audience précise, avec date d'expiration et un usage par bénéficiaire.
|
||
Préférer une durée bornée à une réduction permanente proposée par défaut. Ne pas écrire « pendant 7 jours » pour confondre validité du lien et durée de la remise.
|
||
Pour un forfait annuel, afficher le total annuel réduit et l'équivalent mensuel ; préciser que la réduction porte sur une facture annuelle. Ne jamais présenter une réduction annuelle comme un seul mois offert.
|
||
|
||
Avec l'essai gratuit de 7 jours, vérifier en mode Stripe test quelle facture consomme la remise, notamment une facture initiale à zéro. Ne promettre « première facture payante » qu'après validation du comportement de la version d'API utilisée. La restriction Stripe « premier achat » peut exclure une personne ayant déjà démarré un essai : ne pas l'activer aveuglément pour une relance de fin d'essai.
|
||
|
||
### 4.3 Distribution recommandée
|
||
|
||
Deux modes : code partagé pour une campagne publique ; code individuel restreint au client Stripe pour une offre ciblée. Préférer le second pour fidélisation et réactivation.
|
||
Bouton du courriel vers une route Memento, avec jeton opaque et date de validité ; aucun courriel ou identifiant personnel lisible dans l'URL. Le code reste copiable comme solution de secours si prévu.
|
||
Un simple clic GET, y compris par un robot d'analyse de courriel, ne crée pas de réduction, d'abonnement ou de réservation consommable.
|
||
Après connexion, vérifier le destinataire, l'offre, la formule et les restrictions. Afficher le prix et les conditions ; appliquer uniquement après action utilisateur explicite.
|
||
Le lien doit retrouver l'offre après authentification, sans redirection ouverte et sans divulguer les données du bénéficiaire.
|
||
|
||
### 4.4 Nouvel abonnement versus abonnement existant
|
||
|
||
- **Sans abonnement payant actif** : enrichir la création de session existante avec l'offre validée côté serveur. Choisir soit remise préappliquée, soit saisie libre de code ; vérifier la compatibilité API, ne pas transmettre les deux options sans contrôle. Préserver les deux modes de paiement.
|
||
- **Abonné actif** : ne pas créer un second abonnement. Prévoir une application contrôlée sur l'abonnement existant, avec aperçu de la prochaine facture, consentement explicite et règles de cumul. La version initiale peut exclure ces personnes des campagnes de conversion, mais le parcours de fidélisation reste une livraison identifiée.
|
||
- **Annulation programmée / impayé** : expliquer ce que l'offre change ; elle ne réactive pas automatiquement un abonnement et ne règle pas un impayé. Ne pas modifier le calendrier ni les proratisations à l'insu du client.
|
||
|
||
Le serveur et Stripe font autorité sur les limites. Une restriction par périodicité doit être contrôlée côté Memento : les restrictions Stripe par produit ne suffisent pas forcément lorsque le même produit porte un prix mensuel et annuel.
|
||
Séparer strictement mode test et mode réel dans les données, codes, compteurs et interfaces.
|
||
Réconciliation des objets Stripe modifiés depuis son interface. Désactiver les nouveaux usages sans prétendre retirer les remises déjà appliquées.
|
||
Création et activation idempotentes ; journal des objets créés et état récupérable si Stripe réussit mais que la sauvegarde locale échoue.
|
||
|
||
## 5. Consentement, délivrabilité et envoi fiable
|
||
|
||
### 5.1 Préférences
|
||
|
||
La première version doit privilégier un consentement marketing explicite, distinct de l'inscription, de l'IA et des courriels nécessaires au service. Les utilisateurs historiques ne sont pas automatiquement inscrits aux campagnes.
|
||
Prévoir un choix dans les préférences utilisateur et, si validé, à l'inscription, non précoché. Journaliser texte/version, date, source et retrait. Une exception de prospection client ne doit être activée que si ses conditions sont établies ; la seule création d'un compte ne suffit pas. Voir la source CNIL en fin de document.
|
||
Ne pas envoyer un courriel commercial de « demande de consentement » aux exclus comme contournement.
|
||
Le désabonnement marketing ne bloque pas vérification de compte, réinitialisation de mot de passe ou notifications indispensables de facturation. Une remise promotionnelle n'est pas ajoutée à ces messages transactionnels pour contourner les règles.
|
||
|
||
Lien de désabonnement sans connexion, signé/opaque, indépendant de la durée de l'offre. GET affiche la page de confirmation pour éviter les désabonnements par robots ; POST traite l'action. Ajouter les en-têtes de désabonnement en un clic conformément aux fournisseurs, avec POST sans session pour cette voie spécifique. Recontrôler l'exclusion juste avant chaque envoi.
|
||
Retrait global marketing immédiat ; plaintes et rebonds définitifs ajoutent une suppression. Une campagne déjà confiée au fournisseur ne peut pas être rappelée : le signaler honnêtement.
|
||
|
||
### 5.2 Service d'envoi
|
||
|
||
Préférer Resend explicitement pour les campagnes, car les événements de livraison sont exploitables. Garder les messages transactionnels sur le service existant. SMTP reste une option identifiée avec limites de mesure ; ne pas promettre un statut « délivré » sur le seul succès SMTP.
|
||
Étendre le transport sans casser ses appelants : texte alternatif, en-têtes autorisés, identifiant de campagne, identifiant de message, clé d'idempotence. Fournisseur fixé par exécution.
|
||
File durable en PostgreSQL pour la vérité des destinataires et états ; Redis peut aider à la limitation et au verrouillage. Réutiliser les pratiques de tâches planifiées du dépôt avant d'ajouter une dépendance. Aucun envoi de masse dans une requête HTTP longue ni simple tâche mémoire.
|
||
Réservation atomique d'un message, bail limité, reprises avec délai et nombre d'essais borné. État `UNKNOWN` pour un résultat fournisseur ambigu ; ne pas basculer automatiquement sur SMTP. Vérifier le fournisseur avant réémission et tenir compte de sa fenêtre de déduplication.
|
||
Une clé unique campagne/exécution/destinataire/langue empêche les doublons métier. Un redémarrage ou double clic d'administrateur ne recrée pas les destinataires.
|
||
Ne pas utiliser BCC pour diffuser à toute une audience. Envoi individualisé, sans exposition d'autres adresses.
|
||
Rythme progressif, plafond global et par personne configurables, pause manuelle et automatique si plaintes ou erreurs anormales. Seuils configurables, pas de valeurs fournisseur inventées.
|
||
|
||
### 5.3 Test et validation serveur
|
||
|
||
Version immuable du message : sujet, aperçu, blocs, rendu HTML/texte, modèle, offre, liens, expéditeur et langue. Empreinte calculée côté serveur.
|
||
Un test accepté par le fournisseur pour cette version autorise une validation humaine ; il ne prouve pas la réception en boîte principale. Le statut doit refléter cette distinction.
|
||
À l'envoi réel, vérifier la version testée, l'identité administrateur, la validité de l'offre, les variantes de langue et l'état de campagne dans une transition atomique.
|
||
Les liens individuels sont issus de paramètres contrôlés ; tester leur structure sans consommer une vraie réduction. Toute modification structurelle après test invalide celui-ci.
|
||
Tests et aperçus ne comptent pas dans les conversions ni statistiques de campagne.
|
||
|
||
## 6. Statistiques : indicateurs utiles et définitions
|
||
|
||
Route `/admin/stats`. Période globale, comparaison à période précédente de même durée, fuseau explicite, date de dernière synchronisation et actualisation manuelle. Ne pas recopier une période « 30 jours » sur une carte pilotée par « Aujourd'hui ».
|
||
Sections : **Revenus**, **Abonnements**, **Usage**, **Campagnes**. Quatre à six indicateurs principaux par section, courbes utiles et tableaux détaillables ; pas de grandes zones vides artificielles.
|
||
|
||
| Indicateur | Définition et source attendue |
|
||
| --- | --- |
|
||
| Encaissements de la période | Paiements effectivement réussis, datés au paiement ; séparés des factures créées et des sessions terminées |
|
||
| Remboursements | Montants réellement remboursés sur la période ; montrer séparément brut encaissé et net après remboursement, en précisant traitement des taxes/frais |
|
||
| Revenus récurrents mensuels estimés | Récurrent contractuel actif ramené au mois, annuel / 12 ; exclure crédits ponctuels et essais non payants ; distinguer avant et après remises récurrentes |
|
||
| Abonnements | Payants actifs, essais, annulations programmées, terminés, impayés ; ne pas mélanger les statuts |
|
||
| Conversion d'essai | Cohorte d'essais ayant eu le temps d'arriver à échéance, puis premier paiement réussi ; exclure cohorte encore immature |
|
||
| Résiliations | Abonnements réellement terminés pendant la période / base active au début ; afficher nombre et formule |
|
||
| Activité humaine | Utilisateurs ayant une action produit définie ; ne pas déduire l'activité de créations automatiques de notes |
|
||
| Usage IA | Réservations/consommations par fonction, séparées des appels réussis/échoués ; `UsageLog` seul ne donne ni détail quotidien ni taux d'erreur |
|
||
| Campagnes | Destinataires autorisés, acceptés, délivrés, rebonds, plaintes, désabonnements, clics si autorisés, offres appliquées, paiements attribués |
|
||
|
||
Plusieurs devises : jamais additionner sans conversion explicite documentée. Version initiale : tableaux séparés par devise. Aucun MRR calculé en multipliant tous les abonnés par le prix public actuel.
|
||
Le cumul historique doit afficher sa date de couverture. Ne pas inventer une série quotidienne à partir d'agrégats mensuels. Prévoir import paginé Stripe en lecture seule, reprise et déduplication pour l'historique disponible.
|
||
Échecs de synchronisation : « indisponible » ou « données au [date] », jamais zéro silencieux. Si dénominateur nul, afficher « non calculable » plutôt que 100 % de réussite.
|
||
La comparaison ne doit pas mélanger données test et réelles, période complète et période partielle.
|
||
|
||
### Attribution commerciale
|
||
|
||
Transporter des identifiants opaques de campagne/offre dans les métadonnées de paiement puis les objets nécessaires au rapprochement des factures. Une session terminée avec essai n'est pas un revenu.
|
||
Version initiale : conversion directe si offre de campagne appliquée et paiement réussi, au plus une première conversion par abonnement/campagne ; présenter séparément nombre d'acheteurs et total de leurs paiements attribués.
|
||
Déduire les remboursements selon une règle explicitée. Un code partagé peut circuler hors audience : distinguer usages du code et conversions prouvées d'un destinataire.
|
||
Ouvertures de courriel non prioritaires, tracking désactivé par défaut : elles ne sont pas une preuve fiable de lecture. Les clics peuvent inclure des robots ; ne pas les appeler utilisateurs engagés sans qualification. L'attribution ne prouve pas que la campagne a causé la vente.
|
||
Budget/coût fournisseur inconnu : ne pas afficher un retour sur investissement ou une marge fictive. Le classement des utilisateurs reste un outil admin agrégé, sans exposer leurs notes privées.
|
||
|
||
## 7. Architecture et données proposées
|
||
|
||
Les noms suivants sont des propositions, pas des modèles déjà présents. Adapter au schéma réel sans créer de doublons.
|
||
|
||
| Modèle | Rôle / contraintes essentielles |
|
||
| --- | --- |
|
||
| MarketingPreference + journal | Choix actuel par utilisateur/adresse, langue préférée, preuve/version et historique ; opposition conservée selon politique de rétention |
|
||
| EmailSuppression | Adresse normalisée ou empreinte compatible avec la politique de données, motif, source et date ; filtrage avant envoi |
|
||
| MarketingCampaign | Objectif, auteur, segment versionné, statut, programmation, dernière version |
|
||
| CampaignVersion | Contenu et conditions immuables par langue, empreinte, modèle IA et version de modèle de courriel |
|
||
| CampaignTest | Version testée, administrateur, adresse de test protégée, résultat fournisseur et validation |
|
||
| CampaignRun | Audience figée, exclusions, version approuvée, compteurs et progression |
|
||
| CampaignRecipient | Unicité run/utilisateur/variante ; état, essais, bail, identifiant fournisseur, version rendue, erreurs expurgées |
|
||
| MarketingOffer | Conditions versionnées, mode Stripe, identifiants coupon/code, statut, limites et dates |
|
||
| OfferClaim | Bénéficiaire, code individuel éventuel, état de réservation/application et lien abonnement/facture ; unicité anti-double application |
|
||
| ProviderEvent | Fournisseur + identifiant événement uniques, signature vérifiée, horodatage, traitement et erreurs |
|
||
| BillingTransaction / projection facture | Identifiants Stripe uniques, devise, montants, paiement/remboursement, campagne/offre et dates ; source financier locale réconciliable |
|
||
| ProductActivity / agrégat | Événements minimaux nécessaires aux statistiques futures ; aucune note ni consigne privée dans la mesure |
|
||
|
||
Index : état/date prévue pour tâches ; run/état pour destinataires ; fournisseur/eventId ; mode Stripe/objet ; user/date pour activité. Pagination des audiences. Durées de conservation configurées et documentées, pas conservation illimitée des contenus et adresses de campagne par défaut.
|
||
Journal `AuditLog` pour création, validation, envoi, pause, changement d'offre et accès/export sensibles. Ne pas stocker secrets, corps privés ou jetons utilisables dans les journaux.
|
||
|
||
États campagne : DRAFT → READY → SCHEDULED ou QUEUED → SENDING → COMPLETED/PARTIAL_FAILED ; PAUSED/CANCELED pour le restant. Une édition après READY crée une nouvelle version et retire l'approbation.
|
||
État destinataire : PENDING → SENDING → ACCEPTED → DELIVERED ; FAILED/UNKNOWN/SUPPRESSED selon résultat. Les événements arrivent parfois en désordre ; conserver les faits plutôt qu'écraser une plainte par une livraison tardive.
|
||
|
||
### Routes/services envisagés
|
||
|
||
- Pages sous `app/(admin)/admin/marketing/` et `app/(admin)/admin/stats/`.
|
||
- Services sous `lib/marketing/` : audiences, contenu, validation, offres, envoi, suppression, attribution.
|
||
- Actions/API admin : campagnes CRUD, audience-preview, generate, test, approve-send, pause, resume ; offres create/sync/deactivate ; statistiques read/export.
|
||
- `/api/marketing/unsubscribe` public à jeton ; `/api/marketing/email-webhook` public à signature fournisseur.
|
||
- `/offers/[token]` pour consulter l'offre, puis endpoint authentifié POST pour l'appliquer ; aucun effet facturation sur GET.
|
||
- Étendre le webhook Stripe existant, sans second traitement concurrent des mêmes événements. Vérifier la signature sur corps brut, dédupliquer, enregistrer durablement puis traiter/reprendre.
|
||
- Tâche d'envoi et tâche de réconciliation utilisant le mécanisme cron/worker existant ; protection par secret serveur et verrous.
|
||
|
||
Chaque action admin vérifie le rôle côté serveur, y compris aperçu d'audience, génération, export et endpoints appelés directement. Contrôles CSRF/origine adaptés aux sessions, limitations de fréquence et validation Zod. URL publiques depuis configuration serveur approuvée, pas depuis un Host utilisateur non validé. Aucun domaine ou IP codé en dur dans le produit.
|
||
|
||
## 8. Livraison par fonctionnalités
|
||
|
||
Une fonctionnalité à la fois, vérification et validation utilisateur avant la suivante. Les dépendances de fondation peuvent être développées sans activer les envois réels.
|
||
|
||
| Ordre | Livraison | Acceptation principale |
|
||
| --- | --- | --- |
|
||
| M1 | Navigation et pages de travail | **Livré** — `/admin/marketing`, `/admin/stats`, menu admin. Tableau campagnes vide honnête ; statistiques « pas encore disponible » (pas de zéro). Fichiers : `admin-sidebar.tsx`, `app/(admin)/admin/marketing/`, `app/(admin)/admin/stats/`, clés i18n `admin.marketing` / `admin.stats`. |
|
||
| M2 | Préférences et exclusions | Consentement explicite, retrait sans connexion, anciennes inscriptions non admises automatiquement |
|
||
| M3 | Audiences | Nombre cohérent, exclusions expliquées, segmentation réelle, pas d'utilisation de notes privées |
|
||
| M4 | Brouillons et éditeur | Sauvegarde, version texte/HTML, aperçu sécurisé, personnalisation contrôlée |
|
||
| M5 | Génération IA | Modèle serveur, consignes produit validées, langue et réservation de quota, aucun envoi automatique |
|
||
| M6 | Offres Stripe test | Création/version/synchronisation, 20 %, expiration, limites et séparation test/réel |
|
||
| M7 | Activation nouvel abonné | Offre validée côté serveur, parcours après login, interaction essai vérifiée, pas de double abonnement |
|
||
| M8 | Test et validation | Envoi test de version exacte, invalidation après modification, décision finale atomique |
|
||
| M9 | File et historique | Pause/reprise, absence de doublons métier, erreurs ambiguës gérées, exclusions revérifiées |
|
||
| M10 | Événements et mesures d'envoi | Signatures, doublons, désordre, rebonds/plaintes, test hors statistiques |
|
||
| M11 | Statistiques financières | Paiements/remboursements réconciliés, MRR défini, couverture et devises visibles |
|
||
| M12 | Usage et résultats marketing | Mesures disponibles distinguées des absentes, attribution directe vérifiable |
|
||
| M13 | Fidélisation abonnés actifs | Aperçu facture, consentement, application sur abonnement existant, cumul/prorata contrôlés |
|
||
| M14 | Planification et relances | Dates/fuseaux, règles explicites, plafonds, déduplication avec rappels existants, désactivé par défaut |
|
||
|
||
Options ultérieures, non autorisées par ce plan : tests de variantes A/B, import de prospects externes, séquences complexes, score automatique de propension, export public, comparaison causale de campagnes. Ne pas les développer spontanément.
|
||
|
||
## 9. Vérification et protection des données
|
||
|
||
Respecter l'interdiction actuelle d'écrire de nouveaux tests sans demande explicite. Préparer une matrice de vérification manuelle et exécuter les contrôles existants pertinents ; proposer une autorisation ciblée de tests automatisés pour ces mécanismes critiques lors de leur développement, sans la présumer acquise.
|
||
|
||
Scénarios indispensables :
|
||
- compte non administrateur refusé sur chaque endpoint ; aperçu HTML malveillant neutralisé ; liens externes non autorisés rejetés ; données privées absentes du contexte IA ;
|
||
- absence de consentement, retrait après mise en file, plainte, adresse invalide et dépassement de fréquence ;
|
||
- version modifiée après test, une langue non testée, offre expirée entre test et envoi ;
|
||
- double clic, deux workers, arrêt après acceptation fournisseur, événement reçu deux fois ou dans le désordre ;
|
||
- offre à 20 %, code d'un autre client, code partagé épuisé, mensualité contre annualité, coupon désactivé et ancien lien ;
|
||
- essai 7 jours, facture à zéro, premier paiement, abonnement actif, annulation programmée, remboursement partiel et plusieurs devises ;
|
||
- Stripe indisponible, historique incomplet, absence de données, erreur qui ne doit pas devenir zéro ;
|
||
- français, anglais, persan/RTL, écran de téléphone, clavier, lecture des conditions et liens de désabonnement ;
|
||
- comparaison des chiffres d'un jeu Stripe test avec son interface, sans utiliser la production comme banc d'essai.
|
||
|
||
Ne pas envoyer de vrais courriels, créer de coupons réels ou toucher à un abonnement réel sans autorisation explicite de l'utilisateur portant sur l'action concrète. Cette demande autorise uniquement le plan.
|
||
Migrations additives et procédure du dépôt. Aucune commande destructive. Ne pas intégrer des migrations au workflow de déploiement en contredisant les règles existantes.
|
||
|
||
## 10. Décisions à faire valider avant activation réelle
|
||
|
||
1. Expéditeur et adresse de réponse ; Resend recommandé pour les campagnes, transport transactionnel conservé.
|
||
2. Consentement explicite par défaut et parcours de recueil pour les utilisateurs existants.
|
||
3. Offre initiale : pourcentage, formule, durée, expiration, population ; aucune remise permanente présélectionnée.
|
||
4. Traitement de l'essai gratuit et des abonnés déjà actifs, après scénario Stripe test concluant.
|
||
5. Budget de génération IA et fréquence maximale d'envoi ; paramètres métier dans l'administration.
|
||
6. Langue préférée : source existante à identifier, stockage explicite si nécessaire ; ne pas deviner à partir du contenu des notes.
|
||
7. Suivi de clics et durée de conservation ; pas de suivi d'ouverture par défaut.
|
||
8. Définition finale du MRR et périmètre de l'historique importable ; ne pas annoncer de précision comptable non démontrée.
|
||
|
||
Ces décisions ne bloquent pas la lecture du code, la conception des écrans ou la préparation d'une migration additive. Elles bloquent seulement les actions qui dépendent réellement de leur réponse.
|
||
|
||
## 11. Sources officielles consultées
|
||
|
||
Vérifiées le 6 septembre 2026. Recontrôler les paramètres exacts contre les types Stripe/Resend installés au moment de l'implémentation.
|
||
- [Stripe : coupons et codes promotionnels](https://docs.stripe.com/billing/subscriptions/coupons) — distinction entre réduction et code, restrictions et application à un abonnement.
|
||
- [Stripe : réductions dans Checkout](https://docs.stripe.com/payments/checkout/discounts) — parcours de paiement et limites de remise.
|
||
- [Resend : clés d'idempotence](https://resend.com/docs/dashboard/emails/idempotency-keys) — déduplication fournisseur ; vérifier sa durée de validité lors de l'implémentation.
|
||
- [Resend : notifications serveur](https://resend.com/docs/webhooks/introduction) et [types d'événements](https://resend.com/docs/webhooks/event-types) — livraison, erreurs et réception potentiellement désordonnée.
|
||
- [CNIL : prospection par courrier électronique](https://www.cnil.fr/la-prospection-commerciale-par-courrier-electronique) — consentement, opposition et limites de l'exception client. Ce plan retient une politique explicite par défaut, pas une qualification juridique automatique de toute audience.
|
||
|
||
## 12. Reprise par un autre agent
|
||
|
||
- Lire ce document puis AGENTS.md, PRODUCT.md et le code réellement présent.
|
||
- Vérifier `git status` et la branche actuelle ; conserver tous les changements préexistants. Ne pas supposer que les anciens constats sont encore valides.
|
||
- Demander quelle fonctionnalité M1–M14 démarrer si aucune n'a été autorisée. Ne pas transformer la demande de plan en autorisation d'envoi ou d'implémentation complète.
|
||
- Utiliser des modèles légers pour recherche de fichiers et vérification de clés. Réserver l'analyse approfondie aux garanties d'envoi, aux remises et à la mesure financière.
|
||
- Chaque livraison met à jour ce document et `docs/user-stories.md` avec état, fichiers, vérifications, limites et prochaine étape. Ne pas marquer « terminé » sans preuve.
|
||
- Ne jamais recopier de secrets, sessions, adresses privées de test ou mots de passe dans les documents.
|
||
- Ne pas continuer les précédents chantiers de design de Carnets/éditeur : ils sont hors de ce périmètre.
|