Commit Graph

21 Commits

Author SHA1 Message Date
Serge RAKOTO HARRY-NAIVO
ec4b06c4fa fix(legal): politique de confidentialite - sous-traitants reels (RGPD, audit M13)
La page declarait des sous-traitants faux/obsoletes (risque de conformite RGPD): retire HubSpot (decommissionne 2026-05-10) + son transfert hors-UE; Brevo -> Resend (USA) pour les emails; ajoute Cloudflare/Turnstile (USA, traite l'IP du visiteur, sous-traitant non declare); precise que la base de donnees (inscriptions/contacts) est hebergee par Hostinger (Allemagne, UE); corrige l'Article 6 transferts hors-UE en consequence. Applique aux 3 langues FR/EN/MG. Nettoie aussi les commentaires JS obsoletes (worker mva-hubspot-proxy decommissionne).

Verifs: 0 mention HubSpot/Brevo restante, node --check OK sur form-handler.js + confirmation.js.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-29 19:22:38 +02:00
Serge RAKOTO HARRY-NAIVO
7217f12bd2 feat(api): migrate Worker mva-hubspot-proxy → mva-api /leads/* routes
Le Cloudflare Worker hubspot-proxy était une solution temporaire car
le panel admin AdminJS n'était pas encore disponible. Maintenant qu'
AdminJS marche, on rapatrie tout le flow inscription côté MVA backend.

## Changements

- `js/form-handler.js`
  - WORKER_PROXY_URL → API_BASE_URL = https://api.mva.mind4solutions.com
  - checkExistingContact : POST /leads/check-email
    (response shape : {exists, firstname, reference_client})
  - setupContactForm : POST /leads/request-verification
  - sendWelcomeBackEmail : POST /leads/welcome-back

- `js/confirmation.js`
  - WORKER_PROXY_URL → API_BASE_URL
  - POST /leads/verify-token (= au lieu de Worker action verifyToken)
  - Detection token expiré/invalide via code INVALID_OR_EXPIRED

## Aucun changement HTML

Les forms HTML, IDs des éléments, validation côté client, gestion
Turnstile sont tous inchangés. Seules les URLs API changent.

## Côté backend (PR #44 mva-prestige-v2)

Les routes mva-api /leads/* sont déployées séparément avec :
- Validation Zod + Turnstile + rate limit
- DB Postgres (table leads + leads_pending) remplace HubSpot Contacts + KV
- Resend pour les emails (= unification écosystème M4S)
- AdminJS Resource leads pour Mélissa CRUD

## Cutover

Cette PR doit être merged + déployée APRÈS la migration backend
(PR #44) + après le run du script migrate-hubspot-to-postgres.js
(= les 4 contacts HubSpot existants en DB).
2026-05-10 11:34:07 +02:00
2774c25a61 chore: post-review cleanup (3 Important + dead code purge -116 lines) (#10)
Some checks are pending
Deploy site to GitHub Pages / deploy (push) Waiting to run
2026-05-07 18:37:10 +03:00
5c34e59a8d feat(worker): re-enable welcome-back email via Worker + Resend (footer 2026) (#8)
Some checks are pending
Deploy site to GitHub Pages / deploy (push) Waiting to run
2026-05-07 16:43:58 +03:00
5b84e5697e chore(post-cutover): fix 3 polish bugs (welcome-back, mobile lang switcher, animate-on-scroll) (#6)
Some checks are pending
Deploy site to GitHub Pages / deploy (push) Waiting to run
2026-05-07 16:36:28 +03:00
10960e8ae1 feat(cloudflare): point HTML/JS to new Mind4Solutions Worker + Turnstile sitekey (#4)
Some checks are pending
Deploy site to GitHub Pages / deploy (push) Waiting to run
2026-05-07 15:28:23 +03:00
MVA Global Fret
07ccec0808 Anti-spam: only register HubSpot contact AFTER email confirmation
Previously the Forms API created the contact at form submission time —
which meant unverified signups (bots that pass Turnstile, typos, fake
emails) polluted HubSpot. Now:

- Form submit → Worker stores all data in KV (24h TTL) + sends Brevo
  verification email (no HubSpot write)
- User clicks email link → Worker generates ref + creates HubSpot
  contact via CRM API + sends welcome email with ref + Paris address

Plus this commit:
- Email header gets the MVA logo on the left of the dark blue banner
- Welcome email's first address line auto-injects (MVA-XXX) so the
  customer can copy it directly onto their package

Also handles idempotency — clicking the verification link a second time
returns the existing ref without creating a duplicate.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 13:50:32 +02:00
MVA Global Fret
82bc8ba358 Switch from Resend to Brevo for transactional emails
Resend requires a verified domain to send to arbitrary recipients —
mvaglobalfret.com isn't registered. Brevo accepts single-sender
verification on a free email address, so we can send from
mvaglobalfret@gmail.com without owning a domain.

- Worker: replace resendSend() with brevoSend() (api.brevo.com/v3/smtp/email)
- Env vars: BREVO_API_KEY, BREVO_SENDER_EMAIL, BREVO_SENDER_NAME
- Update comments in confirmation.js and form-handler.js

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 12:26:50 +02:00
MVA Global Fret
eb5c4f1cee Email verification flow via Resend (Turnstile + click-to-confirm)
Architecture finale :

1. User remplit formulaire + passe Turnstile CAPTCHA → form-handler.js
2. form-handler.js POST au Worker avec action 'requestVerification'
3. Worker valide Turnstile, génère un token UUID, le stocke en KV (TTL 24h)
   avec firstname/email/reference_client, puis envoie un email via Resend
   avec un lien : confirmation.html?token=XXX
4. User reçoit email, clique 'Confirmer mon email'
5. confirmation.html lit le token de l'URL, POST au Worker avec action
   'verifyToken'
6. Worker valide le token, envoie le welcome email via Resend (avec ref +
   adresse Paris depuis env var), marque le token comme utilisé
7. confirmation.html affiche 'Inscription confirmée !'

Ainsi : ref + adresse Paris ne sortent JAMAIS avant validation email,
et les bots sont bloqués à l'étape 1 par Turnstile.

Setup Cloudflare requis (côté user) :
- RESEND_API_KEY  : clé API Resend (re_...)
- RESEND_FROM     : adresse expéditrice ('onboarding@resend.dev' pour test,
                    ou domain vérifié pour prod)
- SITE_URL        : optionnel, défaut https://mva-global-fret.github.io/site-mva-global-fret

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 10:59:26 +02:00
MVA Global Fret
a3a36df811 Anti-spam: add Cloudflare Turnstile (CAPTCHA) on registration form
- contact.html: ajout du widget Turnstile (site key: 0x4AAAAAADKDuc7Rmlb1svIL)
- form-handler.js: blocage de la soumission si pas de token Turnstile valide
- Worker: validation server-side du token via /turnstile/v0/siteverify
  avant chaque appel sendWelcomeNow → bloque les bots qui n'auraient
  pas passé le challenge côté client.

Le secret Turnstile est en env var Cloudflare (TURNSTILE_SECRET).

Limite humain : Turnstile détecte les bots avec très peu d'interaction
côté utilisateur (mode 'Managed', le plus souvent invisible).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 10:47:29 +02:00
MVA Global Fret
313c870ea4 Fix bugs inscription: ref dupliquée + email de bienvenue manquant
Bug 1 — Ref MVA-001 dupliquée :
Le filtre HubSpot 'HAS_PROPERTY' avec value:'' retournait 0 résultats.
Suppression du value:'' → maintenant le worker liste correctement les
contacts avec reference_client et incrémente bien (testé : MVA-004).

Bug 2 — Email post-inscription jamais reçu :
Le double opt-in HubSpot ne se déclenche pas via Forms API sans
subscription consent (impossible à configurer sans nouveaux scopes
Private App). Pivot vers une approche plus simple :
- L'email de bienvenue est désormais envoyé directement après
  soumission du formulaire (pas de DOI HubSpot)
- L'envoi passe par le Cloudflare Worker (action sendWelcomeNow)
  pour que l'adresse Paris reste dans les env vars Cloudflare et
  ne soit JAMAIS dans le JS public
- Worker appelle EmailJS REST avec firstname + reference + paris_address

Cleanup : message de succès reverti à 'Inscription réussie' (FR/EN/MG).

Anti-spam : protection légère via filtre email/téléphone côté formulaire.
La cron-based welcome (post-DOI) reste en place mais sera inerte tant
que aucun contact n'a le statut CONFIRMED côté HubSpot.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 09:52:48 +02:00
MVA Global Fret
c713d40946 Contact: ne plus afficher la référence avant validation email
- Retire le bloc 'Numéro de référence client' de la page de succès
- Met à jour le message en FR/EN/MG : 'Vous recevrez ensuite votre numéro
  de référence client' après confirmation
- Désactive l'envoi immédiat de l'email EmailJS de bienvenue (qui
  contenait déjà la référence). HubSpot envoie son email de
  double opt-in qui sera customisé pour inclure la référence
  via le token {{contact.reference_client}}.

Résultat : la référence n'est jamais visible avant que l'email ne soit
vérifié (puisque seuls les emails valides reçoivent le double opt-in).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 22:53:23 +02:00
MVA Global Fret
48664683e5 Send welcome-back email to clients already registered
When a client tries to re-register with an existing email:
- The form still shows the on-screen "already registered" message
- HubSpot data is still untouched (no duplicate, ref number preserved)
- NEW: a welcome-back email is now sent via EmailJS reminding them
  of their existing client reference number
- The internal MVA notification (Formspree) is preserved

Requires creating a new EmailJS template (id: template_welcome_back)
with variables: firstname, email, reference_client.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-04 18:18:22 +02:00
MVA Global Fret
15e98b9c32 feat: numérotation séquentielle MVA-XXX, texte succès corrigé, message email/spam 2026-05-04 16:28:28 +02:00
MVA Global Fret
eea5717143 fix: update EmailJS service ID to service_aeamo3x (Gmail connected) 2026-05-04 15:52:09 +02:00
MVA Global Fret
168a26ba32 feat: email de bienvenue automatique via EmailJS
- Ajout du SDK EmailJS (CDN) dans contact.html
- Initialisation EmailJS avec la clé publique dans form-handler.js
- Nouvelle fonction sendWelcomeEmail() : envoie au client son prénom,
  numéro de référence et l'adresse de dépôt Paris (AEIC Forwarding, Orly)
- Appel automatique dans showSuccess() après inscription réussie

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-04 15:15:44 +02:00
MVA Global Fret
7ea43c3b72 feat: activer le proxy Cloudflare pour la détection des doublons
Active WORKER_PROXY_URL pointant vers mva-hubspot-proxy.mvaglobalfret.workers.dev.
Le Worker interroge l'API CRM HubSpot côté serveur (contourne le CORS) et
retourne les données du contact si l'email est déjà enregistré.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-04 14:37:16 +02:00
MVA Global Fret
1970b10089 Sécurise form-handler : retire token côté client, prépare proxy Worker
- Supprime HUBSPOT_SERVICE_KEY du code JS public (évite l'exposition du token)
- Remplace l'appel CORS-bloqué vers api.hubapi.com par un appel au proxy
  Cloudflare Worker (WORKER_PROXY_URL, vide par défaut = sans blocage)
- Ajoute cloudflare-worker/hubspot-proxy.js : code complet du Worker à
  déployer gratuitement depuis dash.cloudflare.com (sans CLI ni Node.js)
- Quand WORKER_PROXY_URL est renseigné, la détection doublon est active :
  un client existant voit son message "déjà inscrit" sans re-soumission

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-05-04 14:13:17 +02:00
MVA Global Fret
fa4b49e1b8 Unicité référence client + détection doublon email
- generateRefNumber() basé sur timestamp : références jamais identiques
- checkExistingContact() : lecture HubSpot via clé de service (read-only)
- Si email déjà connu : affiche message 'déjà client' + référence existante,
  AUCUNE soumission envoyée (référence existante jamais modifiée)
- Notification interne Formspree si tentative double inscription
- Traductions FR/EN/MG pour les nouveaux messages
2026-05-03 16:23:49 +02:00
MVA Global Fret
64f5401112 feat: generate client reference number (MVA-YYYY-XXXX), save to HubSpot reference_client field, display in success message 2026-05-03 11:20:52 +02:00
MVA Global Fret
938efe582f Initial commit — Site MVA Global Fret 2026-05-02 22:23:48 +02:00