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

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) ». Le metaTitle de la page le repetait, ses Stats…

Statut

Accepté · 2026-09-12

Piliers : billing, growth-web, marketplace

Contexte

/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) ». Le metaTitle de la page le repetait, ses Stats l'affichaient comme un terme contractuel, et sa FAQ stackWithReferral s'en servait comme preuve d'elle-meme (« the agency share is for life »).

Aucun chemin de code ne payait cela, et aucun ne pouvait le payer. Le seul ledger de commission du depot est AffiliateCommission (src/config/affiliate.ts) :

TauxAFFILIATE_COMMISSION_PCT = 30, plafond dur (Math.min(asked, 30))
DureeAFFILIATE_COMMISSION_MONTHS = 12, comptees en factures payees
Cleun code par affilie (AffiliateCode.code @unique)

Il n'existe ni agencyShare, ni taux a vie, ni attribution store → partenaire, ni aucune table qui rattacherait une agence aux abonnements qu'elle deploie.

La page portait quatre autres promesses sans implementation, verifiees une par une :

PromesseEtat reel
« Private Slack channel »zero Slack dans le depot. La communaute est Discord, et ecosystem-alerts.ts ecrit « no Slack »
Annuaire « filterable by region, vertical, language and technical expertise »AGENCY_FIELDS porte services, location, hourlyRateCents. Aucun filtre sur /marketplace/[type]
« Early access 3-4 weeks before public release »aucun feature-flag, aucun gating par partenaire
« Pass the technical assessment » + « 30-minute onboarding call »le parcours reel est un formulaire de trois champs, une ligne NetworkApplication, un e-mail best-effort vers MARKETPLACE_ADMIN_EMAIL et un tri manuel dans /admin/revenue/network-applications

Et une cinquieme, ailleurs : la FAQ de la home et de /pricing (home.faq.groups.network.items.agencies) promettait en plus de revendre BoostEcom en white-label avec un vetting en 2-3 jours, quand la page annonce deux semaines. Le white_label du depot est une option de plan Custom / Max 20x pour le CLIENT (src/types/billing-enterprise.ts), pas un mecanisme de revente.

L'ecart etait deja compte, pas decouvert : backlog/billing/0369 (type: "decision", P1) le nommait, et src/test/affiliate-terms-match-the-ledger.test.ts tenait marketingPages.network.agencies dans PENDING_OWNER_DECISION pour l'empecher de se repandre. Ce qui manquait etait une reponse du proprietaire, qu'aucun agent n'a le droit d'inventer : c'est un prix et un contrat client.

Décision

Le programme partenaire ne verse aucune commission. Il echange une fiche dans l'annuaire public, les demandes entrantes qui arrivent dessus, et un acces delegue dans l'organisation du client. Le partenaire facture ses propres clients, et rien ne passe par nous.

Le chemin paye pour une introduction reste le parrainage, inchange : 30 % sur 12 factures payees, un seul ledger, ouvert a tout compte sans revue.

Corollaire d'URL : /network/agencies devient /network/partners en 308. L'ancienne URL excluait les freelances seniors que sa propre copie, sa FAQ et son formulaire invitaient a candidater, alors que le marketplace porte deja agencies et freelancers comme deux annuaires distincts.

Repondu le 2026-09-12, apres verification qu'aucune candidature agence n'avait ete acceptee : la reecriture ne laisse donc personne engage sur les anciennes conditions.

Alternatives écartées

OptionPourquoi non
Construire un vrai ledger agence a 20 % a vie (sortie 2 de billing/0369)Une feature complete : table de commission, attribution store → partenaire, payouts Connect, et la reouverture du calcul de liability. config/affiliate.ts chiffre deja le prix d'un taux a vie : « 30 % pour toujours sur un Max 20x, c'est 90 $/mois indefiniment pour une acquisition faite une fois ». Pas un chantier a lancer avant d'avoir le volume qui le justifie
Aligner le partenaire sur le parrainage : 30 % / 12 factures (sortie 3, celle que le registre recommandait)Un seul ledger et zero mensonge, mais ca fait payer deux fois le meme client : l'agence facture son implementation ET touche une commission sur l'abonnement qu'elle a elle-meme vendu. Et ca plafonne a 12 mois une relation qui, cote agence, est censee durer
Fermer le programme, 308 vers /network/referral (sortie 1)Honnete en quelques heures, mais on perd un funnel d'acquisition deja construit et indexe (sitemap 0.75, llms.txt, nav), et la capacite de recruter des agences, qui sont le canal de distribution le moins cher d'une plateforme e-commerce
Garder /network/agencies comme URLL'URL aurait continue d'exclure les freelances que la page invite explicitement a postuler, pendant que le marketplace leur reserve son propre annuaire

Conséquences

Ce que ca rend facile. La page devient verifiable ligne par ligne : chaque promesse restante correspond a une surface qui existe (listing-types.ts pour la fiche, POST /api/marketplace/leads pour les demandes, OrganizationMember + le namespace studio.* pour l'acces delegue, le Store Graph pour l'audit de prospect). Et le programme ne cree aucune dette financiere : il n'y a rien a verser, donc rien a reconcilier, rien a clawbacker, aucun modele de liability a rouvrir.

Ce que ca coute. Un programme partenaire sans revenue share est moins attractif a la lecture qu'un programme qui en promet un, et Shopify Partners, la reference du marche, en verse un. On echange une promesse forte et fausse contre une offre plus petite et tenue. La page l'assume explicitement : une section « Ce que ce programme n'est pas » enumere les cinq absences, pour que personne ne rebatisse un plan d'affaires dessus.

La dette qu'on accepte sciemment. L'annuaire contient une fiche, boostecom-agency.json, ownedByBoostecom: true. Un partenaire qui clique « Parcourir les agences » nous voit nous. La FAQ le dit au lieu de le cacher, sans chiffre qui puisse pourrir, mais ca reste le point faible de l'offre : la valeur d'un annuaire croit avec son remplissage, et celui-ci demarre a un.

Le signal qui indiquerait de revisiter. Des agences qui candidatent, deploient, puis demandent une part de l'abonnement. Si ca revient trois fois, la sortie 2 redevient une question ouverte, avec cette fois du volume pour la chiffrer.

Ce qui reste ouvert. billing/0369 ne se ferme pas : sa moitie affiliation (/network/affiliate, « 20 % a vie », liens par asset, dashboard de clics) n'est pas tranchee et reste dans PENDING_OWNER_DECISION.

Comment c'est appliqué

src/test/affiliate-terms-match-the-ledger.test.ts lit les six catalogues et refuse tout pourcentage ou toute duree que config/affiliate.ts ne porte pas. Le sous-arbre marketingPages.network.partners n'est pas exempte : il ne peut donc contenir aucun pourcentage, et les deux chiffres qui s'affichent sur la page sont interpoles depuis AFFILIATE_COMMISSION_PCT et AFFILIATE_COMMISSION_MONTHS parce qu'ils decrivent le parrainage. Reintroduire « 20 % a vie » sur cette page fait echouer la suite dans les six langues.

L'entree marketingPages.network.agencies a quitte PENDING_OWNER_DECISION, une liste qui ne peut que retrecir : c'est la dette, comptee, et cette decision en solde une entree sur six.

marketingPages.network.compare y reste, et c'est deliberé. Le comparatif est partage par trois pages et garde une colonne affiliation qui lit « 20 % » et « Lifetime ». /network/partners n'affiche simplement pas cette colonne : il rend la tranche partenaire + parrainage. Le chiffre pendant reste donc hors de la page faite pour ne plus en imprimer, et l'exemption continue de pointer des chaines qui contredisent reellement le ledger, ce qui est la condition que la garde verifie.

src/test/claude-md-marketing-routes.test.ts derive le tableau des routes de CLAUDE.md du disque, donc /network/partners et le 308 y figurent ou la garde echoue.