Le slot 02 croise une application déjà debout sur le poste (nuage, 4002) : la table des applications existantes de satellites.md est incomplète, et cli.ports-du-gabarit ne peut pas le voir #77

Closed
opened 2026-09-17 10:57:20 +00:00 by nicolas-fryder · 2 comments

Ce qui ne va pas

Le slot 02 attribué à nicolas-fryder/projet (#74) porte le port web 4002.
Sur le poste de ce satellite, 4002 est publié depuis 28 heures par un
conteneur qui n'est pas de la flotte :

$ docker ps --format '{{.Names}}\t{{.Status}}\t{{.Ports}}' | grep 4002
nuage-api   Up 28 hours (healthy)   0.0.0.0:4002->4002/tcp, [::]:4002->4002/tcp

$ docker inspect nuage-api --format '{{.Config.Image}}'
nuage-nuage-api

Le front ne démarre donc pas :

$ cd apps/web && PORT_WEB=4002 node scripts/next.mjs start
⨯ Failed to start server
Error: listen EADDRINUSE: address already in use :::4002
  code: 'EADDRINUSE', port: 4002

C'est le critère que le registre s'impose à lui-même, et il n'a pas pu
s'appliquer. reference/satellites.md dit, à propos du slot 01 :

Un numéro de slot ne vaut que s'il ne croise aucune des applications
existantes ; deux numéros perdus coûtent moins qu'un port is already allocated cherché une heure.

Le raisonnement est juste. Ce qui manque, c'est que la table « Applications
existantes, hors socle » ne liste que HQ, ATLAS, Topologie, MCP Hub et CODEX.
nuage n'y est pas — donc le croisement était invisible au moment de
l'allocation, et la première attribution réelle du registre est tombée
dessus
.

Ce que ça coûte

Bloquant pour le développement du front sur ce poste, et — c'est le point
gênant — cli.ports-du-gabarit ne peut pas l'attraper. Le contrôle refuse
la plage du slot 00, ce qui est exactement ce qu'il annonce et ce qui
répondait à #74. Mais il valide 4002 sans rien savoir de l'occupation réelle
de la machine : il vérifie qu'on n'est plus sur les ports du gabarit, pas qu'on
est sur des ports libres.

Le mode d'échec a donc simplement changé de forme. Avant #74 : deux piles se
marchaient dessus en silence. Après : la porte est verte, et c'est
EADDRINUSE au premier pnpm dev — franc, au moins, mais découvert par
la personne et pas par l'outil.

Ce que je proposerais

  1. Réattribuer, et mettre satellites.md à jour. Mesuré sur ce poste, les
    slots 03 à 11 ont leurs quatre ports libres :

    slot 03 : 4103 / 4003 / 55403 / 43103   LIBRE
    slot 04 : 4104 / 4004 / 55404 / 43104   LIBRE
    …
    

    Je ne me sers pas tout seul : c'est précisément ce que #74 a établi —
    consulter n'alloue rien, et se choisir un numéro reproduit le défaut d'un
    cran plus loin.

  2. Compléter la table des applications existantes avec nuage
    (nuage-api sur 4002, plus ses nuage-postgres, nuage-redis,
    nuage-minio). Une table d'exclusion incomplète ne protège de rien, et
    c'est elle qui décide de la validité d'un slot.

  3. Faire regarder l'occupation réelle, à titre indicatif et non bloquant :
    un eqs doctor qui teste les quatre ports du dépôt — une socket qu'on ouvre
    et qu'on referme — dirait « 4002 est déjà pris sur cette machine » au moment
    où c'est réparable, plutôt qu'au premier pnpm dev. Non bloquant parce que
    l'occupation dépend de la machine et de l'heure : un contrôle bloquant sur
    un état volatil est un contrôle qu'on finit par dispenser. Mais l'avertir
    coûte trois lignes.

    C'est complémentaire de cli.ports-du-gabarit, pas un remplacement : l'un
    dit « tu n'as pas de réservation », l'autre « ta réservation ne tient pas
    ici ». Ce sont deux défauts différents et ils se trouvent à deux moments
    différents.

Versions

eqs --version 0.12.0, @eqs/* tous en 0.12.0, profil nest, gabarit
eqs-satellite-template@228f8e4. Windows 11, Docker 29.1.3.

Contournement posé

Aucun pour l'instant : .env et .env.example portent le slot 02 tel
qu'attribué, et eqs doctor est vert. Le front ne se lève pas sur ce poste
tant que le port n'est pas réattribué ou nuage déplacé.

## Ce qui ne va pas Le slot `02` attribué à `nicolas-fryder/projet` (#74) porte le port web **4002**. Sur le poste de ce satellite, `4002` est publié depuis 28 heures par un conteneur qui n'est pas de la flotte : ``` $ docker ps --format '{{.Names}}\t{{.Status}}\t{{.Ports}}' | grep 4002 nuage-api Up 28 hours (healthy) 0.0.0.0:4002->4002/tcp, [::]:4002->4002/tcp $ docker inspect nuage-api --format '{{.Config.Image}}' nuage-nuage-api ``` Le front ne démarre donc pas : ``` $ cd apps/web && PORT_WEB=4002 node scripts/next.mjs start ⨯ Failed to start server Error: listen EADDRINUSE: address already in use :::4002 code: 'EADDRINUSE', port: 4002 ``` C'est le critère que le registre s'impose à lui-même, et il n'a pas pu s'appliquer. `reference/satellites.md` dit, à propos du slot `01` : > Un numéro de slot ne vaut que s'il ne croise aucune des applications > existantes ; deux numéros perdus coûtent moins qu'un `port is already > allocated` cherché une heure. Le raisonnement est juste. Ce qui manque, c'est que la table « Applications existantes, hors socle » ne liste que HQ, ATLAS, Topologie, MCP Hub et CODEX. `nuage` n'y est pas — donc le croisement était invisible au moment de l'allocation, et la **première attribution réelle du registre est tombée dessus**. ## Ce que ça coûte Bloquant pour le développement du front sur ce poste, et — c'est le point gênant — **`cli.ports-du-gabarit` ne peut pas l'attraper**. Le contrôle refuse la plage du slot `00`, ce qui est exactement ce qu'il annonce et ce qui répondait à #74. Mais il valide `4002` sans rien savoir de l'occupation réelle de la machine : il vérifie qu'on n'est plus sur les ports du gabarit, pas qu'on est sur des ports libres. Le mode d'échec a donc simplement changé de forme. Avant #74 : deux piles se marchaient dessus en silence. Après : la porte est verte, et c'est `EADDRINUSE` au premier `pnpm dev` — franc, au moins, mais découvert par la personne et pas par l'outil. ## Ce que je proposerais 1. **Réattribuer**, et mettre `satellites.md` à jour. Mesuré sur ce poste, les slots `03` à `11` ont leurs quatre ports libres : ``` slot 03 : 4103 / 4003 / 55403 / 43103 LIBRE slot 04 : 4104 / 4004 / 55404 / 43104 LIBRE … ``` Je ne me sers pas tout seul : c'est précisément ce que #74 a établi — consulter n'alloue rien, et se choisir un numéro reproduit le défaut d'un cran plus loin. 2. **Compléter la table des applications existantes** avec `nuage` (`nuage-api` sur 4002, plus ses `nuage-postgres`, `nuage-redis`, `nuage-minio`). Une table d'exclusion incomplète ne protège de rien, et c'est elle qui décide de la validité d'un slot. 3. **Faire regarder l'occupation réelle**, à titre indicatif et non bloquant : un `eqs doctor` qui teste les quatre ports du dépôt — une socket qu'on ouvre et qu'on referme — dirait « 4002 est déjà pris sur cette machine » au moment où c'est réparable, plutôt qu'au premier `pnpm dev`. Non bloquant parce que l'occupation dépend de la machine et de l'heure : un contrôle bloquant sur un état volatil est un contrôle qu'on finit par dispenser. Mais l'avertir coûte trois lignes. C'est complémentaire de `cli.ports-du-gabarit`, pas un remplacement : l'un dit « tu n'as pas de réservation », l'autre « ta réservation ne tient pas ici ». Ce sont deux défauts différents et ils se trouvent à deux moments différents. ## Versions `eqs --version` 0.12.0, `@eqs/*` tous en 0.12.0, profil `nest`, gabarit `eqs-satellite-template@228f8e4`. Windows 11, Docker 29.1.3. ## Contournement posé Aucun pour l'instant : `.env` et `.env.example` portent le slot `02` tel qu'attribué, et `eqs doctor` est vert. Le front ne se lève pas sur ce poste tant que le port n'est pas réattribué ou `nuage` déplacé.
Author
Owner

Vos points 1 et 2 sont faits — et trouvés indépendamment le 2026-09-20, en attribuant son slot à eqs-demo. La machine a démenti le registre deux fois de suite ce jour-là : le 02 croisait nuage, puis le 03 proposé à eqs-demo a répondu port is already allocated sur 55403, c'est-à-dire votre .env.

Réattribution. atelier porte le slot 03 au registre — celui qu'il fait déjà tourner. eqs-demo a pris le 05, éprouvé en levant sa pile et en lisant les ports publiés avant de la redescendre.

Table complétée. nuage y figure (4002 / 3001 / 5433), et un tableau des slots hors service dit pourquoi 01, 02 et 06 sont perdus, avec leur raison.

Et la règle que votre ticket appelait, écrite dans reference/satellites.md :

Un registre incomplet est un registre qui ment. Il ne dit pas seulement ce qui est réservé : il doit dire ce qui est PRIS, y compris par ce qui n'est pas un satellite. […] attribuer un slot se vérifie contre la machine, pas contre ce fichier.

docker ps --format '{{.Names}}\t{{.Ports}}'   # avant d'écrire une ligne ici

Ce qui reste chez vous : votre .env.example committé annonce encore 02. À passer en 03 pour s'aligner sur votre .env et sur le registre.


Votre point 3 n'est pas fait, et le ticket reste ouvert pour lui. Votre argument est juste — cli.ports-du-gabarit dit « tu n'as pas de réservation », pas « ta réservation ne tient pas ici », et ce sont deux défauts qui se trouvent à deux moments différents.

Une difficulté à trancher avant d'écrire ce contrôle, et je préfère la poser que la découvrir : si la pile du dépôt tourne, ses propres ports sont occupés — par lui. Un contrôle qui les signale crie à chaque eqs doctor lancé pendant un pnpm dev, et c'est le chemin le plus court vers une dispense. Distinguer « pris par moi » de « pris par un autre » demande de comparer le projet Compose du conteneur qui publie le port au SERVICE_NAME du dépôt — faisable, eqs doctor sait déjà interroger Docker, mais ce n'est plus les trois lignes que vous estimiez.

Deux voies, et votre avis m'intéresse :

  1. le contrôle compare au projet Compose et ne signale que ce qui appartient à quelqu'un d'autre — exact, une trentaine de lignes, et il dépend de Docker ;
  2. la vérification vit dans eqs doctor seulement quand la pile est éteinte, ou dans une commande d'initialisation jouée au moment où on demande un slot — ce qui est le seul moment où l'information sert vraiment.

La 2 me paraît plus juste sur le fond : votre besoin est né à l'attribution, pas au diagnostic quotidien.

Vos points 1 et 2 sont faits — et trouvés indépendamment le 2026-09-20, en attribuant son slot à `eqs-demo`. La machine a démenti le registre **deux fois de suite** ce jour-là : le `02` croisait `nuage`, puis le `03` proposé à `eqs-demo` a répondu `port is already allocated` sur 55403, c'est-à-dire votre `.env`. **Réattribution.** `atelier` porte le slot `03` au registre — celui qu'il fait déjà tourner. `eqs-demo` a pris le `05`, éprouvé en levant sa pile et en lisant les ports publiés avant de la redescendre. **Table complétée.** `nuage` y figure (`4002 / 3001 / 5433`), et un tableau des slots **hors service** dit pourquoi `01`, `02` et `06` sont perdus, avec leur raison. **Et la règle que votre ticket appelait**, écrite dans `reference/satellites.md` : > **Un registre incomplet est un registre qui ment.** Il ne dit pas seulement ce qui est réservé : il doit dire ce qui est PRIS, y compris par ce qui n'est pas un satellite. […] **attribuer un slot se vérifie contre la machine, pas contre ce fichier.** > > ```bash > docker ps --format '{{.Names}}\t{{.Ports}}' # avant d'écrire une ligne ici > ``` **Ce qui reste chez vous** : votre `.env.example` committé annonce encore `02`. À passer en `03` pour s'aligner sur votre `.env` et sur le registre. --- **Votre point 3 n'est pas fait, et le ticket reste ouvert pour lui.** Votre argument est juste — `cli.ports-du-gabarit` dit « tu n'as pas de réservation », pas « ta réservation ne tient pas ici », et ce sont deux défauts qui se trouvent à deux moments différents. Une difficulté à trancher avant d'écrire ce contrôle, et je préfère la poser que la découvrir : **si la pile du dépôt tourne, ses propres ports sont occupés — par lui.** Un contrôle qui les signale crie à chaque `eqs doctor` lancé pendant un `pnpm dev`, et c'est le chemin le plus court vers une dispense. Distinguer « pris par moi » de « pris par un autre » demande de comparer le projet Compose du conteneur qui publie le port au `SERVICE_NAME` du dépôt — faisable, `eqs doctor` sait déjà interroger Docker, mais ce n'est plus les trois lignes que vous estimiez. Deux voies, et votre avis m'intéresse : 1. le contrôle compare au projet Compose et ne signale que ce qui appartient à quelqu'un d'autre — exact, une trentaine de lignes, et il dépend de Docker ; 2. la vérification vit dans `eqs doctor` seulement quand la pile est éteinte, ou dans une commande d'initialisation jouée **au moment où on demande un slot** — ce qui est le seul moment où l'information sert vraiment. La 2 me paraît plus juste sur le fond : votre besoin est né à l'attribution, pas au diagnostic quotidien.
Author
Owner

La prémisse de ce ticket vient de changer

nuage est en cours de rétrofit sur le socle depuis aujourd'hui (EQS-Sandbox/NUAGE, branche retrofit-socle-eqs, les dix packages en 0.13.0, auth comprise). Il entre dans la flotte.

Ce ticket proposait, en point 2, de « compléter la table des applications existantes avec nuage » — c'est-à-dire de le traiter comme une exclusion permanente, au même titre que Dolibarr ou un service sur site. Ce n'est plus la bonne réponse : il lui faut une ligne dans le tableau des satellites, pas dans celui des applications qu'on contourne.

Ce qui reste à trancher, et qui n'est pas mécanique

nuage occupe aujourd'hui, en développement :

port plage du registre
api 4002 41xx
web 3001 40xx
postgres 5433 554xx
collecteur OTel — (aucun) 431xx

Aucun des trois ports ne tombe dans sa plage. Et 4002 est précisément le port qui a fait sortir ce ticket : il croise le web du slot 02.

Deux sorties, et je n'ai pas d'avis tranché :

  1. nuage prend un vrai slot et déplace ses ports. Le registre reste régulier, cli.ports-du-gabarit et le futur contrôle d'occupation réelle (point 3 de ce ticket) fonctionnent sans cas particulier. Coût : les ports sont écrits dans .env, .env.example, docker-compose.yml, la pile e2e, le README et les scripts de smoke — et ils sont dans la tête de qui travaille dessus depuis un an.
  2. Le registre enregistre nuage hors plage, avec une colonne qui dit pourquoi. Le slot 02 reste consommé, comme 06 l'est par la seconde base d'eqs-demo — il y a donc déjà un précédent de slot consommé et documenté.

La 2 me paraît plus honnête vis-à-vis de ce que le registre existe pour faire — dire ce qui est pris, pas ce qui est joli — et la 1 plus durable. C'est une décision de flotte, pas une décision de nuage : je ne me sers pas tout seul, pour la même raison que #74.

Ce que je retiens du ticket en attendant : un rétrofit change la catégorie d'un dépôt, et le registre n'a pas de moyen d'exprimer « était hors flotte, entre en flotte, garde ses ports ». C'est peut-être ça, le vrai manque.

En passant

La même table de docs/profils.md range nuage en next-fullstack alors qu'il est nest, et y liste metalfrom, qui est sur une autre forge — ouvert en #92. Les deux registres tenus à la main ont le même défaut au même moment, ce qui plaide pour le point 3 de ce ticket : faire regarder la machine plutôt que le fichier.

## La prémisse de ce ticket vient de changer `nuage` est en cours de rétrofit sur le socle depuis aujourd'hui (`EQS-Sandbox/NUAGE`, branche `retrofit-socle-eqs`, les dix packages en 0.13.0, auth comprise). Il **entre dans la flotte**. Ce ticket proposait, en point 2, de « compléter la table des applications existantes avec `nuage` » — c'est-à-dire de le traiter comme une exclusion permanente, au même titre que Dolibarr ou un service sur site. Ce n'est plus la bonne réponse : il lui faut une ligne dans le tableau des **satellites**, pas dans celui des applications qu'on contourne. ## Ce qui reste à trancher, et qui n'est pas mécanique `nuage` occupe aujourd'hui, en développement : | | port | plage du registre | | --- | --- | --- | | api | **4002** | `41xx` | | web | **3001** | `40xx` | | postgres | **5433** | `554xx` | | collecteur OTel | — (aucun) | `431xx` | **Aucun des trois ports ne tombe dans sa plage.** Et `4002` est précisément le port qui a fait sortir ce ticket : il croise le `web` du slot `02`. Deux sorties, et je n'ai pas d'avis tranché : 1. **`nuage` prend un vrai slot et déplace ses ports.** Le registre reste régulier, `cli.ports-du-gabarit` et le futur contrôle d'occupation réelle (point 3 de ce ticket) fonctionnent sans cas particulier. Coût : les ports sont écrits dans `.env`, `.env.example`, `docker-compose.yml`, la pile e2e, le `README` et les scripts de smoke — et ils sont dans la tête de qui travaille dessus depuis un an. 2. **Le registre enregistre `nuage` hors plage**, avec une colonne qui dit pourquoi. Le slot `02` reste consommé, comme `06` l'est par la seconde base d'`eqs-demo` — il y a donc déjà un précédent de slot consommé et documenté. La 2 me paraît plus honnête vis-à-vis de ce que le registre existe pour faire — dire ce qui est **pris**, pas ce qui est joli — et la 1 plus durable. C'est une décision de flotte, pas une décision de `nuage` : je ne me sers pas tout seul, pour la même raison que #74. Ce que je retiens du ticket en attendant : **un rétrofit change la catégorie d'un dépôt**, et le registre n'a pas de moyen d'exprimer « était hors flotte, entre en flotte, garde ses ports ». C'est peut-être ça, le vrai manque. ## En passant La même table de `docs/profils.md` range `nuage` en `next-fullstack` alors qu'il est `nest`, et y liste `metalfrom`, qui est sur une autre forge — ouvert en #92. Les deux registres tenus à la main ont le même défaut au même moment, ce qui plaide pour le point 3 de ce ticket : faire regarder la machine plutôt que le fichier.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Infrastructure/eqs-platform#77
No description provided.