feat(banking): mode "Bientôt disponible" pendant la fenêtre KYC Powens
All checks were successful
Build & Deploy Web / build-and-deploy (push) Successful in 36s
Build & Deploy API / build-and-deploy (push) Successful in 1m29s

Ajoute un état intermédiaire entre "feature désactivée silencieusement"
et "feature pleinement active" : un teaser visible dans /parametres
pour les Pro/Business qui annonce que la connexion bancaire arrive,
avec une note rassurante sur la lecture seule. Permet d'annoncer la
feature aux users payants pendant le délai d'agrément AISP / KYC
Powens, sans risque de cliquer dans le vide.

- Nouveau flag d'env `BANKING_TEASER_ENABLED` (boolean, default false)
- `GET /banking/status` renvoie désormais `{ enabled, comingSoon }`
  où comingSoon = !enabled && BANKING_TEASER_ENABLED
- `BankingSection` : nouveau composant `ComingSoonCard` (halo glow,
  copy explicite sur l'agrément AISP en cours, rassurance lecture
  seule) affiché quand comingSoon=true et l'org est Pro/Business
- `parametres.tsx` : la section "Banque" apparaît si enabled OU
  comingSoon (au lieu de uniquement enabled)
- ConfigMap K3s : `BANKING_TEASER_ENABLED='true'` en prod pour
  annoncer la feature aux clients payants pendant le KYC

Trois états possibles désormais :
  enabled=true                       → feature active (post-KYC)
  enabled=false + comingSoon=true    → teaser "Bientôt disponible"
  enabled=false + comingSoon=false   → section invisible (kill switch dur)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
ordinarthur 2026-05-12 14:14:33 +02:00
parent 51217175ad
commit 3207f873e9
6 changed files with 75 additions and 13 deletions

View File

@ -66,17 +66,20 @@ export default class BankingController {
/** /**
* GET /banking/status public. * GET /banking/status public.
* *
* Kill switch lu côté SPA pour décider d'afficher la section banque. * Trois états :
* On considère banking activé si : * - { enabled: true } feature pleinement active
* - `BANKING_ENABLED` == 'true' (ou non défini = true par défaut en dev) * - { enabled: false, comingSoon: true } KYC Powens en cours,
* - ET les credentials Powens sont configurés * teaser "Bientôt disponible" affiché aux Pro/Business
* * - { enabled: false, comingSoon: false } section complètement
* En prod on déploie avec `BANKING_ENABLED=false` tant que le KYC * cachée (kill switch dur)
* Powens prod n'est pas finalisé la feature est dormante, aucun
* bouton n'apparaît, aucun call init n'est tenté.
*/ */
async status({ response }: HttpContext) { async status({ response }: HttpContext) {
return response.json({ data: { enabled: isBankingEnabled() } }) return response.json({
data: {
enabled: isBankingEnabled(),
comingSoon: !isBankingEnabled() && env.get('BANKING_TEASER_ENABLED') === true,
},
})
} }
/** /**

View File

@ -127,6 +127,13 @@ export default await Env.create(new URL('../', import.meta.url), {
| (sinon calculée : https://<slug>.biapi.pro/2.0/). | (sinon calculée : https://<slug>.biapi.pro/2.0/).
*/ */
BANKING_ENABLED: Env.schema.boolean.optional(), BANKING_ENABLED: Env.schema.boolean.optional(),
/**
* Teaser "Bientôt disponible" affiché dans /parametres pour les
* Pro/Business quand BANKING_ENABLED=false. Permet d'annoncer la
* feature aux users payants pendant la fenêtre KYC Powens. Si false,
* la section est complètement cachée.
*/
BANKING_TEASER_ENABLED: Env.schema.boolean.optional(),
BANKING_PROVIDER: Env.schema.enum.optional(['powens'] as const), BANKING_PROVIDER: Env.schema.enum.optional(['powens'] as const),
POWENS_DOMAIN: Env.schema.string.optional(), POWENS_DOMAIN: Env.schema.string.optional(),
POWENS_API_BASE_URL: Env.schema.string.optional({ format: 'url', tld: false }), POWENS_API_BASE_URL: Env.schema.string.optional({ format: 'url', tld: false }),

View File

@ -4,6 +4,7 @@ import { toast } from "sonner";
import { import {
Banknote, Banknote,
ArrowRight, ArrowRight,
Clock,
Lock, Lock,
Loader2, Loader2,
Trash2, Trash2,
@ -84,6 +85,12 @@ export function BankingSection({
return <UpsellCard />; return <UpsellCard />;
} }
// Banking pas encore activé mais teaser ON → afficher "Bientôt disponible"
// pour annoncer la feature aux Pro/Business pendant la fenêtre KYC Powens.
if (status?.comingSoon) {
return <ComingSoonCard />;
}
return ( return (
<BankingPaidView <BankingPaidView
isLoading={connectionsQuery.isLoading} isLoading={connectionsQuery.isLoading}
@ -96,6 +103,42 @@ export function BankingSection({
// Upsell (Free) — visuel cohérent avec la section Marque (Business) // Upsell (Free) — visuel cohérent avec la section Marque (Business)
// -------------------------------------------------------------------- // --------------------------------------------------------------------
// --------------------------------------------------------------------
// Coming Soon (Pro/Business, KYC Powens en cours)
// --------------------------------------------------------------------
function ComingSoonCard() {
return (
<Card padding="md" className="flex items-start gap-4 flex-wrap">
<div className="flex items-start gap-3 flex-1 min-w-[280px]">
<div className="relative shrink-0">
<div className="absolute inset-0 rounded-full bg-rubis-glow blur-xl opacity-60" />
<div className="relative rounded-full bg-rubis-glow p-2.5 text-rubis-deep">
<Clock size={18} aria-hidden="true" />
</div>
</div>
<div>
<p className="text-[10.5px] uppercase tracking-[0.12em] text-rubis font-semibold">
Bientôt disponible
</p>
<p className="mt-1.5 font-display text-[18px] font-bold text-ink leading-tight">
Connexion bancaire en finalisation
</p>
<p className="mt-2 text-[13px] text-ink-2 leading-relaxed max-w-[480px]">
Rubis termine son agrément AISP (lecture seule, lecture des
virements entrants uniquement) pour détecter automatiquement
les factures payées. Vous serez notifié dès l&apos;ouverture.
</p>
<p className="mt-2 text-[12px] text-ink-3 leading-relaxed">
🔒 Lecture seule · Aucun déplacement de fonds · Compatible
toutes banques françaises
</p>
</div>
</div>
</Card>
);
}
function UpsellCard() { function UpsellCard() {
return ( return (
<Card padding="md" className="flex items-center justify-between gap-4 flex-wrap"> <Card padding="md" className="flex items-center justify-between gap-4 flex-wrap">

View File

@ -47,7 +47,10 @@ export type BankingSettings = {
export function useBankingStatus() { export function useBankingStatus() {
return useQuery({ return useQuery({
queryKey: ["banking", "status"] as const, queryKey: ["banking", "status"] as const,
queryFn: () => api.get<{ enabled: boolean }>("/api/v1/banking/status"), queryFn: () =>
api.get<{ enabled: boolean; comingSoon: boolean }>(
"/api/v1/banking/status",
),
// Le flag bouge rarement — long cache OK. // Le flag bouge rarement — long cache OK.
staleTime: 5 * 60_000, staleTime: 5 * 60_000,
}); });

View File

@ -46,10 +46,12 @@ function ParametresPage() {
const { data: sub } = useSubscription(); const { data: sub } = useSubscription();
const planLabel = sub?.plan === "pro" ? "Pro" : sub?.plan === "business" ? "Business" : "Free"; const planLabel = sub?.plan === "pro" ? "Pro" : sub?.plan === "business" ? "Business" : "Free";
const search = Route.useSearch(); const search = Route.useSearch();
// Kill switch banking : la section ENTIÈRE disparaît si BANKING_ENABLED=false // Kill switch banking : la section apparaît si la feature est ON, OU si
// côté API (typiquement en prod tant que le KYC Powens n'est pas validé). // la prod est en mode "teaser" (KYC Powens en cours, mais on annonce
// qu'elle arrive). Sinon la section reste invisible.
const { data: bankingStatus } = useBankingStatus(); const { data: bankingStatus } = useBankingStatus();
const showBanking = bankingStatus?.enabled === true; const showBanking =
bankingStatus?.enabled === true || bankingStatus?.comingSoon === true;
return ( return (
<div className="flex flex-col gap-2"> <div className="flex flex-col gap-2">

View File

@ -156,6 +156,10 @@ data:
# - POWENS_REDIRECT_URI doit matcher EXACTEMENT ce qui est whitelisté # - POWENS_REDIRECT_URI doit matcher EXACTEMENT ce qui est whitelisté
# côté console Powens prod. # côté console Powens prod.
BANKING_ENABLED: 'false' BANKING_ENABLED: 'false'
# Teaser "Bientôt disponible" affiché aux Pro/Business pendant la
# fenêtre KYC Powens. Flip à 'false' pour cacher complètement la
# section (cas où on veut remettre la feature sous le tapis).
BANKING_TEASER_ENABLED: 'true'
BANKING_PROVIDER: 'powens' BANKING_PROVIDER: 'powens'
POWENS_DOMAIN: 'rubis' POWENS_DOMAIN: 'rubis'
POWENS_API_BASE_URL: 'https://rubis.biapi.pro/2.0/' POWENS_API_BASE_URL: 'https://rubis.biapi.pro/2.0/'