Skip to content

Story 32-5a : les tables MCP (clés, réglages du serveur) et leur place dans la sauvegarde (refs #723, refs #722) - #751

Merged
guycorbaz merged 29 commits into
mainfrom
story/32-5
Oct 25, 2026
Merged

guycorbaz merged 29 commits into
mainfrom
story/32-5

Conversation

@guycorbaz

Copy link
Copy Markdown
Owner

Première partie de la Story 32-5, découpée en quatre parties (a → b → d → c), qui partagent une seule fiche. Celle-ci, 32-5-cles-et-reglages-mcp.md, est jointe à la PR.

Ce que fait la 32-5a

  • Migration non breaking 20261025000001_mcp_keys_and_server_settings (CREATE TABLE) :
    • mcp_keys : condensat, portées en JSON, validation avant envoi required/exempt par clé (décision Q12), révocation, expiration ;
    • mcp_server_settings : serveur désactivé par défaut, filtre d'adresse, plages admises.
    • Les CHECK ont été éprouvés sur MariaDB 10.11 : REGEXP pour le nom, utf8mb4_nopad_bin pour send_validation.
    • La ligne de migrations.sha384 n'a été inscrite qu'ensuite (P8).
  • Sauvegarde : les deux tables entrent au .keshbackup, et l'inventaire passe de 39 à 41 tables. Une clé restaurée revient dans l'état où elle était à la sauvegarde.
  • Lecture tolérante des portées (C-32-5-37) : une portée inconnue, par exemple venue d'une version future, est ignorée avec un avertissement au journal, qui nomme l'id de la clé et jamais son condensat. Une clé qui n'a plus aucune portée connue reste listable et révocable, mais ne peut plus s'authentifier. L'écriture et les entrées de l'API restent strictes.
  • P7 :
    • ajouter des tables referme la fenêtre de rejeu, si bien que le rejeu du lettrage 20261010000001 passe à RETIRED_BACKFILLS, avec une exemption « Hors fenêtre » ;
    • les justifications devenues fausses sont réécrites ;
    • le test de la fixture 0.14.0 devient un test de refus : 400, et rien n'est écrit.
  • P5, P6 : l'audit d'idempotence passe à 84 migrations (10 + 74 + 0), et les sites positionnels sont recomptés.
  • Manuels :
    • restauration et compatibilité : une sauvegarde ne se réimporte que dans une version qui porte les mêmes tables (décision Q4, « à documenter au cas où ») ;
    • rappel de prendre une sauvegarde complète juste après la mise à jour ;
    • § Reprises corrigé ;
    • PDF régénérés.
  • CHANGELOG : rubrique ### Modifié.

Validation de la fiche : huit passes, terminée au plafond selon la règle du 2026-10-24.

  • Trend : 2 HIGH et 8 MEDIUM en P1, puis 0 HIGH et 1 à 2 MEDIUM de la P3 à la P8.
  • Six formes recyclées du même défaut sur la restauration d'une sauvegarde ancienne ont été retirées (C-32-5-28).
  • Les points restants ont été traités à l'étape 0 du développement, ligne lue citée au Change Log.

Revue de code

Passe Modèle B E A
P1 Sonnet ×3 0/0/0/4 0/0/1/4 0/0/0/3
P2 ciblée Opus 0/0/1/4
P3 ciblée Sonnet 0/0/0/0

Mutations : 16 jouées, 16 tuées.

Gates

  • Dernier commit de code 88eae2b2 :
    • gate complet 4051/4051 (7 ignorés) ;
    • E2E 314 passés, 8 échecs : les 7 KF-029, plus la KF-052, rejouée seule au vert.
  • État fusionné avec main (32-4b comprise) : gate complet 4062/4062.

Issues ouvertes en route

Liée à #723 et #722. #722 reste ouverte : _kesh_backup_schedule reste hors de la sauvegarde, et les prompts relèvent de la 32-10a.

🤖 Generated with Claude Code

guycorbaz and others added 29 commits October 25, 2026 00:25
…base (refs #723, refs #722)

Fiche 32-5-cles-et-reglages-mcp.md : une fiche, trois parties proposées
en clés distinctes — 32-5a tables et sauvegarde, 32-5b la clé MCP comme
principal, 32-5c routes de gestion (onze modules relevés au code, au-delà
du plafond de cinq). 29 AC, 19 tâches, 20 mutations. Registre
epic-32-choix-autonomes-325.md (C-32-5-1 à 21) ; prompt de validation P1
(Sonnet, lentilles R et F) ; sprint-status : 32-5 ready-for-dev.

Constat du relevé : la création de mcp_keys referme la fenêtre de P7 —
le rejeu 20261010000001 se retire et quatre tests d'import passent au
registre retiré ; la conservation des clés à la remise à zéro étend la
règle des principaux orphelins.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… sprint (refs #723)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…723, refs #722)

Validation P1 (Sonnet ×2) : R 0/2/3/7, F 0/0/5/4. HIGH : ligne de
migrations.sha384 dans la PR de la migration (R1) ; services_motif.rs
énumère les deux portées et se réécrit (R2 = F1). MEDIUM : test de la
remise à zéro dans onboarding_audit_e2e.rs (R3), quatre consommateurs
d'OrphanPrincipals et tests à JSON strict (R4 = F3), justifications
d'exemption réécrites (R5), ac10_vi 5 → 6 (F2), le manuel corrigé par la
partie qui change le comportement (F4), orphelin MCP seul (F5).

Recompte : l'ancienne partie b passait à six modules ; elle se scinde en
32-5b (authentification, 3) et 32-5d (remise à zéro et réparation, 5).
Clés de sprint : 32-5b renommée, 32-5d ajoutée. 30 AC, 23 tâches,
22 mutations ; registre C-32-5-1 à 25 (#722 : cohérence écrite) ;
prompt de validation P2 (Opus, R et F).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…723, refs #722)

Validation P2 (Opus ×2) : R 0/0/3/7, F 0/1/4/10 (P1 : 2 HIGH, 8 MEDIUM →
P2 : 1 HIGH, 7 MEDIUM). HIGH : la procédure de restauration du manuel
(version « égale ou plus récente », format 1 restaurable) devient fausse
dès la 32-5a — réécrite, depuis une base vide (F1, R2). MEDIUM : la
fixture 0.14.0 devient le test du refus (F2, AC-a15) ; EMPTY_BEFORE_RESET
et populate (F3, 32-5a à cinq modules) ; § Reprises et son avertissement
(F4 = R4) ; une erreur de base n'est jamais un 401 (F5) ; sites manqués
du retrait de 20261010000001, dont le test d'ordre (R1) ; manuel
utilisateur en 32-5d (R3).

Ordre des parties imposé a → b → d → c. Recyclage déclaré : cinq findings
nés de la remédiation P1. Fichier d'epic : annotation datée de la puce Q4
(la décision de Guy inchangée), reports inscrits aux sections 32-6 et
32-7. 31 AC, 23 tâches, 23 mutations ; registre C-32-5-1 à 27 ; prompt de
validation P3 (Sonnet, R et F, sans gh, #722 recopié).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…723, refs #722)

Validation P3 (Sonnet ×2) : R 0/0/0/7, F 0/0/1/9. MEDIUM F1 :
ROLE_CLE_MCP ne règle que l'authentification ; la création est gardée par
require_admin_role, Role::Admin en dur. C-32-5-7, l'esquisse et le point 1
à Guy disent le vrai coût d'une ouverture au Comptable (une modification
de routage) ; la constante n'est pas branchée sur le handler.

LOW : compteurs d'admin_pat_denied_e2e, règle de la valeur pour P6, sept
« n'est PAS vide », lignes de l'audit d'idempotence, quatre sites
antérieurs à Q11, ContexteAcces, citations, ordre squash/sha384 après les
tests des CHECK, ExemptionBasis::Durable, versions sans l'assistant,
comptes relatifs de la 32-5b (la 32-4 la précède), mod common, 32-5b à
quatre modules (onze distincts), annotations du registre de sprint.

Remédiation sur la fiche seule : prompt de la passe ciblée P4 (regression
hunter, Opus).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…fiche (refs #723, refs #722)

Passe ciblée P4 (Opus, regression hunter) : 0/0/1/6. H1 (MEDIUM),
troisième forme recyclée de la procédure de restauration d'une
sauvegarde ancienne (R2 en P2, F6 en P3, H1 en P4) : retrait, décision de
l'orchestrateur (C-32-5-28). L'AC-a13 (1) et le manuel ne disent plus que
trois choses : mêmes tables ; l'image de la version qui a produit la
sauvegarde, sur une base vide, et le manuel de cette version publié à son
tag (lieu dit en mots : un gabarit d'URL raw ferait rougir G19) ; puis la
mise à jour. Point 7 à Guy et précision datée du fichier d'epic alignés.

LOW H2 à H7 : onze modules distincts, annotation de la 32-5b (4 modules),
doc-comment et généalogie d'admin_pat_denied_e2e, acces.rs:57-58, ligne
de 20261010000002 à l'audit d'idempotence, coût d'une ouverture au
Comptable sur les quatre routes des clés (39 → 35, (9, 26)).

Prompt de la passe ciblée P5 (regression hunter, Sonnet).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…fiche (refs #723, refs #722)

Passe ciblée P5 (Sonnet, regression hunter) : 0/0/1/4. P5-1 (MEDIUM) :
aucun PDF n'est joint aux releases (release.yml:161-165). L'AC-a13 (1),
C-32-5-28, la précision du fichier d'epic et le point 7 à Guy ne disent
plus que trois énoncés vérifiables : mêmes tables ; une sauvegarde plus
ancienne se restaure avec la version qui l'a produite, dont le manuel est
dans le dépôt au tag de cette version ; ensuite, on met à jour. Aucune
procédure, aucune section d'un manuel ancien ; la phrase fausse du manuel
(l. 2430) est tracée en #746, non corrigée ici.

LOW P5-3 à P5-5 : décompte du grep de l'entrée P4 annoté, état de la clé
32-5 au registre de sprint, redite retirée. Le prompt P6 désignera le
commit par son SHA.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…#723, refs #722)

Regression hunter, Opus, sur le seul commit de la remédiation P5, désigné
par son SHA (b750539) et non par un motif de git log. Passe 6 sur 8.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…fiche (refs #723, refs #722)

Passe ciblée P6 (Opus, regression hunter) : 0/0/2/1. Recyclage déclaré,
cinquième forme du défaut de la restauration d'une sauvegarde ancienne.

P6-1, par retrait : l'AC-a13 (5) ne fait plus nommer de version à
installer à l'étape 1 de « Restaurer sur une nouvelle machine » ; elle se
réduit à la règle des mêmes tables et renvoie à « Compatibilité ». Seule
l'AC-a13 (1) porte la phrase sur une sauvegarde plus ancienne ; point 7,
C-32-5-21, C-32-5-28 et la précision du fichier d'epic y renvoient.

P6-2, par rétablissement : « prendre une sauvegarde complète juste après
la mise à jour » redevient une phrase distincte du manuel et du CHANGELOG,
contrôlée au PDF ; l'entrée P5 qui le disait déplacé est annotée.

P6-3 : les occurrences datées de « base vide » sont annotées.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…#723, refs #722)

Regression hunter, Sonnet, sur le seul commit de la remédiation P6,
désigné par son SHA (2e0ea04), avec un axe qui relit toute la fiche et le
registre à la recherche d'une prescription restante pour une sauvegarde
ancienne. Passe 7 sur 8.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…fiche (refs #723, refs #722)

Passe ciblée P7 (Sonnet, regression hunter, axe sur toute la fiche) :
0/0/1/5. P7-1 (MEDIUM), sixième forme du même défaut — « format 2
(0.15.0 ou plus récente) » au manuel l. 2373 —, traité par classe :
l'AC-a13 (5) fait relire en entier « Restaurer sur une nouvelle machine »
et « Compatibilité », réécrire toute mention de format ou de version, et
fermer la liste par un grep sur le .tex et le PDF aplati, sorties citées
au Dev Agent Record ; AC-a14 et le contrôle du PDF reçoivent les motifs.

LOW : point 7 à Guy (P7-2), annotation de C-32-5-21 déplacée (P7-3),
précision datée P4 du fichier d'epic annotée sans nouvelle réécriture
(P7-4), en-tête (P7-5). P7-6 reporté à « À recontrôler à l'étape 0 ».

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#723, refs #722)

Regression hunter, Opus, sur le seul commit de la remédiation P7, désigné
par son SHA (3a57bbc). Passe 8 sur 8 : le prompt le dit, et demande pour
chaque finding s'il se corrige par une annotation ou doit être retiré ou
renvoyé à l'étape 0 du développement.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
, refs #722)

Passe ciblée P8 (Opus, regression hunter), dernière permise : 0/0/1/3.
Clôture au plafond selon la règle de Guy du 2026-10-24 : aucune
remédiation de fond ; P8-1 à P8-4 et user-manual.tex:1914 renvoyés au
§ « À recontrôler à l'étape 0 du développement », à corriger et déclarer
par l'agent de développement, ligne lue citée ; renvoi d'une ligne à T-a6.
Change Log : trend P1 à P8, six formes recyclées, retraits C-32-5-28.
sprint-status : 32-5 split, 32-5a à 32-5d ready-for-dev, annotées.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…pôts — Story 32-5a, T-a0 à T-a2 (refs #723, refs #722)

Migration 20261025000001 (non breaking, deux CREATE TABLE, aucune donnée
écrite) ; CHECK éprouvés à la main puis par mcp_keys_repository.rs. Deux
écarts au patron d'api_keys, constatés au test : REGEXP pour le nom (TRIM
ne retire pas une tabulation), comparaison utf8mb4_nopad_bin pour
send_validation (la collation _ci de la table acceptait 'Required').
Squash régénéré ; ligne de migrations.sha384 inscrite en dernier (P8).

Étape 0 : P8-2 et P8-4 annotés (fichier d'epic, registre, point 7).
L'inventaire de la sauvegarde suit en T-a3.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…rs export global — Story 32-5a, T-a3 (refs #723, refs #722)

TABLES_TO_TRUNCATE passe de 39 à 41 tables (mcp_keys à côté d'api_keys,
mcp_server_settings à côté de company_invoice_settings) ; TABLES_HORS_EXPORT
de neuf à onze, avec leur motif. L'aller-retour par HTTP rend les deux
tables colonne par colonne, et un serveur activé l'est après l'import
(hypothèse Q7). populate peuple les deux tables : la remise à zéro les
vide, EMPTY_BEFORE_RESET inchangée.

Gate ciblé : 128/128.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e se retire ; la sauvegarde 0.14.0 est refusée — Story 32-5a, T-a4 (refs #723, refs #722)

20261010000001 passe de POST_RESTORE_BACKFILLS (désormais vide) à
RETIRED_BACKFILLS, et entre à EXEMPT_MIGRATIONS (Durable, « Hors fenêtre
depuis 20261025000001 ») ; compteurs 8 -> 9 et 20 -> 21. Justifications de
20261010000002, 20261009000001, 20261011000001, 20261015000001 et
20260917000001 réécrites, commentaires de letterings.rs et des tests
alignés. Les quatre tests d'import du lettrage passent par replay_retired ;
le miroir du registre attend un rapport vide ; l'ordre de rejeu, cinq
entrées. ac10_la_sauvegarde_de_la_0_14_0_est_refusee : 400, rien d'écrit.

Gate ciblé : 89/89.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…025000001 — Story 32-5a, T-a5 (refs #723)

Ligne de la migration (tracked-by-sqlx), mentions des lignes de
20261010000001 (retirée du registre) et 20261010000002 (coût assumé sans
objet) ; en-tête et Total 84, partitions 10 / 74 / 0 recomptées. P6 :
total == 84, total - 50, frontière 34 inchangée.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…5a, T-a6 (refs #723, refs #722)

Manuel d'administration : Compatibilité (la règle des mêmes tables, la
0.16.0 refuse les sauvegardes de la 0.15.0 et d'avant, la phrase sur une
sauvegarde plus ancienne), avertissement distinct sur la sauvegarde
complète à prendre après la mise à jour, clés et réglages du serveur MCP
dans le fichier et dans l'avertissement « secret », réglage de la
sauvegarde automatique hors du fichier, § Reprises (plus aucune reprise
rejouée, recalcul des numéros de client et réparation #528 nommés,
avertissement réécrit), Restaurer sur une nouvelle machine (plus aucune
version nommée à l'étape 1), :1505 et Les pièces à l'import bornés à la
0.15.x. Manuel utilisateur : :3027 et :1914. PDF régénérés et contrôlés
aplatis. CHANGELOG [0.16.0] : ### Modifié créé.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…32-5-29 à 36, prompt de la revue P1 (refs #723, refs #722)

Dev Agent Record et entrée « Développement 32-5a » au Change Log : étape 0
(ligne lue citée), gate complet 4046/4046, frontend vert (1939 tests),
E2E 314 passés et 8 échecs attendus (7 KF-029 + KF-052, rejouée seule
verte) — l'E2E a tourné après une première commande refusée, montage
repris en commandes séparées sans suppression ; mutations 10/10 tuées.
Registre : huit choix, #747 et #748 cités. Clé 32-5a à review. Prompt
325a-review-prompt-p1.md (Sonnet, lentilles B, E, A).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… code P1 de la Story 32-5a (refs #723, refs #722)

E1 (MEDIUM), décision de l'orchestrateur, C-32-5-37 : StoredMcpScopes lit
la colonne scopes sans jamais échouer — portées connues gardées, le reste
mis de côté et journalisé par id de clé (jamais le condensat). Une ligne ne
fait plus échouer list_by_company ; une clé sans portée connue se liste et
se révoque, mais find_active_auth_by_key_hash ne la rend jamais
(McpKeyAuthRow.scopes reste un McpScopes non vide). L'écriture et
McpScopes::from_json restent stricts (Ma3).

LOW : E5 (ordre de list_by_company, frontière d'expiration ; assertions
« pas du json » resserrées), B4 (RESTRICT des deux FK vers companies),
E2 (la clé révoquée après l'export redevient active à l'import : test et
manuel), A2 (renvoi au paragraphe Compatibilité), A3 (forme normalisée trop
longue).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…constat B2 au registre, reports aux 32-5b et 32-5c (refs #723, refs #722)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…evue P1 de la 32-5a, propagation de C-32-5-37 (refs #723, refs #722)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…mpt de la passe P2 (refs #723, refs #722)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…de la casse et des espaces — revue de code P2 de la 32-5a, R1 et R3 (refs #723, refs #722)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…-5-37 (AC-a4, Dev Notes, C-32-5-3, Change Log), U+00A0 non éprouvé, R5 reporté à la 32-5b (refs #723, refs #722)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…mpt de la passe P3 (refs #723, refs #722)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…dernier commit de code, clé à done (refs #723, refs #722)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@guycorbaz
guycorbaz merged commit b723e3d into main Oct 25, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant