RFC 0020 — Fediverse: tests d'interopérabilité wiremock (signed delivery round-trip)
- Auteur : EBO (rustwarden)
- Date : 2026-05-10
- Statut : Accepted (auto-revue mainteneur unique 2026-05-10, score 26/35)
- Apps consommatrices concernées : toute app fediverse en production qui veut une garantie reproductible que les signatures HTTP draft-cavage produites localement sont vérifiables par un récepteur tiers (Mastodon-style).
- Plan associé : Phase 5 — production polish.
- Dépendances : RFC 0015 (signatures), RFC 0016 (HttpSignedDelivery), RFC 0017 (auto-resolve), RFC 0011 (file outbound).
Summary
Ajouter un binaire de tests d'intégration tests/fediverse_interop.rs dans rustwarden-core qui monte un serveur HTTP local via wiremock joué comme « faux Mastodon ». Trois scénarios :
- Sign + verify round-trip : la couche
HttpSignedDelivery(couche privée) signe un POSTapplication/activity+json, le serveur capture la requête, et le test re-vérifie la signature en local avecparse_and_verify_cavage. - Inbox 202 → delivered :
drain_onecontre une route wiremock qui répond202 Acceptedmet la row àDelivered. - Inbox 503 → deferred : même chose mais avec
503 Service Unavailable; la row restePendingavecnext_retry_atcalé sur le ladder RFC 0010.
Aucune nouvelle API publique. Aucune nouvelle migration. Une seule nouvelle dev-dependency : wiremock = "0.6".
Motivation
Sans tests interop, les RFCs 0015–0017 reposent sur des unit tests qui exercent les fonctions pures (rsa_sha256_sign, parse_signature_header). Aucun chemin n'exerce le moteur HTTP réel ni la sérialisation Date/Host/Signature telle que reqwest la transmet. Un mismatch silencieux (capitalisation des noms d'header, espaces, ré-encodage URL) ne sera détecté qu'en production face à Mastodon.
Le master plan §10 Phase 5 : « tests interop avec Mastodon : profil discoverable mais auth refusée proprement (degrade gracieux selon interop_scope) ». Cette RFC livre le squelette générique réutilisable ; les scénarios spécifiques (NodeInfo refus, auth fédérée e2e) restent ouverts pour des RFCs successives qui ré-utiliseront le même harness.
Non-goals
- Pas de Docker Mastodon réel : trop coûteux en CI (image Ruby + DB Postgres dédiée). Le master plan §11 prévoit
docker-compose.fediverse-test.ymlpour les tests#[ignore]manuels. - Pas de tests
#[ignore]: les tests de cette RFC tournent dans le suite par défaut (cargo test --features experimental-fediverse). - Pas de couverture HTTP/2 : Mastodon parle HTTP/1.1 ; wiremock supporte les deux mais on cible la cible commune.
- Pas de mesure de latence : couvert par le bench Phase 5 (charge 1×1000×50, hors scope CI).
API proposée
Aucune. Les tests sont binaires sous crates/rustwarden-core/tests/fediverse_interop.rs. Ils consomment uniquement les APIs publiques existantes :
crate::fediverse::http_signatures::{rsa_sha256_sign, build_signature_input, parse_and_verify_cavage}crate::services::actor_key_service::ActorKeyService(generate)crate::services::fediverse_outbound_service::{FediverseOutboundService, OutboundDelivery, OutboundStatus}crate::fediverse::http_signatures::HttpSignedDelivery(instance avecMockDatabase)
Compatibilité
Aucun impact sur les apps consommatrices : ces tests sont internes à rustwarden-core et n'exposent ni route ni type. La feature experimental-fediverse reste obligatoire (#[cfg(feature = "experimental-fediverse")] au sommet du fichier).
Alternatives
- Ne rien faire — rejeté : régressions silencieuses sur le format de signature passeraient le CI.
- Mock
reqwest::Clientavecmockito— rejeté :reqwest::Clientn'expose pas d'injection de transport ; il faudrait passer parBuilder::resolve+ serveur local, ce quewiremocksimplifie déjà. - Lancer un Mastodon réel via
testcontainers— rejeté à ce stade : démarrage 30 s+, dépendances Ruby, instabilité CI ; gardé en option future pour un binairetests/interop_mastodon.rs#[ignore]. - Tester uniquement la couche pure (déjà couverte) — insuffisant : ne lève pas les bugs « signature passe localement mais reqwest envoie un header capitalisé que Mastodon rejette ».
Testing plan
Trois cas dans tests/fediverse_interop.rs :
| Test | Comportement attendu |
|---|---|
signed_request_round_trip_through_wiremock | POST signé reçu, Signature parsable, vérifié contre la public key locale. |
outbound_delivers_when_inbox_returns_202 | drain_one retourne Delivered, delivered_at non-NULL. |
outbound_defers_when_inbox_returns_503 | drain_one retourne Pending (count++) avec next_retry_at = now + 5min. |
Les tests utilisent un MockDatabase SeaORM pour fixturer la users row (clés générées en RAM via ActorKeyService::generate()) et la fediverse_outbound_queue row. Pas de PostgreSQL requis.
Migration guide
Aucune. Pure addition de tests + dev-dep.
Open questions
- Q1 : faut-il un harness réutilisable (
tests/common/wiremock_inbox.rs) pour les futures RFCs interop ? Réponse provisoire : non, on attend la troisième RFC qui en aurait besoin (règle de trois).
Score (26/35)
| Critère | Note | Note |
|---|---|---|
| Généralité | 4/5 | Tests utiles à toutes les apps consommatrices. |
| Stabilité API | 5/5 | Pas d'API publique modifiée. |
| Performance | 4/5 | wiremock ~50–100 ms par test ; négligeable en CI. |
| Sécurité | 3/5 | Couvre la chaîne signature mais pas les attaques (replay, tampering) — RFC distincte. |
| Complexité | 4/5 | Squelette de ~150 LoC + 1 dev-dep. |
| Maintenance | 3/5 | wiremock 0.6 stable depuis 2024 ; surface d'API minimale utilisée. |
| Documentation | 3/5 | Cette RFC + commentaires inline ; pas de guide séparé. |
GitRust