ADRIndex ADR

Décisions d’architecture — ADR

Pourquoi le code de BoostEcom est comme ça : une décision par fichier, jamais réécrite, en une seule série numérotée.

Pourquoi le code est comme ça. Un fichier par décision, jamais réécrit.

ADR-0001 · Le verrou d'un item de travail est une branche git, pas une checklist partagee

La codebase passe d'un seul developpeur a une flotte d'agents Claude Code travaillant en parallele. Ces agents ont trois proprietes qui cassent les methodes de…

ADR-0002 · Modèle d'URL multilingue : préfixe de locale, migration phasée

Remplacée par ADR-0038. BoostEcom sert 6 locales (en, fr, de, es, it, pt) avec un catalogue à parité parfaite (~1935 clés × 6) et ~31 000 mots déjà traduits dans le…

ADR-0003 · BoostEcom Creative est un process vertical de l'OS, pas un deuxieme produit

BoostEcom Creative est une offre de production de creatives publicitaires e-commerce vendue en abonnement mensuel a des marques Shopify. La question posee etait : quelle…

ADR-0004 · Le Studio agence est un tenant de la plateforme, pas un back-office separe

Remplacée par ADR-0043. BoostEcom Studio est aujourd'hui deux choses qui portent le meme nom et ne se parlent pas.

ADR-0005 · Les credits sont livres a l'anniversaire de l'abonnement

Deux horloges tournaient en parallele et ne se croisaient jamais.

ADR-0006 · Trois niveaux de preuve d'identite, et la fleche va du store vers l'org

Deux questions differentes se sont retrouvees derriere le meme mot.

ADR-0007 · La famille de cles sk_ est retiree, pas reparee

lib/security/api-keys.ts exposait un ApiKeyManager qui frappait trois formats de credential — sk_user_, sk_org_, sk_proj_ — et les gardait dans un Map au niveau du…

ADR-0008 · Le harnais d'eval est vitest, pas un framework

5 900 tests, zero eval (ai-platform/0138). La suite couvre le deterministe — idempotence de facturation, cloisonnement tenant, heal du schema, webhooks Stripe, gardes de…

ADR-0009 · Db push + guard genere plutot que migrations Prisma

Ce depot n'a pas de prisma/migrations/. Le repertoire n'existe pas, il n'a jamais existe, et prisma/schema.prisma:10 le dit : « pas de migrations, schema-first ».

ADR-0010 · Un seul markup, porte par le plan

Le catalogue v3.0 declare le markup applique au cout brut de l'AI Gateway dans ADMIN_PRICING_CONFIG.markupByPlan (src/types/billing-plans.ts) : 1.5x sur Pro / Max 5x /…

ADR-0011 · La porte KYC du marketplace est la signature de l'APA par l'acheteur

Le pipeline KYC « enhanced » de la V5.1 existe en entier : la table KycVerification, le chiffrement at-rest du rapport provider, le client Stripe Identity, le verdict…

ADR-0012 · Le prix de l'abonnement se decouple du grant de credits

Le catalogue v3.0 vendait chaque tier payant comme rendant 100% de son prix en credits : Pro $49/mo -> $49 de credits, Max 5x $149/mo -> $149, Max 20x $299/mo -> $299…

ADR-0013 · Le metier de l'agence et la production creative sont deux namespaces de permissions

Precise l'ADR 0004, ne le revoque pas. L'agence reste une Organization de la plateforme, operee par ses membres, sans back-office parallele. Ce que ce document change…

ADR-0014 · Le programme partenaire echange de la distribution, pas une commission

/network/agencies vendait publiquement, dans les six locales et depuis des mois : « Lifetime 20% revenue share on every BoostEcom store you implement (no 12-month cap)…

ADR-0015 · Deux audiences, un seul jeu de conditions

Remplacée par ADR-0041. Moitie PAYANTE de billing/0369. La moitie agence est tranchee separement par l'ADR 0014…

ADR-0016 · Une seule porte d'audit dans le chat, et le focus est le levier de cout

Le chat exposait trois outils qui disaient tous auditer une boutique : Rien dans les deux premieres phrases ne dit au modele laquelle prendre. Et le plus couteux n'etait…

ADR-0017 · Remotion est le moteur vidéo des planes A et C

Le skill boostecom-creative avait retenu Motion.so (Mosaic) comme outil payant unique après le retrait de Higgsfield (2678). En pratique : crédits opaques, pas…

ADR-0018 · Le Playbook maître docx est remplacé

Le 2026-09-15, le propriétaire a fourni BoostEcom_Playbook_Maitre_Produit_Codebase_Growth_2026.docx (~64k caractères, 18 sections : doctrine, codebase, growth, prompt…

ADR-0019 · Un seul moteur markdown dans le chat, et la 6 du SDK jusqu'a une eval verte

L'audit du chat du 2026-09-17 (docs/audits/2026-09-17-audit-chat-composer-et-moteur.md) a mis deux ecarts de version cote a cote, et ils n'ont pas la meme nature.

ADR-0020 · L'onboarding se termine sur le scan, jamais sur le paiement

Le wizard de premiere inscription (src/app/(minimal)/onboarding/_components/onboarding-client.tsx) enchaine quatre etapes : Account → Organization (+Plan) → Store →…

ADR-0021 · Une ligne du plan @Atlas est du travail executable, jamais un lien

L'ADR 0020 pose que l'onboarding se termine sur le scan, et que le bouton qui ouvre le checkout porte le nom d'une action. C'est la regle 3, et c'est elle qui supprime…

ADR-0022 · Le kernel @Atlas est un texte versionne, pas un dossier YAML a charger

src/features/ai/prompts/loader.ts etait un chargeur de 240 lignes pour un dossier @Atlas/ : kernel.yaml (identite, lois), routing.yaml (routage par mots-cles vers un…

ADR-0023 · Une capacite, un contexte, N grammaires

La vision de la plateforme tient en une phrase, ecrite : BoostEcom doit devenir la couche d'intelligence qui connait simultanement le store de l'interieur, le store de…

ADR-0024 · Un moteur creatif, deux profils : la plateforme est un tenant de son propre Studio

Prolonge l'ADR 0023 (une capacite, un contexte, N grammaires) et l'ADR 0017 (Remotion est le moteur video des planes A et C). Ne revoque ni l'ADR 0003 (Creative est un…

ADR-0025 · Quatre relations, trois mecanismes

Demande, a plusieurs reprises, que « chaque acces puisse gerer : user platform, affiliate platform, revendeur platform, partner platform, admin platform ». La…

ADR-0026 · Le tenant Fondateur est designe, pas devine

Corrige la mise en oeuvre de l'ADR 0024 §4. Ne revoque pas son principe : « la plateforme est un tenant de son propre Studio ».

ADR-0027 · Le siege interne reste dans la codebase

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…

ADR-0028 · Deux bibliotheques de skills, jamais une avec un drapeau

Le depot appelait deja trois choses differentes « skill », sans un seul import entre elles : les skills @Atlas sur disque (src/features/ai/skills/) : un prompt + ; les…

ADR-0029 · BoostEcom opere le growth et le storefront, Shopify garde la logistique commerce

Le cockpit store est structure en quatre modes (Preview · Builder · Workflow · Studio). La tentation, une fois shopifyAdminGraphQL ouvert, est de laisser @Atlas tout…

ADR-0030 · Preview Design edite le storefront, Builder redige, Workflow orchestre

Remplacée par ADR-0031. Builder est le canvas Onlook; Preview lit seulement; les formats sont un outil dans Builder.

ADR-0031 · Builder est le canvas Onlook; Preview lit; formats sont un outil

Remplacée par ADR-0032. Builder est l'editeur Onlook. La Preview est la seule stage storefront. Le chrome Design sur l'iframe n'est plus le…

ADR-0032 · Builder est l'editeur Onlook; Preview reste la vitrine

ADR 0031 a mis le mot Onlook sur le Builder, puis a monte le chrome Design autour de l'iframe storefront. Ce n'est pas Onlook. Onlook est un editeur: canvas, frames…

ADR-0033 · La connexion Shopify principale est une Custom App merchant-owned

BoostEcom n'est pas seulement un lecteur de catalogue. @Atlas doit pouvoir observer et, avec les autorisations internes requises, agir sur l'ensemble de l'admin Shopify…

ADR-0034 · Un workflow ne tourne que devant l'operateur

ai-platform/0366 posait deux questions sur l'ancien runner, qui repondait 501 et n'executait rien : Qui paie un run que personne ne regarde ? ; Que veut dire une…

ADR-0035 · Qualifier le catalogue avec des preuves indépendantes

Proposée. Le besoin : des boutiques actives avec un plan commercial payant. La disponibilité HTTP, le prix d’un thème et la réussite d’un enrichissement ne prouvent pas…

ADR-0036 · Découvrir indépendamment des boutiques connectées et filtrer à la lecture

Proposée. Les boutiques clientes restent généralement privées. Le catalogue concurrentiel doit se constituer indépendamment de leurs connexions et conserver des…

ADR-0037 · Les plans sont des paliers d'usage, pas des nombres de boutiques

Jusqu'au 2026-09-25, un plan limitait deux fois la meme valeur : un nombre de boutiques (Free 1, Pro 1, Max 5x 5, Max 20x 20, les noms « 5x / 20x » etant ce nombre) ET…

ADR-0038 · Préfixe de langue as-needed, sur les pages publiques seulement

L'ADR 0002 a constaté le problème et il n'a pas changé. La langue voyage dans le cookie NEXT_LOCALE et une même URL sert les six langues, donc Google n'indexe que…

ADR-0039 · Chaque palier payant inclut un nombre de boutiques, sans add-on

L'ADR 0037 a rendu boutiques et membres illimites sur les plans payants, sur la premisse qu'« une boutique connectee qui ne fait rien ne coute presque rien ». Le code…

ADR-0040 · Les profils d'agent sont adressés par prénom, et décrivent les rôles du runtime

Le site décrivait les cinq spécialistes de deux façons incompatibles.

ADR-0041 · Un programme qui paie, une page

L'ADR 0015 a aligne les deux pages qui paient sur un seul jeu de conditions : 30 % du net, 12 factures payees, 60 jours d'attribution, 30 jours de retention, tous lus…

ADR-0042 · Les connecteurs sont le produit : pas de registre d'outils tiers

La question a ete posee deux fois : faut-il brancher treg.to (un registre d'outils d'agent, « une cle pour 3 600 endpoints chez 97 fournisseurs », facture a l'appel)…

ADR-0043 · Le plan C (agence) est retire

Remplace l'ADR 0004. Restreint, sans les revoquer, les ADR 0013, 0017, 0024 et 0026 : ce qu'ils disent des plans A et B reste vrai, ce qu'ils disent d'une marque cliente…

ADR-0044 · Mirror reconstruit une section, il ne copie pas une page

Etend le tableau des surfaces du stage de l'ADR 0032 : mirror est un sixieme mode de la scene, a cote de Preview, Worktree, Builder, Workflow et Studio. Il n'est ni un…

ADR-0045 · Mirror est un onglet du Builder, pas un mode de la scene

L'ADR 0044 a fait de Mirror un sixieme WorkspaceMode (?mode=mirror), une cinquieme etape du stepper, avec sa propre ligne d'en-tete de 56 px, sa bande d'onglets Source /…

ADR-0046 · Les frames du Builder rendent la page de la Preview en mode editeur

L'ADR 0032 a ecarte « Frame = URL de preview » parce que « la Preview ne vit pas dans le canvas ». Le code a fait ce choix quand meme. Une frame de template demande…

ADR-0047 · Pages publiques cacheables par le CDN et CSP à nonce

Tranche backlog/app-shell/0365. Garde-fous : src/test/public-static-contract.test.ts, src/test/isr-is-disabled-by-the-nonce.test.ts. Outils…

ADR-0048 · Le tableau de bord est desktop-only (>= 1024 px), les surfaces publiques mobile-first

L'application authentifiee (tout ce qui vit sous src/app/(dashboard) : le cockpit d'une boutique et sa scene, le chat @Atlas, le Studio, l'espace vendeur, /account…

ADR-0049 · Annuaires publics de boutiques et dossiers du haut du classement

Proposée. Code : src/services/directories/, pages sous src/app/(marketing)/intelligence/directory et .../dossier, sitemaps sous src/app/sitemaps. Cadre de rendu : ADR…

ADR-0050 · Analyse automatique avec file existante

Proposée. L’extension 1.0.3 résolvait un domaine via l’autocomplétion publique puis demandait un second clic de scan. Réutiliser automatiquement le scan anonyme aurait…

Une seule série

Cette série est la série d’ADR de BoostEcom. Elle vient du dépôt applicatif BoostEcom/boostecom.app (copie du 2026-10-08, sha cee5f0f0) : chaque ADR garde son numéro, sa date, son statut et ses remplacements, repris dans sa section « Statut ». Deux exceptions, notées dans la section « Statut » de l’ADR concernée et dans la provenance de la migration :

  • le dépôt applicatif portait deux ADR 0043 : « Le plan C (agence) est retiré » garde 0043, « Le tableau de bord est desktop-only » devient ADR-0048, le seul numéro libre de la série ;
  • l’ADR 2977 (numéro de l’item de backlog intelligence/2977, hors de la série) devient ADR-0050.

Un commentaire de code qui cite « ADR 0043 » parle du plan C ; « ADR 2977 » se lit ADR-0050.

Le problème que ça résout

Une flotte d'agents redécide. Chaque session démarre sans mémoire : elle voit un choix bizarre dans le code, le juge sous-optimal, et le « corrige », en réintroduisant le bug que ce choix évitait. Six mois plus tard, personne ne sait plus pourquoi Credit est un ledger append-only, pourquoi /api/me n'utilise jamais include: true, ni pourquoi le payout marketplace attend 14 jours.

Le commit qui porte la décision est introuvable. Le fil où elle a été prise n'existe plus. Le code seul ne dit que le « quoi ».

Un ADR est la réponse minimale : le « pourquoi », écrit une fois, lisible en deux minutes, versionné à côté du code qu'il explique.

Quand en écrire un

Quand la réponse à « pourquoi pas plus simple ? » n'est pas évidente en lisant le code. En pratique :

  • un choix structurel (schéma, frontière de module, dépendance, protocole)
  • un compromis assumé (on accepte X pour éviter Y)
  • une contrainte externe qui n'est pas visible dans le code (limite Vercel, fenêtre de litige légale, comportement de Stripe)
  • un choix qu'un agent futur voudra « nettoyer » et ne doit pas
  • l'abandon d'une approche : ce qu'on a essayé et pourquoi ça n'a pas marché

Pas pour une décision réversible en une heure. Un ADR par PR est un formalisme qui tue le format.

Format

adr/NNNN-titre-court.mdx

NNNN est un compteur à quatre chiffres, jamais réutilisé, et la série reste contiguë (le prochain ADR prend le numéro qui suit le dernier). Le frontmatter ne porte que title (« ADR-NNNN — titre ») et description ; la date, le statut, les piliers et les remplacements vont dans la section « Statut » en tête de page. Chaque ADR a sa carte dans l’index ci-dessus. Copie le modèle.

Cycle de vie

Un ADR n'est jamais modifié ni supprimé après acceptation. Il est superseded (remplacé) par un nouveau, qui le référence. C'est ce qui permet de lire l'historique d'un choix plutôt que son dernier état : « on a fait A, puis B parce que A cassait sous charge » vaut infiniment plus que « on fait B ».

StatutSens
proposedécrit, pas encore tranché
accepteden vigueur, contraignant pour les piliers listés
superseded by NNNNremplacé, gardé pour l'histoire
rejectedenvisagé et écarté, gardé pour ne pas le reproposer

Les rejected ont autant de valeur que les accepted : ils empêchent la flotte de reproposer tous les trois mois la même idée déjà écartée.

Dans la section « Statut », ces valeurs s’écrivent Proposé, Accepté, Remplacé par ADR-NNNN et Rejeté.

Qui lit quoi

Chaque ADR déclare les piliers qu'il contraint (ligne « Piliers » de sa section « Statut »). Un agent qui prend un item lit les ADR acceptés de son pilier avant de coder. C'est court : un pilier sain en a une poignée, pas cinquante.

Rapport avec le reste

SurfaceContenu
adr/ (cette série)pourquoi un choix a été fait (immuable)
architecture/comment le système marche aujourd'hui (vivant)
audits/ce qui ne va pas, à une date donnée
Insightsce que les chiffres disent, à une date donnée
backlog/ du dépôt applicatifce qu'on va faire
pnpm fleet:status (dépôt applicatif)où on en est, maintenant

Modele

Une nouvelle page adr/NNNN-titre-court.mdx :

---
title: "ADR-NNNN — <titre>"
description: "<la décision en une phrase>"
---

## Statut

**Proposé** · YYYY-MM-DD

Piliers : `billing`, `data-platform`

Remplace : ADR-NNNN (si applicable)

## Contexte

La situation qui a forcé un choix. Les contraintes réelles : techniques,
légales, de coût, de calendrier. Ce qui était vrai au moment de décider, même si
ça ne l'est plus aujourd'hui.

Pas de solution ici. Si un lecteur ne comprend pas le problème, la décision lui
paraîtra arbitraire.

## Décision

Ce qu'on fait, à l'indicatif présent. Une phrase si possible.

## Alternatives écartées

Ce qu'on a envisagé, et la raison précise du rejet. **C'est la section la plus
utile du document** : c'est elle qui empêche la flotte de reproposer dans six
mois l'option qu'on a déjà étudiée et écartée.

| Option | Pourquoi non |
|---|---|
| | |

## Conséquences

Ce que ça coûte. Ce que ça rend difficile. La dette qu'on accepte sciemment, et
le signal qui indiquerait qu'il faut revisiter ce choix.

Une décision sans conséquence écrite est une décision dont personne n'a mesuré
le prix.

## Comment c'est appliqué

Le code, le test, ou le gate qui rend cette décision effective plutôt que
déclarative. S'il n'y en a pas, dis-le : c'est une règle tenue à la main, donc
une règle qui sera violée.

Le gabarit d’origine du dépôt applicatif, avec son frontmatter (id, title, status, date, pillars, supersedes) :

---
id: "0000"
title: ""
status: "proposed" # proposed | accepted | rejected | superseded by NNNN
date: "YYYY-MM-DD"
pillars: [] # les piliers que cette decision contraint, ex: ["billing", "data-platform"]
supersedes: "" # id de l'ADR remplace, si applicable
---

# NNNN — <titre>

## Contexte

La situation qui a force un choix. Les contraintes reelles : techniques,
legales, de cout, de calendrier. Ce qui etait vrai au moment de decider, meme si
ca ne l'est plus aujourd'hui.

Pas de solution ici. Si un lecteur ne comprend pas le probleme, la decision lui
paraitra arbitraire.

## Decision

Ce qu'on fait, a l'indicatif present. Une phrase si possible.

## Alternatives ecartees

Ce qu'on a envisage, et la raison precise du rejet. **C'est la section la plus
utile du document** : c'est elle qui empeche la flotte de re-proposer dans six
mois l'option qu'on a deja etudiee et ecartee.

| Option | Pourquoi non |
|---|---|
| | |

## Consequences

Ce que ca coute. Ce que ca rend difficile. La dette qu'on accepte sciemment, et
le signal qui indiquerait qu'il faut revisiter ce choix.

Une decision sans consequence ecrite est une decision dont personne n'a mesure
le prix.

## Comment c'est applique

Le code, le test, ou le gate qui rend cette decision effective plutot que
declarative. S'il n'y en a pas, dis-le : c'est une regle tenue a la main, donc
une regle qui sera violee.