Note d’intégration — Anti-Restriction, côté application mobile
Cette note complète CONTRAT-API-BRIDAGE (la référence complète des routes). Ici, seulement ce
que l’application doit faire, dans quel ordre, et ce qu’il ne faut surtout pas faire.
Base : https://live.jmoai.net/api/v1/radius
1. Le partage des rôles, en une phrase
Le backend calcule et trace. L’application pose, depuis le LAN. Le backend reprend ensuite la main sur le routeur et le dit au gérant.
L’application est la seule à pouvoir poser ces commandes, et ce n’est pas un manque de temps
côté serveur. Changer la MAC du WAN renégocie le bail DHCP : si Starlink lie la session à
l’adresse, le lien tombe — et le tunnel de gestion comme la voie de secours BTH empruntent ce
même lien. Le serveur perdrait le seul chemin qui lui permettrait de revenir en arrière.
Depuis le LAN, vous en gardez toujours un. C’est pour ça que le serveur refuse ces écritures
même à lui-même (routerWriteGuard).
1 bis. Jusqu’où le masquage porte — à lire avant de dessiner l’écran
Un MikroTik n’est pas toujours branché sur la parabole. Le cas le plus fréquent du parc : il est derrière un routeur du client (Omada, box opérateur, routeur bi-WAN). Son WAN a alors une adresse privée, et ce que le fournisseur voit, c’est la carte du routeur placé devant — jamais celle du MikroTik. Masquer sa MAC ne change alors rien côté fournisseur.
Envoyez adresse_wan (lue dans /ip dhcp-client print) et le serveur tranche :
masquage.portee |
Sens | Ce que l’app affiche |
|---|---|---|
FOURNISSEUR |
adresse publique ou CGNAT 100.64/10 → le routeur fait face au fournisseur |
rien de spécial |
ROUTEUR_INTERMEDIAIRE |
adresse privée (10/8, 172.16/12, 192.168/16, 169.254/16) | masquage.avertissement, avant le bouton |
INCONNUE |
adresse absente ou illisible | ne rien affirmer |
⚠️ La CGNAT n’est PAS un routeur intermédiaire. Une parabole Starlink délivre par défaut du
100.64.0.0/10, qui n’est ni public ni privé : le routeur fait bel et bien face au fournisseur,
et le masquage porte. Traiter « non publique » comme « derrière un routeur » ferait dire à
l’application que la fonction ne sert à rien précisément chez les clients Starlink directs —
c’est-à-dire sa cible.
On ne bloque pas : masquer un MikroTik derrière un Omada reste défendable, le gérant peut vouloir la discrétion sur son réseau intermédiaire. On le dit, il décide.
2. Avant tout : le droit
Révision 2026-09-17 — camouflage Standalone : aucune association NAS/RADIUS n’est requise pour le camouflage manuel. Sans
nas_idou sans activation volontaire de la gestion Cloud, l’application applique et vérifie le changement de MAC localement, sans aucun appel aux routes Starlink MAC ou bridage. Les sections Cloud de ce document, y compris les consignes, déclarations, statuts et calendriers, ne s’appliquent qu’à un NAS existant que le gérant a choisi de gérer. L’application ne crée jamais un NAS pour lever un blocage de camouflage.
GET /bandwidth/program et GET /starlink/mac/{nasId}/consigne renvoient un objet droit :
router_serial est obligatoire pour chaque appel de camouflage. Si l’application ne parvient
pas à le lire, elle envoie UNKNOWN-SERIAL : le backend l’accepte sans 400, résout la série
canonique si possible et garde sinon une identité interne stable par NAS.
{ "autorise": false, "motif": "STARLINK_X_REQUIRED", "enforced": false, "prix_xof": 25000 }
enforced: false→ bouton actif, même siautoriseest faux. L’enforcement est en veille : griser le bouton mentirait à un gérant dont la fonction marche.enforced: true+autorise: false→ bouton grisé + proposition d’abonnement.autorise: null→ les droits sont indisponibles. N’affichez pas de proposition d’achat : le gérant a peut-être déjà payé. Affichez l’écran normal.
3. Préparer la pose : ce qu’il faut lire sur le routeur
L’application est sur le LAN, elle voit ce que le serveur ne voit pas. Le serveur ne devine rien de tout ceci, et c’est délibéré : se tromper d’interface coupe le gérant de son routeur.
| À lire | Commande RouterOS | Sert à |
|---|---|---|
| tous les liens fournisseur | /ip dhcp-client print → une ligne par client DHCP |
interface=, interfaces_wan= |
| l’adresse du WAN | même sortie, colonne address |
adresse_wan= |
| la MAC actuelle de l’interface masquée | /interface ethernet get [find name=…] mac-address |
mac_origine |
| les ponts | /interface bridge print |
ponts= |
| les membres des ponts | /interface bridge port print |
vérifier qu’aucun WAN n’y est |
| les interfaces locales | /interface print |
interfaces_locales= |
Le WAN ne s’appelle pas toujours ether1. Relevé sur un routeur du parc : il s’appelle
ether1-TP-LinkGiga. Lisez le nom, ne le supposez pas.
Un routeur peut avoir plusieurs liens fournisseur. Ce même routeur en a deux : la fibre sur
ether1-TP-LinkGiga et le Starlink de secours sur ether2-Bakup. La découverte se règle
globalement, donc la liste locale les couvre tous ; mais le nom d’hôte se retire client DHCP
par client DHCP. Envoyez-les tous dans interfaces_wan, sinon le routeur continuera
d’annoncer son identité au second fournisseur pendant que l’écran affichera « appliqué ».
interface = celui dont on masque la MAC. interfaces_wan = tous les liens fournisseur.
Envoyez la liste des ponts. Ne comptez pas sur le serveur pour les deviner : sur ce routeur
ils s’appellent HOTSPOT et Container-bridge. Un gérant nomme ses ponts par leur fonction,
pas par leur type — sans ponts=, l’avertissement sur la visibilité côté clients ne s’affiche
pas, précisément là où il sert.
Pour les interfaces locales, le cas normal est un seul pont. Envoyez ce pont, rien d’autre : la découverte y atteint tous ses membres, ports et Wi-Fi compris.
⚠️ Vérifiez que ce pont ne contient aucun WAN (/interface bridge port print). S’il en
contient un, la découverte ressortirait par le WAN — exactement ce qu’on veut empêcher. Dans ce
cas, n’envoyez pas ce pont.
4. La consigne
GET /starlink/mac/{nasId}/consigne
?interface=ether2-Bakup
&router_serial=HH40AF7YVNP
&interfaces_wan=ether1-TP-LinkGiga
&interfaces_locales=HOTSPOT
&ponts=HOTSPOT,Container-bridge
&adresse_wan=10.100.4.2/24
Consigne réellement produite pour un routeur bi-WAN du parc :
1. :if ([:len [/interface list find name=JSLOCAL]] = 0) do={/interface list add name=JSLOCAL comment=JSLOCAL}
2. :if ([:len [/interface list member find list=JSLOCAL interface=HOTSPOT]] = 0) do={/interface list member add list=JSLOCAL interface=HOTSPOT}
3. /ip neighbor discovery-settings set discover-interface-list=JSLOCAL
4. /ip dhcp-client set [find interface=ether2-Bakup] dhcp-options=clientid
5. /ip dhcp-client set [find interface=ether1-TP-LinkGiga] dhcp-options=clientid
6. /interface ethernet set [find name=ether2-Bakup] mac-address=02:20:F9:E9:9B:50 ← EN DERNIER
Ajoutez &nom_hote=box-4f21 si le gérant veut un nom d’hôte de substitution. Sans ce
paramètre, aucun nom d’hôte n’est envoyé au fournisseur — c’est le réglage le plus discret.
Ajoutez &masquer_ttl=true pour effacer la trace du NAT. Chaque routeur traversé décrémente
le TTL d’un paquet : un fournisseur qui voit arriver un TTL de 63 sait qu’un routeur se cache
derrière. Avec ce paramètre, discretion.commandes contient une règle mangle de plus qui
réécrit le TTL sortant à 64 sur chaque lien fournisseur — le MikroTik redevient un appareil
comme les autres. C’est le seul des quatre signaux qui révèle la NATURE de l’appareil ; la
MAC ne révèle que sa marque.
⚠️ Opt-in, et pour une raison. Réécrire le TTL casse le traceroute DEPUIS le LAN vers
l’extérieur (les sauts ne se comptent plus). N’envoyez masquer_ttl=true que si le gérant
veut la discrétion maximale, et dites-le-lui. Le champ de retour discretion.ttl_masque
confirme si la règle est dans le lot. La règle porte le commentaire JSTTL — rejouable sans
créer de doublon.
Vous récupérez commande (la MAC), discretion.commandes (la discrétion WAN), precautions,
et discretion.avertissement.
Affichez precautions avant le bouton, pas dans un écran d’aide. Et affichez
discretion.avertissement quand il n’est pas null : c’est le seul moment où le gérant peut
encore choisir une interface de gestion hors du pont plutôt que d’être visible de ses clients.
5. L’ORDRE de pose — le point le plus important de cette note
1. discretion.commandes (toutes, dans l'ordre reçu)
2. commande (la MAC) ← EN DERNIER
La MAC se pose en dernier, et c’est la seule règle qu’il ne faut pas inverser. Les commandes de discrétion ne coupent rien : elles se posent tranquillement, sur un lien qui fonctionne. La MAC, elle, fait tomber le lien le temps de la renégociation du bail. Poser la discrétion après la MAC reviendrait à écrire sur un routeur qui est justement en train de perdre son WAN.
Les commandes de discrétion sont idempotentes : si l’une échoue, rejouez tout le bloc, rien ne sera dupliqué.
Gardez commande_retour en local, sur le téléphone, avant de poser quoi que ce soit. C’est
la commande qui rétablit l’adresse d’origine. Elle doit rester lisible hors ligne : le
moment où on en a besoin est précisément celui où le routeur n’a plus Internet.
5 bis. Le routeur refuse les commandes ? Les trois causes, dans l’ordre
Cause n°1 — vous envoyez du script à une API qui n’en veut pas
Les commandes de discretion.commandes sont du script RouterOS :
:if ([:len [/interface list find name=JSLOCAL]] = 0) do={/interface list add name=JSLOCAL comment=JSLOCAL}
Cette forme fonctionne en terminal — SSH, Telnet, terminal WinBox. Elle n’existe pas en
API REST (/rest/...) ni en API binaire (8728) : ces deux-là ne connaissent que des ressources
et des champs, pas :if, pas :len, pas do={}. Envoyer ça à REST donne une erreur de syntaxe
qui n’a rien à voir avec la commande elle-même.
Si votre app parle en SSH : collez les commandes telles quelles, une par ligne. Rien à faire.
Si votre app parle en REST : il faut porter l’idempotence côté client. Une commande
:if ([:len [X find …]] = 0) do={X add …} se traduit par « je fais un GET pour voir si ça
existe, et je ne fais le PUT que si la liste est vide ». Le tableau du §5 ter donne la
correspondance.
Cause n°2 — la cible n’existe pas, et le lot entier tombe
/ip dhcp-client set [find interface=ether1] sur une interface qui n’a pas de client DHCP
fait échouer la commande. Et comme un lot fautif échoue en entier, toute la pose tombe —
alors qu’il n’y avait simplement rien à masquer sur ce lien.
C’est fréquent : un WAN en PPPoE ou en IP fixe n’a pas de client DHCP. Depuis le 2026-08-29 le serveur garde donc chaque écriture sur l’existence de sa cible. Si vous aviez copié une ancienne version des commandes, redemandez la consigne : la forme actuelle est
:if ([:len [/ip dhcp-client find interface=ether1]] > 0) do={/ip dhcp-client set [find interface=ether1] dhcp-options=clientid}
Note : sur un WAN PPPoE il n’y a de toute façon pas de nom d’hôte DHCP à cacher — PPPoE s’annonce par un identifiant, pas par l’option 12.
Cause n°3 — le nom de l’interface
Un nom mal recopié fait find sur du vide, donc rien, donc l’erreur ci-dessus. Vérifié sur un
routeur du parc : les noms contiennent des tirets (ether1-TP-LinkGiga), et [find name=…]
les accepte tels quels sans guillemets. En revanche, un nom contenant un espace doit
être entre guillemets : [find name="mon interface"].
Les messages de RouterOS, traduits
| Ce que dit le routeur | Ce que ça veut dire |
|---|---|
expected end of command / syntax error |
du script envoyé à REST ou à l’API binaire — cause n°1 |
no such item |
find n’a rien trouvé : cause n°2 ou n°3 |
already have such name |
vous avez retiré le :if : la liste existe déjà |
input does not match any value of interface |
nom d’interface inexistant — cause n°3 |
not enough permissions |
l’utilisateur RouterOS n’a pas la politique write |
5 ter. Correspondance REST, si votre app ne passe pas par SSH
| Commande script | Ressource REST | Idempotence à faire vous-même |
|---|---|---|
/interface list add name=JSLOCAL |
PUT /rest/interface/list |
GET /rest/interface/list?name=JSLOCAL d’abord |
/interface list member add … |
PUT /rest/interface/list/member |
GET /rest/interface/list/member?list=JSLOCAL&interface=HOTSPOT |
/ip neighbor discovery-settings set … |
réglage unique : POST /rest/ip/neighbor/discovery-settings/set |
aucune, c’est un set |
/ip dhcp-client set [find interface=X] … |
GET /rest/ip/dhcp-client?interface=X puis PATCH /rest/ip/dhcp-client/<.id> |
le GET est la garde |
/interface ethernet set [find name=X] mac-address=… |
GET /rest/interface/ethernet?name=X puis PATCH /rest/interface/ethernet/<.id> |
le GET est la garde |
Les chemins REST exacts varient un peu selon la version de RouterOS : validez-les par un GET
avant d’écrire. En cas de doute, le terminal SSH reste la voie la plus sûre — c’est celle
pour laquelle les commandes sont écrites.
6. Vérifier qu’Internet est revenu — vraiment
Après la pose, attendez. Deux vérifications, les deux nécessaires :
1. :put [/ip dhcp-client get [find interface=ether1] status] → doit valoir "bound"
2. /ping 1.1.1.1 count=3 → doit répondre
Le premier dit que le bail a été renégocié, le second que le trafic passe. Un bail obtenu ne prouve pas qu’Internet fonctionne.
Laissez jusqu’à 2 minutes. Au-delà, proposez la restauration (commande_retour) — ne la
déclenchez pas toute seule : le gérant doit décider, il est peut-être en train de regarder la
parabole.
7. Déclarer, puis suivre
POST /starlink/mac/{nasId}
{
"router_serial": "HH40AF7YVNP",
"resultat": "POSEE",
"interface": "ether1",
"mac_origine": "48:A9:8A:11:22:33",
"camouflage_mac": "02:AB:CD:EF:01:02",
"internet_confirme": true,
"discretion_appliquee": true,
"interfaces_locales": ["bridge-hotspot"]
}
internet_confirme n’est pas une case à cocher par principe. C’est lui qui déclenche la
reprise en main côté serveur. Un true optimiste la ferait démarrer sur un routeur encore en
train de renégocier son bail, et le gérant lirait un échec là où il n’y avait qu’une attente.
La réponse porte déjà service_etat: "INITIALISATION" et son titre : enchaînez sur l’écran de
suivi sans second appel.
Puis sondez toutes les 5 s :
GET /starlink/mac/{nasId}/statut?router_serial=HH40AF7YVNP
- Affichez
titre, jamaisservice_etat— la phrase vient du serveur, elle est identique dans la notification push. - Affichez les
etapes(ROUTEUR,SAUVEGARDE,PROGRAMME).IGNOREEn’est pas un problème : seuleROUTEURest bloquante. - Arrêtez de sonder dès que
service_etatn’est plusINITIALISATION. La reprise dure typiquement moins d’une minute, sauvegarde comprise. - Le sondage de statut est une lecture dédiée : la cadence normale de 12 requêtes/minute ne
doit pas être traitée comme un abus ni produire un
429. - Un
429est une protection d’infrastructure : stoppez immédiatement la boucle et affichez l’erreur, sans répétition locale. Un second appui pendant l’initialisation reçoit409 MAC_ALREADY_IN_PROGRESSavec le message « Un camouflage est déjà en cours d’application. » : conservez alors l’écran de suivi déjà ouvert. - Ne recalculez jamais
peut_relancer. L’expiration d’une reprise interrompue est une règle serveur ; deux versions de l’app la calculeraient différemment. Quand il vauttrue, montrez « Réessayer » →POST /starlink/mac/{nasId}/relancer.
En cas d’échec de pose, déclarez-le : resultat: "ECHEC", avec mac_origine quand même.
C’est justement quand ça a raté qu’il faut savoir vers quoi revenir.
Pour revenir en arrière : resultat: "RESTAUREE". Le service repasse à EN_ATTENTE.
8. Les notifications
Type STARLINK_X. Elles arrivent en plus de l’écran, pour le gérant qui a quitté l’app :
event_type |
Texte |
|---|---|
SERVICE_INITIALIZING |
Service Anti-Restriction en cours d’initialisation… |
SERVICE_READY |
Système Anti-Restriction actif sur SN…… |
SERVICE_DEGRADED |
L’adresse est posée, mais le routeur n’a pas encore répondu au serveur |
Un appui dessus doit ouvrir l’écran de statut du bon nas_id (il est dans metadata).
9. Ce qu’il faut dire au gérant, et ne pas embellir
Le camouflage est bon, il n’est pas total. Cinq signaux trahissent un MikroTik ; quatre sont traités depuis le 2026-08-31 :
| Signal | État |
|---|---|
| Adresse MAC | masquée. Sur cette infra, chaque routeur porte un préfixe d’un VRAI constructeur varié (Apple, Samsung, Intel, Google, Xiaomi…) : le parc ressemble à un mélange d’appareils du commerce, pas à un « fabricant inconnu » ni à une flotte homogène |
| Découverte de voisinage (MNDP/LLDP) | limitée aux interfaces locales |
| Nom d’hôte DHCP | retiré, ou remplacé |
| TTL | réécrit à 64 si masquer_ttl=true — efface la trace du NAT |
| Empreinte DHCP (option 55) | reste reconnaissable — ne se change pas |
Le champ discretion.limites porte cette liste. Affichez-la. Un camouflage annoncé comme
total et qui ne l’est pas ferait prendre au gérant des risques qu’il croit couverts.
Et dites-lui aussi ce qui ne change pas : le nom du routeur (/system identity) reste le
vrai. C’est ce que son technicien lit dans WinBox. Seul le nom envoyé au fournisseur est masqué.
10. Les erreurs, et ce qu’elles veulent dire pour le gérant
| Code | Message à afficher |
|---|---|
MAC_SERIAL_UNKNOWN |
« Ce routeur n’est pas encore reconnu par la plateforme. » (bloquant) |
MAC_INTERFACE_INVALID |
interface mal lue — refaites l’étape 3 |
MAC_ORIGIN_INVALID |
l’adresse d’origine n’a pas été lue avant la pose |
MAC_NO_EFFECT |
l’adresse posée est identique à l’origine — rien n’aurait été masqué |
MAC_CAMOUFLAGE_NOT_UNICAST |
adresse de groupe : une carte ne peut pas la porter |
MAC_COLLISION |
générer une autre MAC et rejouer la demande |
MAC_LOCAL_IFACES_REQUIRED |
discrétion déclarée sans dire sur quelles interfaces |
MAC_HOSTNAME_INVALID |
nom d’hôte : lettres, chiffres et tirets uniquement |
MAC_NOT_POSED |
relance demandée sur un routeur qui n’est pas masqué |
MAC_ALREADY_IN_PROGRESS |
une pose est déjà en cours : conserver l’écran de suivi |
ROUTER_WRITE_FORBIDDEN |
ne devrait jamais arriver depuis l’app — signalez-le |
Déviation documentée
UNKNOWN-SERIAL est accepté afin qu’une lecture RouterOS indisponible ne bloque pas le
gérant. Le serveur résout d’abord la série canonique du NAS. S’il ne peut pas encore le faire,
il utilise une identité stable propre à ce NAS pour éviter qu’une même MAC soit attribuée à tous
les routeurs en repli. Cette identité ne prouve pas le matériel : l’application doit transmettre
la vraie série dès qu’elle est lisible, afin que la reprise distante puisse cibler le routeur.
11. Protocole de test — les 12 routes, dans l’ordre
Toutes les routes sont sous https://live.jmoai.net/api/v1/radius. Chaque appel porte
Authorization: Bearer <jeton du gérant>. Un compte client lié à un NAS est requis :
requireClientRole + requireLinkedClient + requireRadiusLicense sont posés sur toutes.
Posez d’abord :
API=https://live.jmoai.net/api/v1/radius
T="Bearer <jeton>"
NAS=<uuid du NAS>
Phase 0 — les gardes (à faire une fois, sans jeton)
| # | Appel | Attendu |
|---|---|---|
| 0.1 | n’importe quelle route sans Authorization |
401 |
| 0.2 | une route avec le jeton d’un autre client + votre NAS |
404 MAC_NAS_NOT_OWNED |
| 0.3 | PUT /bandwidth/program 6 fois en moins d’une minute |
la 6ᵉ en 429 |
Un 403 en 0.1 au lieu d’un 401, ou un 200 en 0.2, sont bloquants : arrêtez la recette.
Phase 1 — lectures, sans rien changer
| # | Appel | Vérifier |
|---|---|---|
| 1.1 | GET $API/bandwidth/classes |
la liste des classes, chacune avec plages > 0 |
| 1.2 | GET $API/bandwidth/program |
droit.enforced présent ; programmes (vide au début) |
| 1.3 | GET $API/bandwidth/activity?limite=5 |
activites[] + suivant ; texte en français |
| 1.4 | GET $API/bandwidth/impact?jours=30 |
si fiabilite: "INSUFFISANTE" → reduction_pct null |
| 1.5 | GET $API/starlink/mac |
substitutions: [] au premier passage |
| 1.6 | GET $API/starlink/mac/$NAS/statut |
service_etat: "EN_ATTENTE", peut_relancer: false |
1.4 est le piège classique : si l’app affiche un pourcentage alors que fiabilite vaut
INSUFFISANTE, c’est un défaut bloquant — elle inventerait un chiffre.
Phase 2 — la consigne, sans rien poser
| # | Appel | Vérifier |
|---|---|---|
| 2.1 | /starlink/mac/$NAS/consigne sans interface |
generation_par: "APP_LAN", discretion: null, discretion_motif: "INTERFACE_WAN_MANQUANTE" |
| 2.2 | avec interface=ether1 seul |
generation_par: "APP_LAN", discretion_motif: "INVENTAIRE_INTERFACES_MANQUANT" |
| 2.3 | avec interface + interfaces_locales + ponts |
discretion.commandes (≥ 4), portee: "PONT", avertissement non nul |
| 2.4 | même appel, deux fois | aucune MAC renvoyée : l’app la génère avant la déclaration |
| 2.5 | avec adresse_wan=10.0.0.2 |
masquage.portee: "ROUTEUR_INTERMEDIAIRE" |
| 2.6 | avec adresse_wan=100.75.1.2 |
masquage.portee: "FOURNISSEUR" (CGNAT Starlink) |
| 2.7 | avec interface=ether1;/system reboot |
400 MAC_INTERFACE_INVALID |
| 2.8 | avec nom_hote=nom impossible ! |
discretion: null (nom refusé) |
La MAC est désormais produite par l’app puis réservée par le serveur à la déclaration ; un 409 MAC_COLLISION impose de générer une nouvelle valeur avant le retry.
Phase 3 — la pose réelle, sur un routeur d’essai, depuis le LAN
Ne faites cette phase que sur un routeur que vous pouvez atteindre physiquement.
- Notez
commande_retour— ou l’adresse d’origine — sur papier ou hors ligne. - Posez
discretion.commandesdans l’ordre. Vérifiez :/ip neighbor discovery-settings print→discover-interface-list: JSLOCAL,/ip dhcp-client print→dhcp-options=clientidsur chaque WAN. - Rejouez le même bloc une seconde fois → aucune erreur, aucun doublon dans
/interface list member print(les commandes sont idempotentes). - Posez
commande(la MAC) en dernier. Attendez le bail :status: bound, puis un ping. POST $API/starlink/mac/$NASavecresultat: "POSEE",internet_confirme: true,discretion_appliquee: true,interfaces_locales.
| # | Vérifier |
|---|---|
| 3.1 | la réponse porte service_etat: "INITIALISATION" et un titre |
| 3.2 | une notification push SERVICE_INITIALIZING arrive |
| 3.3 | GET /statut passe ROUTEUR à OK en moins de 30 s |
| 3.4 | service_etat finit à OPERATIONNEL, operationnel_depuis renseigné |
| 3.5 | une notification SERVICE_READY nomme le numéro de série |
| 3.6 | GET /bandwidth/activity contient MAC_SUBSTITUTED et WAN_DISCRETION_APPLIED, racontés en français |
| 3.7 | GET /starlink/mac liste le routeur avec discretion_appliquee: true |
Phase 4 — les refus
| # | Corps envoyé à POST /starlink/mac/$NAS |
Attendu |
|---|---|---|
| 4.1 | camouflage_mac = mac_origine |
400 MAC_NO_EFFECT |
| 4.2 | camouflage_mac: "03:AB:CD:EF:01:02" |
400 MAC_CAMOUFLAGE_NOT_UNICAST |
| 4.3 | camouflage_mac déjà enregistrée par un autre routeur |
409 MAC_COLLISION |
| 4.4 | resultat: "ECHEC" sans mac_origine |
400 MAC_ORIGIN_INVALID |
| 4.5 | discretion_appliquee: true sans interfaces_locales |
400 MAC_LOCAL_IFACES_REQUIRED |
| 4.6 | nom_hote: "nom impossible !" |
400 MAC_HOSTNAME_INVALID |
| 4.7 | resultat: "OK" |
400 MAC_RESULT_INVALID |
Phase 5 — reprise et retour arrière
| # | Appel | Attendu |
|---|---|---|
| 5.1 | POST /starlink/mac/$NAS/relancer pendant une reprise en cours |
relance: false (pas deux sauvegardes concurrentes) |
| 5.2 | POST …/relancer sur un routeur non masqué |
409 MAC_NOT_POSED |
| 5.3 | posez commande_retour sur le routeur, puis POST avec resultat: "RESTAUREE" |
service_etat repasse à EN_ATTENTE |
| 5.4 | GET /statut après restauration |
plus de « actif », peut_relancer: false |
| 5.5 | GET /bandwidth/activity |
une ligne MAC_RESTORED |
Phase 6 — le bridage, si le gérant en a un
| # | Appel | Attendu |
|---|---|---|
| 6.1 | PUT /bandwidth/program {nas_id, limit_mbps: 10} |
200, application: "PLANIFIEE" |
| 6.2 | PUT avec mode: "SCHEDULED" sans dates |
400 BW_SCHEDULE_EMPTY |
| 6.3 | PUT sans limit_mbps |
400 BW_LIMIT_REQUIRED |
| 6.4 | attendre un passage du cron (≤ 5 min), puis GET /bandwidth/program |
etat_constate renseigné, en_erreur: false |
| 6.5 | sur le routeur : /queue simple print where comment=JSBRIDAGE |
les files sont là |
| 6.6 | DELETE /bandwidth/program/{nasId} |
200, puis les files disparaissent du routeur |
Ce qui doit rester vrai après toute la recette
- Aucune écriture du backend dans
/interface ethernet,/ip neighbor,/ip dhcp-clientni/interface list: ces chemins sont gardés, seule l’app les pose. /system identityn’a pas changé : le routeur porte toujours son vrai nom dans WinBox.- Le retrait du bridage ne vise que le commentaire
JSBRIDAGE: aucune file du client, du hotspot ou d’un revendeur ne doit avoir bougé.
12. Recette — à cocher avant publication
- [ ] Le WAN est lu sur le routeur, jamais supposé
ether1. - [ ] Le pont envoyé en
interfaces_localesne contient pas le WAN. - [ ]
commande_retourest stockée avant la pose, et lisible hors ligne. - [ ] La discrétion est posée avant la MAC.
- [ ]
internet_confirmen’est envoyé qu’après les deux vérifications (bail + ping). - [ ] L’écran affiche
titre, passervice_etat. - [ ]
discretion.avertissementetdiscretion.limitessont affichés au gérant. - [ ] Le bouton suit
enforced, pasautorise. - [ ] Sondage arrêté dès la sortie de
INITIALISATION. - [ ] Un appui sur la notification ouvre le bon routeur.
- [ ]
masquage.avertissementest affiché quand la portée vautROUTEUR_INTERMEDIAIRE. - [ ] Tous les liens fournisseur sont envoyés dans
interfaces_wan, pas seulement le masqué. - [ ]
ponts=est envoyé, sans quoi l’avertissement sur la visibilité se tait.