Protocol-first design
Qu'est-ce que Protocol-first
Protocol-first est une approche dans laquelle le contrat d'interaction entre les composants (services, clients, partenaires externes) est conçu et fixé avant la mise en œuvre. Le code, le stockage, l'infrastructure et la documentation sont soumis au contrat et générés automatiquement à partir de celui-ci, et non l'inverse.
Contrairement au « code-first », où l'API n'est qu'un sous-produit du code, Protocol-first fait du protocole un artefact primaire : il possède les concepts de domaine, de modèle de données, de statut, d'erreur, de sémantique d'idempotence, de SLO/SLI et même de politique de version.
Pourquoi est-ce nécessaire
Cohérence et prévisibilité des interfaces à l'échelle de l'organisation.
Onbording rapide (auto-génération SDK/stab/clients, erreurs et codes uniques).
Une évolution fiable (compatibilité des circuits, contrats-tests, politique de version claire).
Focus produit : Discutons du comportement, de l'intégration SLA et UX avant d'écrire le code.
Automatisation : CI/CD recueille des artefacts (clients, bouchons de serveur, validateurs) à partir d'une seule source de vérité.
Sécurité et conformité : les droits, le masquage des IPI, les politiques de rétractation sont inscrits dans le contrat.
Noyau de l'approche
1. Source unique de vérité (SSOT) - spécifications lisibles par machine :
REST: OpenAPI/JSON Schema.
Événements et streaming : AsyncAPI, Avro/JSON Schema.
RPC: Protobuf (gRPC), Thrift, Smithy.
GraphQL : Directives/politiques SDL +.
2. Dispositions préalables à la mise en œuvre : glossaire de domaine, codes d'erreur, sémantique de l'idempotence, dédelines, retraits, déduplication.
3. Production automatique : clients/serveurs, types, SDK, contrats-tests, moki, collections Postman, Terraform/OpenAPI Gateway-config.
4. Governance : linters/polices (naming, pagination, filtres, erreurs), review via API guilde, change-advisory pour les versions majeures.
5. Compatibilité : vérification rigoureuse des diffs « additive-only », versioning sémantique, tests canary/consumer-driven.
6. L'observation au niveau du contrat : ID de corrélation, modèles d'erreurs, budgets de retard sont précisés dans le protocole.
À quoi ressemble le processus (squelette)
1. Initiation : brief produit → user journeys → API/Protocole PRD (ressources/méthodes/événements, SLA/SLO, erreurs, limites).
2. Simulation : brouillon de spécifications (OpenAPI/AsyncAPI/Proto) + schémas de données, dictionnaire de termes.
3. Contrats et intégration UX : exemples de charge utile, contrats d'erreur, cartes de statut, règles de versioning.
4. Revew et governance : linters/standards, discussion sur les invariants de domaine, lock-in MGC (contrat minimum de garantie).
5. Autogénération des artefacts : SDK, meutes, fiches de test, bouchons d'infrastructure (Gateways, IAM scopes).
6. Mise en œuvre et tests contractuels : le fournisseur et les consommateurs font l'objet d'un contrôle de compatibilité à CI.
7. Observation et SLO : trace par correlation-id, error catalogue, budgets rétroactifs/temporels.
8. Sorties et évolution : additive-first, politique de déprécation, canary, A/B capability flags.
Protocoles et styles d'interaction
REST/HTTP
Normes : modèle de ressources, 'GET/POST/PATCH/DELETE', pagination (cursor), filtres, triage.
Champs et schémas : JSON Schema, formats ('date-time', 'uuid'), invariants (regex/enum/min-max).
Erreurs : format unique ('type', 'code', 'titre', 'detail', 'trace _ id'), mapping sur les piles HTTP.
Contrôle des changements : ETag/If-Match, clés idempotentes pour POST, sémantiques explicites 409/422.
gRPC/RPC
Protobuf : numérotation stable des étiquettes, 'optional', interdiction de réutiliser les champs supprimés.
Deadlines et les priorités du contrat ; statuts stables (OK, INVALID_ARGUMENT, FAILED_PRECONDITION, etc.).
Streaming : spécification de l'ordre des messages, backpressure, remorques finales.
Event-driven (Kafka/NATS/SNS/SQS)
AsyncAPI : thèmes/canaux, clés de lot, accords de clés de déduplication, retences, sémantique « exactement une fois » vs « au moins une fois ».
Événement-noyau et enrichissement : séparez le minimum de payload et d'extensions ; Versez 'event _ type '/' schema _ version'.
Idempotence : 'event _ id', 'producer _ id', politique par retraits et déduplication.
GraphQL
SDL comme contrat, directives pour le deprecate, limites de profondeur et de complexité, contrat d'erreur (error codes/extensions).
Intégration avec les principes architecturaux
Inverse Pyramid/Critical Path First : dans la spécification, allouer MGC (minimum obligatoire), les extensions sont via '? include = '/capabilities.
Paved Roads : ensemble de modèles de spécifications prêtes à l'emploi (payment, KYC, audit, recherche, fichiers) + linters.
API Gateways & Service Mesh : politiques basées sur les contrats (rate-limits, auth scopes, retries, circuits-breakers).
Versioning et évolution
Semantic Versioning:- Minor = champs/canaux additifs uniquement.
- Major = modifications brisantes (supprimer, renommer, modifier la sémantique).
- Politique de suppression : fenêtres de support, en-têtes 'Sunset', événements-notifications.
- Contrats consommateurs-conducteurs (CDC) : nous vérifions que l'API actuelle satisfait les consommateurs spécifiques.
- Répertoire des schémas : registre (Schema Registry/Artifact Registry) avec historique et règles de compatibilité (BACKWARD/FORWARD/FULL).
Sécurité et conformité
Authentification/autorisation dans le cadre du contrat (OAuth2/OIDC scopes, mTLS, JWT claims).
PII/PCI : masquage, formats de tokenization, champs avec modes de stockage spéciaux/TTL.
Stratégies d'audit : attributs obligatoires ('actor', 'subject', 'action', 'occurred _ at', 'trace _ id').
Limites : rate limit headers, quotas, tailles de messages, deadlines.
Observabilité contractuelle
Correlation/Request-ID : obligatoire dans la spécification.
Error Catalogue : liste fixe des codes et SLA à éliminer.
SLI/SLO : p50/p95 latitude, proportion de réponses réussies, proportion d'événements compatibles, proportion de répétitions idempotentes.
Tests et qualité
Tests de contrat (fournisseur ↔ consommateur), schema bou en CI, génération de serveurs moq.
Samples d'or : exemples de référence de demandes/réponses, fiches pour e2e.
Chaos/latency injection : vérification des délais/retraits, dégradation des extensions tout en conservant le MGC.
Modèles de domaine exemplaires
Paiement (REST + événements)
'POST/payments '(clé idempotent) →' 201 Created 'avec' payment _ id', 'status = autorisé'.
L'événement 'payment'. authorized. v1` (ядро): `{ payment_id, amount, currency, method, occurred_at }`.
Extension 'payment. enriched. v1 ': risque-score, géo, device-fingerprint.
Erreurs : '422' (validation), '402' (paiement exigé), '409' (duplicate).
SLA : autorisation ≤ 800ms p95 ; l'événement noyau ≤ 2c lag p95.
KYC (files d'attente gRPC +)
RPC `StartVerification(user_id)` → `operation_id`.
Evénements de progrès en topic'kyc. status. v1` (`PENDING` → `APPROVED/REJECTED`).
Le contrat spécifie les champs PII, la durée de conservation, le masquage, les codes causaux de défaillance.
Audit (Event-only)
`audit. recorded. v1` (ядро): `actor`, `subject`, `action`, `occurred_at`, `trace_id`.
Enrichissement : IP, device, geo - un événement/flux séparé, ne bloque pas le noyau.
Outils et automatisation (pile approximative)
Спеки: OpenAPI/AsyncAPI/Protobuf/Avro/GraphQL SDL.
Линтеры: Spectral, OpenAPI Diff, Buf (protobuf), Confluent SR compatibility checks.
Генерация: OpenAPI Generator, Buf/Protoc, GraphQL Codegen, AsyncAPI Generator.
Gateway : Kong/Apigee/Azure/GCP GW, Envoy.
Тесты: Pact/CDC, Dredd, Schemathesis, Hoverfly, MockServer.
Registre : Git-annuaire des schémas + Schema Registry/Artifact Registry.
Documentation : Redocly/Stoplight/Swagger-UI/GraphiQL/Explorer.
Anti-modèles
Code-first par accent : « d'abord MVP sur les contrôleurs », spécification post-fact, divergence de la documentation et du comportement.
Swagger-wash : OpenAPI formelle sans règles réelles (erreurs, limites, SLA, versions).
Déchirure de compatibilité : supprimé le champ/modifié le type sans la version major ; réutilisation des étiquettes protobuf.
Réponse « épaisse » sans pagination/filtres ; manque d'idempotence.
Titrisations hors contrat : auth/Scopes sont décrits dans le wiki, mais pas dans le cahier des charges.
Relation avec l'organisation du processus
API Guild : administrateurs de normes, révisions, formation.
Design Docs : pour chaque API - PRD, ADR (solutions), SLA, matrice de risques.
Gestion du changement : processus RFC, release notes, hydes de migration, deprecation-timline.
Paved Road & Templates : générateurs de carcasse de service à partir d'un cahier des charges (squelette de handler, validation, logage).
Chèques-feuilles
Avant de commencer
- Il y a un PRD et un glossaire de domaine.
- Le style (REST/gRPC/Event/GraphQL) et le format de schéma sont sélectionnés.
- MGC, erreurs, SLA/SLO, règles d'idempotence définies.
En développement
- La spécification passe par les linters et la revue.
- L'auto-génération SDK/stabs/fixtur est configurée.
- Les contrats-tests (CDC) sont inclus dans l'IC ; schema-diff bloque les modifications incompatibles.
Avant la sortie
- Documentation pour les intégrateurs avec exemples et codes d'erreur.
- Observabilité contractuelle : correlation-id, error bou, dashboards SLI.
- La politique de versionalité et de déprécation a été annoncée.
FAQ
En quoi Protocol-first diffère-t-il de l'API-first ?
Les termes sont souvent utilisés comme synonymes. Dans cet article, sous Protocol-first, nous soulignons la rigueur du contrat et la couverture de tous les styles (REST/RPC/Events/GraphQL), y compris la SLA, la sécurité et l'observabilité.
Cela ne ralentira-t-il pas le développement ?
Le démarrage peut être un peu plus long, mais ensuite nous gagnons sur les intégrations, la stabilité et les vitesses de développement parallèle (auto-génération, SDK stable).
Que faire des expériences rapides ?
Utilisez les versions « brouillon » des schémas (draft), des flags fonctionnels et du bac à sable, mais ne manquez pas les linters et les règles de compatibilité de base.
Résultat
Protocol-first design fait du contrat le centre de l'architecture : nous harmonisons les comportements, fixons les schémas, automatisons la génération et les tests, évoluons de manière additive. Il en résulte des intégrations prévisibles, une vitesse de développement élevée et la résilience des systèmes aux changements d'échelle et de commande.