Files
ASPIC/journal/ASPIC-Journal. 18. Formulaire de Prospect Externe.md
T

24 KiB

18. Prospection — formulaire de prospect externe, vérification mail, suivi de lecture documentation (26 août 2026)

Contexte. Reprise du pivot amorcé le 23-25 août (sections 14 et 17) : premier chantier concret de prospection, avec un formulaire web public comme premier canal d'entrée. Décision actée en tout début de session : la partie "gestion des contacts" est laissée en l'état (voir section 7), le développement bascule sur cette nouvelle fonctionnalité. Chantier mené jusqu'au bout dans la même session : conception, développement, déploiement et test réel réussi en production.

Modèle de données — nouvelles tables (structures finales, créées par Jean-Marc au fil de la session).

CREATE TABLE `ASP_Campagnes` (
  `CMP_Incr` int NOT NULL AUTO_INCREMENT,
  `CMP_CodeCampagne` varchar(20) NOT NULL,
  `CMP_Explications` text,
  `CMP_DocDefaut` int DEFAULT NULL,
  `CMP_Creation` date NOT NULL DEFAULT (CURRENT_DATE),
  PRIMARY KEY (`CMP_Incr`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

CREATE TABLE `ASP_Prospects` (
  `PSP_Incr` int NOT NULL AUTO_INCREMENT,
  `PSP_Nom` varchar(40) DEFAULT NULL,
  `PSP_Prenom` varchar(40) DEFAULT NULL,
  `PSP_Statut` varchar(3) DEFAULT NULL,
  `PSP_Societe` varchar(40) DEFAULT NULL,
  `PSP_Service` varchar(40) DEFAULT NULL,
  `PSP_Fonction` varchar(40) DEFAULT NULL,
  `PSP_AdrLig1` varchar(40) DEFAULT NULL,
  `PSP_AdrLig2` varchar(40) DEFAULT NULL,
  `PSP_AdrLig3` varchar(40) DEFAULT NULL,
  `PSP_AdrCP` varchar(6) DEFAULT NULL,
  `PSP_AdrVille` varchar(40) DEFAULT NULL,
  `PSP_SIRET` varchar(20) DEFAULT NULL,
  `PSP_Tel` varchar(15) DEFAULT NULL,
  `PSP_Portable` varchar(15) DEFAULT NULL,
  `PSP_Mail` varchar(40) DEFAULT NULL,
  `PSP_Notes` text,
  `PSP_CodeProfession` int DEFAULT NULL,
  `PSP_CodeCampagne` varchar(20) NOT NULL,
  `PSP_IncrContact` int DEFAULT NULL,
  `PSP_MailVerifie` tinyint(1) NOT NULL DEFAULT '0',
  `PSP_TokenVerification` varchar(64) DEFAULT NULL,
  `PSP_TokenExpiration` datetime DEFAULT NULL,
  `PSP_Actif` tinyint(1) NOT NULL DEFAULT '1',
  PRIMARY KEY (`PSP_Incr`),
  KEY `PSP_Statut` (`PSP_Statut`),
  KEY `PSP_CodeProfession` (`PSP_CodeProfession`),
  KEY `PSP_CodeCampagne` (`PSP_CodeCampagne`),
  KEY `PSP_IncrContact` (`PSP_IncrContact`),
  UNIQUE KEY `PSP_TokenVerification` (`PSP_TokenVerification`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

CREATE TABLE `ASP_Operations` (
  `OPE_Incr` int NOT NULL AUTO_INCREMENT,
  `OPE_IncrProspect` int NOT NULL,
  `OPE_CodeUser` varchar(3) NOT NULL,
  `OPE_Date` datetime NOT NULL,
  `OPE_Action` varchar(20) NOT NULL,
  `OPE_Comment` text,
  PRIMARY KEY (`OPE_Incr`),
  KEY `OPE_IncrProspect` (`OPE_IncrProspect`),
  KEY `OPE_CodeUser` (`OPE_CodeUser`) USING BTREE,
  KEY `OPE_Action` (`OPE_Action`) USING BTREE,
  KEY `OPE_Date` (`OPE_Date`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

CREATE TABLE `ASP_Mails` (
  `MAI_Incr` int NOT NULL AUTO_INCREMENT,
  `MAI_Code` varchar(30) NOT NULL,
  `MAI_Objet` varchar(150) NOT NULL,
  `MAI_Corps` text NOT NULL,
  `MAI_CorpsHtml` text DEFAULT NULL,
  PRIMARY KEY (`MAI_Incr`),
  UNIQUE KEY `MAI_Code` (`MAI_Code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

CREATE TABLE `ASP_Docs` (
  `DOC_Incr` int NOT NULL AUTO_INCREMENT,
  `DOC_Libelle` varchar(40) NOT NULL,
  `DOC_URL` varchar(255) NOT NULL,
  PRIMARY KEY (`DOC_Incr`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

Toutes gérées à la main (comme ASP_Statuts/ASP_Actions/ASP_Professions), sauf ASP_Prospects et ASP_Operations qui sont alimentées par le code. Voir section 2 pour les évolutions de longueur associées sur ASP_Actions/ASP_Realisations (ACT_Code/REA_Action/OPE_Action en varchar(20), ACT_Libelle en varchar(40)). MAI_CorpsHtml ajoutée en fin de session (voir plus bas, passage des mails en HTML).

Conventions actées.

  • Préfixe PSP_ pour tous les champs de ASP_Prospects, choisi par Jean-Marc pour bien distinguer ce domaine de celui des contacts (CNT_).
  • Réutilisation de ASP_Actions comme table de référence commune aux contacts et aux prospects (plutôt qu'une table séparée) — argument de Jean-Marc, validé : garantit la cohérence en lecture de l'historique le jour où un prospect bascule en contact qualifié (voir PSP_IncrContact, prévu pour cette bascule mais pas encore implémentée).
  • Convention de dérivation des codes ASP_Actions à partir du code de campagne : <campagne>-CRE (création du prospect), <campagne>-VER (mail de vérification envoyé), <campagne>-VAL (adresse validée), <campagne>-DOC (doc envoyée), <campagne>-LEC (doc lue). Le code PHP dérive ces codes automatiquement à partir du code de campagne — une nouvelle campagne qui suit ce même schéma ne demande aucune configuration supplémentaire côté code.
  • MAI_Code suit le même principe pour le mail de vérification (<campagne>-DEM), mais Jean-Marc a tranché pour des modèles de mail dédiés à chaque usage plutôt que mutualisés, même en cas de contenu identique au départ — argument : traçabilité de ce qui a réellement été envoyé (un modèle modifié après coup ferait perdre la trace du texte exact envoyé à une vague de prospects), et possibilité de faire des tests A/B entre variantes. Le mail "doc" ne suit donc pas la même dérivation automatique que les codes ASP_Actions : son MAI_Code est <campagne>-DOC, choisi manuellement par Jean-Marc au moment de la création de la ligne.
  • Syntaxe des variables dans MAI_Corps/MAI_CorpsHtml/MAI_Objet : {(NomVariable)}, casse PascalCase ({(Prenom)}, {(Nom)}, {(Lien)}, {(Titre)}, {(LogoUrl)}). Point de vigilance retenu suite à une erreur de Claude en fin de session : n'écrire les caractères accentués qu'en clair dans le SQL (la base est nativement UTF-8), jamais en séquences d'échappement \u00xx (syntaxe JavaScript/JSON, non reconnue par MySQL — laisse un texte du type "demandu00e9" au lieu de "demandé").
  • OPE_CodeUser systématiquement 'Vik' pour tous les événements automatiques journalisés dans ASP_Operations — ces événements ne sont jamais déclenchés par un utilisateur ASPIC connecté au sens de la session PHP (section 15).
  • ORIGINES_CORS_AUTORISEES (dans prospects_core.php) : https://mevelia-solutions.bzh (confirmé sans www, formulaire déposé sur mevelia-solutions.bzh/form).

Nouvel utilisateur système — Viktor. Ligne créée dans ASP_Users, USR_Code = 'Vik', pour "Viktor", le premier assistant IA de Jean-Marc. Sert d'identité pour la journalisation automatique (ASP_Operations) et comme expéditeur des mails (viktor@ms.bzh). Pas de mot de passe fonctionnel utilisé à ce stade : le formulaire public et les scripts associés ne passent pas par le mécanisme de connexion/session existant (aspic.php + $_SESSION, section 15) — ils écrivent le code 'Vik' directement. Le mot de passe de Viktor aura un rôle réel le jour où des automatisations externes (agents IA de suivi, orchestration n8n — voir section 17) devront appeler les endpoints protégés existants (contacts.php, realisations.php…) en son nom — pas nécessaire pour ce chantier.

Envoi de mail — choix de Brevo. Reprise du point resté ouvert depuis le 19 août (section 6) : une tentative antérieure avec Brevo semblait avoir perturbé la réception Outlook sur la même boîte mail. Cause probable identifiée en discussion : configuration DNS non isolée entre domaine d'envoi et boîte de réception (Jean-Marc a confirmé avoir réussi à faire cohabiter Mailjet et Outlook dans une précédente société, moyennant un paramétrage DNS spécifique). Solution retenue : domaine d'envoi dédié ms.bzh (déjà chez OVH, partiellement paramétré lors d'essais Budibase antérieurs), adresse d'expédition viktor@ms.bzh, et un Reply-To séparé pointant vers contact@mevelia-solutions.bzh. Appel direct à l'API REST Brevo en PHP (cURL, sans bibliothèque) — pas de relais SMTP à configurer dans le conteneur. Clé API (format xkeysib-..., bien la clé API REST et non les identifiants SMTP distincts de Brevo — point de vigilance signalé par Claude avant déploiement, confirmé correct par Jean-Marc) stockée dans BREVO_API_KEY (même principe que DB_PASS), générée sans date d'expiration et déployée avec succès en fin de session.

Envoi immédiat, pas de file d'attente. Décision de Jean-Marc : le mail de vérification doit partir immédiatement après la soumission du formulaire, dans la même requête HTTP — pas de cron ni de déclenchement différé pour cette étape (contrairement à une première piste envisagée avec n8n, écartée pour ce besoin précis une fois la contrainte d'immédiateté clarifiée ; le sujet cron/n8n redeviendra pertinent pour de futures étapes différées d'un parcours de prospection).

Vérification de l'adresse mail — mécanisme retenu. Un token aléatoire imprévisible (random_bytes(32), 64 caractères hexadécimaux), valable 48h, inséré dans un lien de vérification envoyé par mail. Une piste alternative (valider par la réponse du prospect au mail, avec traitement automatique du contenu entrant via IMAP) a été explorée en détail puis abandonnée par Jean-Marc lui-même comme trop complexe pour ce premier jet ("pas besoin de sortir l'artillerie lourde") — un simple clic suffit. PSP_MailVerifie/PSP_TokenVerification/PSP_TokenExpiration portent cet état directement sur ASP_Prospects (pas de champ de date de création/conversion séparé sur la table : ces événements sont journalisés dans ASP_Operations, cohérent avec le principe déjà en place pour ASP_Contacts/ASP_Realisations où la date de création n'est pas un champ mais un enregistrement).

Anti-spam. Champ honeypot (champ caché, invisible pour un humain via CSS, laissé accessible pour un robot) sur le formulaire public — soumission silencieusement ignorée (réponse 200 neutre) si ce champ est rempli. Choisi plutôt qu'un captcha, pour rester léger.

Nommage des scripts par campagne — décision de Jean-Marc, avec une factorisation proposée par Claude. Jean-Marc voulait des scripts publics nommés explicitement par campagne (prospect_<campagne>_ajoute.php), quitte à dupliquer du code, pour s'y retrouver facilement à mesure que le nombre de campagnes grandit — avec un vrai bénéfice de sécurité identifié en discussion : le code de campagne n'est jamais un paramètre manipulable par le visiteur, il est implicite dans le fichier appelé (contrairement à un ?campagne=... en paramètre). Pour éviter la duplication de la logique elle-même (risque déjà rencontré sur ce projet, cf. le bug CNT_MAJ/MAJ_CNT, section 2), la logique commune vit dans prospects_core.php, et chaque campagne n'a qu'un tout petit fichier qui l'appelle avec son code en dur (prospect_web-form-001_ajoute.php, 3 lignes). Le script de vérification (prospects_verifier.php) et celui de suivi de lecture (prospect_doc.php) restent en revanche communs à toutes les campagnes : rien dans leur logique ne dépend de savoir à l'avance quelle campagne est concernée (l'information est déjà portée par la ligne trouvée en base).

Suivi de la lecture de la documentation — lien signé. Le mail "doc" contient un lien vers prospect_doc.php?a=<PSP_Incr>&b=<DOC_Incr>&c=<CMP_Incr>&d=<signature>, qui journalise la lecture puis redirige (302) vers l'URL réelle du document (table ASP_Docs, gérée à la main — DOC_URL modifiable indépendamment du mail déjà envoyé, si le document change d'adresse après coup ; un des arguments de Jean-Marc en faveur de cette indirection). Le paramètre d est une signature HMAC-SHA256 (tronquée à 16 caractères hexadécimaux) des paramètres a/b/c, calculée avec une clé secrète côté serveur (LIEN_DOC_CLE_SECRETE, générée par Jean-Marc et déployée en fin de session) — empêche un visiteur de modifier les paramètres de l'URL sans que ce soit détecté (comparaison en temps constant via hash_equals(), même principe que la vérification du mot de passe dans aspic.php, section 15). Motivé par un vrai précédent vécu par Jean-Marc (manipulation de paramètres constatée sur ses annonces eBay il y a 20 ans par un tiers ayant réutilisé ses URLs d'images). En cas de signature invalide, redirection neutre vers la page provisoire de mevelia-solutions.bzh plutôt qu'une page d'erreur qui confirmerait la tentative au visiteur (et plutôt qu'une redirection délibérément désagréable, évoquée en plaisanterie par Jean-Marc puis écartée d'un commun accord : un domaine qui redirige vers un contenu problématique risquerait d'être mal classé par les filtres anti-spam/proxys d'entreprise qui scannent les liens des mails — l'inverse de l'objectif de délivrabilité recherché par toute la démarche).

Point de vigilance signalé par Claude, accepté comme non bloquant pour cette v1 : la signature empêche bien la modification de a/b/c sans la clé secrète ; le point de vigilance résiduel est mineur (numérotation séquentielle visible dans un lien légitimement reçu, sans conséquence pratique au-delà de révéler approximativement le volume de prospects).

Table des scénarios d'entrée — idée jugée pertinente mais reportée. Jean-Marc a proposé, en cours de session, l'idée d'une table générique de "scénarios" décrivant les étapes d'entrée d'un prospect (explicitement distincte du suivi commercial ultérieur, volontairement laissé sans script rigide — parallèle fait par Jean-Marc lui-même avec les anciens chatbots à arbre de décision, cassants au premier cas non prévu). Trois exemples concrets donnés par Jean-Marc : formulaire web (avec vérification et abandon — "on brûle le prospect" — si pas de réponse), scraping LinkedIn ciblé par profession et taille d'entreprise (sans vérification, adresses jugées fiables, envoi direct d'une doc spécifique au métier), traitement d'un message vocal transcrit par IA (contenu de mail entièrement dynamique, pas un simple remplissage de variables). Recommandation de Claude, acceptée par Jean-Marc : ne pas construire de moteur générique piloté par une table pour l'instant — la règle déjà en place sur ce projet pour ce genre d'arbitrage (généraliser à partir de 3 répétitions concrètes constatées, section 6) est satisfaite en nombre d'exemples mais pas en homogénéité : les trois formes diffèrent trop structurellement (branchement conditionnel avec délai pour l'un, envoi direct sans attente pour l'autre, contenu généré dynamiquement pour le troisième) pour être couvertes proprement par une même structure de données sans complexité disproportionnée pour ce que ça résout. Décision : factoriser seulement les briques réellement communes (envoi de mail depuis un modèle, journalisation ASP_Operations — déjà fait), et coder chaque parcours en PHP normal, au fur et à mesure. "Brûler" un prospect sans réponse réutilisera PSP_Actif = 0 (même principe que CNT_Actif, jamais de suppression physique) ; "rejoindre le pool" (le prospect quitte l'onboarding et devient suivi par l'agent commercial) sera un événement ASP_Operations dédié plutôt qu'un nouveau champ, un indicateur rapide pouvant être ajouté plus tard si un futur écran de suivi en a besoin pour ses filtres. Sujet à reprendre une fois un deuxième parcours (LinkedIn ou répondeur) vraiment engagé — pas avant, pour ne pas concevoir dans le vide.

Test en conditions réelles et évolutions du jour (26 août 2026, fin de session). Formulaire déposé sur mevelia-solutions.bzh/form, clé Brevo API générée et déployée, DNS de ms.bzh déjà en ordre depuis les essais Budibase antérieurs, ORIGINES_CORS_AUTORISEES corrigée à https://mevelia-solutions.bzh (sans www). Chaîne complète testée et validée en production le jour même.

Deux bugs rencontrés et corrigés en tout premier test :

  • Dérive de schéma : premier essai en échec ("erreur serveur" générique, volontairement sans détail exposé au client — voir la gestion catch (PDOException) dans traiterAjoutProspect()). Diagnostic via les logs du conteneur crm-app (error_log()) : ASP_Prospects avait été créée par Jean-Marc avant l'ajout, en cours de conception, des trois colonnes de vérification (PSP_MailVerifie, PSP_TokenVerification, PSP_TokenExpiration) — colonnes absentes en base bien que déjà actées dans ce journal. Corrigé par un ALTER TABLE ciblé. Point de méthode à valeur générale, déjà noté en section 2 pour les tables de référence gérées à la main, mais qui s'applique ici à une table alimentée par le code également : toute évolution de structure décidée en cours de conversation doit être répercutée en base par Jean-Marc avant le prochain test, sinon la dérive n'apparaît qu'à l'usage.
  • Mail de vérification sans lien cliquable : le contenu de MAI_Corps pour WEB-FORM-001-DEM, saisi par Jean-Marc avant que la syntaxe {(Lien)} soit définitivement actée, contenait un texte d'attente ("lien(bouton/image) suivant ???") jamais remplacé par la vraie variable — corrigé par UPDATE direct en base, sans toucher au code.

Passage des mails en HTML (fin de session, 26 août 2026). Demande de Jean-Marc après avoir vu le premier mail de vérification en texte brut (URL du script PHP affichée en clair, pas de logo) : passer les mails de prospection en HTML, avec un bouton plutôt qu'un lien brut, et le logo de l'agence. Choix technique retenu : mail multipart plutôt qu'un remplacement pur HTML — ASP_Mails reçoit une nouvelle colonne MAI_CorpsHtml (text, nullable), MAI_Corps (texte brut) restant systématiquement renseignée comme repli pour les clients mail qui n'affichent pas le HTML, et pour la délivrabilité (un mail 100 % HTML avec peu de texte réel est un signal surveillé par les filtres anti-spam). envoyerMail() (dans prospects_core.php) envoie les deux (textContent + htmlContent) à l'API Brevo quand MAI_CorpsHtml est renseignée, sinon repasse en texte brut seul comme avant — rétrocompatible avec un MAI_Code qui n'aurait pas encore de version HTML. Nouvelle constante LOGO_URL (https://aspic.mvl-tls.fr/logo.png, fichier statique déposé à la racine du même dossier que les scripts PHP), injectée automatiquement dans les variables de substitution de tout mail sous {(LogoUrl)}, sans avoir à la passer explicitement à chaque appel. Bouton en HTML/CSS inline (couleur #FF5A1F, cohérente avec la charte du formulaire, avec attribut width en plus du style pour un rendu fiable y compris sous Outlook) à la place du lien brut — répond aussi au besoin de ne pas exposer le nom du script PHP en clair dans le texte du mail.

Deux bugs supplémentaires rencontrés et corrigés lors de ce passage au HTML :

  • Accents mal échappés en SQL : premier jet des UPDATE MAI_CorpsHtml utilisant par erreur des séquences é (échappement Unicode JavaScript/JSON) — non reconnu par MySQL, qui les a laissées telles quelles dans le texte ("demandu00e9" au lieu de "demandé"). Corrigé en réécrivant les UPDATE avec les caractères accentués directement (la base est nativement en UTF-8, aucun échappement n'est nécessaire) — voir aussi la convention actée plus haut dans cette section.
  • Logo introuvable malgré une URL valide : le logo ne s'affichait dans aucun client (y compris l'aperçu du tableau de bord Brevo lui-même), avec l'icône d'image cassée et le texte alternatif "Mevelia Solutions" à la place. Diagnostiqué via les logs d'accès du conteneur crm-app : les requêtes réelles portaient sur /logo-mevelia.png (ancien nom de fichier utilisé dans une version antérieure de la constante LOGO_URL), preuve que le fichier prospects_core.php déployé sur le serveur n'était pas la toute dernière version envoyée. Corrigé en redéployant le bon fichier. Effet de bord instructif noté au passage : Brevo dispose de son propre service de pré-chargement/cache des images de mail (Brevo/1.0 (redirection-images...), visible dans les logs d'accès), qui interroge le serveur avant l'envoi — utile à savoir pour de futurs diagnostics d'image dans un mail transactionnel.

Délivrabilité — premier constat. Le tout premier mail de test est arrivé dans les spams (Gmail) plutôt qu'en boîte de réception — attendu pour un domaine d'envoi tout juste remis en service (ms.bzh), la réputation se construit avec le volume et le temps. Jean-Marc l'a marqué manuellement "Ce n'est pas un spam" dans Gmail. Point non bloquant, à surveiller plutôt qu'à corriger dans l'immédiat ; le SPF/DKIM déjà en place côté Brevo pour ce domaine est le levier principal si le problème persiste dans la durée.

Fichiers livrés le 26 août 2026, vérifiés (php -l, node --check), testés et validés en conditions réelles :

  • prospects_core.php — logique commune : connexion DB (réutilise db.php), envoi de mail via l'API Brevo avec substitution de variables {(...)} (texte et HTML, {(LogoUrl)} injectée automatiquement), journalisation ASP_Operations, routage téléphone Tel/Portable (préfixe 06/07 après suppression des espaces), génération et vérification de la signature HMAC des liens de doc (signerParametresDoc()/genererLienDoc()), gestion CORS (autoriserCorsSiNecessaire(), liste blanche d'origines dans ORIGINES_CORS_AUTORISEES), validation des champs (longueurs, email, au moins mail ou téléphone requis).
  • prospect_web-form-001_ajoute.php — point d'entrée public de la campagne WEB-FORM-001, simple appel à traiterAjoutProspect('WEB-FORM-001').
  • prospects_verifier.php — validation du token de vérification (avec expiration), puis envoi automatique de la doc par défaut de la campagne (lookup dynamique via ASP_Campagnes.CMP_DocDefaut, aucune configuration supplémentaire nécessaire pour une future campagne suivant le même principe).
  • prospect_doc.php — vérifie la signature du lien (a/b/c/d), journalise la lecture (<campagne>-LEC), redirige vers l'URL réelle du document ; redirection neutre vers mevelia-solutions.bzh si signature invalide ou paramètres introuvables.
  • prospects_form_web.html — formulaire public autonome (Nom/Prénom/Téléphone/Mail + honeypot), CSS/JS inline, déposé sur mevelia-solutions.bzh/form. Visuel encore basique, à peaufiner — non urgent, mis de côté pour une prochaine session.

Données réelles en base (26 août 2026), transmises par Jean-Marc au fil de la session :

  • ASP_Campagnes : une ligne, WEB-FORM-001 (CMP_Incr = 1, CMP_DocDefaut = 1, créée le 26/08/2026).
  • ASP_Actions : 5 nouveaux codes de prospection (WEB-FORM-001-CRE/-VER/-VAL/-DOC/-LEC, incréments 9 à 13), voir le tableau complet en section 2.
  • ASP_Mails : deux lignes — WEB-FORM-001-DEM (mail de vérification) et WEB-FORM-001-DOC (mail d'envoi de la doc, avec {(Lien)} et {(Titre)}) — chacune désormais avec une version MAI_CorpsHtml en plus de MAI_Corps.
  • ASP_Docs : une ligne, "Documentation Mevelia Solutions" (DOC_Incr = 1), pointant vers https://mvl-dcs.fr/docs/DocumentationGenerale.pdf — URL probablement provisoire, le site définitif de Jean-Marc n'est pas encore en ligne.

Reste à faire, plus tard : peaufiner le visuel du formulaire public prospects_form_web.html (non urgent). Peupler ASP_Docs à mesure que d'autres documents (spécifiques à de futures campagnes) existeront. Concevoir un deuxième parcours d'entrée (LinkedIn ciblé ou répondeur transcrit) une fois un besoin concret réel — éclairera la question laissée ouverte sur une éventuelle généralisation en "table des scénarios". Mécanisme de bascule d'un prospect qualifié vers ASP_Contacts (PSP_IncrContact) pas encore conçu. Suivre dans la durée la délivrabilité du domaine ms.bzh (sortie des spams une fois la réputation établie).