


Modifier une API Go et une SPA React en changeant d'abord la spécification OpenAPI
Pour un dépôt où un backend Go et une SPA React partagent une spécification OpenAPI. Modifie la spécification puis régénère le code sans retoucher le généré, suit des règles pour réglages, erreurs, sessions, téléchargements et mises à jour, et teste avant de rendre compte.
Pour utiliser ces règles d'IA
## Prendre la spécification OpenAPI comme source de vérité et séparer le rôle de chaque couche
- Traite la spécification OpenAPI comme la source de vérité pour les routes, les schémas de request et response et les modèles partagés.
- Maintiens le backend Go et la SPA React compilables séparément pendant le développement.
- En production, préfère incorporer la SPA compilée dans le binaire du backend et servir l’API et l’UI depuis la même origine.
- Utilise le serveur de développement uniquement comme proxy pratique ; ne laisse pas les ports ou hôtes propres au développement s’infiltrer dans le code de production.
- Préserve des responsabilités claires : la couche API possède le transport, les services le comportement métier, les stores la persistance et le frontend la présentation.
- Étends les contrats existants avant d’inventer des routes, stores de configuration, canaux d’événements ou modèles d’état parallèles.
- N’ajoute aucun sous-système explicitement reporté sans exigence délimitée et décision architecturale.
- Lorsque la documentation et l’implémentation divergent, arrête la modification concernée et résous d’abord le conflit entre sources de vérité.
## Modifier la spécification et régénérer le code au lieu de retoucher les fichiers générés
1. Examine la spécification, les interfaces générées, l’implémentation, les tests et la documentation opérationnelle pertinente.
2. Modifie la source autoritative : les fichiers OpenAPI pour la forme de l’API, les structures de configuration pour les réglages et les catalogues de messages pour les textes de l’UI.
3. Régénère les artefacts du backend et du frontend avec les commandes du dépôt.
4. Implémente l’interface générée et actualise uniquement les services et wrappers d’UI directement concernés.
5. Exécute le formatage, l’analyse statique, des tests ciblés et la plus petite vérification d’exécution pertinente.
6. Examine les diffs générés pour confirmer que la spécification a produit le contrat prévu.
- Ne modifie jamais manuellement les fichiers générés ; corrige plutôt la spécification ou la configuration du générateur.
- N’enregistre jamais une route improvisée qui contourne l’interface de serveur générée.
- Maintiens les identifiants d’opération uniques et stables, car ils deviennent des noms de méthodes générées.
## Regrouper les schémas partagés au même endroit et aligner les types générés sur l'API
- Sépare les définitions de chemins par domaine tout en conservant les schémas, paramètres et responses partagés dans une section components canonique unique.
- Réutilise les références partagées au lieu de dupliquer des schémas presque identiques entre les fichiers de chemins.
- Préserve les mappages d’import et les contrôles d’élagage propres au générateur, nécessaires aux références entre fichiers.
- Lorsqu’un schéma reflète un type d’une bibliothèque upstream, synchronise le mappage machine et les propriétés JSON.
- Déclare chaque champ sérialisé et marque comme required chaque champ toujours présent pour les consommateurs autres que Go.
- Représente les références nullable dans la forme exigée par la version OpenAPI et le générateur, puis teste le résultat généré.
- Génère les types du frontend à partir du document d’API réellement servi par le backend lorsque la fidélité d’exécution importe.
- Committe les types d’API générés lorsque la politique du dépôt utilise leurs diffs comme preuve d’examen du contrat.
- Garde les clients API derrière des wrappers de domaine afin que les composants ne dépendent pas des détails du transport.
## Renvoyer des erreurs structurées sans divulguer le texte des erreurs internes
- Implémente les endpoints par l’interface de serveur générée et regroupe les méthodes de handler par domaine.
- Utilise un seul helper partagé pour les responses JSON et un classificateur d’erreurs central.
- Renvoie des erreurs structurées avec des codes machine stables, un type d’affichage, des champs facultatifs sûrs et un identifiant de request.
- Ne copie jamais le texte brut d’une erreur interne ou upstream dans une response destinée au client.
- Place les détails de validation de champs dans une map dédiée et réserve une clé générale aux échecs non liés à un champ.
- Convertis les échecs upstream en identifiants de motif stables ; conserve les bodies bruts uniquement dans des logs protégés.
- N’utilise des erreurs typées visibles par l’utilisateur que lorsque le texte dynamique est volontairement sûr à afficher.
- Ne construis pas d’enveloppe d’erreur du protocole en dehors du classificateur.
- Renvoie des codes d’état et des erreurs JSON au lieu d’utiliser des panics pour contrôler le flux.
- Traite la récupération des panics comme un filet de sécurité structuré et journalisé, non comme un comportement normal.
## Définir chaque réglage une seule fois et indiquer ceux qui exigent un redémarrage
- Définis les réglages une seule fois dans des structures de configuration typées ; dérive-en les valeurs par défaut, la validation, les métadonnées de schéma et les clés d’environnement.
- Applique toujours la même priorité : valeurs par défaut, fichier de réglages, puis remplacements d’environnement.
- Ne persiste que les valeurs différentes des valeurs par défaut intégrées.
- Pour chaque nouveau réglage, définis sa valeur par défaut, sa validation, sa catégorie d’UI, sa sensibilité, sa visibilité et son comportement de redémarrage.
- Un réglage rechargeable à chaud doit avoir un consommateur actif ou un hook de rechargement ; sinon, marque-le comme nécessitant un redémarrage.
- Les valeurs nécessitant un redémarrage peuvent être persistées immédiatement, mais doivent rester figées dans la vue d’exécution effective jusqu’au redémarrage.
- Masque les valeurs sensibles dans les responses de l’API et traite les placeholders masqués comme no-op lors d’une actualisation.
- Maintiens les réglages réservés au programme en read-only via l’API d’exécution et exclus les réglages cachés du schéma d’UI réfléchi.
- Exécute les mêmes validateurs au démarrage et avant la persistance pour qu’une configuration enregistrée ne casse pas le prochain démarrage.
- Écris les réglages de façon atomique et ancre les chemins relatifs gérés à une racine de données stable, non au répertoire de lancement.
## Garder un seul format de logs et arrêter le serveur sans laisser de travail en cours
- Utilise des logs structurés avec un schéma unique pour les requests HTTP, événements de cycle de vie et workers en arrière-plan.
- Attache les champs et erreurs du handler au log de la request courante au lieu d’émettre des événements en double par request.
- Maintiens les logs du backend dans une seule langue opérationnelle ; la localisation de l’UI appartient au frontend.
- Préserve l’ordre du middleware lorsque les ID de request, adresses réelles des clients, logs des requests et récupération des panics en dépendent.
- Place tout nouveau middleware dans la limite de récupération, sauf s’il doit modifier des champs avant le début des logs de requests.
- Lors de l’arrêt, ferme les abonnés aux événements persistants avant de drainer le serveur HTTP.
- Donne aux requests en cours un délai de drainage limité et définis explicitement le comportement à son expiration.
- Lors d’un redémarrage, termine le nettoyage des services avant de remplacer ou de générer le processus.
- Fais revenir les handlers de streaming lors de la fermeture du hub ou de l’annulation de la request.
- Enregistre chaque worker en arrière-plan dans la même séquence d’arrêt afin de ne laisser aucun travail orphelin.
## Utiliser des clés de requête stables et vider le cache quand l'utilisateur change
- Rends explicite l’ordre des providers lorsque les suivants dépendent de contextes de query, locale, authentification ou événements.
- Expose des factories d’options de query depuis les modules de features et garde les appels API bruts dans des wrappers de domaine.
- Utilise des clés de query stables qui incluent chaque paramètre modifiant l’identité.
- Préserve les anciennes données de liste uniquement lors de véritables changements de page ; abandonne-les lorsque changent les filtres, utilisateurs, onglets ou l’identité de recherche.
- Vide les caches propres au compte lorsque la session authentifiée change.
- Centralise les mises à jour optimistes, snapshots de rollback et invalidations afin que chaque copie en cache d’une entité reste cohérente.
- Traite les événements serveur comme des signaux de refresh ; l’état autoritatif provient toujours des queries ou endpoints d’état.
- Lis les fonctions de messages localisés à travers un contexte réactif dans les chemins de rendu.
- Mappe les clés de traduction dynamiques au moyen de résolveurs statiques explicites et conserve une forme de placeholder identique entre locales.
- Garde les libellés de configuration lisibles par les humains dans les catalogues du frontend plutôt que dans les schémas du backend.
## Stocker la session à part et ne pas déconnecter l'utilisateur pour une panne passagère
- Stocke les identifiants de session dans un seul fichier d’état dédié aux permissions restrictives ; ne les mélange jamais aux réglages généraux.
- Traite l’identifiant de refresh comme autorité de session et les identifiants d’accès de courte durée comme remplaçables.
- Renouvelle proactivement à l’approche de l’expiration et une fois de manière réactive après un échec d’authentification, avec coordination single-flight.
- Préserve la session lors des échecs transitoires ; efface-la uniquement après confirmation d’un rejet permanent.
- Maintiens les vérificateurs d’autorisation à durée courte, capacité limitée et usage unique.
- Valide les valeurs de callback collées avant de les envoyer upstream et renvoie des erreurs localisées et exploitables.
- Retire les identifiants des résultats de détection de proxy et maintiens cette détection en read-only.
- Protège les écritures d’onboarding non authentifié afin qu’elles ne puissent pas modifier les réglages après le login.
- Protège les endpoints de mutation sensibles par authentification et avec un header CSRF propre à l’application.
- N’expose jamais au client les bodies d’authentification upstream, les identifiants ni les erreurs de packages internes.
## Enregistrer les téléchargements via des fichiers temporaires et ne jamais effacer un fichier que l'app n'a pas créé
- Fais du job la limite de transaction et persiste atomiquement chaque transition d’état significative.
- Envoie les progressions très fréquentes par événements plutôt que de réécrire l’état persistant à chaque tick.
- Écris les payloads dans des fichiers temporaires aux noms uniques et renomme-les seulement après réussite ; retire les fichiers partiels lors d’une annulation ou d’un échec.
- Ne retente que les échecs pouvant l’être avec un backoff exponentiel limité.
- Note si l’application a créé chaque fichier final avant le nettoyage ; ne retire jamais un chemin en te fondant uniquement sur son nom attendu.
- Résous les collisions avec le contenu du disque et les réservations en cours, selon une stratégie de fallback limitée.
- Résous de nouveau les chemins pendant la récupération après redémarrage, sauf si un payload terminé possède déjà sa destination.
- Analyse les modèles de chemins au démarrage et valide-les de nouveau avant d’accepter des changements de configuration.
- Assainis chaque segment de chemin, préserve les racines explicites, limite les noms de fichiers en octets et compte en caractères la troncature visible.
- Fige les décisions de conversion et de nommage par job afin que les réglages rechargés à chaud ne modifient pas les travaux en cours.
## Renvoyer les événements manqués à la reconnexion, sinon resynchroniser
- Maintiens l’état persistant comme autoritatif et traite les événements comme une optimisation.
- Donne aux événements des ID, timestamps, topics, types et payloads reconstructibles stables.
- Lors d’une reconnexion, rejoue les événements postérieurs au dernier ID connu du client si le buffer les contient encore.
- Si le rejeu est impossible, émet un seul événement de resynchronisation et impose aux clients de récupérer à nouveau l’état autoritatif.
- Utilise des keepalives pour empêcher les intermédiaires de fermer silencieusement les streams inactifs.
- Seuls les événements de niveau job définissent l’état global du job ; les événements de task actualisent la task sans recalculer les règles détenues par le serveur.
- Actualise les vues concernées après une reconnexion et après un signal de resynchronisation.
- Limite la fréquence des notifications de progression, mais contourne cette limite pour les transitions terminales et l’actualisation finale de progression.
- Maintiens le transport d’événements indépendant des gestionnaires de domaine grâce à une petite interface publisher.
## Limiter les cibles du proxy et vérifier la signature avant de mettre à jour l'app
- Autorise les cibles de proxy selon une politique d’hôtes exacte et vérifie chaque redirection pour empêcher la falsification de requests côté serveur.
- Partage les échecs simultanés de cache pour une même ressource et refuse les bodies trop volumineux avant de les mettre en cache.
- Traite le système de fichiers comme vérité du cache ; réconcilie sa taille périodiquement et après les écritures en expulsant d’abord les accès les plus anciens.
- Maintiens le stockage du cache déplaçable et séparé de l’état durable de l’utilisateur.
- Injecte les emplacements du feed de mises à jour et les clés de signature fiables au build de release ; refuse toute mise à jour si le matériel de confiance manque.
- Vérifie un manifeste signé avant de faire confiance à toute version, URL, checksum ou champ de notes de release.
- Vérifie l’archive téléchargée par rapport au manifeste signé avant de remplacer un binaire.
- Exécute l’application des mises à jour en single-flight, refuse-la dans les builds de développement et exige authentification et protection CSRF.
- Résous l’exécutable de remplacement de façon déterministe et refuse les archives ambiguës.
- Draine les services et redémarre uniquement après préparation du remplacement vérifié.
## Tester l'app en marche et s'arrêter avant une publication ou un changement en production
- Parcours la génération, l’implémentation, les tests ciblés et la vérification directe d’exécution sans ignorer une étape en échec.
- Vérifie l’endpoint de santé, le document OpenAPI servi, le comportement de l’API concernée et le chemin d’UI directement touché.
- Exécute le formatage, l’analyse statique, les tests du backend sensibles aux conditions de concurrence, les contrôles du frontend et les builds de production lorsque la modification les concerne.
- Confirme par des tests ciblés la persistance atomique, la sémantique de redémarrage, le masquage des secrets et la non-divulgation des erreurs.
- Pour les travaux de release, valide le versionnage sémantique strict, la continuité du feed signé, les checksums et la résolution des archives par plateforme.
- Maintiens les features reportées comme telles, sauf si l’exigence actuelle les inclut explicitement dans le périmètre.
- Évite les refactorisations sans rapport, les stores d’état parallèles, les systèmes d’erreurs dupliqués et l’infrastructure spéculative.
- Arrête-toi avant une release externe, une migration destructrice, un changement d’identifiants ou une mutation de production sans autorisation explicite.
- Rapporte ce qui a changé, ce qui a été vérifié, ce qui reste hors périmètre et tout conflit de contrat non résolu.
