Skip to content

Desafio 11: KYC System — Onboarding Digital à Prova de Fraude

🇧🇷 Sistema de Verificação de Identidade
🇬🇧 Know Your Customer System


KYC (Know Your Customer) é o processo regulatório obrigatório para toda instituição financeira no Brasil. Regulamentado pelo BACEN (Resolução 4.753/2019) e pela Lei 9.613/1998 (Lavagem de Dinheiro), o KYC é a primeira linha de defesa contra fraudes, lavagem de dinheiro e financiamento ao terrorismo.

Switch: React (Vite) vs Next.js

Por que React (Vite) para KYC?

VantagemDescrição
SPA nativoFluxo contínuo sem reloads
MediaDevicesAcesso direto à câmera
ML client-sideTensorFlow.js para edge detection
Bundle pequenoCarrega rápido em mobile
Hot ReloadDX excelente

Arquitetura

UseCamera Hook

typescript
export function useCamera(options: UseCameraOptions = {}): UseCameraReturn {
  const { facingMode = 'environment', resolution = { width: 1920, height: 1080 } } = options;
  const videoRef = useRef<HTMLVideoElement>(null);
  const streamRef = useRef<MediaStream | null>(null);
  const [isStreaming, setIsStreaming] = useState(false);

  const startCamera = useCallback(async () => {
    const stream = await navigator.mediaDevices.getUserMedia({
      video: { facingMode, width: { ideal: resolution.width }, height: { ideal: resolution.height } },
      audio: false,
    });
    streamRef.current = stream;
    if (videoRef.current) {
      videoRef.current.srcObject = stream;
      await videoRef.current.play();
      setIsStreaming(true);
    }
  }, [facingMode]);

  const captureImage = useCallback((): string | null => {
    if (!videoRef.current || !canvasRef.current) return null;
    const canvas = canvasRef.current;
    canvas.width = videoRef.current.videoWidth;
    canvas.height = videoRef.current.videoHeight;
    canvas.getContext('2d')!.drawImage(videoRef.current, 0, 0);
    return canvas.toDataURL('image/jpeg', 0.92);
  }, []);

  const stopCamera = useCallback(() => {
    streamRef.current?.getTracks().forEach(t => t.stop());
    setIsStreaming(false);
  }, []);

  useEffect(() => () => stopCamera(), [stopCamera]);
  return { videoRef, canvasRef, isStreaming, startCamera, stopCamera, captureImage };
}

Zustand Store

typescript
export const useKYCStore = create<KYCStore>()(
  persist(
    (set) => ({
      session: null,
      initializeSession: (sessionId) => set({ session: { sessionId, currentStep: 'PERSONAL_DATA', status: 'PENDING' } }),
      setCurrentStep: (step) => set((s) => ({ session: s.session ? { ...s.session, currentStep: step } : null })),
      setDocument: (data) => set((s) => ({ session: s.session ? { ...s.session, document: data } : null })),
      setLiveness: (data) => set((s) => ({ session: s.session ? { ...s.session, liveness: data } : null })),
      reset: () => set({ session: null }),
    }),
    { name: 'kyc-session', storage: createJSONStorage(() => sessionStorage) }
  )
);

Comparação: React (Vite) vs Next.js

AspectoReact (Vite)Next.js
Fluxo SPANativo, sem reloadsHydration overhead
Camera/MediaDevicesAcesso diretoMais complexo
ML client-sideTensorFlow.js fácilServer Components limitam
Bundle~150KB gzipped~300KB+
SEONão precisa (KYC)SSR útil para landing
API RoutesBackend separadoIntegrado

Casos Reais

  • Nubank (React Native + React) — 80M+ clientes, onboarding < 5min
  • C6 Bank (React) — 20M+ clientes, OCR próprio
  • Stone (React) — 5M+ merchants, KYC empresarial

Como testar

bash
# React (Vite)
cd packages/frontend/kyc-web
pnpm dev

# Next.js
cd packages/frontend/kyc-portal
pnpm dev

Lições aprendidas

  1. KYC = porta de entrada — Onboarding rápido (5min) converte 3x mais
  2. Active liveness é obrigatório — Selfie estática é vulnerável
  3. Edge detection client-side — Reduz retakes drasticamente
  4. Logs imutáveis — 5+ anos (BACEN)
  5. Acessibilidade — Upload como fallback para câmera
  6. React (Vite) — Melhor para KYC isolado, performance máxima
  7. Next.js — Melhor para portal unificado (landing + KYC + dashboard)
  8. CPF validation — Sempre client-side E server-side
  9. OCR preciso — P95 < 3s, accuracy > 98%
  10. Face match — > 95% para aprovação automática