Migration SQLite — file des réseaux (bascule reseaux-file) [t_b914b746] #1682

Merged
hermes-fusion merged 1 commit from hermes/migration-reseaux-sqlite into main 2026-10-15 11:30:03 +02:00
Collaborator

Carte t_b914b746 — migrer /opt/studio/reseaux-file.json vers SQLite, sur la recette de STUD-1107.

Ce que fait la branche

  • etat_partage.sql : table reseaux_file — une ligne par entree du fichier, rang pour garder l'ordre de la LISTE d'origine, un champ par colonne (pas de colonne fourre-tout JSON, regle commune du schema). quand est refuse deux fois : le motif, et strftime('%Y-%m-%d %H:%M', quand) IS quand (une heure qui n'existe pas, mesure sur SQLite 3.54 : 2026-10-01 25:00 rend NULL).
  • etat_partage.py : reseaux_lire, reseaux_remplacer (tout ou rien, maj gardee si rien ne change), entree_reseaux (champ inconnu REFUSE, jamais rogne), et _reparer_bascules.
  • bascules.nom n'est plus une liste fermee de noms mais un motif ([a-z0-9][a-z0-9_.-]*). Raison : douze migrations ajoutent chacune leur nom, et SQLite ne modifie pas un CHECK — CREATE TABLE IF NOT EXISTS ne touche pas une table en place, donc une base ouverte avant ce changement refusait reseaux-file en CHECK constraint failed. _reparer_bascules renomme, repose le schema, recopie les lignes, jette l'ancienne ; renommage et recopie en deux temps, l'ensemble idempotent (une coupure laisse bascules_avant, que l'ouverture suivante termine).
  • _infra/etat-service.py : GET /reseaux, POST /reseaux/remplacer.
  • etat_client.py : reseaux(), reseaux_remplacer(), en_service(nom), basculer reseaux-file [--essai], revenir reseaux-file, reseaux <fichier> (ecriture du plan dans la base), en-service <nom>. Le chemin se regle par $RESEAUX_FILE (defaut /opt/studio/reseaux-file.json). Pas de verrou de montage pour ce fichier : il n'a rien a voir avec le montage, et les montages tournent en continu — l'attendre aurait rendu la bascule impossible.
  • _tableau/collecte.py : l'onglet Reseaux lit GET /reseaux des que la bascule est posee, sinon le fichier comme avant. Le 132 n'a pas etat_client.py (deploy-132.sh ne livre que _tableau/ et jetons.py) : l'appel se fait en urllib, comme serveur_depenses.py. Un banc ne parle jamais au service de production : hors de /opt/studio, il faut STUDIO_ETAT_URL.
  • _reseaux/pousser-tableau.sh : quand la bascule est posee, le plan entre dans la base (etat_client.py reseaux) et le JSON n'est plus pousse au 132. Service injoignable : en-service sort en 1 en le disant, et le script retombe sur le chemin d'avant.

Criteres d'acceptation de la carte

  • la table reseaux_file existe et bascules.nom='reseaux-file' est possible
  • basculer reseaux-file --essai sort en 0
  • apres basculer reseaux-file, l'ancien JSON est renomme en .bak-sqlite-YYYY-MM-DD
  • revenir reseaux-file restaure le fichier (l'etat en vigueur, dans la forme qu'ecrivent les producteurs de _reseaux/)

Preuves

  • controle/test_etat_partage.py : TOUT PASSE, dont ok 8a (essai IDENTIQUES, fichier absent et formes refusees sans rien toucher, bascule avec .bak-sqlite, base identique au fichier, ecriture dans la base, retour arriere, re-bascule) et ok 8b (une base d'avant le 2026-10-14 accepte le nouveau nom).
  • _tableau/test_collecte.py : OK (la file vient du service une fois basculee, et le refus est dit).
  • _tableau/lancer-tests.py : sortie en commentaire de la carte.
  • _tableau/rust : cargo test --release --locked vert (10 binaires, 0 echec), cargo build --release --locked sans avertissement.

Limites, dites

  • Les producteurs du plan (_reseaux/preparer-file.py, marquer.py, tiktok-web.py) ecrivent toujours _reseaux/file.json : c'est la copie reseaux-file.json que la carte demande de migrer. Le chemin d'ecriture vers la base passe par pousser-tableau.sh.
  • sorties et file_montage ne sont pas touches.
  • Aucune route /api/... du service Rust n'est touchee : le front Svelte n'a rien a changer.

Hotspot

etat_partage.sql, etat_partage.py et etat_client.py sont touches par les douze cartes de migration en cours, dont hermes/migration-atelier-sqlite (t_56665067) qui tourne en meme temps : un rebase sur ces trois fichiers est probable pour la seconde fusion.

Carte t_b914b746 — migrer `/opt/studio/reseaux-file.json` vers SQLite, sur la recette de STUD-1107. ## Ce que fait la branche - **`etat_partage.sql`** : table `reseaux_file` — une ligne par entree du fichier, `rang` pour garder l'ordre de la LISTE d'origine, un champ par colonne (pas de colonne fourre-tout JSON, regle commune du schema). `quand` est refuse deux fois : le motif, et `strftime('%Y-%m-%d %H:%M', quand) IS quand` (une heure qui n'existe pas, mesure sur SQLite 3.54 : `2026-10-01 25:00` rend NULL). - **`etat_partage.py`** : `reseaux_lire`, `reseaux_remplacer` (tout ou rien, `maj` gardee si rien ne change), `entree_reseaux` (champ inconnu REFUSE, jamais rogne), et `_reparer_bascules`. - **`bascules.nom` n'est plus une liste fermee de noms mais un motif** (`[a-z0-9][a-z0-9_.-]*`). Raison : douze migrations ajoutent chacune leur nom, et SQLite ne modifie pas un `CHECK` — `CREATE TABLE IF NOT EXISTS` ne touche pas une table en place, donc une base ouverte avant ce changement refusait `reseaux-file` en `CHECK constraint failed`. `_reparer_bascules` renomme, repose le schema, recopie les lignes, jette l'ancienne ; renommage et recopie en deux temps, l'ensemble idempotent (une coupure laisse `bascules_avant`, que l'ouverture suivante termine). - **`_infra/etat-service.py`** : `GET /reseaux`, `POST /reseaux/remplacer`. - **`etat_client.py`** : `reseaux()`, `reseaux_remplacer()`, `en_service(nom)`, `basculer reseaux-file [--essai]`, `revenir reseaux-file`, `reseaux <fichier>` (ecriture du plan dans la base), `en-service <nom>`. Le chemin se regle par `$RESEAUX_FILE` (defaut `/opt/studio/reseaux-file.json`). **Pas de verrou de montage** pour ce fichier : il n'a rien a voir avec le montage, et les montages tournent en continu — l'attendre aurait rendu la bascule impossible. - **`_tableau/collecte.py`** : l'onglet Reseaux lit `GET /reseaux` des que la bascule est posee, sinon le fichier comme avant. Le 132 n'a pas `etat_client.py` (`deploy-132.sh` ne livre que `_tableau/` et `jetons.py`) : l'appel se fait en `urllib`, comme `serveur_depenses.py`. Un banc ne parle jamais au service de production : hors de `/opt/studio`, il faut `STUDIO_ETAT_URL`. - **`_reseaux/pousser-tableau.sh`** : quand la bascule est posee, le plan entre dans la base (`etat_client.py reseaux`) et le JSON n'est plus pousse au 132. Service injoignable : `en-service` sort en 1 en le disant, et le script retombe sur le chemin d'avant. ## Criteres d'acceptation de la carte - [x] la table `reseaux_file` existe et `bascules.nom='reseaux-file'` est possible - [x] `basculer reseaux-file --essai` sort en 0 - [x] apres `basculer reseaux-file`, l'ancien JSON est renomme en `.bak-sqlite-YYYY-MM-DD` - [x] `revenir reseaux-file` restaure le fichier (l'etat en vigueur, dans la forme qu'ecrivent les producteurs de `_reseaux/`) ## Preuves - `controle/test_etat_partage.py` : **TOUT PASSE**, dont `ok 8a` (essai IDENTIQUES, fichier absent et formes refusees sans rien toucher, bascule avec `.bak-sqlite`, base identique au fichier, ecriture dans la base, retour arriere, re-bascule) et `ok 8b` (une base d'avant le 2026-10-14 accepte le nouveau nom). - `_tableau/test_collecte.py` : OK (la file vient du service une fois basculee, et le refus est dit). - `_tableau/lancer-tests.py` : sortie en commentaire de la carte. - `_tableau/rust` : `cargo test --release --locked` vert (10 binaires, 0 echec), `cargo build --release --locked` sans avertissement. ## Limites, dites - Les producteurs du plan (`_reseaux/preparer-file.py`, `marquer.py`, `tiktok-web.py`) ecrivent toujours `_reseaux/file.json` : c'est la copie `reseaux-file.json` que la carte demande de migrer. Le chemin d'ecriture vers la base passe par `pousser-tableau.sh`. - `sorties` et `file_montage` ne sont pas touches. - **Aucune route `/api/...` du service Rust n'est touchee** : le front Svelte n'a rien a changer. ## Hotspot `etat_partage.sql`, `etat_partage.py` et `etat_client.py` sont touches par les douze cartes de migration en cours, dont `hermes/migration-atelier-sqlite` (t_56665067) qui tourne en meme temps : un rebase sur ces trois fichiers est probable pour la seconde fusion.
La file des réseaux passe dans la base du service d'état (bascule reseaux-file)
All checks were successful
Tests du tableau (Rust + Svelte) / Rust (_tableau/rust) (push) Successful in 21s
Tests du tableau (Rust + Svelte) / Front Svelte (_tableau/front) (push) Successful in 12s
Tests du tableau (Rust + Svelte) / Rust (_tableau/rust) (pull_request) Successful in 24s
Tests du tableau (Rust + Svelte) / Front Svelte (_tableau/front) (pull_request) Successful in 12s
2804dd85d7
Cause : `reseaux-file.json` était le dernier état lu par le tableau qui vivait encore
dans un fichier — lu par `collecte.py`, recopié par `_reseaux/pousser-tableau.sh`, sans
transaction, sans contrainte, et sans qu'on puisse prouver ce que le tableau avait lu.

Remède : table `reseaux_file` (une ligne par entrée, `rang` pour garder l'ordre du
fichier, un champ par colonne, `quand` refusé s'il n'existe pas au calendrier), routes
`GET /reseaux` et `POST /reseaux/remplacer`, `basculer reseaux-file [--essai]` et
`revenir reseaux-file` sur la recette de STUD-1107 (comparaison avant bascule, ancien
gardé en `.bak-sqlite-<date>`, retour qui rend l'état en vigueur dans la forme des
producteurs de `_reseaux/`), lecture depuis la base dès que la bascule est posée, et
`bascules.nom` qui passe d'une liste fermée de noms à un motif — `_reparer_bascules`
refait la table d'une base ouverte avant ce changement, sinon l'insertion sortait en
`CHECK constraint failed`.

Banc : `controle/test_etat_partage.py` (ok 8a et 8b : essai, formes refusées, bascule,
`.bak-sqlite`, écriture dans la base, retour arrière, re-bascule, base d'avant le
2026-10-14) et le cas de `_tableau/test_collecte.py` qui lit la file du service.
hermes-bot force-pushed hermes/migration-reseaux-sqlite from 2804dd85d7
All checks were successful
Tests du tableau (Rust + Svelte) / Rust (_tableau/rust) (push) Successful in 21s
Tests du tableau (Rust + Svelte) / Front Svelte (_tableau/front) (push) Successful in 12s
Tests du tableau (Rust + Svelte) / Rust (_tableau/rust) (pull_request) Successful in 24s
Tests du tableau (Rust + Svelte) / Front Svelte (_tableau/front) (pull_request) Successful in 12s
to 0edc0c7dcc
Some checks failed
Tests du tableau (Rust + Svelte) / Rust (_tableau/rust) (push) Successful in 21s
Tests du tableau (Rust + Svelte) / Front Svelte (_tableau/front) (push) Failing after 11s
Tests du tableau (Rust + Svelte) / Rust (_tableau/rust) (pull_request) Successful in 25s
Tests du tableau (Rust + Svelte) / Front Svelte (_tableau/front) (pull_request) Failing after 12s
2026-10-15 00:03:45 +02:00
Compare
Collaborator

fusion-auto : pas de fusion, la CI est rouge (Front Svelte). Le chef de l'atelier renvoie la carte à l'agent ; l'étiquette tombera d'elle-même une fois corrigé.

`fusion-auto` : pas de fusion, la CI est rouge (Front Svelte). Le chef de l'atelier renvoie la carte à l'agent ; l'étiquette tombera d'elle-même une fois corrigé.
Collaborator

fusion-auto : pas de fusion, la PR est en conflit avec main : à rebaser. Le chef de l'atelier renvoie la carte à l'agent ; l'étiquette tombera d'elle-même une fois corrigé.

`fusion-auto` : pas de fusion, la PR est en conflit avec main : à rebaser. Le chef de l'atelier renvoie la carte à l'agent ; l'étiquette tombera d'elle-même une fois corrigé.
hermes-bot force-pushed hermes/migration-reseaux-sqlite from 0edc0c7dcc
Some checks failed
Tests du tableau (Rust + Svelte) / Rust (_tableau/rust) (push) Successful in 21s
Tests du tableau (Rust + Svelte) / Front Svelte (_tableau/front) (push) Failing after 11s
Tests du tableau (Rust + Svelte) / Rust (_tableau/rust) (pull_request) Successful in 25s
Tests du tableau (Rust + Svelte) / Front Svelte (_tableau/front) (pull_request) Failing after 12s
to 7659a64d5f
Some checks failed
Tests du tableau (Rust + Svelte) / Front Svelte (_tableau/front) (pull_request) Successful in 1m37s
Tests du tableau (Rust + Svelte) / Rust (_tableau/rust) (pull_request) Failing after 5m24s
Tests du tableau (Rust + Svelte) / Front Svelte (_tableau/front) (push) Successful in 1m34s
Tests du tableau (Rust + Svelte) / Rust (_tableau/rust) (push) Failing after 4m8s
2026-10-15 10:36:32 +02:00
Compare
Collaborator

fusion-auto : pas de fusion, la CI est rouge (Rust). Le chef de l'atelier renvoie la carte à l'agent ; l'étiquette tombera d'elle-même une fois corrigé.

`fusion-auto` : pas de fusion, la CI est rouge (Rust). Le chef de l'atelier renvoie la carte à l'agent ; l'étiquette tombera d'elle-même une fois corrigé.
hermes-bot force-pushed hermes/migration-reseaux-sqlite from 7659a64d5f
Some checks failed
Tests du tableau (Rust + Svelte) / Front Svelte (_tableau/front) (pull_request) Successful in 1m37s
Tests du tableau (Rust + Svelte) / Rust (_tableau/rust) (pull_request) Failing after 5m24s
Tests du tableau (Rust + Svelte) / Front Svelte (_tableau/front) (push) Successful in 1m34s
Tests du tableau (Rust + Svelte) / Rust (_tableau/rust) (push) Failing after 4m8s
to 004d5865f6
Some checks failed
Tests du tableau (Rust + Svelte) / Front Svelte (_tableau/front) (push) Successful in 1m57s
Tests du tableau (Rust + Svelte) / Front Svelte (_tableau/front) (pull_request) Successful in 1m36s
Tests du tableau (Rust + Svelte) / Rust (_tableau/rust) (push) Failing after 9m40s
Tests du tableau (Rust + Svelte) / Rust (_tableau/rust) (pull_request) Successful in 9m23s
2026-10-15 10:50:44 +02:00
Compare
hermes-bot force-pushed hermes/migration-reseaux-sqlite from 004d5865f6
Some checks failed
Tests du tableau (Rust + Svelte) / Front Svelte (_tableau/front) (push) Successful in 1m57s
Tests du tableau (Rust + Svelte) / Front Svelte (_tableau/front) (pull_request) Successful in 1m36s
Tests du tableau (Rust + Svelte) / Rust (_tableau/rust) (push) Failing after 9m40s
Tests du tableau (Rust + Svelte) / Rust (_tableau/rust) (pull_request) Successful in 9m23s
to ab9835ca88
All checks were successful
Tests du tableau (Rust + Svelte) / Front Svelte (_tableau/front) (push) Successful in 1m39s
Tests du tableau (Rust + Svelte) / Front Svelte (_tableau/front) (pull_request) Successful in 1m32s
Tests du tableau (Rust + Svelte) / Rust (_tableau/rust) (push) Successful in 9m43s
Tests du tableau (Rust + Svelte) / Rust (_tableau/rust) (pull_request) Successful in 9m17s
2026-10-15 11:02:01 +02:00
Compare
hermes-fusion deleted branch hermes/migration-reseaux-sqlite 2026-10-15 11:30:03 +02:00
Collaborator

Fusionnée automatiquement par fusion-auto (forge) : CI verte (Rust et Front Svelte), PR relue (étiquette relu), sans conflit.

Fusionnée automatiquement par `fusion-auto` (forge) : CI verte (Rust et Front Svelte), PR relue (étiquette `relu`), sans conflit.
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
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
foXaCe/studio!1682
No description provided.