{"openapi":"3.0.3","info":{"title":"Geo Tracking — API de géolocalisation","version":"0.1.0","description":"Documentation de l'API. Deux réalms d'authentification : PLATEFORME (super administrateurs + personnel, développeurs) et COMPAGNIE (administrateur principal + personnel). Les 4 types de compte compagnie (super_admin_compagnie, corridor, safe_zone, maintenance) sont portés par le rôle de l'utilisateur."},"servers":[{"url":"https://trackingcontroller.isittci.com/api/v1","description":"Serveur courant"},{"url":"http://localhost:4000/api/v1","description":"Développement local"}],"tags":[{"name":"Auth · Plateforme","description":"Connexion et gestion des comptes plateforme (super admin, développeur)."},{"name":"Auth · Compagnie","description":"Connexion et gestion des comptes de compagnie (admin principal + personnel)."},{"name":"Auth · MFA","description":"Authentification à deux facteurs (obligatoire). Flux en 2 temps : la connexion renvoie un challenge, la vérification du 2e facteur (TOTP / SMS / code de secours) délivre les tokens."},{"name":"Rôles","description":"Gestion du catalogue global des rôles (réservée au super administrateur plateforme). Les compagnies attribuent ces rôles à leurs membres."},{"name":"Permissions","description":"Catalogue global des permissions composant les rôles (super administrateur plateforme)."},{"name":"Compagnie · Rôles","description":"Consultation des rôles disponibles et attribution aux utilisateurs de la compagnie."},{"name":"Compagnies","description":"Gestion complète des comptes compagnie : création (avec administrateur principal et lien de confirmation), liste, détail, mise à jour, activation et statistiques. Une compagnie ne peut consulter et modifier que son propre profil."},{"name":"Utilisateurs compagnie","description":"Membres d'une compagnie : listing, détail, mise à jour, activation et suppression. Deux vues : plateforme (toute compagnie) et compagnie (la sienne). La création passe par /auth/compagnie/personnel."},{"name":"Référentiels","description":"Catalogues globaux : pays, fabricants, protocoles de communication, types de zones, types d'événements. Lecture ouverte à tout compte authentifié ; écriture réservée au super administrateur plateforme."},{"name":"Modèles de balises","description":"Catalogue global des modèles de balises (caractéristiques techniques : matériel, connectivité, fonctionnalités, performance, sécurité). Lecture ouverte ; écriture réservée au super administrateur plateforme."},{"name":"Balises","description":"Unités physiques rattachées à une compagnie. L'accès est automatiquement restreint selon le token : une compagnie ne voit que ses balises, filtrées par le rôle du compte (corridor → armées, safe_zone → en safezone, maintenance → en stock, super_admin_compagnie → toutes)."},{"name":"Zones","description":"Lieux géographiques (safezones, arrêts, villes, postes frontières, territoires, bureaux). Géométrie GeoJSON (polygone ou cercle), nomenclature automatique, détection géospatiale et proximité. Accès scopé par compagnie."},{"name":"Corridors","description":"Itinéraires de transit (tronçons polygonaux) reliant une safezone de départ à une safezone d'arrivée. Duplication bidirectionnelle du tracé (départ ↔ arrivée) sans redessiner. Accès scopé par compagnie."},{"name":"Véhicules","description":"Flotte d'une compagnie. Le périmètre est déduit du token : un compte plateforme consulte tout le parc (filtre ?compagnieId=), un compte compagnie ne voit que ses véhicules. Les ÉCRITURES sont réservées aux membres de la compagnie : les colonnes d'audit référencent la table `utilisateurs`, dans laquelle un compte plateforme n'existe pas."},{"name":"Conducteurs","description":"Conducteurs employés par une compagnie, et leurs codes d'activation (phrase permettant de démarrer un véhicule équipé d'une balise avec coupure moteur). Périmètre déduit du token ; écritures réservées aux membres de la compagnie."},{"name":"Affectations","description":"Historique des périodes d'affectation conducteur ↔ véhicule. Une affectation ouverte a `dateFin: null`. Un conducteur comme un véhicule n'ont qu'une affectation ouverte à la fois (garanti par index unique)."},{"name":"Attelages","description":"Historique des couplages entre un véhicule tracteur et un élément remorquable (remorque, semi-remorque, citerne). Un attelage ouvert a `dateFin: null`. Un tracteur ne tire qu'une remorque à la fois, et réciproquement — garanti par index unique. Le couple tracteur/remorque n'est pas modifiable : on dételle puis on réattelle, ce qui préserve l'historique."}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Coller l'access token obtenu à la connexion."},"mfaChallenge":{"type":"apiKey","in":"header","name":"X-MFA-Challenge","description":"Token de challenge renvoyé par la connexion (étape 1). À présenter sur /auth/mfa/setup, /auth/mfa/verify et /auth/mfa/sms/send."}},"schemas":{"ErrorResponse":{"type":"object","properties":{"success":{"type":"boolean","example":false},"message":{"type":"string","example":"Identifiants invalides"},"details":{"type":"object","nullable":true,"description":"Détails de validation éventuels (par champ).","additionalProperties":true}},"required":["success","message"]},"CoupleTokens":{"type":"object","properties":{"accessToken":{"type":"string","description":"JWT court (Bearer)."},"refreshToken":{"type":"string","description":"JWT long (rotation à chaque refresh)."},"expiresIn":{"type":"integer","description":"Durée de vie de l'access token (secondes).","example":900}},"required":["accessToken","refreshToken","expiresIn"]},"ConnexionRequest":{"type":"object","properties":{"email":{"type":"string","format":"email","example":"admin@exemple.com"},"motDePasse":{"type":"string","format":"password","example":"MotDePasse#2026"}},"required":["email","motDePasse"]},"RefreshRequest":{"type":"object","properties":{"refreshToken":{"type":"string"}},"required":["refreshToken"]},"ChangementMotDePasseRequest":{"type":"object","properties":{"ancienMotDePasse":{"type":"string","format":"password"},"nouveauMotDePasse":{"type":"string","format":"password","description":"≥ 10 caractères, avec minuscule, majuscule, chiffre et caractère spécial."}},"required":["ancienMotDePasse","nouveauMotDePasse"]},"CreerPersonnelSuperAdminRequest":{"type":"object","properties":{"nom":{"type":"string","example":"Kouassi"},"prenom":{"type":"string","example":"Awa"},"email":{"type":"string","format":"email"},"motDePasse":{"type":"string","format":"password"},"telephone":{"type":"string","nullable":true,"example":"+2250700000000"}},"required":["nom","prenom","email","motDePasse"]},"CreerPersonnelCompagnieRequest":{"type":"object","properties":{"nom":{"type":"string"},"prenom":{"type":"string"},"email":{"type":"string","format":"email"},"motDePasse":{"type":"string","format":"password"},"telephone":{"type":"string","nullable":true},"roleId":{"type":"string","format":"uuid","description":"Rôle du membre (corridor / safe_zone / maintenance...). Le rôle super_admin_compagnie est interdit par cette route."}},"required":["nom","prenom","email","motDePasse","roleId"]},"ComptePlateforme":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"nom":{"type":"string"},"prenom":{"type":"string"},"email":{"type":"string","format":"email"},"typeCompte":{"type":"string","enum":["super_administrateur","developpeur"]}}},"ConnexionPlateformeResponse":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"compte":{"$ref":"#/components/schemas/ComptePlateforme"},"tokens":{"$ref":"#/components/schemas/CoupleTokens"}}}}},"UtilisateurCompagnie":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"nom":{"type":"string"},"prenom":{"type":"string"},"email":{"type":"string","format":"email"},"estPrincipal":{"type":"boolean"},"compagnie":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"raisonSociale":{"type":"string"},"code":{"type":"string"}}},"role":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"code":{"type":"string","enum":["super_admin_compagnie","corridor","safe_zone","maintenance"]},"nom":{"type":"string"}}},"permissions":{"type":"array","items":{"type":"string"},"example":["balises.lire","corridors.lire"]}}},"ConnexionCompagnieResponse":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"utilisateur":{"$ref":"#/components/schemas/UtilisateurCompagnie"},"tokens":{"$ref":"#/components/schemas/CoupleTokens"}}}}},"TokensResponse":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"tokens":{"$ref":"#/components/schemas/CoupleTokens"}}}}},"MessageResponse":{"type":"object","properties":{"success":{"type":"boolean","example":true},"message":{"type":"string","example":"Déconnecté"}}},"ChallengeResponse":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"mfaRequired":{"type":"boolean","example":true},"setupRequired":{"type":"boolean","description":"true si la 2FA n'a jamais été configurée pour ce compte."},"challengeToken":{"type":"string","description":"JWT court (5 min) à passer en en-tête X-MFA-Challenge."}},"required":["mfaRequired","setupRequired","challengeToken"]}}},"MfaSetupResponse":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"secret":{"type":"string","description":"Secret TOTP base32 (saisie manuelle possible)."},"otpauthUrl":{"type":"string","example":"otpauth://totp/Geo%20Tracking:..."},"qrCodeDataUrl":{"type":"string","description":"Image PNG (data URL base64) du QR code à scanner.","example":"data:image/png;base64,iVBORw0KGgo..."},"message":{"type":"string"}}}}},"MfaVerifyRequest":{"type":"object","properties":{"methode":{"type":"string","enum":["totp","sms","backup"],"description":"Méthode du 2e facteur. À la première activation, seul \"totp\" est accepté."},"code":{"type":"string","example":"123456"},"challengeToken":{"type":"string","description":"Optionnel si le challenge est passé en en-tête X-MFA-Challenge."}},"required":["methode","code"]},"MfaVerifyResponse":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"tokens":{"$ref":"#/components/schemas/CoupleTokens"},"backupCodes":{"type":"array","items":{"type":"string"},"description":"Présent UNIQUEMENT à la première activation. Codes de secours en clair, à montrer une seule fois."}}}}},"MfaTelephoneRequest":{"type":"object","properties":{"telephone":{"type":"string","description":"Numéro au format international E.164.","example":"+2250700000000"}},"required":["telephone"]},"MfaBackupCodesResponse":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"backupCodes":{"type":"array","items":{"type":"string"}}}},"message":{"type":"string"}}},"Permission":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"code":{"type":"string","example":"balises.creer"},"libelle":{"type":"string","example":"Créer une balise"},"module":{"type":"string","example":"balises"},"description":{"type":"string","nullable":true},"actif":{"type":"boolean"}}},"Role":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"nom":{"type":"string","example":"Compte corridor"},"code":{"type":"string","example":"corridor"},"description":{"type":"string","nullable":true},"estSysteme":{"type":"boolean","description":"Rôle protégé (non modifiable/supprimable)."},"actif":{"type":"boolean"},"permissions":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"code":{"type":"string"},"libelle":{"type":"string"},"module":{"type":"string"}}}}}},"RoleResponse":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/Role"}}},"RoleListResponse":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/Role"}}}},"CreerRoleRequest":{"type":"object","properties":{"nom":{"type":"string","example":"Superviseur"},"code":{"type":"string","description":"Optionnel — dérivé du nom si absent (snake_case).","example":"superviseur"},"description":{"type":"string","nullable":true},"permissionIds":{"type":"array","items":{"type":"string","format":"uuid"},"description":"Permissions à accorder à la création."}},"required":["nom"]},"MettreAJourRoleRequest":{"type":"object","properties":{"nom":{"type":"string"},"code":{"type":"string","description":"Ignoré pour un rôle système."},"description":{"type":"string","nullable":true},"actif":{"type":"boolean"}}},"DefinirPermissionsRequest":{"type":"object","properties":{"permissionIds":{"type":"array","items":{"type":"string","format":"uuid"},"description":"Liste complète des permissions du rôle (remplace l'existant)."}},"required":["permissionIds"]},"PermissionResponse":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/Permission"}}},"PermissionListResponse":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/Permission"}}}},"CreerPermissionRequest":{"type":"object","properties":{"code":{"type":"string","example":"zones.gerer","description":"Convention \"module.action\"."},"libelle":{"type":"string","example":"Gérer les zones"},"module":{"type":"string","example":"zones"},"description":{"type":"string","nullable":true}},"required":["code","libelle","module"]},"MettreAJourPermissionRequest":{"type":"object","properties":{"libelle":{"type":"string"},"module":{"type":"string"},"description":{"type":"string","nullable":true}}},"ActivationPermissionRequest":{"type":"object","properties":{"actif":{"type":"boolean"}},"required":["actif"]},"RolesDisponiblesResponse":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"nom":{"type":"string"},"code":{"type":"string"},"description":{"type":"string","nullable":true},"permissions":{"type":"array","items":{"type":"string"}}}}}}},"ChangerRoleRequest":{"type":"object","properties":{"roleId":{"type":"string","format":"uuid"}},"required":["roleId"]},"CreerCompagnieRequest":{"type":"object","properties":{"compagnie":{"type":"object","properties":{"code":{"type":"string","maxLength":15,"example":"CT-001"},"raisonSociale":{"type":"string","example":"Transports Atlantique SA"},"email":{"type":"string","format":"email","example":"contact@atlantique.ci"},"telephone":{"type":"string","example":"+2252700000000"},"adresse":{"type":"string","nullable":true},"paysId":{"type":"string","format":"uuid"}},"required":["code","raisonSociale","email","telephone","paysId"]},"adminPrincipal":{"type":"object","properties":{"nom":{"type":"string","example":"Kouassi"},"prenom":{"type":"string","example":"Awa"},"email":{"type":"string","format":"email","example":"awa.kouassi@atlantique.ci"},"telephone":{"type":"string","nullable":true}},"required":["nom","prenom","email"]}},"required":["compagnie","adminPrincipal"]},"CreerCompagnieResponse":{"type":"object","properties":{"success":{"type":"boolean","example":true},"message":{"type":"string"},"data":{"type":"object","properties":{"compagnie":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"code":{"type":"string"},"raisonSociale":{"type":"string"},"email":{"type":"string","format":"email"},"actif":{"type":"boolean"}}},"adminPrincipal":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"nom":{"type":"string"},"prenom":{"type":"string"},"email":{"type":"string","format":"email"},"actif":{"type":"boolean","description":"false tant que le compte n'est pas confirmé (mot de passe non défini)."}}},"emailEnvoye":{"type":"boolean"}}}}},"InfoConfirmationResponse":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"email":{"type":"string","format":"email"},"prenom":{"type":"string"},"nom":{"type":"string"}}}}},"ConfirmerCompteRequest":{"type":"object","properties":{"token":{"type":"string","description":"Token reçu dans le lien email."},"motDePasse":{"type":"string","format":"password","description":"≥ 10 caractères, avec minuscule, majuscule, chiffre et caractère spécial."}},"required":["token","motDePasse"]},"Pays":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"nom":{"type":"string","example":"Côte d'Ivoire"},"codeIso2":{"type":"string","example":"CI"},"codeIso3":{"type":"string","example":"CIV"},"indicatifTelephonique":{"type":"string","nullable":true,"example":"+225"},"devise":{"type":"string","nullable":true,"example":"XOF"},"actif":{"type":"boolean"}}},"Fabricant":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"nom":{"type":"string","example":"Concox"},"niveau_support":{"type":"string","nullable":true},"actif":{"type":"boolean"}}},"Protocole":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"nom":{"type":"string","example":"MQTT"},"code":{"type":"string","example":"mqtt"},"description":{"type":"string","nullable":true},"port_defaut":{"type":"integer","nullable":true,"example":1883},"supporte_chiffrement":{"type":"boolean"},"actif":{"type":"boolean"}}},"TypeZone":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"libelle":{"type":"string","example":"Safezone"},"code":{"type":"string","example":"safezone"},"description":{"type":"string","nullable":true},"declencheAlerteEntree":{"type":"boolean"},"declencheAlerteSortie":{"type":"boolean"},"actif":{"type":"boolean"}}},"TypeEvenement":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"libelle":{"type":"string","example":"Sortie de corridor"},"code":{"type":"string","example":"sortie_corridor"},"categorie":{"type":"string","enum":["geofencing","vitesse","batterie","sabotage","sos","maintenance","connexion","activation"]},"niveauGravite":{"type":"string","enum":["info","avertissement","critique"]},"icone":{"type":"string","nullable":true},"couleur":{"type":"string","nullable":true,"example":"#EF4444"},"description":{"type":"string","nullable":true},"actif":{"type":"boolean"}}},"CreerPaysRequest":{"type":"object","properties":{"nom":{"type":"string"},"codeIso2":{"type":"string","minLength":2,"maxLength":2},"codeIso3":{"type":"string","minLength":3,"maxLength":3},"indicatifTelephonique":{"type":"string","nullable":true},"devise":{"type":"string","nullable":true}},"required":["nom","codeIso2","codeIso3"]},"CreerFabricantRequest":{"type":"object","properties":{"nom":{"type":"string"},"niveau_support":{"type":"string","nullable":true}},"required":["nom"]},"CreerProtocoleRequest":{"type":"object","properties":{"nom":{"type":"string"},"code":{"type":"string","description":"snake_case"},"description":{"type":"string","nullable":true},"port_defaut":{"type":"integer","nullable":true},"supporte_chiffrement":{"type":"boolean"}},"required":["nom","code"]},"CreerTypeZoneRequest":{"type":"object","properties":{"libelle":{"type":"string"},"code":{"type":"string","description":"snake_case"},"description":{"type":"string","nullable":true},"declencheAlerteEntree":{"type":"boolean"},"declencheAlerteSortie":{"type":"boolean"}},"required":["libelle","code"]},"CreerTypeEvenementRequest":{"type":"object","properties":{"libelle":{"type":"string"},"code":{"type":"string","description":"snake_case"},"categorie":{"type":"string","enum":["geofencing","vitesse","batterie","sabotage","sos","maintenance","connexion","activation"]},"niveauGravite":{"type":"string","enum":["info","avertissement","critique"]},"icone":{"type":"string","nullable":true},"couleur":{"type":"string","nullable":true,"description":"Hex #RRGGBB"},"description":{"type":"string","nullable":true}},"required":["libelle","code","categorie"]},"ActivationRequest":{"type":"object","properties":{"actif":{"type":"boolean"}},"required":["actif"]},"ModeleBalise":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"nom":{"type":"string","example":"GT06N"},"actif":{"type":"boolean"},"fabricant":{"type":"object","nullable":true,"properties":{"id":{"type":"string","format":"uuid"},"nom":{"type":"string"}}},"protocoleCommunication":{"type":"object","nullable":true,"properties":{"id":{"type":"string","format":"uuid"},"nom":{"type":"string"},"code":{"type":"string"}}},"materiel":{"type":"object","properties":{"typePuceGnss":{"type":"string","nullable":true,"example":"GPS/GLONASS"},"capaciteBatterieMah":{"type":"integer","nullable":true,"example":450},"typeAlimentation":{"type":"string","nullable":true},"indiceProtection":{"type":"string","nullable":true,"example":"IP67"},"poidsGrammes":{"type":"number","nullable":true},"temperatureMin":{"type":"number","nullable":true},"temperatureMax":{"type":"number","nullable":true}}},"connectivite":{"type":"object","properties":{"typeReseau":{"type":"string","nullable":true,"example":"4G"},"frequenceTransmissionSecondes":{"type":"integer","nullable":true,"example":30}}},"fonctionnalites":{"type":"object","properties":{"aAccelerometre":{"type":"boolean"},"aCapteurTemperature":{"type":"boolean"},"aBoutonSos":{"type":"boolean"},"aMicro":{"type":"boolean"},"aCoupureMoteur":{"type":"boolean"},"aDetectionSabotage":{"type":"boolean"},"modeEconomieEnergie":{"type":"boolean"}}},"performance":{"type":"object","properties":{"precisionMetres":{"type":"number","nullable":true},"ttffSecondes":{"type":"integer","nullable":true},"nombreSatellitesMax":{"type":"integer","nullable":true}}},"securite":{"type":"object","properties":{"communicationChiffree":{"type":"boolean"},"antiJamming":{"type":"boolean"}}}}},"CreerModeleBaliseRequest":{"type":"object","properties":{"nom":{"type":"string","example":"GT06N"},"fabricantId":{"type":"string","format":"uuid"},"protocoleCommunicationId":{"type":"string","format":"uuid","nullable":true},"typePuceGnss":{"type":"string","nullable":true},"capaciteBatterieMah":{"type":"integer","nullable":true},"typeAlimentation":{"type":"string","nullable":true},"indiceProtection":{"type":"string","nullable":true},"poidsGrammes":{"type":"number","nullable":true},"temperatureMin":{"type":"number","nullable":true},"temperatureMax":{"type":"number","nullable":true},"typeReseau":{"type":"string","nullable":true},"frequenceTransmissionSecondes":{"type":"integer","nullable":true},"aAccelerometre":{"type":"boolean"},"aCapteurTemperature":{"type":"boolean"},"aBoutonSos":{"type":"boolean"},"aMicro":{"type":"boolean"},"aCoupureMoteur":{"type":"boolean"},"aDetectionSabotage":{"type":"boolean"},"modeEconomieEnergie":{"type":"boolean"},"precisionMetres":{"type":"number","nullable":true},"ttffSecondes":{"type":"integer","nullable":true},"nombreSatellitesMax":{"type":"integer","nullable":true},"communicationChiffree":{"type":"boolean"},"antiJamming":{"type":"boolean"}},"required":["nom","fabricantId"]},"Balise":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"imei":{"type":"string","example":"351756051523999"},"numeroSerie":{"type":"string","nullable":true},"idBalise":{"type":"string","nullable":true,"description":"Identifiant plateforme, distinct de l'IMEI."},"typeBalise":{"type":"string","nullable":true,"description":"Type commercial (ex. TT10C), distinct du modèle."},"iccidSim":{"type":"string","nullable":true},"numeroTelephoneSim":{"type":"string","nullable":true},"codePinSim":{"type":"string","nullable":true,"description":"PIN de la carte SIM (4 chiffres)."},"pinActif":{"type":"boolean"},"apn":{"type":"string","nullable":true},"fournisseurGeolocalisation":{"type":"string","nullable":true,"example":"Mondial Track"},"etat":{"type":"string","enum":["en_stock","armee","desarmee","endommagee","transferee"],"description":"Cycle de vie de la balise (fusion de l'ancien statut matériel et de l'état métier)."},"nomAffichage":{"type":"string","nullable":true,"example":"2604-BSE12345"},"referenceBse":{"type":"string","nullable":true,"description":"Obligatoire lorsque etat = armee."},"dateDerniereMaintenance":{"type":"string","format":"date","nullable":true},"dateDeclaration":{"type":"string","format":"date","nullable":true},"dateSuppression":{"type":"string","format":"date","nullable":true},"dateRedeclaration":{"type":"string","format":"date","nullable":true},"activeeSurPlateforme":{"type":"boolean"},"modele":{"type":"object","nullable":true,"properties":{"id":{"type":"string","format":"uuid"},"nom":{"type":"string"},"fabricant":{"type":"object","nullable":true},"protocole":{"type":"object","nullable":true}}},"compagnie":{"type":"object","nullable":true,"properties":{"id":{"type":"string","format":"uuid"},"code":{"type":"string"},"raisonSociale":{"type":"string"}}},"creeLe":{"type":"string","format":"date-time"}}},"BaliseListResponse":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/Balise"}},"pagination":{"type":"object","properties":{"total":{"type":"integer"},"limite":{"type":"integer"},"offset":{"type":"integer"}}}}},"ImporterBalisesCsvRequest":{"type":"object","description":"Import en masse (pages « Gestion des balises » et « Déclaration balises » — deux jeux de libellés de colonnes reconnus, voir ENTETES_CSV dans balise.service.ts). Toutes les lignes sont rattachées à la même compagnie ; « Compte PF » éventuel est ignoré. Si `modeleId` est fourni, toutes les lignes l'utilisent ; sinon il est résolu ligne par ligne par correspondance exacte entre la colonne Type de balise/Modele du CSV et ModeleBalise.nom. Séparateur `;`. Seule colonne obligatoire : Tracker Imei Number (ou « N° IMEI balise »).","properties":{"contenuCsv":{"type":"string","description":"Contenu brut du fichier .csv."},"compagnieId":{"type":"string","format":"uuid"},"modeleId":{"type":"string","format":"uuid","nullable":true,"description":"Omis : résolu ligne par ligne depuis le CSV (voir description)."}},"required":["contenuCsv","compagnieId"]},"ImporterBalisesCsvResponse":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"total":{"type":"integer","description":"Nombre de lignes de données lues."},"creees":{"type":"integer"},"erreurs":{"type":"array","items":{"type":"object","properties":{"ligne":{"type":"integer"},"message":{"type":"string"}}}}}}}},"CreerBaliseRequest":{"type":"object","properties":{"imei":{"type":"string","description":"15 à 17 chiffres.","example":"351756051523999"},"numeroSerie":{"type":"string","nullable":true},"idBalise":{"type":"string","nullable":true},"typeBalise":{"type":"string","nullable":true},"iccidSim":{"type":"string","nullable":true,"description":"18 à 22 chiffres."},"numeroTelephoneSim":{"type":"string","nullable":true},"codePinSim":{"type":"string","nullable":true,"description":"4 chiffres."},"pinActif":{"type":"boolean"},"apn":{"type":"string","nullable":true},"fournisseurGeolocalisation":{"type":"string","nullable":true},"modeleId":{"type":"string","format":"uuid"},"compagnieId":{"type":"string","format":"uuid","description":"Compagnie propriétaire."},"etat":{"type":"string","enum":["en_stock","armee","desarmee","endommagee","transferee"]},"nomAffichage":{"type":"string","nullable":true},"referenceBse":{"type":"string","nullable":true,"description":"Requis si etat = armee."},"dateDerniereMaintenance":{"type":"string","format":"date","nullable":true},"dateDeclaration":{"type":"string","format":"date","nullable":true},"dateSuppression":{"type":"string","format":"date","nullable":true},"dateRedeclaration":{"type":"string","format":"date","nullable":true},"activeeSurPlateforme":{"type":"boolean"}},"required":["imei","modeleId","compagnieId"]},"MajBaliseRequest":{"type":"object","description":"Champs modifiables par une COMPAGNIE : iccidSim, numeroTelephoneSim, codePinSim, pinActif, apn, etat, nomAffichage, referenceBse, dateDerniereMaintenance. Les champs imei / modeleId / compagnieId et les champs de déclaration sont réservés à la plateforme.","properties":{"imei":{"type":"string"},"numeroSerie":{"type":"string","nullable":true},"idBalise":{"type":"string","nullable":true},"typeBalise":{"type":"string","nullable":true},"iccidSim":{"type":"string","nullable":true},"numeroTelephoneSim":{"type":"string","nullable":true},"codePinSim":{"type":"string","nullable":true},"pinActif":{"type":"boolean"},"apn":{"type":"string","nullable":true},"fournisseurGeolocalisation":{"type":"string","nullable":true},"modeleId":{"type":"string","format":"uuid"},"compagnieId":{"type":"string","format":"uuid"},"etat":{"type":"string","enum":["en_stock","armee","desarmee","endommagee","transferee"]},"nomAffichage":{"type":"string","nullable":true},"referenceBse":{"type":"string","nullable":true},"dateDerniereMaintenance":{"type":"string","format":"date","nullable":true},"dateDeclaration":{"type":"string","format":"date","nullable":true},"dateSuppression":{"type":"string","format":"date","nullable":true},"dateRedeclaration":{"type":"string","format":"date","nullable":true},"activeeSurPlateforme":{"type":"boolean"}}},"ChangerEtatBaliseRequest":{"type":"object","properties":{"etat":{"type":"string","enum":["en_stock","armee","desarmee","endommagee","transferee"]},"referenceBse":{"type":"string","nullable":true,"description":"Requis si état = armee."}},"required":["etat"]},"ReaffecterBaliseRequest":{"type":"object","properties":{"compagnieId":{"type":"string","format":"uuid"}},"required":["compagnieId"]},"StatistiquesParcResponse":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"total":{"type":"integer"},"parEtat":{"type":"object","additionalProperties":{"type":"integer"},"example":{"en_stock":12,"armee":24,"desarmee":8,"endommagee":3,"transferee":1}},"parStatutTempsReel":{"type":"object","additionalProperties":{"type":"integer"},"description":"Calculé à la volée depuis la dernière position (voir statut-temps-reel.service.ts).","example":{"actif":5,"en_pause":2,"arrete":10,"inactif":20,"deconnecte":3}}}}}},"Compagnie":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"code":{"type":"string","example":"CT-001","description":"Identifiant métier — non modifiable."},"raisonSociale":{"type":"string","example":"Transports Atlantique SA"},"email":{"type":"string","format":"email"},"telephone":{"type":"string"},"adresse":{"type":"string","nullable":true},"actif":{"type":"boolean"},"pays":{"type":"object","nullable":true,"properties":{"id":{"type":"string","format":"uuid"},"nom":{"type":"string"},"codeIso2":{"type":"string"}}},"creeLe":{"type":"string","format":"date-time"}}},"CompagnieDetail":{"allOf":[{"$ref":"#/components/schemas/Compagnie"},{"type":"object","properties":{"adminPrincipal":{"type":"object","nullable":true,"properties":{"id":{"type":"string","format":"uuid"},"nom":{"type":"string"},"prenom":{"type":"string"},"email":{"type":"string","format":"email"},"telephone":{"type":"string","nullable":true},"actif":{"type":"boolean","description":"false tant que le compte n'est pas confirmé."},"estPrincipal":{"type":"boolean"},"role":{"type":"object","nullable":true}}}}}]},"CompagnieListResponse":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/Compagnie"}},"pagination":{"type":"object","properties":{"total":{"type":"integer"},"limite":{"type":"integer"},"offset":{"type":"integer"}}}}},"MajCompagnieRequest":{"type":"object","description":"Le `code` n'est jamais modifiable. Le champ `pays_id` est réservé aux comptes plateforme (ignoré pour une compagnie).","properties":{"raisonSociale":{"type":"string"},"email":{"type":"string","format":"email"},"telephone":{"type":"string"},"adresse":{"type":"string","nullable":true},"pays_id":{"type":"string","format":"uuid","description":"Plateforme uniquement."}}},"StatistiquesCompagnieResponse":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"utilisateurs":{"type":"object","properties":{"total":{"type":"integer"},"actifs":{"type":"integer"},"inactifs":{"type":"integer"}}},"balises":{"type":"object","properties":{"total":{"type":"integer"},"parEtat":{"type":"object","additionalProperties":{"type":"integer"}}}}}}}},"MembreCompagnie":{"type":"object","description":"Membre d'une compagnie tel que renvoyé par les endpoints de gestion des utilisateurs (distinct de UtilisateurCompagnie, utilisé par /auth).","properties":{"id":{"type":"string","format":"uuid"},"nom":{"type":"string"},"prenom":{"type":"string"},"email":{"type":"string","format":"email","description":"Non modifiable (identifiant de connexion)."},"telephone":{"type":"string","nullable":true},"actif":{"type":"boolean"},"estPrincipal":{"type":"boolean"},"derniereConnexionLe":{"type":"string","format":"date-time","nullable":true},"role":{"type":"object","nullable":true,"properties":{"id":{"type":"string","format":"uuid"},"code":{"type":"string"},"nom":{"type":"string"}}},"compagnie":{"type":"object","nullable":true,"properties":{"id":{"type":"string","format":"uuid"},"code":{"type":"string"},"raisonSociale":{"type":"string"}}}}},"UtilisateurListResponse":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/MembreCompagnie"}},"pagination":{"type":"object","properties":{"total":{"type":"integer"},"limite":{"type":"integer"},"offset":{"type":"integer"}}}}},"MajUtilisateurRequest":{"type":"object","description":"L'email et le rôle ne se modifient pas ici (voir /compagnie/utilisateurs/{id}/role).","properties":{"nom":{"type":"string"},"prenom":{"type":"string"},"telephone":{"type":"string","nullable":true}}},"GeoJSONGeometry":{"type":"object","description":"Géométrie GeoJSON (SRID 4326). Le type dépend de l'usage.","properties":{"type":{"type":"string","enum":["Polygon","MultiPolygon","Point","LineString"]},"coordinates":{"type":"array","items":{},"description":"Coordonnées imbriquées selon le type GeoJSON."}},"required":["type","coordinates"]},"Cercle":{"type":"object","description":"Zone circulaire : centre [lon, lat] et rayon en mètres.","properties":{"centre":{"type":"array","items":{"type":"number"},"minItems":2,"maxItems":2,"example":[-4.0083,5.3599]},"rayonMetres":{"type":"number","example":500}},"required":["centre","rayonMetres"]},"Zone":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"nom":{"type":"string","example":"ABIDJAN-SAFEZONE","description":"Généré automatiquement."},"categorie":{"type":"string","enum":["safezone","arret_autorise","arret_non_autorise","ville","poste_frontiere","territoire","bureau"]},"typeZoneId":{"type":"string","format":"uuid"},"compagnieId":{"type":"string","format":"uuid"},"tag":{"type":"string","nullable":true,"description":"Mots-clés pour rapports personnalisés."},"description":{"type":"string","nullable":true},"actif":{"type":"boolean","description":"Désactivée : exclue du monitoring auto, reste utilisable pour les alertes."},"geometrie":{"$ref":"#/components/schemas/GeoJSONGeometry"},"aireM2":{"type":"number","description":"Aire en mètres carrés (calculée)."},"creeLe":{"type":"string","format":"date-time"}}},"ZoneListResponse":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/Zone"}},"pagination":{"type":"object","properties":{"total":{"type":"integer"},"limite":{"type":"integer"},"offset":{"type":"integer"}}}}},"CreerZoneRequest":{"type":"object","description":"Fournir soit `geometrie` (polygone), soit `cercle` (centre + rayon).","properties":{"typeZoneId":{"type":"string","format":"uuid"},"categorie":{"type":"string","enum":["safezone","arret_autorise","arret_non_autorise","ville","poste_frontiere","territoire","bureau"]},"libelle":{"type":"string","description":"Sert à générer le nom normalisé.","example":"Abidjan"},"tag":{"type":"string","nullable":true},"description":{"type":"string","nullable":true},"actif":{"type":"boolean"},"compagnieId":{"type":"string","format":"uuid","description":"Requis pour un compte plateforme."},"geometrie":{"$ref":"#/components/schemas/GeoJSONGeometry"},"cercle":{"$ref":"#/components/schemas/Cercle"}},"required":["typeZoneId","categorie","libelle"]},"MajZoneRequest":{"type":"object","properties":{"typeZoneId":{"type":"string","format":"uuid"},"libelle":{"type":"string","description":"Renomme la zone (nom régénéré)."},"tag":{"type":"string","nullable":true},"description":{"type":"string","nullable":true},"actif":{"type":"boolean"},"geometrie":{"$ref":"#/components/schemas/GeoJSONGeometry"}}},"DupliquerZoneRequest":{"type":"object","properties":{"nouveauLibelle":{"type":"string"}},"required":["nouveauLibelle"]},"Corridor":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"nom":{"type":"string","example":"CR-ABIDJAN-KORHOGO","description":"Généré automatiquement."},"code":{"type":"string","example":"cr_abidjan_korhogo","description":"Unique par compagnie ; dérivé du nom si non fourni."},"compagnieId":{"type":"string","format":"uuid"},"safezoneDepartId":{"type":"string","format":"uuid"},"safezoneArriveeId":{"type":"string","format":"uuid"},"largeurMetres":{"type":"number","example":60},"delaiSortieNotificationSecondes":{"type":"integer","example":300,"description":"Durée hors couloir avant alerte (règle des 5 minutes du CDC)."},"tag":{"type":"string","nullable":true},"description":{"type":"string","nullable":true},"actif":{"type":"boolean"},"couleurAffichage":{"type":"string","nullable":true,"example":"#3b82f6","description":"Couleur du tracé sur la carte (front), format hexadécimal #RRGGBB."},"epaisseurAffichage":{"type":"integer","example":3,"description":"Épaisseur du trait sur la carte (front), en pixels (1 à 12, défaut 3)."},"trace":{"$ref":"#/components/schemas/GeoJSONGeometry"},"ligneCentrale":{"allOf":[{"$ref":"#/components/schemas/GeoJSONGeometry"}],"nullable":true,"description":"Ligne centrale d'origine (LineString), avant élargissement en `trace` — permet de ré-ajuster le tracé en modification. Nulle pour un corridor créé directement via un polygone (`trace`)."},"longueurM":{"type":"number","description":"Longueur approchée du couloir en mètres, déduite du périmètre : (périmètre − π×largeur) / 2. Le tracé étant surfacique, cette valeur est une approximation, exacte pour un couloir issu d'une ligne centrale élargie."},"creeLe":{"type":"string","format":"date-time"}}},"CorridorListResponse":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/Corridor"}},"pagination":{"type":"object","properties":{"total":{"type":"integer"},"limite":{"type":"integer"},"offset":{"type":"integer"}}}}},"CreerCorridorRequest":{"type":"object","description":"Fournir soit `trace` (tronçon polygone), soit `ligneCentrale` (élargie à `largeurMetres`, défaut 60 m).","properties":{"depart":{"type":"string","example":"Abidjan"},"destination":{"type":"string","example":"Korhogo"},"safezoneDepartId":{"type":"string","format":"uuid"},"safezoneArriveeId":{"type":"string","format":"uuid"},"code":{"type":"string","example":"cr_abidjan_korhogo","description":"Optionnel — dérivé du nom généré si omis."},"largeurMetres":{"type":"number","example":60},"delaiSortieNotificationSecondes":{"type":"integer","example":300,"description":"Défaut 300 s (règle des 5 minutes du CDC)."},"tag":{"type":"string","nullable":true},"description":{"type":"string","nullable":true},"actif":{"type":"boolean"},"compagnieId":{"type":"string","format":"uuid","description":"Requis pour un compte plateforme."},"trace":{"$ref":"#/components/schemas/GeoJSONGeometry"},"ligneCentrale":{"$ref":"#/components/schemas/GeoJSONGeometry"},"couleurAffichage":{"type":"string","nullable":true,"example":"#3b82f6","description":"Format hexadécimal #RRGGBB."},"epaisseurAffichage":{"type":"integer","example":3,"description":"En pixels, 1 à 12 (défaut 3)."}},"required":["depart","destination","safezoneDepartId","safezoneArriveeId"]},"MajCorridorRequest":{"type":"object","description":"Pour ajuster le tracé, fournir soit `trace` (polygone direct), soit `ligneCentrale` (ré-élargie côté serveur à la largeur courante ou nouvellement fournie) — jamais les deux.","properties":{"code":{"type":"string","example":"cr_abidjan_korhogo"},"largeurMetres":{"type":"number"},"delaiSortieNotificationSecondes":{"type":"integer","example":300},"tag":{"type":"string","nullable":true},"description":{"type":"string","nullable":true},"actif":{"type":"boolean"},"trace":{"$ref":"#/components/schemas/GeoJSONGeometry"},"ligneCentrale":{"$ref":"#/components/schemas/GeoJSONGeometry"},"couleurAffichage":{"type":"string","nullable":true,"example":"#3b82f6","description":"Format hexadécimal #RRGGBB."},"epaisseurAffichage":{"type":"integer","example":3,"description":"En pixels, 1 à 12."}}},"Vehicule":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"immatriculation":{"type":"string","example":"CI 1234 AB","description":"Normalisée en majuscules."},"marque":{"type":"string","example":"Mercedes"},"modele":{"type":"string","example":"Sprinter"},"couleur":{"type":"string","nullable":true,"example":"blanc"},"typeVehicule":{"type":"string","enum":["bus","minibus","car","camion","voiture","tracteur","remorque","semi_remorque","citerne"]},"annee":{"type":"integer","nullable":true,"example":2020},"numeroChassis":{"type":"string","nullable":true,"description":"VIN. Unique au sein de la compagnie."},"capacitePassagers":{"type":"integer","nullable":true,"description":"Interdit pour un véhicule tracté (remorque, semi_remorque, citerne)."},"capaciteChargeKg":{"type":"integer","nullable":true,"description":"Charge utile (camion, remorque, citerne)."},"statut":{"type":"string","enum":["actif","en_maintenance","hors_service"]},"dateMiseEnCirculation":{"type":"string","format":"date","nullable":true},"balise":{"type":"object","nullable":true,"description":"Balise GPS installée, le cas échéant.","properties":{"id":{"type":"string","format":"uuid"},"imei":{"type":"string"},"nomAffichage":{"type":"string","nullable":true},"etat":{"type":"string"}}},"compagnie":{"type":"object","nullable":true,"properties":{"id":{"type":"string","format":"uuid"},"code":{"type":"string"},"raisonSociale":{"type":"string"}}},"createur":{"type":"object","nullable":true,"description":"Membre de la compagnie ayant créé le véhicule.","properties":{"id":{"type":"string","format":"uuid"},"nom":{"type":"string"},"prenom":{"type":"string"}}},"creeLe":{"type":"string","format":"date-time"},"modifieLe":{"type":"string","format":"date-time"}}},"VehiculeListResponse":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/Vehicule"}},"pagination":{"type":"object","properties":{"total":{"type":"integer","example":12},"limite":{"type":"integer","example":50},"offset":{"type":"integer","example":0}}}}},"CreerVehiculeRequest":{"type":"object","required":["immatriculation","marque","modele","typeVehicule"],"properties":{"immatriculation":{"type":"string","maxLength":20,"example":"CI 1234 AB"},"marque":{"type":"string","maxLength":64,"example":"Mercedes"},"modele":{"type":"string","maxLength":64,"example":"Sprinter"},"couleur":{"type":"string","maxLength":32,"nullable":true,"example":"blanc"},"typeVehicule":{"type":"string","enum":["bus","minibus","car","camion","voiture","tracteur","remorque","semi_remorque","citerne"],"example":"minibus"},"annee":{"type":"integer","nullable":true,"example":2020},"numeroChassis":{"type":"string","maxLength":64,"nullable":true},"capacitePassagers":{"type":"integer","nullable":true,"example":18},"capaciteChargeKg":{"type":"integer","nullable":true},"baliseId":{"type":"string","format":"uuid","nullable":true,"description":"Doit appartenir à la même compagnie et ne pas déjà équiper un autre véhicule."},"statut":{"type":"string","enum":["actif","en_maintenance","hors_service"],"default":"actif"},"dateMiseEnCirculation":{"type":"string","format":"date","nullable":true}}},"MajVehiculeRequest":{"type":"object","description":"Tous les champs sont optionnels ; au moins un est requis.","properties":{"immatriculation":{"type":"string","maxLength":20},"marque":{"type":"string","maxLength":64},"modele":{"type":"string","maxLength":64},"couleur":{"type":"string","maxLength":32,"nullable":true},"typeVehicule":{"type":"string","enum":["bus","minibus","car","camion","voiture","tracteur","remorque","semi_remorque","citerne"]},"annee":{"type":"integer","nullable":true},"numeroChassis":{"type":"string","maxLength":64,"nullable":true},"capacitePassagers":{"type":"integer","nullable":true},"capaciteChargeKg":{"type":"integer","nullable":true},"baliseId":{"type":"string","format":"uuid","nullable":true},"statut":{"type":"string","enum":["actif","en_maintenance","hors_service"]},"dateMiseEnCirculation":{"type":"string","format":"date","nullable":true}}},"AssocierBaliseRequest":{"type":"object","required":["baliseId"],"properties":{"baliseId":{"type":"string","format":"uuid","nullable":true,"description":"null pour dissocier la balise du véhicule."}}},"ChangerStatutVehiculeRequest":{"type":"object","required":["statut"],"properties":{"statut":{"type":"string","enum":["actif","en_maintenance","hors_service"]}}},"Conducteur":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"nom":{"type":"string","example":"Kone"},"prenoms":{"type":"string","example":"Ibrahim"},"dateNaissance":{"type":"string","format":"date","nullable":true},"telephone":{"type":"string","example":"+225 0701020304"},"email":{"type":"string","format":"email","nullable":true},"adresse":{"type":"string","nullable":true},"numeroPermis":{"type":"string","example":"CI-PERM-9981","description":"Normalisé en majuscules. Unique au sein de la compagnie."},"categoriePermis":{"type":"string","example":"D","description":"B, C, D, D1…"},"datePermisDelivrance":{"type":"string","format":"date","nullable":true},"datePermisExpiration":{"type":"string","format":"date","nullable":true},"statut":{"type":"string","enum":["actif","en_conge","suspendu","inactif"]},"dateEmbauche":{"type":"string","format":"date","nullable":true},"photoUrl":{"type":"string","nullable":true},"compagnie":{"type":"object","nullable":true,"properties":{"id":{"type":"string","format":"uuid"},"code":{"type":"string"},"raisonSociale":{"type":"string"}}},"creeLe":{"type":"string","format":"date-time"},"modifieLe":{"type":"string","format":"date-time"}}},"ConducteurListResponse":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/Conducteur"}},"pagination":{"type":"object","properties":{"total":{"type":"integer"},"limite":{"type":"integer"},"offset":{"type":"integer"}}}}},"CreerConducteurRequest":{"type":"object","required":["nom","prenoms","telephone","numeroPermis","categoriePermis"],"properties":{"nom":{"type":"string","maxLength":128,"example":"Kone"},"prenoms":{"type":"string","maxLength":128,"example":"Ibrahim"},"dateNaissance":{"type":"string","format":"date","nullable":true},"telephone":{"type":"string","example":"+225 0701020304"},"email":{"type":"string","format":"email","nullable":true},"adresse":{"type":"string","maxLength":255,"nullable":true},"numeroPermis":{"type":"string","maxLength":64,"example":"CI-PERM-9981"},"categoriePermis":{"type":"string","maxLength":8,"example":"D"},"datePermisDelivrance":{"type":"string","format":"date","nullable":true},"datePermisExpiration":{"type":"string","format":"date","nullable":true,"description":"Doit être postérieure à la date de délivrance."},"statut":{"type":"string","enum":["actif","en_conge","suspendu","inactif"],"default":"actif"},"dateEmbauche":{"type":"string","format":"date","nullable":true},"photoUrl":{"type":"string","format":"uri","nullable":true}}},"MajConducteurRequest":{"type":"object","description":"Tous les champs sont optionnels ; au moins un est requis.","properties":{"nom":{"type":"string","maxLength":128},"prenoms":{"type":"string","maxLength":128},"dateNaissance":{"type":"string","format":"date","nullable":true},"telephone":{"type":"string"},"email":{"type":"string","format":"email","nullable":true},"adresse":{"type":"string","maxLength":255,"nullable":true},"numeroPermis":{"type":"string","maxLength":64},"categoriePermis":{"type":"string","maxLength":8},"datePermisDelivrance":{"type":"string","format":"date","nullable":true},"datePermisExpiration":{"type":"string","format":"date","nullable":true},"statut":{"type":"string","enum":["actif","en_conge","suspendu","inactif"]},"dateEmbauche":{"type":"string","format":"date","nullable":true},"photoUrl":{"type":"string","format":"uri","nullable":true}}},"ChangerStatutConducteurRequest":{"type":"object","required":["statut"],"properties":{"statut":{"type":"string","enum":["actif","en_conge","suspendu","inactif"]}}},"CodeActivation":{"type":"object","description":"La phrase d'activation n'apparaît JAMAIS ici : seul son hash est conservé. Elle n'est renvoyée qu'à la création et à la régénération.","properties":{"id":{"type":"string","format":"uuid"},"conducteurId":{"type":"string","format":"uuid"},"vehiculeId":{"type":"string","format":"uuid"},"vehicule":{"type":"object","nullable":true,"properties":{"id":{"type":"string","format":"uuid"},"immatriculation":{"type":"string"}}},"dateExpiration":{"type":"string","format":"date-time","nullable":true},"actif":{"type":"boolean"},"creeLe":{"type":"string","format":"date-time"}}},"CodeActivationAvecPhrase":{"allOf":[{"$ref":"#/components/schemas/CodeActivation"},{"type":"object","properties":{"phraseActivation":{"type":"string","example":"P9PLSM4M4KWU","description":"Renvoyée UNE SEULE FOIS. Non récupérable ensuite."}}}]},"CreerCodeActivationRequest":{"type":"object","required":["vehiculeId"],"properties":{"vehiculeId":{"type":"string","format":"uuid","description":"Doit appartenir à la même compagnie que le conducteur."},"phraseActivation":{"type":"string","minLength":6,"maxLength":128,"description":"Optionnelle — le serveur en génère une si elle est omise."},"dateExpiration":{"type":"string","format":"date-time","nullable":true}}},"MajCodeActivationRequest":{"type":"object","properties":{"phraseActivation":{"type":"string","minLength":6,"maxLength":128},"dateExpiration":{"type":"string","format":"date-time","nullable":true},"actif":{"type":"boolean"}}},"VerifierCodeActivationRequest":{"type":"object","required":["conducteurId","vehiculeId","phraseActivation"],"properties":{"conducteurId":{"type":"string","format":"uuid"},"vehiculeId":{"type":"string","format":"uuid"},"phraseActivation":{"type":"string"}}},"Affectation":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"conducteurId":{"type":"string","format":"uuid"},"conducteur":{"type":"object","nullable":true,"properties":{"id":{"type":"string","format":"uuid"},"nom":{"type":"string"},"prenoms":{"type":"string"},"telephone":{"type":"string"}}},"vehiculeId":{"type":"string","format":"uuid"},"vehicule":{"type":"object","nullable":true,"properties":{"id":{"type":"string","format":"uuid"},"immatriculation":{"type":"string"},"marque":{"type":"string"},"modele":{"type":"string"}}},"baliseId":{"type":"string","format":"uuid","nullable":true,"description":"Balise figée au moment de l'affectation (snapshot). Peut différer de celle actuellement installée sur le véhicule."},"balise":{"type":"object","nullable":true,"properties":{"id":{"type":"string","format":"uuid"},"imei":{"type":"string"}}},"dateDebut":{"type":"string","format":"date-time"},"dateFin":{"type":"string","format":"date-time","nullable":true,"description":"null = en cours."},"enCours":{"type":"boolean"},"statut":{"type":"string","enum":["en_cours","terminee","interrompue"]},"motifInterruption":{"type":"string","nullable":true},"creeLe":{"type":"string","format":"date-time"}}},"AffectationListResponse":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/Affectation"}},"pagination":{"type":"object","properties":{"total":{"type":"integer"},"limite":{"type":"integer"},"offset":{"type":"integer"}}}}},"CreerAffectationRequest":{"type":"object","required":["conducteurId","vehiculeId"],"properties":{"conducteurId":{"type":"string","format":"uuid","description":"Doit être de la même compagnie et avoir le statut `actif`."},"vehiculeId":{"type":"string","format":"uuid","description":"Doit être de la même compagnie et ne pas être `hors_service`."},"dateDebut":{"type":"string","format":"date-time","description":"Par défaut : maintenant. Permet de régulariser une affectation passée."}}},"CloturerAffectationRequest":{"type":"object","properties":{"dateFin":{"type":"string","format":"date-time","description":"Par défaut : maintenant. Ne peut pas précéder la date de début."},"statut":{"type":"string","enum":["terminee","interrompue"],"default":"terminee"},"motifInterruption":{"type":"string","maxLength":255,"nullable":true,"description":"Obligatoire si statut = interrompue."}}},"VehiculeAttele":{"type":"object","nullable":true,"properties":{"id":{"type":"string","format":"uuid"},"immatriculation":{"type":"string"},"marque":{"type":"string"},"modele":{"type":"string"},"typeVehicule":{"type":"string"}}},"Attelage":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"tracteurId":{"type":"string","format":"uuid"},"tracteur":{"$ref":"#/components/schemas/VehiculeAttele"},"remorqueId":{"type":"string","format":"uuid"},"remorque":{"$ref":"#/components/schemas/VehiculeAttele"},"dateDebut":{"type":"string","format":"date-time"},"dateFin":{"type":"string","format":"date-time","nullable":true,"description":"null = attelage en cours."},"enCours":{"type":"boolean","description":"Dérivé de dateFin."},"motifFin":{"type":"string","nullable":true,"example":"Fin de mission"},"creeLe":{"type":"string","format":"date-time"},"modifieLe":{"type":"string","format":"date-time"}}},"AttelageListResponse":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/Attelage"}},"pagination":{"type":"object","properties":{"total":{"type":"integer"},"limite":{"type":"integer"},"offset":{"type":"integer"}}}}},"CreerAttelageRequest":{"type":"object","required":["tracteurId","remorqueId"],"properties":{"tracteurId":{"type":"string","format":"uuid","description":"Véhicule tirant la remorque. Ne peut pas être un type remorquable. Doit être de la même compagnie et ne pas être hors service."},"remorqueId":{"type":"string","format":"uuid","description":"Doit être de type remorque, semi_remorque ou citerne, de la même compagnie et non hors service."},"dateDebut":{"type":"string","format":"date-time","description":"Par défaut : maintenant. Permet de régulariser un attelage passé."}}},"DetelerAttelageRequest":{"type":"object","properties":{"dateFin":{"type":"string","format":"date-time","description":"Par défaut : maintenant. Ne peut pas précéder la date d'attelage."},"motifFin":{"type":"string","maxLength":255,"nullable":true,"example":"Fin de mission","description":"Optionnel — un dételage de routine n'en exige pas."}}},"MajAttelageRequest":{"type":"object","description":"Corrections de saisie uniquement. Le couple tracteur/remorque n'est pas modifiable : dételez puis réattelez.","properties":{"dateDebut":{"type":"string","format":"date-time"},"motifFin":{"type":"string","maxLength":255,"nullable":true}}}},"responses":{"BadRequest":{"description":"Requête invalide (validation).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"Unauthorized":{"description":"Non authentifié / identifiants invalides / token expiré.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"Forbidden":{"description":"Accès refusé (rôle/permission/réalm insuffisant, compte désactivé).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"Conflict":{"description":"Conflit (email déjà utilisé).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"TooManyRequests":{"description":"Trop de tentatives (rate-limit connexion/refresh).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"NotFound":{"description":"Ressource introuvable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"paths":{"/auth/plateforme/super-admin/connexion":{"post":{"tags":["Auth · Plateforme"],"summary":"Connexion d'un super administrateur (ou de son personnel)","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnexionRequest"}}}},"responses":{"200":{"description":"Étape 1 réussie — MFA requise (challenge renvoyé).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChallengeResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"}}}},"/auth/plateforme/developpeur/connexion":{"post":{"tags":["Auth · Plateforme"],"summary":"Connexion d'un développeur (accès total)","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnexionRequest"}}}},"responses":{"200":{"description":"Étape 1 réussie — MFA requise (challenge renvoyé).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChallengeResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"}}}},"/auth/plateforme/refresh":{"post":{"tags":["Auth · Plateforme"],"summary":"Rafraîchir le couple de tokens (rotation)","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefreshRequest"}}}},"responses":{"200":{"description":"Nouveau couple de tokens.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokensResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/auth/plateforme/deconnexion":{"post":{"tags":["Auth · Plateforme"],"summary":"Déconnexion (révoque la session du refresh fourni)","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefreshRequest"}}}},"responses":{"200":{"description":"Session révoquée.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/auth/plateforme/deconnexion-globale":{"post":{"tags":["Auth · Plateforme"],"summary":"Déconnexion globale (révoque toutes les sessions du compte)","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Toutes les sessions révoquées.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/auth/plateforme/mot-de-passe":{"patch":{"tags":["Auth · Plateforme"],"summary":"Changer son mot de passe (super admin)","description":"Invalide toutes les autres sessions après changement.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangementMotDePasseRequest"}}}},"responses":{"200":{"description":"Mot de passe mis à jour.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/auth/plateforme/personnel":{"post":{"tags":["Auth · Plateforme"],"summary":"Créer un membre du personnel super administrateur","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreerPersonnelSuperAdminRequest"}}}},"responses":{"201":{"description":"Compte créé.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/ComptePlateforme"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"409":{"$ref":"#/components/responses/Conflict"}}}},"/auth/plateforme/moi":{"get":{"tags":["Auth · Plateforme"],"summary":"Profil du compte plateforme authentifié","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Profil courant.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string","format":"email"},"typeCompte":{"type":"string","enum":["super_administrateur","developpeur"]},"realm":{"type":"string","example":"plateforme"}}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/auth/compagnie/connexion":{"post":{"tags":["Auth · Compagnie"],"summary":"Connexion d'un utilisateur de compagnie (admin principal ou membre)","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnexionRequest"}}}},"responses":{"200":{"description":"Étape 1 réussie — MFA requise (challenge renvoyé).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChallengeResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"}}}},"/auth/compagnie/refresh":{"post":{"tags":["Auth · Compagnie"],"summary":"Rafraîchir le couple de tokens (rotation)","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefreshRequest"}}}},"responses":{"200":{"description":"Nouveau couple de tokens.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokensResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/auth/compagnie/deconnexion":{"post":{"tags":["Auth · Compagnie"],"summary":"Déconnexion (révoque la session du refresh fourni)","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefreshRequest"}}}},"responses":{"200":{"description":"Session révoquée.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/auth/compagnie/deconnexion-globale":{"post":{"tags":["Auth · Compagnie"],"summary":"Déconnexion globale (révoque toutes les sessions)","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Toutes les sessions révoquées.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/auth/compagnie/mot-de-passe":{"patch":{"tags":["Auth · Compagnie"],"summary":"Changer son mot de passe","description":"Invalide toutes les autres sessions après changement.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangementMotDePasseRequest"}}}},"responses":{"200":{"description":"Mot de passe mis à jour.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/auth/compagnie/personnel":{"post":{"tags":["Auth · Compagnie"],"summary":"Créer un membre du personnel de la compagnie","description":"Requiert la permission `utilisateurs.creer`. La compagnie est déduite du token (un admin ne crée des comptes que dans SA compagnie). Le rôle super_admin_compagnie est interdit par cette route.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreerPersonnelCompagnieRequest"}}}},"responses":{"201":{"description":"Membre créé.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"nom":{"type":"string"},"prenom":{"type":"string"},"email":{"type":"string","format":"email"},"roleId":{"type":"string","format":"uuid"},"compagnieId":{"type":"string","format":"uuid"},"actif":{"type":"boolean"}}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"409":{"$ref":"#/components/responses/Conflict"}}}},"/auth/compagnie/moi":{"get":{"tags":["Auth · Compagnie"],"summary":"Profil de l'utilisateur de compagnie authentifié","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Profil courant.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string","format":"email"},"compagnieId":{"type":"string","format":"uuid"},"roleId":{"type":"string","format":"uuid"},"roleCode":{"type":"string","enum":["super_admin_compagnie","corridor","safe_zone","maintenance"]},"estPrincipal":{"type":"boolean"}}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/auth/mfa/setup":{"post":{"tags":["Auth · MFA"],"summary":"Configurer la 2FA (génère secret + QR code)","description":"Étape de configuration initiale (setupRequired=true). Renvoie le QR code à scanner, puis validez via /auth/mfa/verify (methode=totp).","security":[{"mfaChallenge":[]}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"challengeToken":{"type":"string"}}}}}},"responses":{"200":{"description":"Secret et QR code générés.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MfaSetupResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"409":{"$ref":"#/components/responses/Conflict"}}}},"/auth/mfa/verify":{"post":{"tags":["Auth · MFA"],"summary":"Vérifier le 2e facteur et obtenir les tokens","description":"Valide le code (TOTP / SMS / code de secours). À la première activation, active la 2FA et renvoie les codes de secours en clair.","security":[{"mfaChallenge":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MfaVerifyRequest"}}}},"responses":{"200":{"description":"Vérifié — tokens délivrés.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MfaVerifyResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/auth/mfa/sms/send":{"post":{"tags":["Auth · MFA"],"summary":"Envoyer un OTP par SMS (méthode de secours)","description":"Envoie un code à usage unique par SMS (Twilio) au numéro de secours enregistré. Puis vérifiez via /auth/mfa/verify (methode=sms).","security":[{"mfaChallenge":[]}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"challengeToken":{"type":"string"}}}}}},"responses":{"200":{"description":"SMS envoyé.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/TooManyRequests"}}}},"/auth/mfa/telephone":{"post":{"tags":["Auth · MFA"],"summary":"Enregistrer le numéro de secours (compte authentifié)","description":"Nécessaire pour recevoir les OTP par SMS. Format E.164.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MfaTelephoneRequest"}}}},"responses":{"200":{"description":"Numéro enregistré.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/auth/mfa/backup-codes/regen":{"post":{"tags":["Auth · MFA"],"summary":"Régénérer les codes de secours (compte authentifié)","description":"Invalide les anciens codes et renvoie les nouveaux (à afficher une seule fois).","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Nouveaux codes générés.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MfaBackupCodesResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/roles":{"get":{"tags":["Rôles"],"summary":"Lister les rôles","security":[{"bearerAuth":[]}],"parameters":[{"name":"inactifs","in":"query","schema":{"type":"boolean"},"description":"Inclure les rôles inactifs."}],"responses":{"200":{"description":"Liste des rôles.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RoleListResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}},"post":{"tags":["Rôles"],"summary":"Créer un rôle","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreerRoleRequest"}}}},"responses":{"201":{"description":"Rôle créé.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RoleResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"409":{"$ref":"#/components/responses/Conflict"}}}},"/roles/{id}":{"get":{"tags":["Rôles"],"summary":"Détail d'un rôle","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Rôle.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RoleResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"patch":{"tags":["Rôles"],"summary":"Modifier un rôle","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MettreAJourRoleRequest"}}}},"responses":{"200":{"description":"Rôle mis à jour.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RoleResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"}}},"delete":{"tags":["Rôles"],"summary":"Supprimer un rôle","description":"Refusé si rôle système ou si des utilisateurs y sont rattachés.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Rôle supprimé.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"}}}},"/roles/{id}/permissions":{"put":{"tags":["Rôles"],"summary":"Remplacer toutes les permissions d'un rôle","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DefinirPermissionsRequest"}}}},"responses":{"200":{"description":"Permissions redéfinies.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RoleResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/roles/{id}/permissions/{permissionId}":{"post":{"tags":["Rôles"],"summary":"Ajouter une permission à un rôle","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"permissionId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Permission ajoutée.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RoleResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"tags":["Rôles"],"summary":"Retirer une permission d'un rôle","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"permissionId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Permission retirée.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RoleResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/permissions":{"get":{"tags":["Permissions"],"summary":"Lister le catalogue de permissions","security":[{"bearerAuth":[]}],"parameters":[{"name":"module","in":"query","schema":{"type":"string"},"description":"Filtrer par module."},{"name":"groupe","in":"query","schema":{"type":"boolean"},"description":"Regrouper par module."},{"name":"inactives","in":"query","schema":{"type":"boolean"},"description":"Inclure les inactives."}],"responses":{"200":{"description":"Catalogue.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PermissionListResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}},"post":{"tags":["Permissions"],"summary":"Créer une permission","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreerPermissionRequest"}}}},"responses":{"201":{"description":"Permission créée.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PermissionResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"409":{"$ref":"#/components/responses/Conflict"}}}},"/permissions/{id}":{"get":{"tags":["Permissions"],"summary":"Détail d'une permission","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PermissionResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"patch":{"tags":["Permissions"],"summary":"Modifier une permission","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MettreAJourPermissionRequest"}}}},"responses":{"200":{"description":"Permission mise à jour.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PermissionResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/permissions/{id}/activation":{"patch":{"tags":["Permissions"],"summary":"Activer / désactiver une permission","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivationPermissionRequest"}}}},"responses":{"200":{"description":"État mis à jour.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PermissionResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/compagnie/roles":{"get":{"tags":["Compagnie · Rôles"],"summary":"Lister les rôles disponibles (lecture seule)","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Rôles disponibles.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RolesDisponiblesResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/compagnie/utilisateurs/{utilisateurId}/role":{"patch":{"tags":["Compagnie · Rôles"],"summary":"Changer le rôle d'un utilisateur (admin principal)","description":"Scopé à la compagnie du token. L'administrateur principal ne peut pas être rétrogradé, et super_admin_compagnie ne peut pas être attribué.","security":[{"bearerAuth":[]}],"parameters":[{"name":"utilisateurId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangerRoleRequest"}}}},"responses":{"200":{"description":"Rôle mis à jour.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/compagnies":{"get":{"tags":["Compagnies"],"summary":"Lister les compagnies","description":"Réservé aux comptes plateforme. Filtres, recherche, tri et pagination.","security":[{"bearerAuth":[]}],"parameters":[{"name":"q","in":"query","schema":{"type":"string"},"description":"Recherche : raison sociale, code, email, téléphone."},{"name":"actif","in":"query","schema":{"type":"boolean"},"description":"Filtrer par état d'activation."},{"name":"paysId","in":"query","schema":{"type":"string","format":"uuid"}},{"name":"tri","in":"query","schema":{"type":"string","enum":["raisonSociale","code","creer_le"]}},{"name":"ordre","in":"query","schema":{"type":"string","enum":["ASC","DESC"]}},{"name":"limite","in":"query","schema":{"type":"integer","default":25,"maximum":100}},{"name":"offset","in":"query","schema":{"type":"integer","default":0}}],"responses":{"200":{"description":"Liste paginée des compagnies.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompagnieListResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}},"post":{"tags":["Compagnies"],"summary":"Créer un compte compagnie (+ admin principal)","description":"Réservé au super administrateur / collaborateur ayant la permission `compagnies.creer`. Crée la compagnie et son administrateur principal (inactif, sans mot de passe), puis envoie un email de confirmation.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreerCompagnieRequest"}}}},"responses":{"201":{"description":"Compagnie créée — email de confirmation envoyé.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreerCompagnieResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"409":{"$ref":"#/components/responses/Conflict"}}}},"/compagnies/{compagnieId}/renvoyer-confirmation":{"post":{"tags":["Compagnies"],"summary":"Renvoyer l'email de confirmation à l'admin principal","description":"Utile si le premier envoi a échoué ou si le lien a expiré (compte non encore activé).","security":[{"bearerAuth":[]}],"parameters":[{"name":"compagnieId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Email de confirmation renvoyé.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"description":"Le compte est déjà activé.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/compagnies/confirmation":{"get":{"tags":["Compagnies"],"summary":"Infos de préremplissage du formulaire de confirmation (public)","description":"Valide le token du lien email et renvoie email/nom/prénom pour préremplir l'UI.","parameters":[{"name":"token","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Infos du compte à activer.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InfoConfirmationResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}},"post":{"tags":["Compagnies"],"summary":"Confirmer le compte et définir le mot de passe (public)","description":"Active le compte de l'administrateur principal. Token à usage unique.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfirmerCompteRequest"}}}},"responses":{"200":{"description":"Compte activé.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"description":"Le compte est déjà activé.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/referentiels/pays":{"get":{"tags":["Référentiels"],"summary":"Lister les pays","description":"Lecture ouverte à tout compte authentifié.","security":[{"bearerAuth":[]}],"parameters":[{"name":"inactifs","in":"query","schema":{"type":"boolean"},"description":"Inclure les inactifs."},{"name":"q","in":"query","schema":{"type":"string"},"description":"Recherche texte."}],"responses":{"200":{"description":"Liste des pays.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/Pays"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}},"post":{"tags":["Référentiels"],"summary":"Créer un(e) pays","description":"Réservé au super administrateur plateforme.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreerPaysRequest"}}}},"responses":{"201":{"description":"Créé(e).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Pays"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"409":{"$ref":"#/components/responses/Conflict"}}}},"/referentiels/pays/{id}":{"get":{"tags":["Référentiels"],"summary":"Détail d'un(e) pays","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"pays","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/Pays"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}},"patch":{"tags":["Référentiels"],"summary":"Modifier un(e) pays","description":"Réservé au super administrateur plateforme.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreerPaysRequest"}}}},"responses":{"200":{"description":"pays","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/Pays"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"}}},"delete":{"tags":["Référentiels"],"summary":"Supprimer un(e) pays","description":"Suppression logique (soft delete). Réservé au super administrateur plateforme.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Supprimé(e).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/referentiels/pays/{id}/activation":{"patch":{"tags":["Référentiels"],"summary":"Activer / désactiver un(e) pays","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivationRequest"}}}},"responses":{"200":{"description":"pays","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/Pays"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/referentiels/fabricants":{"get":{"tags":["Référentiels"],"summary":"Lister les fabricants","description":"Lecture ouverte à tout compte authentifié.","security":[{"bearerAuth":[]}],"parameters":[{"name":"inactifs","in":"query","schema":{"type":"boolean"},"description":"Inclure les inactifs."},{"name":"q","in":"query","schema":{"type":"string"},"description":"Recherche texte."}],"responses":{"200":{"description":"Liste des fabricants.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/Fabricant"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}},"post":{"tags":["Référentiels"],"summary":"Créer un(e) fabricants","description":"Réservé au super administrateur plateforme.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreerFabricantRequest"}}}},"responses":{"201":{"description":"Créé(e).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fabricant"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"409":{"$ref":"#/components/responses/Conflict"}}}},"/referentiels/fabricants/{id}":{"get":{"tags":["Référentiels"],"summary":"Détail d'un(e) fabricants","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"fabricants","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/Fabricant"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}},"patch":{"tags":["Référentiels"],"summary":"Modifier un(e) fabricants","description":"Réservé au super administrateur plateforme.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreerFabricantRequest"}}}},"responses":{"200":{"description":"fabricants","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/Fabricant"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"}}},"delete":{"tags":["Référentiels"],"summary":"Supprimer un(e) fabricants","description":"Suppression logique (soft delete). Réservé au super administrateur plateforme.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Supprimé(e).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/referentiels/fabricants/{id}/activation":{"patch":{"tags":["Référentiels"],"summary":"Activer / désactiver un(e) fabricants","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivationRequest"}}}},"responses":{"200":{"description":"fabricants","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/Fabricant"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/referentiels/protocoles":{"get":{"tags":["Référentiels"],"summary":"Lister les protocoles","description":"Lecture ouverte à tout compte authentifié.","security":[{"bearerAuth":[]}],"parameters":[{"name":"inactifs","in":"query","schema":{"type":"boolean"},"description":"Inclure les inactifs."},{"name":"q","in":"query","schema":{"type":"string"},"description":"Recherche texte."}],"responses":{"200":{"description":"Liste des protocoles.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/Protocole"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}},"post":{"tags":["Référentiels"],"summary":"Créer un(e) protocoles","description":"Réservé au super administrateur plateforme.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreerProtocoleRequest"}}}},"responses":{"201":{"description":"Créé(e).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Protocole"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"409":{"$ref":"#/components/responses/Conflict"}}}},"/referentiels/protocoles/{id}":{"get":{"tags":["Référentiels"],"summary":"Détail d'un(e) protocoles","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"protocoles","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/Protocole"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}},"patch":{"tags":["Référentiels"],"summary":"Modifier un(e) protocoles","description":"Réservé au super administrateur plateforme.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreerProtocoleRequest"}}}},"responses":{"200":{"description":"protocoles","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/Protocole"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"}}},"delete":{"tags":["Référentiels"],"summary":"Supprimer un(e) protocoles","description":"Suppression logique (soft delete). Réservé au super administrateur plateforme.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Supprimé(e).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/referentiels/protocoles/{id}/activation":{"patch":{"tags":["Référentiels"],"summary":"Activer / désactiver un(e) protocoles","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivationRequest"}}}},"responses":{"200":{"description":"protocoles","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/Protocole"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/referentiels/types-zones":{"get":{"tags":["Référentiels"],"summary":"Lister les types de zones","description":"Lecture ouverte à tout compte authentifié.","security":[{"bearerAuth":[]}],"parameters":[{"name":"inactifs","in":"query","schema":{"type":"boolean"},"description":"Inclure les inactifs."},{"name":"q","in":"query","schema":{"type":"string"},"description":"Recherche texte."}],"responses":{"200":{"description":"Liste des types de zones.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/TypeZone"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}},"post":{"tags":["Référentiels"],"summary":"Créer un(e) types de zones","description":"Réservé au super administrateur plateforme.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreerTypeZoneRequest"}}}},"responses":{"201":{"description":"Créé(e).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TypeZone"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"409":{"$ref":"#/components/responses/Conflict"}}}},"/referentiels/types-zones/{id}":{"get":{"tags":["Référentiels"],"summary":"Détail d'un(e) types de zones","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"types de zones","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/TypeZone"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}},"patch":{"tags":["Référentiels"],"summary":"Modifier un(e) types de zones","description":"Réservé au super administrateur plateforme.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreerTypeZoneRequest"}}}},"responses":{"200":{"description":"types de zones","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/TypeZone"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"}}},"delete":{"tags":["Référentiels"],"summary":"Supprimer un(e) types de zones","description":"Suppression logique (soft delete). Réservé au super administrateur plateforme.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Supprimé(e).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/referentiels/types-zones/{id}/activation":{"patch":{"tags":["Référentiels"],"summary":"Activer / désactiver un(e) types de zones","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivationRequest"}}}},"responses":{"200":{"description":"types de zones","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/TypeZone"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/referentiels/types-evenements":{"get":{"tags":["Référentiels"],"summary":"Lister les types d'événements","description":"Lecture ouverte à tout compte authentifié.","security":[{"bearerAuth":[]}],"parameters":[{"name":"inactifs","in":"query","schema":{"type":"boolean"},"description":"Inclure les inactifs."},{"name":"q","in":"query","schema":{"type":"string"},"description":"Recherche texte."},{"name":"categorie","in":"query","schema":{"type":"string"},"description":"Filtrer par catégorie (geofencing, vitesse, batterie, sabotage, sos, maintenance, connexion, activation)."}],"responses":{"200":{"description":"Liste des types d'événements.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/TypeEvenement"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}},"post":{"tags":["Référentiels"],"summary":"Créer un(e) types d'événements","description":"Réservé au super administrateur plateforme.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreerTypeEvenementRequest"}}}},"responses":{"201":{"description":"Créé(e).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TypeEvenement"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"409":{"$ref":"#/components/responses/Conflict"}}}},"/referentiels/types-evenements/{id}":{"get":{"tags":["Référentiels"],"summary":"Détail d'un(e) types d'événements","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"types d'événements","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/TypeEvenement"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}},"patch":{"tags":["Référentiels"],"summary":"Modifier un(e) types d'événements","description":"Réservé au super administrateur plateforme.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreerTypeEvenementRequest"}}}},"responses":{"200":{"description":"types d'événements","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/TypeEvenement"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"}}},"delete":{"tags":["Référentiels"],"summary":"Supprimer un(e) types d'événements","description":"Suppression logique (soft delete). Réservé au super administrateur plateforme.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Supprimé(e).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/referentiels/types-evenements/{id}/activation":{"patch":{"tags":["Référentiels"],"summary":"Activer / désactiver un(e) types d'événements","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivationRequest"}}}},"responses":{"200":{"description":"types d'événements","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/TypeEvenement"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/modeles-balises":{"get":{"tags":["Modèles de balises"],"summary":"Lister les modèles de balises","description":"Lecture ouverte à tout compte authentifié.","security":[{"bearerAuth":[]}],"parameters":[{"name":"inactifs","in":"query","schema":{"type":"boolean"},"description":"Inclure les modèles inactifs."},{"name":"fabricantId","in":"query","schema":{"type":"string","format":"uuid"},"description":"Filtrer par fabricant."},{"name":"q","in":"query","schema":{"type":"string"},"description":"Recherche sur le nom."}],"responses":{"200":{"description":"Liste des modèles.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/ModeleBalise"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}},"post":{"tags":["Modèles de balises"],"summary":"Créer un modèle de balise","description":"Réservé au super administrateur plateforme. Unicité sur (nom, fabricant).","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreerModeleBaliseRequest"}}}},"responses":{"201":{"description":"Modèle créé.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"$ref":"#/components/schemas/ModeleBalise"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"409":{"$ref":"#/components/responses/Conflict"}}}},"/modeles-balises/{id}":{"get":{"tags":["Modèles de balises"],"summary":"Détail d'un modèle","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Modèle.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"$ref":"#/components/schemas/ModeleBalise"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}},"patch":{"tags":["Modèles de balises"],"summary":"Modifier un modèle","description":"Réservé au super administrateur plateforme.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreerModeleBaliseRequest"}}}},"responses":{"200":{"description":"Modèle mis à jour.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"$ref":"#/components/schemas/ModeleBalise"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"}}},"delete":{"tags":["Modèles de balises"],"summary":"Supprimer un modèle","description":"Refusé (409) si des balises utilisent ce modèle — désactivez-le plutôt.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Modèle supprimé.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"}}}},"/modeles-balises/{id}/activation":{"patch":{"tags":["Modèles de balises"],"summary":"Activer / désactiver un modèle","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivationRequest"}}}},"responses":{"200":{"description":"État mis à jour.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"$ref":"#/components/schemas/ModeleBalise"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/balises":{"get":{"tags":["Balises"],"summary":"Lister les balises (résultat automatiquement restreint)","description":"Le périmètre est déduit du token : un compte plateforme voit tout le parc ; un compte compagnie ne voit que les balises de sa compagnie.","security":[{"bearerAuth":[]}],"parameters":[{"name":"etat","in":"query","schema":{"type":"string","enum":["en_stock","armee","desarmee","endommagee","transferee"]}},{"name":"modeleId","in":"query","schema":{"type":"string","format":"uuid"}},{"name":"compagnieId","in":"query","schema":{"type":"string","format":"uuid"},"description":"Réservé aux comptes plateforme."},{"name":"q","in":"query","schema":{"type":"string"},"description":"Recherche : IMEI, n° de série, ID balise, nom affiché, référence BSE."},{"name":"limite","in":"query","schema":{"type":"integer","default":50,"maximum":200}},{"name":"offset","in":"query","schema":{"type":"integer","default":0}}],"responses":{"200":{"description":"Liste paginée.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BaliseListResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}},"post":{"tags":["Balises"],"summary":"Créer une balise et l'affecter à une compagnie","description":"Réservé au super administrateur plateforme. IMEI et n° de série uniques.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreerBaliseRequest"}}}},"responses":{"201":{"description":"Balise créée.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"$ref":"#/components/schemas/Balise"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"409":{"$ref":"#/components/responses/Conflict"}}}},"/balises/import":{"post":{"tags":["Balises"],"summary":"Importer des balises en masse depuis un CSV","description":"Réservé au super administrateur plateforme. Traitement ligne par ligne : une erreur n'interrompt pas les autres lignes.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImporterBalisesCsvRequest"}}}},"responses":{"200":{"description":"Rapport d'import.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImporterBalisesCsvResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/balises/statistiques":{"get":{"tags":["Balises"],"summary":"Statistiques du parc (comptages par état)","description":"Comptages calculés sur le périmètre visible par le compte appelant.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Statistiques.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatistiquesParcResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/balises/{id}":{"get":{"tags":["Balises"],"summary":"Détail d'une balise","description":"Renvoie 404 si la balise est hors du périmètre du compte (sans révéler son existence).","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Balise.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"$ref":"#/components/schemas/Balise"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}},"patch":{"tags":["Balises"],"summary":"Modifier une balise","description":"Un compte plateforme peut modifier tous les champs ; un compte compagnie uniquement iccidSim, numeroTelephoneSim, codePinSim, pinActif, apn, etat, nomAffichage, referenceBse et dateDerniereMaintenance.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MajBaliseRequest"}}}},"responses":{"200":{"description":"Balise mise à jour.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"$ref":"#/components/schemas/Balise"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"}}},"delete":{"tags":["Balises"],"summary":"Supprimer une balise","description":"Suppression logique. Réservé au super administrateur plateforme.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Balise supprimée.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/balises/{id}/etat":{"patch":{"tags":["Balises"],"summary":"Changer l'état (stock / armée / désarmée / endommagée / transférée)","description":"Une balise armée doit porter une référence BSE ; passer à un autre état efface automatiquement la référence.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangerEtatBaliseRequest"}}}},"responses":{"200":{"description":"État mis à jour.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"$ref":"#/components/schemas/Balise"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/balises/{id}/compagnie":{"patch":{"tags":["Balises"],"summary":"Réaffecter une balise à une autre compagnie","description":"Réservé au super administrateur plateforme. La balise est remise en stock et sa référence BSE est effacée.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReaffecterBaliseRequest"}}}},"responses":{"200":{"description":"Balise réaffectée.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"$ref":"#/components/schemas/Balise"},"message":{"type":"string"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/compagnies/moi":{"get":{"tags":["Compagnies"],"summary":"Profil de ma compagnie","description":"Renvoie la compagnie de l'utilisateur connecté, avec son administrateur principal.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Profil de la compagnie.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"$ref":"#/components/schemas/CompagnieDetail"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/compagnies/{id}":{"get":{"tags":["Compagnies"],"summary":"Détail d'une compagnie","description":"Un compte plateforme accède à toute compagnie ; un compte compagnie uniquement à la sienne (403 sinon).","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Compagnie avec son administrateur principal.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"$ref":"#/components/schemas/CompagnieDetail"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"patch":{"tags":["Compagnies"],"summary":"Modifier une compagnie","description":"Plateforme : tous les champs autorisés (dont le pays). Compagnie : son propre profil, et uniquement par l'administrateur principal. Le `code` n'est jamais modifiable.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MajCompagnieRequest"}}}},"responses":{"200":{"description":"Compagnie mise à jour.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"$ref":"#/components/schemas/Compagnie"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"}}},"delete":{"tags":["Compagnies"],"summary":"Supprimer une compagnie","description":"Suppression logique, réservée au super administrateur plateforme. Refusée (409) si des balises sont encore rattachées à la compagnie.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Compagnie supprimée.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"}}}},"/compagnies/{id}/activation":{"patch":{"tags":["Compagnies"],"summary":"Activer / désactiver une compagnie","description":"Réservé au super administrateur plateforme. Une compagnie désactivée empêche ses utilisateurs de se connecter.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivationRequest"}}}},"responses":{"200":{"description":"État mis à jour.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"$ref":"#/components/schemas/Compagnie"},"message":{"type":"string"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/compagnies/{id}/statistiques":{"get":{"tags":["Compagnies"],"summary":"Statistiques d'une compagnie","description":"Utilisateurs (total/actifs/inactifs) et balises par état.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Statistiques.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatistiquesCompagnieResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/compagnies/{compagnieId}/utilisateurs":{"get":{"tags":["Utilisateurs compagnie"],"summary":"Lister les membres d'une compagnie (plateforme)","security":[{"bearerAuth":[]}],"parameters":[{"name":"compagnieId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"q","in":"query","schema":{"type":"string"},"description":"Recherche : nom, prénom, email."},{"name":"actif","in":"query","schema":{"type":"boolean"}},{"name":"roleId","in":"query","schema":{"type":"string","format":"uuid"}},{"name":"limite","in":"query","schema":{"type":"integer","default":25,"maximum":100}},{"name":"offset","in":"query","schema":{"type":"integer","default":0}}],"responses":{"200":{"description":"Liste paginée des membres.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UtilisateurListResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/compagnies/{compagnieId}/utilisateurs/{utilisateurId}":{"get":{"tags":["Utilisateurs compagnie"],"summary":"Détail d'un membre (plateforme)","security":[{"bearerAuth":[]}],"parameters":[{"name":"compagnieId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"utilisateurId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Utilisateur.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/MembreCompagnie"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"patch":{"tags":["Utilisateurs compagnie"],"summary":"Modifier un membre (plateforme)","security":[{"bearerAuth":[]}],"parameters":[{"name":"compagnieId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"utilisateurId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MajUtilisateurRequest"}}}},"responses":{"200":{"description":"Utilisateur.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/MembreCompagnie"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"tags":["Utilisateurs compagnie"],"summary":"Supprimer un membre (plateforme)","description":"L'administrateur principal ne peut pas être supprimé.","security":[{"bearerAuth":[]}],"parameters":[{"name":"compagnieId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"utilisateurId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Membre supprimé.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/compagnies/{compagnieId}/utilisateurs/{utilisateurId}/activation":{"patch":{"tags":["Utilisateurs compagnie"],"summary":"Activer / désactiver un membre (plateforme)","description":"L'administrateur principal ne peut pas être désactivé. La désactivation révoque immédiatement toutes les sessions du compte.","security":[{"bearerAuth":[]}],"parameters":[{"name":"compagnieId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"utilisateurId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivationRequest"}}}},"responses":{"200":{"description":"Utilisateur.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/MembreCompagnie"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/compagnie/utilisateurs":{"get":{"tags":["Utilisateurs compagnie"],"summary":"Lister les membres de ma compagnie","description":"Scopé automatiquement sur la compagnie du token.","security":[{"bearerAuth":[]}],"parameters":[{"name":"q","in":"query","schema":{"type":"string"},"description":"Recherche : nom, prénom, email."},{"name":"actif","in":"query","schema":{"type":"boolean"}},{"name":"roleId","in":"query","schema":{"type":"string","format":"uuid"}},{"name":"limite","in":"query","schema":{"type":"integer","default":25,"maximum":100}},{"name":"offset","in":"query","schema":{"type":"integer","default":0}}],"responses":{"200":{"description":"Liste paginée des membres.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UtilisateurListResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/compagnie/utilisateurs/{utilisateurId}":{"get":{"tags":["Utilisateurs compagnie"],"summary":"Détail d'un membre de ma compagnie","description":"Renvoie 404 si le membre appartient à une autre compagnie.","security":[{"bearerAuth":[]}],"parameters":[{"name":"utilisateurId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Utilisateur.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/MembreCompagnie"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}},"patch":{"tags":["Utilisateurs compagnie"],"summary":"Modifier un membre de ma compagnie","description":"Chacun peut modifier son propre profil ; modifier un autre membre exige d'être administrateur principal.","security":[{"bearerAuth":[]}],"parameters":[{"name":"utilisateurId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MajUtilisateurRequest"}}}},"responses":{"200":{"description":"Utilisateur.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/MembreCompagnie"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"tags":["Utilisateurs compagnie"],"summary":"Supprimer un membre de ma compagnie","description":"Réservé à l'administrateur principal. Ni l'administrateur principal ni son propre compte ne peuvent être supprimés.","security":[{"bearerAuth":[]}],"parameters":[{"name":"utilisateurId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Membre supprimé.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/compagnie/utilisateurs/{utilisateurId}/activation":{"patch":{"tags":["Utilisateurs compagnie"],"summary":"Activer / désactiver un membre de ma compagnie","description":"Réservé à l'administrateur principal. L'administrateur principal ne peut pas être désactivé, ni un utilisateur son propre compte. La désactivation révoque immédiatement toutes les sessions.","security":[{"bearerAuth":[]}],"parameters":[{"name":"utilisateurId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivationRequest"}}}},"responses":{"200":{"description":"Utilisateur.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/MembreCompagnie"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/zones":{"get":{"tags":["Zones"],"summary":"Lister les zones","description":"Liste paginée, scopée selon le token (plateforme = tout, compagnie = ses zones).","security":[{"bearerAuth":[]}],"parameters":[{"name":"categorie","in":"query","schema":{"type":"string","enum":["safezone","arret_autorise","arret_non_autorise","ville","poste_frontiere","territoire","bureau"]}},{"name":"typeZoneId","in":"query","schema":{"type":"string","format":"uuid"}},{"name":"actif","in":"query","schema":{"type":"boolean"}},{"name":"tag","in":"query","schema":{"type":"string"}},{"name":"q","in":"query","schema":{"type":"string"},"description":"Recherche sur le nom."},{"name":"limite","in":"query","schema":{"type":"integer","default":25,"maximum":200}},{"name":"offset","in":"query","schema":{"type":"integer","default":0}}],"responses":{"200":{"description":"Liste paginée des zones.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ZoneListResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}},"post":{"tags":["Zones"],"summary":"Créer une zone","description":"Polygone GeoJSON ou cercle (centre + rayon). Le nom est généré automatiquement selon la catégorie.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreerZoneRequest"}}}},"responses":{"201":{"description":"Zone.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"$ref":"#/components/schemas/Zone"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"409":{"$ref":"#/components/responses/Conflict"}}}},"/zones/proximite":{"get":{"tags":["Zones"],"summary":"Balises à proximité d'un point","description":"Balises de la compagnie dans un rayon (m) autour d'un point, triées par distance (ST_DWithin).","security":[{"bearerAuth":[]}],"parameters":[{"name":"lon","in":"query","required":true,"schema":{"type":"number"}},{"name":"lat","in":"query","required":true,"schema":{"type":"number"}},{"name":"rayonMetres","in":"query","schema":{"type":"number","default":5000}},{"name":"ancienneteMaxMinutes","in":"query","schema":{"type":"integer"}},{"name":"compagnieId","in":"query","schema":{"type":"string","format":"uuid"},"description":"Requis pour un compte plateforme."}],"responses":{"200":{"description":"Balises triées par distance.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"array","items":{"type":"object","properties":{"baliseId":{"type":"string","format":"uuid"},"distanceM":{"type":"number"}}}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/zones/contenant-point":{"get":{"tags":["Zones"],"summary":"Zones contenant un point","description":"Zones actives contenant le point donné (ST_Contains) — base du géofencing.","security":[{"bearerAuth":[]}],"parameters":[{"name":"lon","in":"query","required":true,"schema":{"type":"number"}},{"name":"lat","in":"query","required":true,"schema":{"type":"number"}},{"name":"compagnieId","in":"query","schema":{"type":"string","format":"uuid"},"description":"Requis pour un compte plateforme."}],"responses":{"200":{"description":"Zones contenant le point.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"array","items":{"$ref":"#/components/schemas/Zone"}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/zones/{id}":{"get":{"tags":["Zones"],"summary":"Détail d'une zone","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Zone.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"$ref":"#/components/schemas/Zone"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}},"patch":{"tags":["Zones"],"summary":"Modifier une zone","description":"Propriétés et/ou géométrie. Modifier le libellé régénère le nom.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MajZoneRequest"}}}},"responses":{"200":{"description":"Zone.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"$ref":"#/components/schemas/Zone"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"}}},"delete":{"tags":["Zones"],"summary":"Supprimer une zone","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Zone supprimée.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/zones/{id}/activation":{"patch":{"tags":["Zones"],"summary":"Activer / désactiver une zone","description":"Une zone désactivée est exclue du monitoring automatique mais reste utilisable pour les alertes.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivationRequest"}}}},"responses":{"200":{"description":"Zone.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"$ref":"#/components/schemas/Zone"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/zones/{id}/dupliquer":{"post":{"tags":["Zones"],"summary":"Dupliquer une zone","description":"Reproduit la forme sous un nouveau libellé (nouveau nom généré).","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DupliquerZoneRequest"}}}},"responses":{"201":{"description":"Zone.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"$ref":"#/components/schemas/Zone"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"}}}},"/corridors":{"get":{"tags":["Corridors"],"summary":"Lister les corridors","description":"Liste paginée, scopée selon le token.","security":[{"bearerAuth":[]}],"parameters":[{"name":"actif","in":"query","schema":{"type":"boolean"}},{"name":"q","in":"query","schema":{"type":"string"},"description":"Recherche sur le nom."},{"name":"safezoneId","in":"query","schema":{"type":"string","format":"uuid"},"description":"Corridors touchant cette safezone."},{"name":"limite","in":"query","schema":{"type":"integer","default":25,"maximum":200}},{"name":"offset","in":"query","schema":{"type":"integer","default":0}}],"responses":{"200":{"description":"Liste paginée des corridors.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CorridorListResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}},"post":{"tags":["Corridors"],"summary":"Créer un corridor","description":"Tronçon polygone, ou ligne centrale élargie à `largeurMetres` (défaut 60 m). Nom auto : CR-[Départ]-[Destination].","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreerCorridorRequest"}}}},"responses":{"201":{"description":"Corridor.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"$ref":"#/components/schemas/Corridor"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"409":{"$ref":"#/components/responses/Conflict"}}}},"/corridors/{id}":{"get":{"tags":["Corridors"],"summary":"Détail d'un corridor","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Corridor.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"$ref":"#/components/schemas/Corridor"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}},"patch":{"tags":["Corridors"],"summary":"Modifier un corridor","description":"Largeur, tronçon et/ou propriétés.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MajCorridorRequest"}}}},"responses":{"200":{"description":"Corridor.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"$ref":"#/components/schemas/Corridor"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"tags":["Corridors"],"summary":"Supprimer un corridor","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Corridor supprimé.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/corridors/{id}/activation":{"patch":{"tags":["Corridors"],"summary":"Activer / désactiver un corridor","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivationRequest"}}}},"responses":{"200":{"description":"Corridor.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"$ref":"#/components/schemas/Corridor"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/corridors/{id}/dupliquer-inverse":{"post":{"tags":["Corridors"],"summary":"Dupliquer un corridor en sens inverse","description":"Crée le corridor inverse (départ ↔ arrivée) à partir du MÊME tronçon, sans redessiner. Ex : CR-Abidjan-Korhogo → CR-Korhogo-Abidjan.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"201":{"description":"Corridor.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"$ref":"#/components/schemas/Corridor"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"}}}},"/vehicules":{"get":{"tags":["Véhicules"],"summary":"Lister les véhicules (résultat automatiquement scopé)","description":"Un compte compagnie ne voit que ses véhicules ; un compte plateforme voit tout le parc et peut filtrer avec ?compagnieId=. Permission requise : `vehicules.lire`.","security":[{"bearerAuth":[]}],"parameters":[{"name":"statut","in":"query","schema":{"type":"string","enum":["actif","en_maintenance","hors_service"]}},{"name":"type","in":"query","schema":{"type":"string","enum":["bus","minibus","car","camion","voiture","tracteur","remorque","semi_remorque","citerne"]}},{"name":"compagnieId","in":"query","schema":{"type":"string","format":"uuid"},"description":"Réservé aux comptes plateforme (403 sinon)."},{"name":"avecBalise","in":"query","schema":{"type":"boolean"},"description":"true = véhicules équipés d'une balise, false = non équipés."},{"name":"q","in":"query","schema":{"type":"string"},"description":"Recherche : immatriculation, marque, modèle, n° de châssis."},{"name":"limite","in":"query","schema":{"type":"integer","default":50,"maximum":200}},{"name":"offset","in":"query","schema":{"type":"integer","default":0}}],"responses":{"200":{"description":"Liste paginée.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VehiculeListResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}},"post":{"tags":["Véhicules"],"summary":"Créer un véhicule","description":"Réservé aux membres de la compagnie (permission `vehicules.gerer`) — un compte plateforme reçoit 403. Le véhicule est rattaché à la compagnie du token. L'immatriculation et le n° de châssis sont uniques AU SEIN de la compagnie.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreerVehiculeRequest"}}}},"responses":{"201":{"description":"Véhicule.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"$ref":"#/components/schemas/Vehicule"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"409":{"$ref":"#/components/responses/Conflict"}}}},"/vehicules/{id}":{"get":{"tags":["Véhicules"],"summary":"Détail d'un véhicule","description":"Renvoie 404 si le véhicule appartient à une autre compagnie, sans révéler son existence.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Véhicule.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"$ref":"#/components/schemas/Vehicule"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}},"patch":{"tags":["Véhicules"],"summary":"Modifier un véhicule","description":"Permission `vehicules.gerer`. La compagnie propriétaire ne peut pas être changée ici.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MajVehiculeRequest"}}}},"responses":{"200":{"description":"Véhicule.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"$ref":"#/components/schemas/Vehicule"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"}}},"delete":{"tags":["Véhicules"],"summary":"Supprimer un véhicule (suppression logique)","description":"Permission `vehicules.gerer`. Refusé (409) si le véhicule est engagé dans un attelage en cours. La balise éventuellement installée est libérée.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Véhicule supprimé.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"message":{"type":"string"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"}}}},"/vehicules/{id}/balise":{"patch":{"tags":["Véhicules"],"summary":"Associer ou dissocier une balise","description":"Permission `vehicules.gerer`. La balise doit appartenir à la même compagnie (400 sinon) et ne pas déjà équiper un autre véhicule (409). Envoyer `{\"baliseId\": null}` pour dissocier.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssocierBaliseRequest"}}}},"responses":{"200":{"description":"Véhicule.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"$ref":"#/components/schemas/Vehicule"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"}}}},"/vehicules/{id}/statut":{"patch":{"tags":["Véhicules"],"summary":"Changer le statut opérationnel","description":"Permission `vehicules.gerer`. actif / en_maintenance / hors_service.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangerStatutVehiculeRequest"}}}},"responses":{"200":{"description":"Véhicule.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"$ref":"#/components/schemas/Vehicule"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/conducteurs":{"get":{"tags":["Conducteurs"],"summary":"Lister les conducteurs (résultat automatiquement scopé)","description":"Permission `conducteurs.lire`.","security":[{"bearerAuth":[]}],"parameters":[{"name":"statut","in":"query","schema":{"type":"string","enum":["actif","en_conge","suspendu","inactif"]}},{"name":"compagnieId","in":"query","schema":{"type":"string","format":"uuid"},"description":"Réservé aux comptes plateforme."},{"name":"categoriePermis","in":"query","schema":{"type":"string"},"example":"D"},{"name":"permisExpire","in":"query","schema":{"type":"boolean"},"description":"true = permis déjà expiré (relances), false = encore valide."},{"name":"q","in":"query","schema":{"type":"string"},"description":"Recherche : nom, prénoms, téléphone, n° de permis."},{"name":"limite","in":"query","schema":{"type":"integer","default":50,"maximum":200}},{"name":"offset","in":"query","schema":{"type":"integer","default":0}}],"responses":{"200":{"description":"Liste paginée.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConducteurListResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}},"post":{"tags":["Conducteurs"],"summary":"Créer un conducteur","description":"Permission `conducteurs.gerer` — réservé aux membres de la compagnie. Numéro de permis et téléphone uniques AU SEIN de la compagnie.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreerConducteurRequest"}}}},"responses":{"201":{"description":"Conducteur.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"$ref":"#/components/schemas/Conducteur"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"409":{"$ref":"#/components/responses/Conflict"}}}},"/conducteurs/codes-activation/verifier":{"post":{"tags":["Conducteurs"],"summary":"Vérifier une phrase d'activation","description":"Appelé par la balise ou l'app mobile pour autoriser le démarrage. Renvoie 401 avec un message générique quelle que soit la cause (code inexistant, inactif, expiré ou phrase erronée) afin de ne rien divulguer.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerifierCodeActivationRequest"}}}},"responses":{"200":{"description":"Code valide.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"valide":{"type":"boolean","example":true},"conducteurId":{"type":"string","format":"uuid"},"vehiculeId":{"type":"string","format":"uuid"}}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/conducteurs/{id}":{"get":{"tags":["Conducteurs"],"summary":"Détail d'un conducteur","description":"404 si le conducteur relève d'une autre compagnie, sans révéler son existence.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Conducteur.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"$ref":"#/components/schemas/Conducteur"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}},"patch":{"tags":["Conducteurs"],"summary":"Modifier un conducteur","description":"Permission `conducteurs.gerer`. La compagnie employeuse ne peut pas être changée ici.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MajConducteurRequest"}}}},"responses":{"200":{"description":"Conducteur.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"$ref":"#/components/schemas/Conducteur"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"}}},"delete":{"tags":["Conducteurs"],"summary":"Supprimer un conducteur (suppression logique)","description":"Permission `conducteurs.gerer`. Refusé (409) si une affectation est en cours. Ses codes d'activation sont révoqués dans la foulée.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Conducteur supprimé.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"message":{"type":"string"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"}}}},"/conducteurs/{id}/statut":{"patch":{"tags":["Conducteurs"],"summary":"Changer le statut du conducteur","description":"Permission `conducteurs.gerer`. Seul un conducteur `actif` peut être affecté à un véhicule.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangerStatutConducteurRequest"}}}},"responses":{"200":{"description":"Conducteur.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"$ref":"#/components/schemas/Conducteur"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/conducteurs/{id}/affectation-courante":{"get":{"tags":["Conducteurs"],"summary":"Affectation en cours du conducteur","description":"Renvoie `data: null` si le conducteur n'est affecté à aucun véhicule.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Affectation en cours, ou null.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","nullable":true}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/conducteurs/{id}/codes-activation":{"get":{"tags":["Conducteurs"],"summary":"Lister les codes d'activation d'un conducteur","description":"Permission `conducteurs.lire`. La phrase n'est jamais renvoyée.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Codes d'activation.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"array","items":{"$ref":"#/components/schemas/CodeActivation"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}},"post":{"tags":["Conducteurs"],"summary":"Générer un code d'activation pour un véhicule","description":"Permission `conducteurs.gerer`. Un seul code par couple (conducteur, véhicule) : en cas de doublon, 409 — régénérez le code existant. ⚠️ La phrase en clair n'est renvoyée QUE dans cette réponse.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreerCodeActivationRequest"}}}},"responses":{"201":{"description":"Code d'activation, avec la phrase en clair (affichée une seule fois).","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"$ref":"#/components/schemas/CodeActivationAvecPhrase"},"message":{"type":"string"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"}}}},"/conducteurs/{id}/codes-activation/{codeId}":{"patch":{"tags":["Conducteurs"],"summary":"Modifier un code d'activation","description":"Permission `conducteurs.gerer`. Fournir `phraseActivation` remplace la phrase (et la renvoie une fois) ; `actif: false` désactive le code.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"codeId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MajCodeActivationRequest"}}}},"responses":{"200":{"description":"Code d'activation, avec la phrase en clair (affichée une seule fois).","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"$ref":"#/components/schemas/CodeActivationAvecPhrase"},"message":{"type":"string"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"tags":["Conducteurs"],"summary":"Révoquer un code d'activation","description":"Permission `conducteurs.gerer`. Suppression logique.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"codeId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Code révoqué.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"message":{"type":"string"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/conducteurs/{id}/codes-activation/{codeId}/regenerer":{"post":{"tags":["Conducteurs"],"summary":"Régénérer la phrase d'un code","description":"Permission `conducteurs.gerer`. À utiliser en cas de perte : l'ancienne phrase cesse immédiatement de fonctionner. La nouvelle est renvoyée une seule fois.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"codeId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Code d'activation, avec la phrase en clair (affichée une seule fois).","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"$ref":"#/components/schemas/CodeActivationAvecPhrase"},"message":{"type":"string"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/affectations":{"get":{"tags":["Affectations"],"summary":"Historique des affectations","description":"Permission `conducteurs.lire`. Filtrer par `conducteurId` donne l'historique d'un conducteur, par `vehiculeId` celui d'un véhicule. `depuis`/`jusqua` sélectionnent les affectations chevauchant la période.","security":[{"bearerAuth":[]}],"parameters":[{"name":"conducteurId","in":"query","schema":{"type":"string","format":"uuid"}},{"name":"vehiculeId","in":"query","schema":{"type":"string","format":"uuid"}},{"name":"statut","in":"query","schema":{"type":"string","enum":["en_cours","terminee","interrompue"]}},{"name":"enCours","in":"query","schema":{"type":"boolean"},"description":"true = uniquement les affectations ouvertes."},{"name":"depuis","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"jusqua","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"limite","in":"query","schema":{"type":"integer","default":50,"maximum":200}},{"name":"offset","in":"query","schema":{"type":"integer","default":0}}],"responses":{"200":{"description":"Historique paginé.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AffectationListResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}},"post":{"tags":["Affectations"],"summary":"Affecter un conducteur à un véhicule (ouvrir une période)","description":"Permission `conducteurs.gerer`. Refusé (409) si le conducteur ou le véhicule a déjà une affectation ouverte. Le conducteur doit être `actif` et le véhicule ne pas être `hors_service`. La balise équipant le véhicule est figée dans l'affectation (snapshot).","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreerAffectationRequest"}}}},"responses":{"201":{"description":"Affectation.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"$ref":"#/components/schemas/Affectation"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"409":{"$ref":"#/components/responses/Conflict"}}}},"/affectations/vehicule/{vehiculeId}/courante":{"get":{"tags":["Affectations"],"summary":"Affectation en cours d'un véhicule","description":"Renvoie `data: null` si le véhicule n'a pas de conducteur affecté.","security":[{"bearerAuth":[]}],"parameters":[{"name":"vehiculeId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Affectation en cours, ou null.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","nullable":true}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/affectations/{id}":{"get":{"tags":["Affectations"],"summary":"Détail d'une affectation","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Affectation.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"$ref":"#/components/schemas/Affectation"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"tags":["Affectations"],"summary":"Supprimer une affectation (saisie erronée)","description":"Permission `conducteurs.gerer`. Réservé aux erreurs de saisie : une affectation terminée se clôture, elle ne se supprime pas.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Affectation supprimée.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"message":{"type":"string"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/affectations/{id}/cloturer":{"patch":{"tags":["Affectations"],"summary":"Clôturer une affectation (fermer la période)","description":"Permission `conducteurs.gerer`. 409 si elle est déjà clôturée, 400 si `dateFin` précède `dateDebut` ou si un motif manque pour une interruption.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CloturerAffectationRequest"}}}},"responses":{"200":{"description":"Affectation.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"$ref":"#/components/schemas/Affectation"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"}}}},"/attelages":{"get":{"tags":["Attelages"],"summary":"Historique des attelages","description":"Permission `vehicules.lire`. `vehiculeId` renvoie l'historique du véhicule qu'il ait servi de tracteur OU de remorque ; `tracteurId` et `remorqueId` ciblent un rôle précis. `depuis`/`jusqua` sélectionnent les attelages chevauchant la période.","security":[{"bearerAuth":[]}],"parameters":[{"name":"tracteurId","in":"query","schema":{"type":"string","format":"uuid"}},{"name":"remorqueId","in":"query","schema":{"type":"string","format":"uuid"}},{"name":"vehiculeId","in":"query","schema":{"type":"string","format":"uuid"},"description":"Tracteur ou remorque indifféremment."},{"name":"enCours","in":"query","schema":{"type":"boolean"},"description":"true = attelages ouverts."},{"name":"depuis","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"jusqua","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"limite","in":"query","schema":{"type":"integer","default":50,"maximum":200}},{"name":"offset","in":"query","schema":{"type":"integer","default":0}}],"responses":{"200":{"description":"Historique paginé.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AttelageListResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}},"post":{"tags":["Attelages"],"summary":"Atteler une remorque à un tracteur","description":"Permission `vehicules.gerer`. Refusé (409) si le tracteur tracte déjà ou si la remorque est déjà attelée. 400 si les types sont incompatibles, si les véhicules relèvent d'une autre compagnie, sont hors service, ou si tracteur et remorque sont le même véhicule.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreerAttelageRequest"}}}},"responses":{"201":{"description":"Attelage.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"$ref":"#/components/schemas/Attelage"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"409":{"$ref":"#/components/responses/Conflict"}}}},"/attelages/vehicule/{vehiculeId}/courant":{"get":{"tags":["Attelages"],"summary":"Attelage en cours d'un véhicule","description":"Fonctionne que le véhicule soit tracteur ou remorque. Renvoie `data: null` s'il n'est pas attelé.","security":[{"bearerAuth":[]}],"parameters":[{"name":"vehiculeId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Attelage en cours, ou null.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","nullable":true}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/attelages/{id}":{"get":{"tags":["Attelages"],"summary":"Détail d'un attelage","description":"404 si l'attelage relève d'une autre compagnie, sans révéler son existence.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Attelage.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"$ref":"#/components/schemas/Attelage"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}},"patch":{"tags":["Attelages"],"summary":"Corriger un attelage","description":"Permission `vehicules.gerer`. Corrections de saisie uniquement (date de début, motif). Le couple tracteur/remorque est immuable.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MajAttelageRequest"}}}},"responses":{"200":{"description":"Attelage.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"$ref":"#/components/schemas/Attelage"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"tags":["Attelages"],"summary":"Supprimer un attelage (saisie erronée)","description":"Permission `vehicules.gerer`. Réservé aux erreurs de saisie : un attelage terminé se dételle, il ne se supprime pas.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Attelage supprimé.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"message":{"type":"string"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/attelages/{id}/deteler":{"patch":{"tags":["Attelages"],"summary":"Dételer (fermer la période)","description":"Permission `vehicules.gerer`. 409 si déjà dételé, 400 si `dateFin` précède `dateDebut`. Le tracteur et la remorque redeviennent aussitôt disponibles pour un nouvel attelage.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DetelerAttelageRequest"}}}},"responses":{"200":{"description":"Attelage.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"$ref":"#/components/schemas/Attelage"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"}}}}},"security":[{"bearerAuth":[]}]}