ADRADR-0027 · Le siege interne reste dans la codebase

ADR-0027 — Le siege interne reste DANS la codebase, derriere une permission

Repond a une question posee le 2026-09-20 : « je me demande si ce n'etait pas mieux de faire le cockpit Admin, Growth, Distribution, Data, Tracking directement en dehors de ma codebase ou du systeme de connexion ».

Statut

Accepté · 2026-09-20

Piliers : design-system, security-identity, platform-ops

Repond a une question posee le 2026-09-20 : « je me demande si ce n'etait pas mieux de faire le cockpit Admin, Growth, Distribution, Data, Tracking directement en dehors de ma codebase ou du systeme de connexion ».

Contexte

La question part d'un vrai constat : le cockpit interne affichait une boutique de CLIENT dans un siege dont le travail est de produire pour la PLATEFORME. Le raisonnement qui suit est logique : si les deux ne parlent pas de la meme chose, peut-etre qu'ils ne devraient pas vivre au meme endroit.

Ce constat est juste. La conclusion ne l'est pas, et il faut nommer pourquoi, sinon la question reviendra.

Ce qui separait mal n'etait pas le DEPOT

Ce qui a produit « Nacre Bijoux · Plateforme » n'est pas la proximite du code interne et du code produit. C'est une designation qui prenait la plus ancienne boutique d'une organisation (design-system/2917). Sortir le siege dans un second depot n'aurait rien corrige : le second depot aurait lu la meme base, pose la meme question, et obtenu la meme mauvaise reponse. Il aurait juste fallu deux deploiements pour la corriger.

Ce que la separation couterait, mesure sur ce depot

  1. La porte. Les pages de /ops s'ouvrent sur une permission platform.* portee par un mandat, pas sur le role ADMIN, et chaque appel relit la base — c'est ce qui permet de recruter quelqu'un pour UNE surface sans lui donner le ledger, le ban et le refund. Hors du systeme de connexion, cette porte est a reecrire : sessions, RBAC, mandats, revocation. Une seconde implementation d'un controle d'acces est la chose qu'on rate.
  2. Les moteurs sont les memes. Une generation interne passe par runStudioImageGeneration, ecrit une ligne GenerationRequest, debite le ledger au cout reel et stocke sous le prefixe Blob de la boutique. Un siege externe rappellerait tout cela par HTTP : il faudrait donc une API d'ecriture interne, authentifiee, versionnee — c'est-a-dire plus de surface d'attaque que le probleme n'en valait.
  3. La derive de forme. Le module Studio est un ilot porte pixel pour pixel. Deux copies dans deux depots divergent au premier correctif applique d'un seul cote, et c'est exactement la raison pour laquelle les onglets de connexion MCP du cockpit IMPORTENT MCP_CLIENTS plutot que de la recopier.
  4. Le meme lecteur. Le fondateur est admin de la plateforme ET premier utilisateur du produit. Deux applications lui demanderaient deux connexions pour un seul cerveau.

Décision

Le siege reste dans ce depot. Ce qui le separe du produit est une PERMISSION et un tenant designe, pas un depot :

  • /admin est garde au bord sur le role, /ops sur une permission platform.* — c'est deja la frontiere, et elle est plus fine qu'une frontiere de depot, parce qu'elle se donne surface par surface ;
  • la marque de la plateforme est DESIGNEE (INTERNAL_ORG_SLUGS + le domaine, ADR 0026 et design-system/2917), jamais deduite ;
  • une production interne est facturee au cout fournisseur, une production cliente au tarif public, et c'est le tenant qui decide, pas l'endroit ou tourne le code (ADR 0024).

Ce qui sortirait legitimement, si un jour

Un seul cas justifierait un depot a part : un outil qui doit survivre a la plateforme. Une console qui sert a diagnostiquer BoostEcom quand BoostEcom est en panne ne peut pas etre servie par BoostEcom. C'est la page /status et ses sondes, et elles sont deja concues pour ca. Rien d'autre dans la liste (Growth, Distribution, Data, Tracking) n'a ce besoin : ces quatre LISENT ce que la plateforme produit, donc une plateforme en panne les rend inutiles de toute facon.