Deux clones du template partagent le projet Compose template : le second docker compose up s'attache à la base du premier et joue ses migrations dessus #62

Closed
opened 2026-09-12 15:53:03 +00:00 by nicolas-fryder · 3 comments

Ce qui ne va pas

docker-compose.yml du template nomme son projet d'après SERVICE_NAME :

name: ${SERVICE_NAME:-template}

et .env.example livre SERVICE_NAME=template, plus des ports fixes :

SERVICE_NAME=template
PORT=4100
PORT_WEB=4000
PORT_POSTGRES=55400
PORT_OTEL=43100

Deux satellites clonés depuis ce template, sur un même poste, ont donc le même nom de projet Compose. Le second docker compose up -d ne signale aucune collision : Docker Compose indexe les conteneurs et les volumes par nom de projet, il trouve le projet template déjà levé, et il s'y attache.

Le second clone se retrouve alors branché sur la base du premier — même hôte, même port, et les trois identifiants identiques puisqu'ils dérivent tous de SERVICE_NAME :

POSTGRES_USER: ${SERVICE_NAME:-template}
POSTGRES_PASSWORD: ${SERVICE_NAME:-template}
POSTGRES_DB: ${SERVICE_NAME:-template}

DATABASE_URL=postgresql://template:template@localhost:55400/template?schema=public est valide dans les deux clones et désigne la même base. Un pnpm --filter api db:dev ou db:deploy dans le second clone écrit dans la base de développement du premier, et réussit.

C'est l'inverse de ce que le dépôt promet. Le commentaire de docker-compose.yml affirme :

Les ports viennent de .env, et .env les tient de la plage réservée au clonage (eqs-platform/reference/satellites.md, D-030). Deux satellites sur un même poste ne se marchent pas dessus.

et AGENTS.md : « Un port est réservé au clonage (docker-compose.yml). On ne le change pas. » Les deux décrivent l'état d'un satellite initialisé. Le template, lui, livre les valeurs du template, et rien dans le dépôt ne se plaint au moment où c'est dangereux.

Reproduction

git clone <eqs-satellite-template> satellite-a && cd satellite-a
cp .env.example .env && docker compose up -d postgres
cd .. && git clone <eqs-satellite-template> satellite-b && cd satellite-b
cp .env.example .env && docker compose up -d postgres
docker compose ls

Obtenu : un seul projet, template. Le second up rend « Running » sans rien créer. docker compose ps depuis satellite-b montre les conteneurs de satellite-a.

Attendu : soit deux projets distincts, soit un refus explicite nommant le conflit.

La démonstration du dégât, ensuite : dans satellite-a, créer une table et y écrire une ligne ; dans satellite-b, jouer pnpm --filter api db:dev. La migration de b s'applique à la base de a.

Ce que ça coûte

Bloquant, et silencieux — la pire combinaison. Le mode d'échec n'est pas une erreur, c'est un succès sur la mauvaise base.

Dans mon cas, un agent de codage a vu les ports 55400 et 43100 déjà pris par un autre satellite du même poste, a compris ce qui se passait, et a corrigé ses ports en local (55401 / 43101) dans un .env non versionné. Il s'en est sorti — mais il a été chanceux : les ports occupés lui ont donné un signal visible. Avec SERVICE_NAME identique, Compose ne donne aucun signal du tout, et corriger les ports ne suffit pas : tant que SERVICE_NAME reste template, les deux clones se disputent le même projet et le même volume.

La perte possible est la base de développement d'un autre projet, écrasée par les migrations d'un projet sans rapport. Sur un poste où tournent plusieurs satellites — ce que le clonage encourage — c'est une question de temps.

Ce que je proposerais

Par ordre d'utilité décroissante.

  1. Ne pas livrer de valeur utilisable pour SERVICE_NAME. .env.example porte SERVICE_NAME= vide, et le schéma baseSchema l'exige non vide. Le clone échoue alors au premier démarrage, avec un message qui nomme la variable — au lieu de réussir sur la base du voisin. Le socle échoue au démarrage, jamais à la première requête : c'est déjà la doctrine de plateforme.ts, elle mérite de s'appliquer ici.

  2. Retirer la valeur par défaut du compose. name: ${SERVICE_NAME:?SERVICE_NAME est requis} au lieu de ${SERVICE_NAME:-template}. Compose refuse alors de lever quoi que ce soit sans nom de service, et le message le dit. Le :-template est précisément ce qui transforme un oubli en collision muette.

  3. Même traitement pour les ports : .env.example les laisse vides, et initialiser-un-satellite.md a l'étape qui les pose depuis la plage réservée. Un port vide se voit ; un port juste-mais-pas-le-tien ne se voit pas.

  4. Un contrôle eqs doctor qui refuse SERVICE_NAME=template (ou toute valeur égale au nom du template) dans un dépôt qui n'est pas le template lui-même. C'est l'écart qu'un clone oublie de fermer, et un contrôle le rattrape une fois pour trente dépôts.

Si la 1 et la 2 vous semblent trop brutales pour l'ergonomie d'un clone neuf, je les défends quand même : le coût d'un démarrage qui échoue en nommant la variable est d'une minute, et le coût de l'alternative est la base de développement de quelqu'un d'autre.

Versions

  • @eqs/cli, @eqs/tooling, @eqs/testing : ^0.8.1.
  • docker-compose.yml et .env.example du template, tels que livrés au clone.
  • Clone neuf, profil nest, constaté le 2026-09-12 sur Windows 11 / Docker Desktop.

Contournement

Dans le clone concerné, .env local (non versionné) : PORT_POSTGRES=55401, PORT_OTEL=43101. Ce contournement est insuffisant et je le dis explicitement : il évite la collision de ports, pas le partage de projet Compose, puisque SERVICE_NAME reste template. Il est à retirer quand le défaut est corrigé, et à ne pas prendre pour modèle.

## Ce qui ne va pas `docker-compose.yml` du template nomme son projet d'après `SERVICE_NAME` : ```yaml name: ${SERVICE_NAME:-template} ``` et `.env.example` livre `SERVICE_NAME=template`, plus des ports fixes : ``` SERVICE_NAME=template PORT=4100 PORT_WEB=4000 PORT_POSTGRES=55400 PORT_OTEL=43100 ``` Deux satellites clonés depuis ce template, sur un même poste, ont donc **le même nom de projet Compose**. Le second `docker compose up -d` ne signale aucune collision : Docker Compose indexe les conteneurs et les volumes par nom de projet, il trouve le projet `template` déjà levé, et il s'y attache. Le second clone se retrouve alors branché sur la base du premier — même hôte, même port, et les trois identifiants identiques puisqu'ils dérivent tous de `SERVICE_NAME` : ```yaml POSTGRES_USER: ${SERVICE_NAME:-template} POSTGRES_PASSWORD: ${SERVICE_NAME:-template} POSTGRES_DB: ${SERVICE_NAME:-template} ``` `DATABASE_URL=postgresql://template:template@localhost:55400/template?schema=public` est valide dans les deux clones et désigne la même base. Un `pnpm --filter api db:dev` ou `db:deploy` dans le second clone **écrit dans la base de développement du premier**, et réussit. C'est l'inverse de ce que le dépôt promet. Le commentaire de `docker-compose.yml` affirme : > Les ports viennent de `.env`, et `.env` les tient de la plage réservée au clonage (`eqs-platform/reference/satellites.md`, D-030). **Deux satellites sur un même poste ne se marchent pas dessus.** et `AGENTS.md` : « Un port est réservé au clonage (`docker-compose.yml`). On ne le change pas. » Les deux décrivent l'état d'un satellite **initialisé**. Le template, lui, livre les valeurs du template, et rien dans le dépôt ne se plaint au moment où c'est dangereux. ## Reproduction ```bash git clone <eqs-satellite-template> satellite-a && cd satellite-a cp .env.example .env && docker compose up -d postgres cd .. && git clone <eqs-satellite-template> satellite-b && cd satellite-b cp .env.example .env && docker compose up -d postgres docker compose ls ``` Obtenu : **un seul** projet, `template`. Le second `up` rend « Running » sans rien créer. `docker compose ps` depuis `satellite-b` montre les conteneurs de `satellite-a`. Attendu : soit deux projets distincts, soit un refus explicite nommant le conflit. La démonstration du dégât, ensuite : dans `satellite-a`, créer une table et y écrire une ligne ; dans `satellite-b`, jouer `pnpm --filter api db:dev`. La migration de `b` s'applique à la base de `a`. ## Ce que ça coûte **Bloquant, et silencieux — la pire combinaison.** Le mode d'échec n'est pas une erreur, c'est un succès sur la mauvaise base. Dans mon cas, un agent de codage a vu les ports 55400 et 43100 déjà pris par un autre satellite du même poste, a compris ce qui se passait, et a corrigé ses ports en local (55401 / 43101) dans un `.env` non versionné. Il s'en est sorti — mais il a été chanceux : les ports occupés lui ont donné un signal visible. Avec `SERVICE_NAME` identique, Compose ne donne aucun signal du tout, et corriger les ports ne suffit pas : tant que `SERVICE_NAME` reste `template`, les deux clones se disputent le même projet et le même volume. La perte possible est la base de développement d'un autre projet, écrasée par les migrations d'un projet sans rapport. Sur un poste où tournent plusieurs satellites — ce que le clonage encourage — c'est une question de temps. ## Ce que je proposerais Par ordre d'utilité décroissante. 1. **Ne pas livrer de valeur utilisable pour `SERVICE_NAME`.** `.env.example` porte `SERVICE_NAME=` vide, et le schéma `baseSchema` l'exige non vide. Le clone échoue alors **au premier démarrage**, avec un message qui nomme la variable — au lieu de réussir sur la base du voisin. Le socle échoue au démarrage, jamais à la première requête : c'est déjà la doctrine de `plateforme.ts`, elle mérite de s'appliquer ici. 2. **Retirer la valeur par défaut du compose.** `name: ${SERVICE_NAME:?SERVICE_NAME est requis}` au lieu de `${SERVICE_NAME:-template}`. Compose refuse alors de lever quoi que ce soit sans nom de service, et le message le dit. Le `:-template` est précisément ce qui transforme un oubli en collision muette. 3. **Même traitement pour les ports** : `.env.example` les laisse vides, et `initialiser-un-satellite.md` a l'étape qui les pose depuis la plage réservée. Un port vide se voit ; un port juste-mais-pas-le-tien ne se voit pas. 4. **Un contrôle `eqs doctor`** qui refuse `SERVICE_NAME=template` (ou toute valeur égale au nom du template) dans un dépôt qui n'est pas le template lui-même. C'est l'écart qu'un clone oublie de fermer, et un contrôle le rattrape une fois pour trente dépôts. Si la 1 et la 2 vous semblent trop brutales pour l'ergonomie d'un clone neuf, je les défends quand même : le coût d'un démarrage qui échoue en nommant la variable est d'une minute, et le coût de l'alternative est la base de développement de quelqu'un d'autre. ## Versions - `@eqs/cli`, `@eqs/tooling`, `@eqs/testing` : `^0.8.1`. - `docker-compose.yml` et `.env.example` du template, tels que livrés au clone. - Clone neuf, profil `nest`, constaté le 2026-09-12 sur Windows 11 / Docker Desktop. ## Contournement Dans le clone concerné, `.env` local (non versionné) : `PORT_POSTGRES=55401`, `PORT_OTEL=43101`. **Ce contournement est insuffisant** et je le dis explicitement : il évite la collision de ports, pas le partage de projet Compose, puisque `SERVICE_NAME` reste `template`. Il est à retirer quand le défaut est corrigé, et à ne pas prendre pour modèle.
Author
Owner

Correction sur le statut de la reproduction, à lire avant de traiter le ticket.

La section « Reproduction » est rédigée au mode observé — « Obtenu : un seul projet, template » — et ce n'est pas exact. Je corrige.

Ce qui est observé :

  • les deux clones existent bien sur le poste, et le second a trouvé les ports 55400 et 43100 déjà occupés par le premier ;
  • docker-compose.yml nomme le projet ${SERVICE_NAME:-template} et dérive POSTGRES_USER, POSTGRES_PASSWORD et POSTGRES_DB de la même variable ;
  • .env.example livre SERVICE_NAME=template et les quatre ports en dur.

Ce qui est déduit, et non joué : le partage de projet Compose entre deux clones, l'attachement du second up aux conteneurs du premier, et la migration du second clone s'appliquant à la base du premier. Cela découle de la façon dont Compose indexe par nom de projet, et les identifiants concordent — mais je n'ai pas exécuté la séquence à deux clones, et je n'ai pas vérifié la perte de données.

La conséquence pratique : le défaut de conception (une valeur par défaut utilisable pour une variable qui doit être unique par clone) est établi par lecture et se corrige tel quel. Le scénario de dégât, lui, demande à être confirmé avant d'être cité comme un fait — et il devrait l'être, parce que c'est lui qui décide de la priorité.

Les quatre propositions restent valables indépendamment : elles ferment la cause, pas le symptôme.

**Correction sur le statut de la reproduction, à lire avant de traiter le ticket.** La section « Reproduction » est rédigée au mode observé — « Obtenu : un seul projet, `template` » — et ce n'est pas exact. Je corrige. **Ce qui est observé :** - les deux clones existent bien sur le poste, et le second a trouvé les ports 55400 et 43100 **déjà occupés** par le premier ; - `docker-compose.yml` nomme le projet `${SERVICE_NAME:-template}` et dérive `POSTGRES_USER`, `POSTGRES_PASSWORD` et `POSTGRES_DB` de la même variable ; - `.env.example` livre `SERVICE_NAME=template` et les quatre ports en dur. **Ce qui est déduit, et non joué :** le partage de projet Compose entre deux clones, l'attachement du second `up` aux conteneurs du premier, et la migration du second clone s'appliquant à la base du premier. Cela découle de la façon dont Compose indexe par nom de projet, et les identifiants concordent — mais **je n'ai pas exécuté la séquence à deux clones**, et je n'ai pas vérifié la perte de données. La conséquence pratique : le défaut de conception (une valeur par défaut utilisable pour une variable qui doit être unique par clone) est établi par lecture et se corrige tel quel. Le scénario de dégât, lui, demande à être confirmé avant d'être cité comme un fait — et il devrait l'être, parce que c'est lui qui décide de la priorité. Les quatre propositions restent valables indépendamment : elles ferment la cause, pas le symptôme.
Author
Owner

Votre correction était la bonne chose à faire, et elle méritait qu'on y réponde par une exécution. Je l'ai jouée. Le scénario de dégât est confirmé.

Ce que j'ai exécuté

Deux clones réels du gabarit, .env copié de .env.example dans chacun, docker compose up -d postgres dans les deux.

Un seul projet :

NAME        STATUS        CONFIG FILES
template    running(1)    …\collision\sat-a\docker-compose.yml

Les deux clones voient le même conteneur — notez que CONFIG FILES pointe sur sat-a pendant que sat-b le pilote :

sat-a : template-postgres-1 postgres Up 15 seconds (healthy)
sat-b : template-postgres-1 postgres Up 19 seconds (healthy)

Et la partie que vous n'aviez pas jouée :

sat-a $ psql -c "CREATE TABLE preuve_a(qui text); INSERT INTO preuve_a VALUES ('ecrit depuis sat-a');"
CREATE TABLE
INSERT 0 1

sat-b $ psql -c "SELECT qui FROM preuve_a;"
        qui
--------------------
 ecrit depuis sat-a
(1 row)

Une écriture depuis un clone se lit depuis l'autre. Une migration jouée dans b s'applique donc bien à la base de développement de a, et réussit — le mode d'échec n'est pas une erreur, c'est un succès sur la mauvaise base, exactement comme vous l'écriviez.

Un détail observé que vous n'aviez pas : le premier up a affiché Container template-postgres-1 Recreate. Un conteneur de ce nom traînait déjà sur le poste, hors de tout projet listé. C'est un symptôme de plus du même défaut : le nom est si générique qu'il se retrouve partout.

(Nettoyé après coup : table supprimée, projet descendu sans -v — le volume pouvait préexister à mon essai, et je n'allais pas détruire les données de quelqu'un pour vérifier qu'on peut détruire les données de quelqu'un.)

Ce que j'ai pris

Vos options 1 et 2, ensemble, parce qu'elles ferment deux portes différentes.

docker-compose.yml :

name: ${SERVICE_NAME:?SERVICE_NAME est requis et doit etre unique a ce satellite — voir .env.example}

Vérifié, avec un .env qui ne l'a pas rempli :

error while interpolating name: required variable SERVICE_NAME is missing a value:
  SERVICE_NAME est requis et doit etre unique a ce satellite — voir .env.example

Et .env.example livre SERVICE_NAME= vide. Votre pari était juste : baseSchema exige déjà /^[a-z][a-z0-9-]{1,40}$/, donc une valeur vide échoue au démarrage en nommant la variable. Le clone qui oublie échoue deux fois plutôt que de réussir sur la base du voisin.

Vous écriviez : « si la 1 et la 2 vous semblent trop brutales pour l'ergonomie d'un clone neuf, je les défends quand même ». Elles ne le sont pas. Une minute de démarrage raté contre la base de développement de quelqu'un d'autre — l'arbitrage n'en est pas un.

Ce que je n'ai pas pris, et pourquoi

Votre option 3, vider les ports. Pendant la reproduction, j'ai eu ceci :

Bind for 127.0.0.1:55400 failed: port is already allocated

Un port déjà pris se voit, bruyamment, et s'attribue tout seul à la bonne cause. C'est précisément ce qui distingue les deux variables : le port collisionne visiblement, le nom de projet collisionne en silence. Vider les ports ajouterait un échec de démarrage à chaque clone pour un problème qui se signale déjà. Si vous pensez qu'il y a un cas où un port valide-mais-pas-le-vôtre passe inaperçu, dites-le — ça changerait l'arbitrage.

Votre option 4, le contrôle eqs doctor. Elle mérite d'être prise, et elle ne pouvait pas l'être maintenant : @eqs/* 0.9.0 vient d'être publié en candidate il y a vingt minutes, et l'ajouter rouvrirait une version déjà vérifiée deux fois. Elle part dans la suivante. Elle garde sa valeur propre : les clones déjà faits portent SERVICE_NAME=template dans leur .env local, et ni le compose ni le schéma ne les rattraperont — c'est le contrôle qui les trouvera.

Votre contournement

Vous aviez raison de le déclarer insuffisant, et de dire pourquoi. Après cette correction, il devient inutile : remplissez SERVICE_NAME avec un nom propre au satellite et les ports redeviennent une question d'hygiène, pas de sécurité.

Branche fix/service-name-unique sur le gabarit, tirée de main, fusionnable tout de suite — elle ne dépend d'aucune version du socle.

Votre correction était la bonne chose à faire, et elle méritait qu'on y réponde par une exécution. **Je l'ai jouée. Le scénario de dégât est confirmé.** ## Ce que j'ai exécuté Deux clones réels du gabarit, `.env` copié de `.env.example` dans chacun, `docker compose up -d postgres` dans les deux. Un seul projet : ``` NAME STATUS CONFIG FILES template running(1) …\collision\sat-a\docker-compose.yml ``` Les deux clones voient le même conteneur — notez que `CONFIG FILES` pointe sur `sat-a` pendant que `sat-b` le pilote : ``` sat-a : template-postgres-1 postgres Up 15 seconds (healthy) sat-b : template-postgres-1 postgres Up 19 seconds (healthy) ``` Et la partie que vous n'aviez pas jouée : ``` sat-a $ psql -c "CREATE TABLE preuve_a(qui text); INSERT INTO preuve_a VALUES ('ecrit depuis sat-a');" CREATE TABLE INSERT 0 1 sat-b $ psql -c "SELECT qui FROM preuve_a;" qui -------------------- ecrit depuis sat-a (1 row) ``` Une écriture depuis un clone se lit depuis l'autre. Une migration jouée dans `b` s'applique donc bien à la base de développement de `a`, et **réussit** — le mode d'échec n'est pas une erreur, c'est un succès sur la mauvaise base, exactement comme vous l'écriviez. Un détail observé que vous n'aviez pas : le **premier** `up` a affiché `Container template-postgres-1 Recreate`. Un conteneur de ce nom traînait déjà sur le poste, hors de tout projet listé. C'est un symptôme de plus du même défaut : le nom est si générique qu'il se retrouve partout. (Nettoyé après coup : table supprimée, projet descendu **sans** `-v` — le volume pouvait préexister à mon essai, et je n'allais pas détruire les données de quelqu'un pour vérifier qu'on peut détruire les données de quelqu'un.) ## Ce que j'ai pris **Vos options 1 et 2**, ensemble, parce qu'elles ferment deux portes différentes. `docker-compose.yml` : ```yaml name: ${SERVICE_NAME:?SERVICE_NAME est requis et doit etre unique a ce satellite — voir .env.example} ``` Vérifié, avec un `.env` qui ne l'a pas rempli : ``` error while interpolating name: required variable SERVICE_NAME is missing a value: SERVICE_NAME est requis et doit etre unique a ce satellite — voir .env.example ``` Et `.env.example` livre `SERVICE_NAME=` **vide**. Votre pari était juste : `baseSchema` exige déjà `/^[a-z][a-z0-9-]{1,40}$/`, donc une valeur vide échoue au démarrage en nommant la variable. Le clone qui oublie échoue deux fois plutôt que de réussir sur la base du voisin. Vous écriviez : « si la 1 et la 2 vous semblent trop brutales pour l'ergonomie d'un clone neuf, je les défends quand même ». Elles ne le sont pas. Une minute de démarrage raté contre la base de développement de quelqu'un d'autre — l'arbitrage n'en est pas un. ## Ce que je n'ai pas pris, et pourquoi **Votre option 3, vider les ports.** Pendant la reproduction, j'ai eu ceci : ``` Bind for 127.0.0.1:55400 failed: port is already allocated ``` Un port déjà pris **se voit**, bruyamment, et s'attribue tout seul à la bonne cause. C'est précisément ce qui distingue les deux variables : le port collisionne visiblement, le nom de projet collisionne en silence. Vider les ports ajouterait un échec de démarrage à chaque clone pour un problème qui se signale déjà. Si vous pensez qu'il y a un cas où un port valide-mais-pas-le-vôtre passe inaperçu, dites-le — ça changerait l'arbitrage. **Votre option 4, le contrôle `eqs doctor`.** Elle mérite d'être prise, et elle ne pouvait pas l'être maintenant : `@eqs/*` 0.9.0 vient d'être publié en candidate il y a vingt minutes, et l'ajouter rouvrirait une version déjà vérifiée deux fois. Elle part dans la suivante. Elle garde sa valeur propre : les clones **déjà faits** portent `SERVICE_NAME=template` dans leur `.env` local, et ni le compose ni le schéma ne les rattraperont — c'est le contrôle qui les trouvera. ## Votre contournement Vous aviez raison de le déclarer insuffisant, et de dire pourquoi. Après cette correction, il devient inutile : remplissez `SERVICE_NAME` avec un nom propre au satellite et les ports redeviennent une question d'hygiène, pas de sécurité. Branche `fix/service-name-unique` sur le gabarit, tirée de `main`, **fusionnable tout de suite** — elle ne dépend d'aucune version du socle.
Author
Owner

Corrigé, côté gabarit. docker-compose.yml ne retombe plus sur un nom de projet par défaut :

name: ${SERVICE_NAME:?SERVICE_NAME est requis et doit etre unique a ce satellite — voir .env.example}

.env.example livre SERVICE_NAME= vide, avec le pourquoi au-dessus : « Compose en fait son nom de projet, et les trois identifiants Postgres en dérivent. Deux clones qui le partagent parlent à la même base sans que rien ne le dise. » Vide, Compose refuse de lever et le nomme.

Le ticket a eu une suite : il a mis en lumière que SERVICE_NAME ne gouverne pas les ports, et c'est ce qui a donné #74 puis cli.ports-du-gabarit (D-047). Deux clones ne se mélangent plus ni par la base, ni par les ports.

Fermé après vérification contre le gabarit à jour le 2026-09-21. Ce ticket restait ouvert faute d'un Closes #62 dans le commit, pas faute de correctif.

Corrigé, côté gabarit. `docker-compose.yml` ne retombe plus sur un nom de projet par défaut : ```yaml name: ${SERVICE_NAME:?SERVICE_NAME est requis et doit etre unique a ce satellite — voir .env.example} ``` `.env.example` livre `SERVICE_NAME=` **vide**, avec le pourquoi au-dessus : « Compose en fait son nom de projet, et les trois identifiants Postgres en dérivent. Deux clones qui le partagent parlent à la même base sans que rien ne le dise. » Vide, Compose refuse de lever et le nomme. Le ticket a eu une suite : il a mis en lumière que `SERVICE_NAME` ne gouverne pas les **ports**, et c'est ce qui a donné #74 puis `cli.ports-du-gabarit` (D-047). Deux clones ne se mélangent plus ni par la base, ni par les ports. Fermé après vérification contre le gabarit à jour le 2026-09-21. Ce ticket restait ouvert faute d'un `Closes #62` dans le commit, pas faute de correctif.
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#62
No description provided.