API Rust — Rythme et Budget : /api/rythme et /api/budget en parité avec Python (t_3b3e3701) #1660
Loading…
Reference in a new issue
No description provided.
Delete branch "hermes/api-rythme-budget-rust"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Mandat : carte t_3b3e3701 (chantier « tableau 132 : 100 % Svelte et 100 % Rust », carte maître t_abdd8136).
Deux routes NOUVELLES :
GET /api/rythmeetGET /api/budget. Le front en dépend — la carte Svelte t_e1c8c087 (replis de l'Atelier) les lira : le chef doit prévenirsvelte. Rien n'est recalculé côté front : les textes et les montants sortent écrits comme l'onglet Python les écrit.Contrat
GET /api/rythme→{"vide", "message", "t", "sections"}. Une section par entrée du rapport,genreh(titre),p(note) out(tableautete/lignes) — ungenreinconnu est un tableau, comme la brancheelsede l'onglet. Les textes sont nettoyés des accents graves et des**et NON échappés (le front échappe).GET /api/budget→{"vide", "message", "t", "jour", "depense", "plafond", "plafond_atteint", "solde", "solde_t", "episodes": [{episode, depense, budget, generations, etat}], "arrets": [{date, raison}]}. Montants écrits au centime (« 3.20 $ »),etatdans l'ordre de l'onglet (« budget atteint », « seconde génération refusée », « forme à valider », sinon vide),arrets= les huit derniers, du plus récent au plus ancien.{"vide": true, "message": …}(la phrase de l'onglet, ses balises retirées) et la route répond 200 — le contrôle des routes derust/deployer.shexige 200. GET seulement : un POST répond 405.SERVICE_RYTHME(défaut/opt/studio/rythme.json) etSERVICE_BUDGET(défaut/opt/studio/budget-runware.json), relus à chaque requête, rien en cache.Ce que la branche contient
_tableau/atelier_replis_donnees.py: les deux rubriques dans UN module de données (donnees_rythme,donnees_budget), la source de vérité du portage. Ce qu'elles partagent n'y existe qu'en une copie : la date d'un relevé, lestr()d'une valeur, et le montant d'onglet_budget._d(importé, pas recopié) — c'est ce que refusetest_garde_doublons.py.rust/service/src/replis/: un module, les deux routes, et leurs règles communes écrites une fois ; les deux lignes dans lematchdemain.rs.rust/service/tests/replis.rs+tests/fixtures/rythme/,tests/fixtures/budget/: huit entrées par rubrique (le relevé réel du dépôt, abîmé, absent, non-objet, arrondis au centime, douze arrêts, cinq états d'épisode)._tableau/test_rythme_parite.py,_tableau/test_budget_parite.py: les bancs qui garantissent que le JSON doré est la sortie de Python, et qui reconstruisent le HTML de la rubrique à partir du JSON pour exiger qu'il soit identique à celui de l'onglet._tableau/LXC-132.md: la section des deux routes..sveltetouché ; les deux<details>Python restent en place jusqu'à la bascule du front ; le LXC 130 reste éteint.Preuves (tête
cfc5f1c9)cargo test --release --locked: code 0, 56 tests, dont 4 neufs (tests/replis.rs), 0 avertissement.cargo build --release --locked: code 0.test_rythme_parite.pyettest_budget_parite.pycode 0 (8 entrées chacun, « HTML identique ») ;test_onglet_budget.pycode 0 ;test_100_svelte_rust.pycode 0 (épreuve passée : Calendrier forcé en Python → verdict 1).test_garde_doublons.py,test_garde_couches.py,test_garde_plafond.py— rouges avec la première version du portage (_texteet_dateen double,_drecopié), verts après le correctif du 4e commit. C'est un rouge de cette branche, pas d'avant : les trois sont verts surorigin/main(1465663e).GET /api/rythmeetGET /api/budget→ 200, corps identique au JSON doré de Python ;POST /api/rythme→ 405 ; relevé absent → le contrat{"vide": true, …}.Non mesuré
Le
curldes deux routes sur le 132 (aucun accès depuis cette carte : elles y arrivent par le déploiement automatique après fusion) et l'onglet au navigateur (porteur : la carte Svelte t_e1c8c087).Bancs du tableau : 153 verts, 9 rouges — tous pré-existants, mesurés sur
origin/main(1465663e) dans un arbre de travail séparé, sans cette branche :test_accueil_taches,test_atelier_a_valider,test_atelier_actions_uniques,test_deploy_132,test_images_apercu,test_navigateur_blocage,test_navigateur_prevoir,test_navigateur_question,test_navigateur_retour.Cause. Les deux rubriques repliées du panneau de l'Atelier n'avaient aucune route : leur contenu ne pouvait venir que du HTML rendu par Python, et le front n'avait rien à lire. Remède. `rust/service/src/replis/` porte les deux routes (`replis::rythme::api`, `replis::budget::api`), à l'identique de `rythme_donnees.donnees_rythme` et `budget_donnees.donnees_budget` ; `main.rs` les sert en GET sur `/api/rythme` et `/api/budget`, avec `SERVICE_RYTHME` (défaut `/opt/studio/rythme.json`) et `SERVICE_BUDGET` (défaut `/opt/studio/budget-runware.json`) — les fichiers que `pousser-rythme.sh` et `pousser-budget.sh` posent à côté de la page. Le relevé est relu à chaque requête, rien n'est mis en cache ; un relevé absent, illisible ou qui n'est pas un objet JSON rend `{"vide": true, "message": …}` en 200, comme l'onglet écrit sa phrase dans la page. Le banc `tests/replis.rs` compare les deux sorties sur les mêmes fichiers d'entrée que le banc Python (`tests/fixtures/rythme/`, `tests/fixtures/budget/`) : huit entrées par rubrique, dont le relevé réel du dépôt, le fichier abîmé, le fichier absent et les arrondis au centime. Il éprouve aussi le contrat du relevé absent et la relecture à chaque appel.Cause. La doc du 132 décrit chaque route portée en Rust (Top vidéos, Analytique, Vidéos) ; les deux replis de l'Atelier n'y étaient pas, et le contrat de leur JSON n'était écrit nulle part. Remède. Une section qui dit les entrées (`SERVICE_RYTHME`, `SERVICE_BUDGET`), le corps des deux routes, le cas du relevé absent (200, `{"vide": true, …}`), les bancs de parité — dont la reconstruction du HTML depuis le JSON — et ce qui reste Python jusqu'à la carte Svelte t_e1c8c087.Fusionnée automatiquement par
fusion-auto(forge) : CI verte (Rust et Front Svelte), PR relue (étiquetterelu), sans conflit.