volontariapp-proto-contract-evolution
Modifier un contrat Protobuf de proto-registry (champ, message, enum, RPC) sans casser la compatibilité wire, puis suivre la cascade proto-registry, PR automatique dans npm-packages, publication, consommateurs. À utiliser avant toute édition d'un .proto.
- License 许可
- MIT
- 最近更新
- 2026-11-10
- Stars
- ★ 0
- Forks
- 0
01 前言 Front Matter
- name
- volontariapp-proto-contract-evolution
- tags
- [ "grpc", "protobuf", "buf", "stop-rule" ]
- type
- Playbook
- paths
- [ "proto-registry/buf.yaml", "proto-registry/buf.gen.yaml", "proto-registry/.github/workflows/**", "proto-registry/proto/**" ]
- title
- Proto Contract Evolution
- status
- stable
- sources
- [ { "id": "buf", "title": "buf.yaml (lint STANDARD, pas de section breaking)", "resource": "proto-registry/buf.yaml" }, { "id": "bufgen", "title": "buf.gen.yaml (ts_proto)", "resource": "proto-registry/buf.gen.yaml" }, { "id": "proto-ci", "title": "sync-to-npm.yml et emergency-reset.yml", "resource": "proto-registry/.github/workflows" }, { "id": "proto-sync", "title": "proto-sync.yml réutilisable (ci-tools)", "resource": "ci-tools/.github/workflows/proto-sync.yml" }, { "id": "contrats", "title": "Contrats et évolutions (numérotation, trou du champ 5)", "resource": "docs/stockage-fichiers/08-contrats-et-evolutions.md" } ]
- verified
- [ { "at": "2026-10-06T15:41:59Z", "by": "claude-code/claude-sonnet-5-5", "digest": "603980fa2fea4e5d" }, { "at": "2026-10-12T12:03:25Z", "by": "claude-code/agent", "digest": "603980fa2fea4e5d" }, { "at": "2026-10-19T08:45:16Z", "by": "human:victor", "digest": "935ad3f0ccce0f4e" }, { "at": "2026-10-30T10:33:27Z", "by": "claude-code/agent", "digest": "f8b99b4837ee3d04" }, { "at": "2026-11-08T11:15:19Z", "by": "claude-code/agent", "digest": "102e056ce670c3c9" } ]
- generated
- { "at": "2026-10-06T08:22:12Z", "by": "claude-code/claude-opus-5-5" }
- mesh_keys
- [ "analyze_grpc", "proto-registry", ".proto", "contracts" ]
- description
- Modifier un contrat Protobuf de proto-registry (champ, message, enum, RPC) sans casser la compatibilité wire, puis suivre la cascade proto-registry, PR automatique dans npm-packages, publication, consommateurs. À utiliser avant toute édition d'un .proto.
02 资源文件 4
- 参考文档index.md946 B
- 参考文档log.md2.0 KB
- 参考文档references/deprecation-playbook.md5.4 KB
- 参考文档references/lessons.md2.0 KB
03 SKILL.md 正文
Proto Contract Evolution & Cycle de Propagation gRPC
Dans Volontariapp, proto-registry est l'unique Source de Vérité (SSOT) de tous les contrats de communication inter-services synchrones (gRPC).
1. Avant de modifier un fichier .proto
- Identifier les consommateurs gRPC en mémoire (MCP Server) :
Ne fais pas de recherche plein texte manuelle. Utilise directement l'outil MCP
analyze_grpcpour localiser en $< 1\text{ms}$ le contrat, les clients dans l'API Gateway et les contrôleurs dans les microservices :analyze_grpc({ "target": "SignUp" }) analyze_grpc({ "target": "UserService" }) - Vérification de non-régression de compatibilité binaire :
Exécute toujours
buf lintetbuf breakingpar rapport au dernier commit demain:buf lint buf breaking --against '.git#branch=main'
2. Le Cycle de Propagation Automatique (proto-registry -> npm-packages)
flowchart TD
A["1. Modification dans proto-registry (.proto)"] --> B["2. Validation locale (buf lint)"]
B --> C["3. Merge sur main dans proto-registry"]
C --> D["4. CI : sync-to-npm.yml appelle proto-sync.yml de ci-tools"]
D --> E["5. Génération auto de PR dans npm-packages\n(@volontariapp/contracts & contracts-nest)"]
E --> F["6. Publication de la version par la CI de npm-packages"]
F --> G["7. Reprise : yarn up dans api-gateway & microservices"]
[!CAUTION]
🛑 RÈGLE BLOQUANTE DU STOP IMMÉDIAT SUR PROTO-REGISTRY
- Dès que tu as fini de modifier un fichier
.protodansproto-registry: TU T'ARRÊTES.- INTERDICTION FORMELLE d'aller toucher au code de
api-gatewayou des microservicesms-*en avance.- Pourquoi ? Parce que le code TypeScript n'est PAS compilé localement : il est généré automatiquement par la CI de
proto-registryqui crée une Pull Request dansnpm-packages!- Ce n'est qu'APRÈS le merge de
proto-registrysurmain, la génération de la PR dansnpm-packages, et la publication effective du nouveau@volontariapp/contractspar la CI que tu as le droit de mettre à jour les microservices consommateurs viayarn up.
3. Gestion des Changements Compatibles vs Cassants
- Changements additifs (Rétrocompatibles) :
- Ajout d'un nouveau champ optionnel avec un nouveau tag protobuf (ex:
string bio = 5;). - Ajout d'une nouvelle méthode
rpc. - Ces changements peuvent être déployés sans risque de rupture d'exécution.
- Ajout d'un nouveau champ optionnel avec un nouveau tag protobuf (ex:
- Changements cassants (Breaking Changes) :
- Renommage ou suppression d'un champ existant.
- Changement de numéro de tag d'un champ.
- Changement de type d'un champ (ex:
int32->string). - Ordre de déploiement obligatoire : Les consommateurs (API Gateway, MS) doivent d'abord cesser de lire/écrire le champ avant que celui-ci ne soit définitivement retiré de
proto-registry. - Pour toute suppression ou renommage, suivre impérativement le Playbook de Dépréciation Protobuf (procédure séquentielle en 3 phases :
[deprecated = true], extinction des consommateurs, puisreserved <tag>; reserved "<nom>";).
4. Règles d'Or
- [ ] Ne JAMAIS renuméroter un tag existant sous prétexte de "nettoyer" la numérotation des champs protobuf (cela corrompt la désérialisation binaire wire gRPC).
- [ ] Toujours vérifier
buf breakingavant de soumettre une modification de schéma. - [ ] Respecter la cascade :
proto-registry$\rightarrow$ PR dansnpm-packages$\rightarrow$ publication NPM $\rightarrow$ microservices consommateurs.
5. Faits vérifiés dans le code (2026-10-06)
| Sujet | Réalité |
|---|---|
CI de proto-registry |
sync-to-npm.yml délègue à proto-sync.yml de ci-tools[^proto-sync] : sur PR, buf lint uniquement ; sur main, lint puis buf generate et PR « chore: sync proto typings » dans npm-packages (contracts et contracts-nest). buf breaking n'est lancé nulle part en CI : c'est à toi de le lancer avant de rendre la main. emergency-reset.yml régénère tout en cas de désynchronisation[^proto-ci]. |
buf breaking local |
buf.yaml n'a pas de section breaking : catégorie par défaut FILE[^buf]. Elle ne détecte pas la réutilisation d'un numéro de champ supprimé sans reserved. |
| Lint | STANDARD (dont RPC_REQUEST_RESPONSE_UNIQUE : un message de réponse par RPC, pas de réponse partagée) sauf PACKAGE_VERSION_SUFFIX, FILE_LOWER_SNAKE_CASE, RPC_REQUEST_STANDARD_NAME, RPC_RESPONSE_STANDARD_NAME[^buf]. Les enums suivent STANDARD : préfixe du type et valeur _UNSPECIFIED = 0. |
| Génération | ts_proto vers gen/ts, options nestJs=true, outputClientImpl=false, useDate=false, addMetadata=true, importSuffix=.js[^bufgen]. Ne jamais éditer contracts/src ni contracts-nest/src (sauf grpc.helpers.ts). |
| Structure | Domaines common, user, event, post, social, storage, ranking. Un domaine = 5 fichiers : <d>.proto (entité), .command.proto, .query.proto, .responses.proto, .services.proto. Exception : post/comment*.proto sans comment.services.proto, RPC exposés par post.services.proto. Un nouveau champ va dans le fichier du bon type. |
| Dette connue | Aucun reserved dans le registre ; CreateEventCommand a un trou au champ 5 (ancien location) à réserver[^contrats]. |
Checklist avant de rendre la main
cd proto-registry
buf lint
buf breaking --against '.git#branch=main'
Puis analyze_grpc({ "target": "<Service ou Method>", "base": "main" }) : liste handlers et clients, et ajoute la vérification wire-format avec les enums (renumérotation, suppression sans reserved).
- Ajout de champ : numéro explicite, au-dessus du maximum actuel du message, jamais un numéro libéré.
- Suppression :
reserved <n>;etreserved "<nom>";dans le même commit. - Nouvel enum : préfixé,
<TYPE>_UNSPECIFIED = 0.
[^proto-sync]: proto-sync.yml réutilisable (ci-tools) [^proto-ci]: sync-to-npm.yml et emergency-reset.yml [^buf]: buf.yaml (lint STANDARD, pas de section breaking) [^bufgen]: buf.gen.yaml (ts_proto) [^contrats]: Contrats et évolutions (numérotation, trou du champ 5)
04 同仓库更多 Skills
volontariapp-user-account-deletion
Suppression de compte en deux temps (PENDING_DELETION): requestDeletionWithUserDeleted, finalizeDeletion, fan-out de user.deleted vers les domaines et gather ws. A utiliser pour tout changement de domain-user touchant la suppression, le statut ou le cycle de vie d'un user.
volontariapp-meta-scripts
Utiliser et faire evoluer la CLI Node de meta (setup, doctor, migrate, certs, repos, bump) et le manifeste repos.json, source unique des repos et unites du workspace.
volontariapp-implement-async-event-flow
Guide pas-à-pas pour concevoir et implémenter un flux asynchrone complet (messaging -> outbox -> post-processors -> ws-service -> client).
research
Investigate a question against high-trust primary sources and capture the findings as a Markdown file in the repo. Use when the user wants a topic researched, docs or API facts gathered, or reading legwork delegated to a background agent.
prototype
Build a throwaway prototype to answer a design question. Use when the user wants to sanity-check whether a state model or logic feels right, or explore what a UI should look like.
grilling
Grill the user relentlessly about a plan, decision, or idea. Use when the user wants to stress-test their thinking, or uses any 'grill' trigger phrases.