237 lines
12 KiB
Markdown
237 lines
12 KiB
Markdown
# RelaisSMS - Lot 0 - Decisions techniques
|
|
|
|
Date : 2026-06-11
|
|
|
|
## Objectif du lot
|
|
|
|
Ce document fixe les decisions de cadrage avant le demarrage du socle applicatif. Il complete le cahier des charges et sert de reference pour les lots suivants.
|
|
|
|
## Decisions actees
|
|
|
|
| Sujet | Decision | Impact |
|
|
| --- | --- | --- |
|
|
| Source CardDAV/Nextcloud | CardDAV/Nextcloud est le premier systeme d'import/synchronisation distant a implementer. | Le lot 3 porte sur `CardDavSourceConnector` et ne depend pas de Galette. |
|
|
| Source Galette | Galette est prepare comme source future, mais le connecteur n'est pas implemente tant que l'instance n'est pas mise a jour. | Galette est reporte au dernier lot. Le socle et CardDAV/Nextcloud avancent sans dependance Galette. |
|
|
| Nommage des sources | CardDAV/Nextcloud et Galette sont deux sources separees, meme si Galette expose ou exporte un format vCard. | Les connecteurs, configurations, cles de source et libelles UI restent distincts. Pas de regroupement sous un meme lot ou nommage. |
|
|
| Version Galette cible | Galette 1.2.1 cote projet. La documentation `latest` consultee affiche 1.2.2. | Les endpoints exacts seront revalides apres upgrade, avant implementation du dernier lot Galette. |
|
|
| Fournisseur SMS | OVHcloud SMS via API REST OVH Europe. | Le connecteur initial depend de l'API OVH, isole derriere `SmsProviderInterface`. |
|
|
| SDK OVH | Ne pas imposer le SDK au lot 0. Preferer un adaptateur HTTP Laravel au demarrage, sauf validation explicite du SDK avec la version PHP cible. | Moins de dependance externe et controle clair de la signature API. |
|
|
| Roles | Un seul role applicatif au MVP : administrateur complet. | Pas de RBAC fin au lot 1. Tous les utilisateurs authentifies ont les memes droits. |
|
|
| Suppression contacts synchronises | Suppression logique par `deleted_at`, pas suppression physique. | L'historique SMS reste auditable meme si un contact disparait d'une source. |
|
|
| Suppression contacts locaux | Jamais supprimes par synchronisation. | Un contact local reste sous controle applicatif. |
|
|
| Refus SMS | Flag manuel `sms_opt_out` au niveau contact. | Les contacts opt-out sont exclus au moment de la resolution des destinataires. |
|
|
| Limite d'envoi | 100 SMS par envoi par defaut, configurable. | Validation cote serveur obligatoire avant creation de campagne. |
|
|
| Conservation historique | 3 ans par defaut, configurable. | `sms_campaigns.expires_at` est calcule a la creation. |
|
|
| Programmation | Prevue dans le modele, activee par configuration. | Le lot 7 pourra utiliser le scheduler sans revoir le modele. |
|
|
|
|
## CardDAV/Nextcloud
|
|
|
|
### Etat retenu
|
|
|
|
CardDAV/Nextcloud est la source distante prioritaire pour l'import/synchronisation. Elle est traitee comme un systeme autonome : son connecteur lit des carnets CardDAV, des vCards, des UID et des ETags, sans reutiliser le contrat Galette.
|
|
|
|
### Contrat cible pour RelaisSMS
|
|
|
|
Le connecteur CardDAV devra fournir au cache local :
|
|
|
|
| Donnee RelaisSMS | Source CardDAV attendue |
|
|
| --- | --- |
|
|
| Identifiant distant | UID vCard, complete par l'URL ou l'adresse du carnet si necessaire. |
|
|
| Nom affiche | `FN` vCard. |
|
|
| Nom / prenom | Champs structures vCard si presents. |
|
|
| Telephones | Proprietes `TEL`, avec conservation du type si disponible. |
|
|
| Groupes | Categories vCard si presentes. |
|
|
| Synchronisation incrementale | ETag, `ctag` ou horodatage distant selon les capacites du serveur. |
|
|
|
|
Decision : nommer cette source `carddav` ou `carddav_nextcloud` cote configuration/UI, jamais `galette_vcard`.
|
|
|
|
## Galette
|
|
|
|
### Etat retenu
|
|
|
|
Galette est laisse de cote pour l'implementation immediate, conformement au cadrage projet : l'upgrade est planifie mais pas encore effectif. Le lot 0 documente donc le contrat attendu sans figer un endpoint qui pourrait changer au moment de l'upgrade. Le connecteur Galette sera le dernier lot.
|
|
|
|
### Documentation consultee
|
|
|
|
- Documentation Galette fournie : <https://apidoc.galette.eu/en/latest/functions_m.html>
|
|
- La page consultee est une documentation Doxygen de classes PHP, pas une specification REST/OpenAPI.
|
|
- Elements reperes utiles au cadrage :
|
|
- `Galette\Controllers\Crud\MembersController::list`
|
|
- `Galette\Controllers\Crud\MembersController::ajaxList`
|
|
- `Galette\Controllers\Crud\MembersController::show`
|
|
- `Galette\Controllers\Crud\MembersController::vcard`
|
|
- `Galette\Controllers\CsvController::membersExport`
|
|
|
|
### Contrat cible pour RelaisSMS
|
|
|
|
Le connecteur Galette devra fournir au cache local :
|
|
|
|
| Donnee RelaisSMS | Source Galette attendue |
|
|
| --- | --- |
|
|
| Identifiant distant | ID adherent Galette, par exemple `Numéro adhérent` dans l'export actuel. |
|
|
| Nom | Champ nom. |
|
|
| Prenom | Champ prenom. |
|
|
| Structure | Personne morale si presente. |
|
|
| Email | Courriel. |
|
|
| Telephones | Telephone et GSM, avec conservation du numero original. |
|
|
| Groupes/statuts | Statut adherent au minimum ; groupes Galette a confirmer apres upgrade. |
|
|
| Date de modification | Date de modification si exposee par API/export. |
|
|
|
|
### Endpoints a valider apres upgrade
|
|
|
|
Avant le lot 9, valider sur l'instance Galette 1.2.1 :
|
|
|
|
| Usage | Endpoint ou mecanisme attendu | Statut |
|
|
| --- | --- | --- |
|
|
| Liste complete des adherents | Endpoint HTTP ou export membres base sur `membersExport` | A confirmer |
|
|
| Detail adherent | Route detail membre ou endpoint dedie | A confirmer |
|
|
| Fiche/export vCard Galette | Route `vcard` si exploitable dans le connecteur Galette | Optionnel, sans lien avec CardDAV/Nextcloud |
|
|
| Groupes/statuts | Route groupes ou champs presents dans la liste/export | A confirmer |
|
|
| Authentification | Session, jeton, basic auth ou autre mecanisme Galette | A confirmer |
|
|
| Filtrage incremental | Date de modification, ETag ou pagination | A confirmer |
|
|
|
|
Decision : ne pas coupler RelaisSMS a une route Galette non confirmee. Le connecteur sera concu avec un adaptateur remplacable : API JSON si disponible, export CSV authentifie en solution de repli. Une eventuelle route vCard Galette reste un mecanisme interne au connecteur Galette, pas une source CardDAV.
|
|
|
|
## OVHcloud SMS
|
|
|
|
### Documentation consultee
|
|
|
|
- Page produit API SMS OVHcloud : <https://www.ovhcloud.com/fr/sms/api-sms/>
|
|
- Definition API OVH SMS Europe : <https://eu.api.ovh.com/1.0/sms.json>
|
|
|
|
### Endpoints retenus pour le MVP
|
|
|
|
Base API : `https://eu.api.ovh.com/1.0`
|
|
|
|
| Usage | Methode | Endpoint | Notes |
|
|
| --- | --- | --- | --- |
|
|
| Lister les services SMS | `GET` | `/sms` | Permet de selectionner `serviceName`. |
|
|
| Lire le compte SMS | `GET` | `/sms/{serviceName}` | Retourne notamment statut et credits restants. |
|
|
| Estimer un message | `POST` | `/sms/estimate` | Parametres : `message`, `noStopClause`, `senderType`. |
|
|
| Envoyer un job SMS | `POST` | `/sms/{serviceName}/jobs` | Parametres principaux : `message`, `receivers`, `sender`, `noStopClause`, `tag`. |
|
|
| Lire jobs en attente | `GET` | `/sms/{serviceName}/jobs` | Utile pour debug et suivi. |
|
|
| Lire un job | `GET` | `/sms/{serviceName}/jobs/{id}` | Suivi fin si necessaire. |
|
|
| Annuler un job | `DELETE` | `/sms/{serviceName}/jobs/{id}` | A utiliser seulement tant que l'envoi est stoppable. |
|
|
| Historique sortant | `GET` | `/sms/{serviceName}/outgoing` | Filtres disponibles : dates, destinataire, sender, tag, etc. |
|
|
| Detail sortant | `GET` | `/sms/{serviceName}/outgoing/{id}` | Permet de recuperer les informations par SMS envoye. |
|
|
| Expediteurs autorises | `GET` | `/sms/{serviceName}/senders` | Pour valider la configuration sender. |
|
|
|
|
Les endpoints batch existent aussi (`/sms/{serviceName}/batches`) et supportent les envois differes via `deferred`. Decision MVP : demarrer avec `/jobs` pour l'envoi immediat et gerer la programmation cote RelaisSMS via queue/scheduler. Les batches restent une option a reevaluer au lot 7 si l'on veut deleguer le differe a OVH.
|
|
|
|
### Credentials attendus
|
|
|
|
Configuration par variables d'environnement :
|
|
|
|
```dotenv
|
|
OVH_ENDPOINT=ovh-eu
|
|
OVH_APPLICATION_KEY=
|
|
OVH_APPLICATION_SECRET=
|
|
OVH_CONSUMER_KEY=
|
|
OVH_SMS_SERVICE_NAME=
|
|
OVH_SMS_SENDER=
|
|
OVH_SMS_NO_STOP_CLAUSE=true
|
|
```
|
|
|
|
Les secrets ne sont pas stockes en clair en base. L'interface pourra afficher l'etat de configuration sans exposer les valeurs.
|
|
|
|
### Quota et garde-fous
|
|
|
|
- Le compte OVH expose `creditsLeft` via `GET /sms/{serviceName}`.
|
|
- RelaisSMS applique sa propre limite de 100 SMS par campagne par defaut.
|
|
- Avant envoi, le connecteur doit refuser une campagne si :
|
|
- aucun `serviceName` n'est configure ;
|
|
- aucun expediteur valide n'est configure quand necessaire ;
|
|
- la liste finale depasse la limite applicative ;
|
|
- OVH retourne des destinataires invalides.
|
|
|
|
## Numeros de telephone
|
|
|
|
### Echantillon Galette
|
|
|
|
Fichier analyse : `doc/tmp/liste_adherents_filtree.csv`
|
|
|
|
- 179 lignes adherents.
|
|
- 86 numeros presents dans `Telephone` ou `GSM`.
|
|
- Exemples fictifs de formats : `06 11 11 11 11`, `0622222222`, `(+33) 6 33 33 33 33`, `+33 (0)6 44 44 44 44`, fixes francais, numeros internationaux.
|
|
|
|
### Regex portable par defaut
|
|
|
|
La regex par defaut detecte les mobiles francais bruts avant normalisation :
|
|
|
|
```regex
|
|
^\s*(?:(?:\(\s*\+33\s*\)|\+33|0033)\s*(?:\(0\)\s*)?|0)\s*[67](?:[\s.-]*\d{2}){4}\s*$
|
|
```
|
|
|
|
Elle accepte notamment :
|
|
|
|
- `06 11 11 11 11`
|
|
- `0622222222`
|
|
- `07 55 55 55 55`
|
|
- `(+33) 6 33 33 33 33`
|
|
- `+33 (0)6 44 44 44 44`
|
|
- `0033 6 11 11 11 11`
|
|
|
|
Elle exclut les fixes francais (`01`, `02`, `03`, `04`, `05`, `09`) et les numeros mobiles non francais. Le pays par defaut est `FR`.
|
|
|
|
Decision importante : cette regex sert a classifier les portables. La normalisation E.164 reste separee et devra etre faite avec `giggsey/libphonenumber-for-php` au lot 2.
|
|
|
|
## Parametres applicatifs par defaut
|
|
|
|
| Cle | Valeur par defaut | Source |
|
|
| --- | --- | --- |
|
|
| `default_country` | `FR` | Cadrage projet |
|
|
| `mobile_phone_regex` | Regex ci-dessus | Echantillon Galette |
|
|
| `max_sms_per_campaign` | `100` | Cahier des charges |
|
|
| `history_retention_years` | `3` | Cahier des charges |
|
|
| `scheduled_sends_enabled` | `true` | MVP |
|
|
| `active_sms_provider` | `ovh` | Fournisseur cible |
|
|
| `galette_sync_enabled` | `false` | Upgrade Galette non fait |
|
|
| `carddav_sync_enabled` | `false` | Active a partir du lot 3 |
|
|
|
|
## Impacts pour les lots suivants
|
|
|
|
### Lot 1
|
|
|
|
- Initialiser Laravel sans dependance Galette active.
|
|
- Authentification simple.
|
|
- Tous les utilisateurs authentifies sont administrateurs.
|
|
- Prevoir `app_settings` ou configuration equivalente pour les parametres non secrets.
|
|
|
|
### Lot 2
|
|
|
|
- Stocker `raw_number`, `normalized_number`, `is_valid`, `is_mobile`.
|
|
- Utiliser la regex configurable pour `is_mobile`.
|
|
- Ajouter `sms_opt_out` sur les contacts.
|
|
- Prevoir `deleted_at` sur contacts synchronises.
|
|
- Prevoir des cles de source distinctes pour `local`, `carddav` et `galette`.
|
|
|
|
### Lot 3
|
|
|
|
- Implementer `CardDavSourceConnector`.
|
|
- Synchroniser les vCards depuis Nextcloud/CardDAV avec UID et ETag si disponibles.
|
|
- Mapper les categories vCard en groupes importes CardDAV.
|
|
|
|
### Lot 5
|
|
|
|
- Implementer `OvhSmsProvider` via client HTTP signe.
|
|
- Journaliser reponse OVH brute et IDs retournes.
|
|
- Utiliser le champ `tag` OVH pour relier les SMS a une campagne RelaisSMS.
|
|
|
|
### Lot 9
|
|
|
|
- Revalider Galette 1.2.1 apres upgrade.
|
|
- Choisir entre API JSON, export CSV authentifie ou route Galette dediee.
|
|
- Mapper les statuts Galette en groupes applicatifs importes.
|
|
- Garder un nommage Galette explicite, separe de CardDAV/Nextcloud.
|
|
|
|
## Points ouverts
|
|
|
|
| Sujet | Question | A trancher avant |
|
|
| --- | --- | --- |
|
|
| Galette auth | Quel mecanisme d'authentification sera disponible apres upgrade ? | Lot 9 |
|
|
| Galette groupes | Les groupes sont-ils exposes directement ou seulement les statuts ? | Lot 9 |
|
|
| CardDAV categories | Les categories Nextcloud sont-elles renseignees et suffisantes comme groupes ? | Lot 3 |
|
|
| OVH sender | Expediteur alphanumerique valide ou numero reponse ? | Lot 5 |
|
|
| STOP OVH | `noStopClause=true` est-il conforme a l'usage AFPMA non publicitaire ? | Lot 5 |
|
|
| Numeros internationaux | Faut-il envoyer aux mobiles non francais presents dans les sources synchronisees ? | Lot 4 |
|