--- title: L'appairage d'une nouvelle tablette répondait 403 depuis mars ---
Trouvé et corrigé le 12/09, en écrivant l'appairage du casque : il butait sur le même mur.
DeviceController porte [Authorize(InstanceAdmin)] sur la classe, et Create n'avait aucune exception. Or une clé d'API ne porte que AppRead et Viewer (ApiKeyAuthenticationHandler), et tablet-app ne s'authentifie jamais autrement — aucun appel d'authentification dans tout le repo. POST /api/device répondait donc 403 à toute tablette.
Depuis quand : commit a452f4a du 13/03/2026, dont le message dit lui-même « need to be tested ». Pourquoi personne ne l'a vu : une tablette déjà appairée ne rappelle jamais Create. Le parc existant continuait de fonctionner ; seul un nouvel appareil échouait — c'est-à-dire exactement ce qu'on ne fait pas tous les jours.
Correctif : Create passe en [AllowAnonymous] + [RequireAppKey], le filtre posé le même jour pour les routes de contenu. Le cloisonnement, lui, était déjà écrit juste en dessous — une clé ne peut créer un appareil que dans son instance.
GET /api/Device/{id}/detail était fermé aux clés lui aussi — or c'est le premier appel d'une tablette qui démarre (tablet-app/lib/main.dart:46) : celui qui lui dit quelle configuration afficher. Une tablette déjà appairée ne retrouvait donc plus son contenu au redémarrage. Ouvert de la même façon.tablet-app/lib/main.dart:38 reconstruisait son client sans clé — Client(host) au lieu de Client(host, apiKey: …) — alors que la clé est persistée en base locale (TabletAppContext.toMap). Une ligne, et tous les appels d'après partaient anonymes.Les deux se tenaient : la route refusait les clés, et l'app n'en envoyait pas. Corrigés ensemble.
⚠️ À vérifier sur le terrain : appairer une vraie nouvelle tablette, et redémarrer une tablette déjà appairée. Le correctif est couvert par les tests, mais les tests appellent le contrôleur directement — aucun filtre d'autorisation ne s'y exécute, donc ils ne prouvent rien sur l'accès lui-même.