Commit History
-
fix(admin): replace vague Meta hints with direct clickable links in Direct Setup modal
CognxSafeTrack- WABA ID → business.facebook.com/settings/whatsapp-business-accounts - Meta Business ID → business.facebook.com/settings/info - Token → business.facebook.com/settings/system-users (new hint added) - Updated i18n labels in en/fr/pt295c327 -
feat(admin): add Direct Setup button for super admins on orgs without phone number
CognxSafeTrack- Add "Direct Setup" button (super admin only) on /clients for orgs without a WhatsApp number - Previously the setup modal was only reachable via the Reconfigure button (orgs with a phone) - Add i18n keys: clients.actions.direct_setup (en/fr/pt) - Add scratch scripts for org configuration and DB queries - Add doc: configurer-token-nouvelle-org.md — how to configure a Meta token on a new orga3df350 -
feat(i18n): complete admin app internationalization across all pages
CognxSafeTrackReplace all hardcoded French strings with t() calls on 14 pages and sync 130+ new keys across fr/en/pt locale files. Language switching now works everywhere in the admin interface. Pages covered: TrackDaysPage, TrackFormPage, TrackListPage, UserListPage, KnowledgeBasePage, SettingsPage, AnalyticsPage, AIAgentSetup, OnboardingWizard, ResetPasswordPage, ClientsManagementView, ContactsPage, TemplatesPage, TrainingLab.d80fec4
-
fix: restore Limite Quotidienne and complete admin i18n
CognxSafeTrackFix messaging_limit_tier disappearing in /clients page: - fetchMetaStatus was querying WhatsAppPhoneNumber separately, which is tenant-filtered by Prisma extension — returns null when called from another org's JWT context (super-admin viewing all orgs) - Fix: include phoneNumbers in the Organization query (excluded from tenant filtering) and use org.phoneNumbers[0].id directly i18n — pages fully translated (fr/en/pt): - LoginPage: org ID, email, password, subtitles, button, footer - ResetPasswordPage: all 4 states (request/sent/new/success) - BillingPage: 62 keys — wallet, transactions, chart, AI assistant, credit packs, QUICK_QUESTIONS, TX_LABELS, FEATURE_LABELS - ClientsManagementView (/clients): 20 key groups — status badges, WABA labels, tier/quality info, all modals (billing, credits, create org, personality, WA setup), validation errors, toasts Fix TemplatesPage status badges showing raw key strings: - Add 5 missing keys to all 3 locale files: status_approved, sta…4f90920
-
chore: remove Stripe — replaced by Orange Money / Wave payment gateway
CognxSafeTrack +1: Claude Sonnet 4.6Delete stripe.ts route file, remove import and /v1/stripe registration from app.ts, drop stripe npm dependency, remove deprecated stripeWebhookRoute stub from payments.ts, and remove stripeCustomerId from admin Organization interface. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>641e72b -
fix(admin): migrate raw fetch() to api client in ClientsManagementView
CognxSafeTrack +1: Claude Sonnet 4.6Removes the last manual fetch() call outside lib/api.ts — billing/admin/allocate now goes through api.post() which injects Authorization and Content-Type automatically. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>60c3938 -
feat: Claude Sonnet 4.6 provider + Stripe billing automation
CognxSafeTrack +1: Claude Sonnet 4.6AI: - packages/ai-sdk: ClaudeProvider implements LLMProvider via tool_use structured outputs + zod-to-json-schema - Claude registered at priority 120 (TEXT only), supersedes Gemini for feedback/lessons/chat — -40% cost, better French - ANTHROPIC_API_KEY added to API and worker env validation Stripe: - apps/api/src/routes/stripe.ts: POST /v1/stripe/webhook handles checkout.session.completed, subscription.updated/deleted, invoice.payment_failed/succeeded - Schema: stripeCustomerId + stripeSubscriptionId added to Organization - tenant.ts: 402 gate for isHardStopped orgs (x-api-key calls always pass) - ClientsManagementView: SUSPENDU badge on hard-stopped orgs - STRIPE_SECRET_KEY + STRIPE_WEBHOOK_SECRET added to config Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>4a0c3ba -
feat(billing): implement full wallet/ledger system with hard-stop enforcement
CognxSafeTrack +1: Claude Sonnet 4.6- Add walletBalance + isHardStopped to Organization schema; WalletTransaction ledger model with full audit trail - wallet.ts (worker): debitWallet (atomic $transaction), creditWallet (with AuditLog), checkWalletBalance (Redis 30s cache), alert queuing (low/critical/exhausted/restored) - wallet.ts (api): creditWallet for admin top-up with cache invalidation - usage-tracker.ts: debitWallet integrated into trackAiUsage, trackAudioUsage, trackWhatsAppSent; BYOK orgs skipped - BroadcastHandler + CampaignHandler: bulk debit after send (BROADCAST_PER_USER per recipient) - requireCredits.ts: migrated from aiCreditsUsed/Limit to walletBalance/isHardStopped; shares Redis cache key with worker - whatsapp-logic.ts: replaced assertCredits/CreditExhaustedError with checkWalletBalance/WalletExhaustedError - ai.ts: added requireCredits preHandler to all 11 AI routes (was 4) - billing.ts: /admin/allocate now calls creditWallet(); new GET /wallet route (balance + 20 last txns) - BillingPage: wallet card…0fd3320 -
feat(billing): enforce AI credit limits across all surfaces
CognxSafeTrack +1: Claude Sonnet 4.6- credit-guard.ts (worker): assertCredits() blocks AI when creditsUsed >= creditsLimit; Redis cache 60s prevents DB hit on every message - whatsapp-logic.ts: credit guard injected before handler chain; RECHARGE keyword bypasses the guard so users can always request a payment link - CommandHandler: new RECHARGE keyword sends payment URL or contact message - i18n: credit_exhausted + recharge_link + recharge_contact in 5 languages - requireCredits middleware (api): 402 on personalize-lesson, tts, generate-feedback, crm/generate-campaign - billing route: POST /v1/billing/admin/allocate (SUPER_ADMIN only) supports set/add actions + optional usage reset + Redis cache invalidation - ClientsManagementView: "Crédits IA" button (SUPER_ADMIN only) per org opens allocation modal with set/add/reset controls - BillingPage: red exhaustion banner when creditsUsed >= creditsLimit Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>6484585
-
fix(admin): make all modals scrollable and responsive on mobile
CognxSafeTrack +1: Claude Sonnet 4.6RechargeModal (BillingPage), create-org modal (ClientsManagementView), and create-template modal (TemplatesPage) now use the bottom-sheet pattern: fixed header + scrollable body + fixed footer, max-h-[90vh], and items-end on mobile so they slide up from the bottom. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>a3f8777 -
feat(billing): complete billing system, push notifications, and tech debt fixes
CognxSafeTrack +1: Claude Sonnet 4.6- Usage tracking: instrument pedagogy, audio transcription, AI Agent mode (was silently untracked) - EmailHandler: implement templates 2 (password reset), 3 (quota alert), 4 (monthly report) - Quota alert: auto-queue email + push at 85% threshold via maybeQueueQuotaAlert - Push notifications: PushHandler + send-push BullMQ job; sendPushToUser scoped by organizationId to prevent cross-tenant reads - BillingPage: add credit recharge modal with 3 packs, null guard for missing orgId - i18n: add nav.billing key in fr/en/es/pt locales - Tests: billing.test.ts (10 tests), payments.test.ts (13 tests) - Tech debt: fix empty catch blocks in ai-pedagogy.ts, exclude usage tokens from CRM API response, pass organizationId to generateChat in AIAgentHandler - Docs: add backlog and business model to docs/business/ Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>8280d7d
-
fix(audit): resolve technical debt + UX issues from 2026-05-11 audit
CognxSafeTrack +1: Claude Sonnet 4.6Backend: - Add missing DB indexes on Response.userId and Response.enrollmentId - Add 15s timeout with fallback on AI personalization in pedagogy.ts - Fix race condition in NavigationHandler with atomic $transaction - Fix OnboardingHandler hard reset: use FK cascades, 5-lang confirmation - Change seedDatabase to static import in CommandHandler - Add proper pagination to /enrollments admin endpoint UX/Admin: - Fix responsive grid on dashboard stats (1col mobile → 5col desktop) - Show filename + status label during file upload in ContactsPage - Add success/error toast with import summary on contact CSV/XLSX upload - Add inline form validation with field-level errors in ClientsManagementView - Wire up Copy button on AI-generated messages in ContactsPage Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>9fe2cc7 -
feat(admin): responsive bottom sheet + spring animation for TierInfoModal
CognxSafeTrack +1: Claude Sonnet 4.6- Mobile: slides up from bottom (spring, damping 32), rounded-t-3xl, drag handle pill, max 85dvh with internal scroll + overscroll-contain - Desktop (sm+): centered card with same spring entrance - AnimatePresence handles exit animation (slides back down) - ESC key closes + body scroll lock during open - Backdrop separated from panel div for correct z-layering Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>74aa3a1 -
feat(admin): tier color + info modal for WhatsApp messaging limits
CognxSafeTrack +1: Claude Sonnet 4.6- Color-coded limit display: red (TIER_50/250), blue (TIER_1K), emerald (10K+) - Info button (ℹ) on DailyLimitCell and billing modal opens TierInfoModal - TierInfoModal: ladder of all 6 Meta tiers with current highlighted, quality rating panel (GREEN/YELLOW/RED) with contextual explanation - BillingTierDisplay: reusable component for billing modal with same colors Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>00b9619 -
refactor(debt): resolve all 10 technical debt items from audit
CognxSafeTrack +1: Claude Sonnet 4.6- Redis: singleton pattern (lib/redis.ts) in api + worker, removes 16+ new Redis() calls - Meta token: systemUserTokenIssuedAt field + weekly cron monitor (warn @50d, critical @55d) - Rate limiting: @fastify/rate-limit global 200/min, login 10/min, forgot-password 3/min - Dead code: delete WhatsAppConnectButton.tsx, archive one-off scripts - Silent catches: logger.warn(err) on all backend catch blocks, console.warn on frontend - Meta API types: 5 typed interfaces replace 6 as any casts in organization.ts - Frontend logger: lib/logger.ts wraps Sentry (active when VITE_SENTRY_DSN is set) - Migration: add systemUserTokenIssuedAt + metaBusinessId to Organization schema Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>a966957
-
feat(meta-status): sync daily limit + quality rating live from Meta phone number API
CognxSafeTrack +1: Claude Sonnet 4.6fetchMetaStatus now calls GET /{phoneNumberId}?fields=messaging_limit_tier,quality_rating to get the real tier from Meta (TIER_1K, TIER_10K, TIER_100K, UNLIMITED) instead of a hardcoded value inferred from WABA status. Frontend: TIER_LABELS map for human-readable labels, QualityDot badge (green/amber/red) displayed next to the limit. dailyLimitLabel now uses the real tier from the API. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>8aa43f4 -
feat(meta-status): store metaBusinessId for reliable business verification
CognxSafeTrack +1: Claude Sonnet 4.6Add optional `metaBusinessId` field to Organization (schema + shared-types). fetchMetaStatus now queries /{businessId}?fields=verification_status directly when metaBusinessId is stored — bypasses WABA edge permission restrictions that block test WABAs and certain system user token scopes. Direct setup form gains a "Business ID Meta" input that saves via PUT /organizations/:id. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>70a5a84 -
fix(meta-status): split combined Meta API call + fix business badge for test WABAs
CognxSafeTrack +1: Claude Sonnet 4.6Split `account_review_status,business{...}` into two independent calls so test WABAs (which forbid the `business` field) no longer poison WABA status. Business verification is now optional/non-fatal (wrapped in try/catch). BusinessBadge and BusinessVerificationCell now show "—" with neutral styling when `businessId` is undefined (field inaccessible) instead of misleading "Non vérifiée" amber warning + "Vérifier →" link. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>7e2166c
-
feat(whatsapp-setup): direct config mode for platform-owner accounts
CognxSafeTrack +1: Claude Sonnet 4.6Backend: - accessToken now optional in /whatsapp-setup — falls back to WHATSAPP_ACCESS_TOKEN env var (for platform-owner self-setup) Frontend: - "Reconfigurer WhatsApp" button now opens a choice modal instead of launching Embedded Signup directly - Option A (Direct): enter WABA ID + optional token — for accounts already configured on Meta (token from env var used if field left empty) - Option B (Embedded Signup): Facebook login popup — for new client accounts - Phone Number ID pre-filled from existing DB record - Auto-refreshes Meta status after successful save Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>2f67731 -
fix(admin): show Reconfigurer WhatsApp when phone exists but token/wabaId missing
CognxSafeTrack +1: Claude Sonnet 4.6Orgs migrated from single-tenant setup have a WhatsAppPhoneNumber record but no wabaId/systemUserToken in Organization table. Without the token the Meta status endpoint returns configured:false and WABA shows "Non connecté". When fetchMetaStatus returns configured:false on an org that already has a phone number, replace the "En ligne" indicator with an amber "Reconfigurer WhatsApp" button that re-triggers the Embedded Signup flow to store the correct wabaId and long-lived token. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>4f87bfb -
feat(meta): live Meta verification status + WhatsApp setup fixes
CognxSafeTrack +1: Claude Sonnet 4.6- GET /v1/organizations/:id/meta-status — fetches WABA account_review_status and business verification_status live from Meta Graph API, cached 1h in Redis - POST /v1/organizations/:id/meta-status/refresh — force-invalidates the cache - ClientsManagementView: replaced static metaVerificationStatus field with live per-org Meta status (WABA badge, Business badge, derived daily limit) - launchEmbeddedSignup: fixed race condition — now waits for both the OAuth code (FB.login) and WABA/phone IDs (WA_EMBEDDED_SIGNUP_EVENT) before resolving - /whatsapp-setup: exchanges OAuth code for long-lived Meta token (60 days) before storing; bypasses exchange if token already starts with EAA - OnboardingWizard: removed broken WhatsApp step (3 steps: welcome, legal, AI) - OrganizationSchema: removed non-existent DB fields (contractSigned, contractSignedAt, contractSignerName, metaVerificationStatus, dailyMessageLimit) that caused prisma.organization.create() to throw Unknown arg at runtime Re…bd9eb5b -
feat: backlog P0→P3 — toast system, payments, tenant isolation, feedback handler, i18n parity
CognxSafeTrack +1: Claude Sonnet 4.6P0 — Critical fixes - Fix generate-feedback job silently dropped: register FeedbackHandler in worker index.ts - Wire FeedbackHandler: AI feedback, Day 11 TeamMember extraction, atomicity enforced P0 — Toast system (replace all alert()) - Add useToast hook + ToastContext + Toaster component - Replace every alert() across admin pages with toast.success/error/warning/info - Migrate all raw fetch() in pages to api.upload() / api.get() / api.post() P1 — Type safety - CrmAIAssistant: icon prop any → React.ElementType - useAudioRecorder: add onError callback instead of alert() - api.ts: add upload() method for multipart FormData P1 — Payment gateway - Add payment-gateway.ts: Orange Money + Wave initiation and webhook parsing - Rewrite payments.ts routes: initiate, status, webhook handlers with auto-enrollment on SUCCESS P1 — AI regression tests - Add apps/api/test/regression/ai-gold-standards.test.ts (12 tests, 5 suites) P2 — Visual recruitment (Day 11) - FeedbackHandler extracts TeamMem…6dd9bad
-
chore: stabilization, audit fixes and project synchronization
CognxSafeTrack7b0c22b
-
fix: implement GET organization by ID route and direct password setting for new tenants
CognxSafeTracke00083b -
feat: add organization useCase selection to modal and backend
CognxSafeTrack55a1607
-
feat: implement PaaS modularity foundation (Contact model, modular OrganizationMode, and redesigned creation modal)
CognxSafeTrack3992613 -
fix: resolve 401/400 errors by centralizing API client and injecting organizationId in backend
CognxSafeTrackcfeac02
-
feat: migrate to multi-tenant SaaS architecture with JWT auth and BullMQ notifications
CognxSafeTrack2ab1980
-
feat: Premium Onboarding with Meta SDK and Technical Debt resolution
CognxSafeTrack6248bf4
-
feat: B2B SaaS Multi-tenant architecture & Tech Debt Resolution
CognxSafeTracke289c5c -
feat: implement end-to-end B2B client management with Meta Embedded Signup
CognxSafeTrackddc506d
-
feat: finalize multi-tenant WhatsApp architecture for Meta Tech Provider review
CognxSafeTrack3bf9adc