Première moitié de la feature marque blanche : la machinerie complète qui permet à un compte Business d'envoyer ses emails de relance avec son propre logo, ses propres couleurs et son nom comme expéditeur, à la place du branding Rubis. Architecture : - Nouvelle colonne JSONB `organizations.brand_settings` (12 tokens customisables : logo, senderName, et 10 couleurs — primary, banner, body bg, card bg, text, text muted, border, link, button text). Null = palette Rubis intacte. Validation hex stricte (#RRGGBB). - Service `#services/brand` avec `resolveBrandTokens(org)` qui merge defaults + overrides en respectant le plan (couleurs/logo = Business only ; senderName = cascade pour tous les plans). Mergeurs avec sémantique "null = reset au default sur ce champ précis" pour les patches partiels. - Service mutualisé `#services/media_storage` qui remplace l'ancien `blog_uploads.ts`. Scopes `blog` (4 MB, jpg/png/webp) et `brand-logo` (1 MB, + svg accepté). Cleanup automatique du logo précédent lors d'un remplacement (pas de versioning — la conv produit est "on écrase"). - Controller `BrandController` (5 endpoints) + middleware `AssertBusinessPlanMiddleware` qui throw 403 `business_plan_required` (code matché par le SPA pour l'upsell card). - Refactor des 3 templates mail (relance, payment thanks, checkin) + layout commun pour accepter `tokens: BrandTokens` en prop. Le dispatcher résout les tokens per-org pour relance + remerciement (= user → client, branded), et passe `DEFAULT_BRAND` au checkin (= Rubis → user, toujours Rubis-branded). - Routes publiques pour le logo : `/api/v1/uploads/brand-logos/:filename` (sans auth, cache immutable, X-Content-Type-Options: nosniff pour les SVG). UI self-service arrive dans la prochaine version (v1.12.0). En attendant, un compte Business peut être configuré via Bruno / API directe. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
18 lines
821 B
TypeScript
18 lines
821 B
TypeScript
/**
|
|
* Version courante de l'app SPA, source de vérité pour :
|
|
* - le toast "Nouvelle version" (<VersionToast/>) qui compare cette valeur à
|
|
* `localStorage["rubis:last-seen-version"]` au mount du root
|
|
* - le release tag Sentry (à brancher si pas déjà fait)
|
|
*
|
|
* À bumper manuellement à chaque release, EN MÊME TEMPS qu'on ajoute le .md
|
|
* correspondant dans `apps/landing/src/content/changelog/<version>.md`. La
|
|
* même PR contient les deux — sinon le toast pointe sur une ancre absente.
|
|
*
|
|
* Convention : semver (major.minor.patch). Le toast affiche `v${APP_VERSION}`
|
|
* et linke vers `https://rubis.pro/changelog#${APP_VERSION}`.
|
|
*/
|
|
export const APP_VERSION = "1.11.0";
|
|
|
|
/** URL absolue de la page changelog (utilisée par le toast). */
|
|
export const CHANGELOG_URL = "https://rubis.pro/changelog";
|