Contrat API — Topologie J+RADIUS
Version : 1.2
Base URL : https://live.jmoai.net/api/v1/radius
Public : application mobile du client titulaire d’une licence J+RADIUS active.
Authentification et périmètre
Toutes les routes ci-dessous exigent le JWT du client. Le tenant est déduit du jeton :
le client ne fournit jamais de client_id et ne peut ni voir ni promouvoir le NAS d’un
autre client.
Un routeur est un NAS RADIUS lié à son allocation VPN canonique. Un NAS MEMBER reste
un routeur RADIUS complet : il authentifie ses propres sessions. Le rôle PRIMARY est
le routeur de référence des écritures de catalogue ; il ne redirige ni ne concentre le
trafic RADIUS des secondaires.
Lire la topologie
GET /topology
Cette route n’est pas mise en cache : chaque appel renvoie 200 avec un corps JSON.
L’application ne doit pas envoyer ni interpréter une réponse 304 pour cette lecture.
Compatibilité mobile : data, result et les champs racine (primary, members,
warnings) décrivent la même topologie. Une application nouvelle lit result ; les
clients historiques peuvent lire data.
La même compatibilité est garantie par GET /nas (nas) et GET /license
(license, nas_count, nas_limit) : les champs existent à la racine, sous data
et sous result.
Capacité NAS
nas_limit est le nombre maximal de routeurs NAS que le client peut rattacher, pas le
nombre de NAS déjà créés. nas_count ne compte que les NAS actifs.
Une offre ne s’additionne pas implicitement à une autre : le serveur applique la plus grande
capacité explicitement accordée, ou la capacité déjà acquise dans l’ancienne licence si elle
est supérieure. Un droit RADIUS sans radius_nas_limit explicite n’ajoute aucun NAS. Le
serveur ne rend jamais une limite inférieure au nombre de NAS actifs existants.
Réponse 200 :
{
"success": true,
"data": {
"primary": {
"id": "uuid",
"nasname": "10.42.0.2",
"role": "PRIMARY"
},
"members": [],
"warnings": []
},
"result": {
"primary": {
"id": "uuid",
"nasname": "10.42.0.2",
"role": "PRIMARY"
},
"members": [],
"warnings": []
},
"primary": {
"id": "uuid",
"nasname": "10.42.0.2",
"role": "PRIMARY",
"status": "ACTIVE",
"tunnel_status": "CONNECTED",
"sessions_open": 4,
"eligibility": { "eligible": true, "code": "ELIGIBLE" }
},
"members": [],
"warnings": []
}
primaryvautnulllorsqu’aucun NAS actif n’est enregistré.memberscontient les NAS actifs non primaires.- Une valeur
eligibility.eligible: falseou une entréewarningsest une anomalie à afficher et à corriger ; ce n’est pas un routeur opérationnel.
Chaque NAS porte aussi board_name (alias de model) et devices. Un équipement
est toujours imbriqué sous le NAS de son allocation_id : il n’existe pas de liste
globale d’équipements dans cette réponse. Les valeurs de devices[].type sont
canoniques : access_point, camera, router, switch, cpe ou other.
Tableau de bord QoE groupé
GET /qoe/dashboard
Cette route applique la même authentification et les mêmes règles de cache que
GET /topology. Elle évite trois appels mobiles : result, data et la racine
contiennent primary, members, warnings et capabilities dans exactement la
même forme que la topologie ; qoe est la charge utile de GET /qoe/status et
usage celle de GET /qoe/usage.
L’application dessine uniquement result.primary, puis result.members, et lit
devices sur chaque NAS. primary: null et devices: [] sont des états normaux.
Pilotage commercial multi-routeurs
GET /commercial-readiness
Cette route est une lecture seule pour le panneau de gestion. Elle ne modifie aucun routeur, aucun NAS et aucune session. Elle donne l’arbre de pilotage à corriger avant une vente multi-routeurs : tunnel, identité routeur, cohérence NAS, inscription FreeRADIUS, premier trafic RADIUS réel, mode RADIUS et preuve CoA/PoD.
Réponse 200 :
{
"success": true,
"summary": {
"technical_status": "TECHNICAL_BLOCKED",
"commercial_status": "NO_GO_COMMERCIAL_MULTI_ROUTER",
"score_sur_10": 6.4,
"total_routers": 2,
"routers_blocked": 1,
"routers_ready_pilot": 1,
"nas_limit": 3,
"blockers": ["COA_POD_PROOF"],
"warnings": ["FREERADIUS_REGISTRATION"]
},
"routers": [
{
"nas_id": "uuid",
"nasname": "10.255.0.10",
"status": "TECHNICAL_BLOCKED",
"blockers": ["COA_POD_PROOF"],
"warnings": [],
"gates": [
{
"code": "COA_POD_PROOF",
"status": "BLOCK",
"message": "CoA/PoD non prouvé sur session réelle : exigence commerciale non satisfaite.",
"evidence": "documenté mais non testé"
}
]
}
],
"pilotage_tree": {
"provider_policy": "NO_GO_COMMERCIAL_MULTI_ROUTER",
"next_required_proofs": [
"NAS auth réel",
"accounting interim réel",
"CoA/PoD confirmé sur ticket de test",
"restore testé",
"charge multi-routeurs mesurée"
]
}
}
commercial_status reste NO_GO_COMMERCIAL_MULTI_ROUTER tant que les validations
Provider Stack ne sont pas produites et approuvées. Même si technical_status vaut
PILOT_READY, l’application ne doit pas afficher une disponibilité commerciale générale.
Promouvoir un routeur secondaire
PUT /nas/:nasId/primary
nasId doit être un NAS actif du client authentifié. Aucun body n’est requis.
Réponse 200 :
{
"success": true,
"nas_id": "uuid",
"role": "PRIMARY",
"previous_primary_nas_id": "uuid",
"changed": true
}
La bascule est atomique : le serveur garantit qu’il n’existe jamais deux NAS PRIMARY
pour le même client. L’application ne doit pas essayer de gérer cette concurrence.
Erreurs :
| Statut | Code | Cas client |
|---|---|---|
401 / 403 |
— | session invalide ou compte non-client |
403 |
RADIUS_LICENSE_INACTIVE ou EXPIRED |
licence non utilisable |
404 |
NAS_NOT_FOUND |
NAS absent, inactif ou hors tenant |
500 |
— | erreur serveur : afficher une erreur réessayable, sans changer l’état local |
Supprimer un routeur
DELETE /nas/:nasId
Avant de supprimer le PRIMARY alors qu’un ou plusieurs secondaires actifs existent,
l’application doit d’abord promouvoir le secondaire choisi avec PUT /nas/:nasId/primary.
Sinon le serveur répond 409 :
{
"error": "Ce NAS est le routeur principal. Désignez d abord un routeur secondaire comme principal.",
"code": "PRIMARY_NAS_REASSIGN_REQUIRED",
"details": {
"primary_nas_id": "uuid",
"candidate_nas_ids": ["uuid"]
}
}
La suppression du dernier NAS actif est admise ; la prochaine inscription d’un NAS actif
le désigne automatiquement PRIMARY.
Règles d’interface recommandées
- Afficher le primaire et les secondaires à partir de
GET /topology, pas d’un cache local. - Proposer la promotion avant le bouton de suppression du primaire.
- Après une promotion ou une suppression réussie, recharger
GET /topology. - Une liste vide ou
primary: nullest un état normal après désinstallation du dernier routeur : ne pas afficher une erreur de paiement ou de compte.
Écart volontaire
Le primaire n’est pas un concentrateur ni un point de défaillance RADIUS : chaque NAS reste enregistré et authentifie localement via FreeRADIUS. Ce choix évite de créer un routage inter-routeurs ou une isolation fournisseur implicite non validée.