← Tous les manuels ·
PortailMANUAL — rp-onboarding
Manuel d'instructions de cette app. À LIRE avant toute intervention, et à METTRE À JOUR après chaque modification (ajouter une ligne au CHANGELOG en bas).
Dernière génération/MAJ : 2026-08-02 · Statut : brouillon auto (à relire)
1. Identité
- Rôle : sert le formulaire client /form/:token (dossier de résidence, multi-étapes, autosave, upsell Permanente) et l'API /api/invitations* consommée par le dashboard ops RP. Le PORTAIL Younes (login + création d'invitation en page d'accueil) a été retiré le 2026-09-02 : / affiche désormais un message "a déménagé" renvoyant vers ops-resident.panelbay.com/contrats. Voir MANUAL de rp-dashboard.- URL publique : https://onboarding.panelbay.com (racine / = message de redirection ; /form/:token = formulaire client, inchangé)- Entité : RP
2. Exécution / infra
- Dossier : /root/workspace/apps/rp-onboarding- Stack : Node.js, HTML/statique- Service systemd : rp-onboarding.service (systemctl restart rp-onboarding.service)- Port : 8320- Reverse proxy (nginx) : onboarding.panelbay.com- Redémarrer : systemctl restart rp-onboarding.service
3. Structure & fichiers clés
- backend/server.js- backend/db.js- frontend/index.html- backend/package.json
4. Données
- Base / stockage : - backend/data/rp-onboarding.db- Modèle / tables : TODO — tables / structure des données
5. API / endpoints
- GET /health (healthcheck, retourne {ok:true})- DELETE /api/invitations/:id- GET /api/invitations- GET /api/invitations/:id- GET /api/me- GET /api/public/resolve/:token- POST /api/invitations- POST /api/invitations/:id/extend- POST /api/invitations/:id/resend- POST /api/login (rate-limité : 8 échecs / 15 min par IP et par email, puis 429)- POST /api/public/create-invitation-from-payment- POST /api/public/draft/:token- POST /api/public/invitations- POST /api/public/submit/:token (valide et assainit chaque champ, exige le consentement RGPD)
6. Intégrations & secrets
- Intégrations (n8n, Google Sheets, Airtable, webhooks, autres apps) : webhooks Make (soumission dossier), Resend (emails d'invitation), Systeme.io (webhooks entrants). Tous pilotés par variables d'env.- rp-dashboard (apps/rp-dashboard/contrats.js) appelle POST /api/invitations en service-à-service (pas de compte utilisateur) avec Authorization: Bearer <CONTRACTS_API_TOKEN ou AUTOMATIONS_TOKEN>. Le middleware auth() de server.js accepte ce jeton partagé en plus des JWT de session (voir §7).- Secrets / clés (indiquer OÙ elles sont, JAMAIS leur valeur) :- -
JWT_SECRET (signature des tokens portail) : backend/.env (perms 600). Voir manifeste Audit-apps/_secret_rotation_rp-onboarding.tsv. - - Mot de passe admin portail : hash bcrypt en base, table
users de backend/data/rp-onboarding.db. - - Clés webhooks/Resend/Systeme.io : variables d'environnement (
.env / unit systemd), jamais en dur.
7. Pièges connus / à savoir
- Le portail Younes (login + "Nouvelle invitation") a été RETIRÉ du frontend (frontend/js/app.js, ancien bloc PORTAL lignes ~122-259) le 2026-09-02. Les routes backend POST /api/login, GET /api/me, /api/invitations* existent TOUJOURS (nécessaires au dashboard ops RP) mais ne sont plus appelées depuis une UI de ce domaine. Ne pas les supprimer.- Le champ invitations.pack n'accepte que temporaire | fiscal | investor (array PACKS, server.js). C'est un concept DIFFÉRENT des packs de contrat de rp-contracts (qui a 4 formules actuelles + 4 legacy) : l'invitation pilote le parcours/prix côté client, le pack de contrat pilote le TEMPLATE légal généré. Ne pas chercher à les unifier sans y réfléchir.- pricing.js : la grille VIVE (dossierPrice, utilisée par server.js pour le funnel) est alignée sur le site au 2026-09-07 (Temporaire 1850€, +Fiscalité 2450€ par pers, dégressif -5%/-10% ; upsell Permanente 1700€/pers fixe ; Investor 3000€). ⚠️ L'ANCIENNE grille par dossier (GRID/buildBreakdown : 2000/3500, 3700/6900, 200k USD) est du code mort (encore importée mais plus appelée par server.js) : à supprimer lors d'un nettoyage.- WorkingDirectory du service = backend/, donc dotenv lit backend/.env (pas la racine de l'app).- JWT_SECRET : le code garde un fallback dev (rp-onboarding-dev-secret) si absent, mais la valeur de prod DOIT rester dans backend/.env. Pour la rotation, changer la valeur invalide toutes les sessions portail existantes.- Rate-limit login en mémoire : un systemctl restart remet à zéro les compteurs (utile si un compte légitime est bloqué).- submit_logs.payload_json est VOLONTAIREMENT rédigé (passeport + date de naissance remplacés par [redacted]). Le payload COMPLET part quand même au webhook Make. Le chiffrement au repos de la PII reste À FAIRE (reporté).- Rétention/purge des dossiers en base : non implémentée (reporté), à définir côté RGPD.- Validation serveur stricte au submit : prénom/nom/date de naissance requis, passeport requis pour les adultes (5-20 car.), email au bon format, consentement RGPD obligatoire. Le front bloque déjà l'avancement, le serveur revalide (400 validation_failed / consent_required).
8. CHANGELOG
- 2026-08-02 — Manuel initialisé (bootstrap auto).
CHANGELOG
- 2026-09-07 : Alignement des prix sur la nouvelle grille du site. Grille vive (dossierPrice, backend/pricing.js) : UNIT_EUR temporaire 1890→1850, fiscal 2490→2450 (upsell Permanente 1700 et Investor 3000 inchangés) ; commentaire + self-test _test_new mis à jour (12/12 OK). L'ANCIENNE grille par dossier (GRID/buildBreakdown, 2000/3500, 3700/6900, 200k USD) est du code mort (importée mais plus appelée par server.js, qui utilise dossierPrice) : laissée en l'état, à supprimer lors d'un nettoyage.- 2026-08-16 : ajout du tracking analytics Plausible (auto-hébergé, stats.panelbay.com). Snippet <script defer data-domain="onboarding.panelbay.com" src="https://stats.panelbay.com/js/script.js"> injecté dans frontend/index.html avant </head>. Sert de site pilote pour la couche analytics centralisée AIOS. Avance partiellement l'item #10 (analytics de funnel) qui était reporté : le tracking pageview est en place, les événements/conversions de funnel restent à définir (Phase 2).- 2026-08-04 : migration vers panelbay.com. Nouvelle URL https://onboarding.panelbay.com (HTTPS Cloudflare + Let's Encrypt). L'ancienne https://onboarding.bouthors-m.tenga.run reste active en parallele (double-service) le temps de la transition.- 2026-08-05 : correctifs d'audit sécurité/RGPD/accessibilité (PII d'identité). Backend (server.js, db.js) : JWT_SECRET déplacé dans backend/.env (valeur inchangée, perms 600) ; validation + assainissement serveur de chaque champ du dossier au submit (présence, email, longueur passeport, date plausible) avec 400 validation_failed ; consentement RGPD exigé (consent_required) ; PII minimisée dans submit_logs (passeport + date de naissance rédigés, payload complet toujours envoyé au webhook) ; rate-limit sur /api/login (8 échecs / 15 min par IP + par email → 429) ; CORS restreint aux origines de l'app ; échappement HTML de client_name/URL dans l'email d'invitation ; endpoint GET /health ; perms 600 sur le .db. Frontend (app.js, styles.css, index.html) : sélecteur de formule et options accessibles (vrais <input radio>, aria-checked, clavier, focus visible) ; case de consentement RGPD + lien politique de confidentialité, submit bloqué tant que non cochée ; récapitulatif affichant les données saisies (contact + personnes/passeports) ; labels for/id, :focus-visible, validation en ligne par champ + hints de format ; <h1>, role=progressbar/aria-valuenow, « Étape X sur Y » ; blocage de l'avancement front tant que les requis d'une étape ne sont pas remplis. REPORTÉ : chiffrement au repos de la PII + rétention/purge (RGPD) ; item #10 analytics de funnel ; item #14 perfs/i18n. Mot de passe admin NON changé (hint retiré du login). Manifeste rotation : Audit-apps/_secret_rotation_rp-onboarding.tsv. Testé : service actif, /health OK, flux submit (invalide→400, sans consentement→400, valide→ok), redaction PII et rate-limit vérifiés.- 2026-08-22 : refonte flux + migration Make #4. Le PACK est choisi par Younes a la creation (colonne invitations.pack : temporaire/fiscal/investor, migration idempotente ; selecteur dans le portail). Le formulaire client ne choisit plus de pack ; nouvelle etape UPSELL Permanente (1700 EUR/pers brut, sans degressif) sur temporaire/fiscal, avec notif prevue cote Younes (paiement non auto). Prix refaits selon la grille du site (pricing.js -> dossierPrice() : temporaire 1890 / fiscal 2490 par pers, degressif -5% 2p / -10% 3p+ ; investor 3000 fixe ; EUR). Submit -> MAKE_WEBHOOK_URL repointe vers l'AIOS http://127.0.0.1:8363/rp/onboarding-submit?token=... (l'app n'avait jamais eu de webhook Make : soumissions stockees en local seulement). L'AIOS cree les fiches Airtable RP + genere le contrat via le systeme interne rp-contracts (contrats.panelbay.com). Teste bout en bout en mode test (prix 8131 fiscal 2p+upsell OK, contrat pack permanent, aucun mail), donnees supprimees. RESTE : templates contrat EN/ES (fallback FR pour l'instant), validation avocat, notif Younes upsell.- 2026-08-25 : service tombé (arrêt propre en masse à 18h37 le 24/08, non rattrapé par Restart=on-failure). Relancé + policy passée à Restart=always pour éviter la rechute.- 2026-09-02 : portail Younes retiré, centralisé dans le dashboard ops RP. Demande Matt : "1 bouton suffit". Frontend (frontend/js/app.js) : bloc PORTAL entier supprimé (login, formulaire "Nouvelle invitation", liste des invitations) ; la racine / affiche désormais un message "Ce portail a déménagé" avec un lien vers https://ops-resident.panelbay.com/contrats. Le formulaire client /form/:token est INCHANGÉ et continue de fonctionner à l'identique (aucune dépendance au bloc portail). Backend (server.js) : middleware auth() accepte désormais aussi un jeton de service partagé (CONTRACTS_API_TOKEN ou repli AUTOMATIONS_TOKEN, même convention que rp-contracts/aios-automations) pour que le dashboard ops RP puisse appeler POST /api/invitations sans compte utilisateur. Les 4 anciennes invitations pending/in_progress trouvées en base (Marie Leroy, Jean Dupont, John Smith, test Matt) ont été identifiées comme données de démo/test (emails @example.com/@x.com, expirations dépassées) : confirmé par Matt, aucune migration nécessaire. Testé : service actif, /health OK, page d'accueil affiche le message de redirection, /js/app.js ne contient plus de code portail.