# 🔐 Fluxo Técnico do KYC - TudoAqui

## 📸 1. CAPTURA (Frontend Flutter)

```dart
// Ecrã: verificacao_documentos.dart

// Passo 1: Tirar foto do BI
ImagePicker().pickImage(source: ImageSource.camera);

// Passo 2: Tirar selfie (Liveness)
ImagePicker().pickImage(source: ImageSource.camera, preferredCameraDevice: CameraDevice.front);

// Enviar para backend
final request = http.MultipartRequest('POST', Uri.parse('/api/v1/kyc/upload-bi'));
request.files.add(await http.MultipartFile.fromPath('file', imagemBI.path));
```

---

## ⚙️ 2. PROCESSAMENTO (Backend Node.js)

### **Etapa 2.1: Receber Foto do BI**

```typescript
// Endpoint: POST /api/v1/kyc/upload-bi
async processBI(userId: string, file: Express.Multer.File) {
  // 1. Adicionar marca d'água "TudoAqui - KYC" (Sharp)
  const watermarked = await this.addWatermark(file.buffer, 'TudoAqui - KYC');
  
  // 2. Guardar em uploads/bi/
  await fs.writeFile(`uploads/bi/${userId}_${Date.now()}.jpg`, watermarked);
  
  // 3. OCR com Google Cloud Vision
  const [result] = await this.visionClient.textDetection({
    image: { content: watermarked },
  });
  
  // 4. Extrair nome e número do BI
  const textoCompleto = result.textAnnotations[0].description;
  const numeroBI = textoCompleto.match(/(\d{9}[A-Z]{2}\d{2})/)[1]; // 123456789AO01
  const nome = extrairNome(textoCompleto); // "João Silva"
  
  // 5. Guardar no PostgreSQL
  user.fotoBI = outputPath;
  user.biNumero = numeroBI;
  await this.userRepository.save(user);
  
  return { dadosExtraidos: { nome, numeroBI } };
}
```

**Formato BI Angolano:** `000000000XY00` (9 dígitos + 2 letras + 2 dígitos)

---

### **Etapa 2.2: Receber Selfie**

```typescript
// Endpoint: POST /api/v1/kyc/upload-selfie
async processSelfie(userId: string, file: Express.Multer.File) {
  // 1. Guardar selfie em uploads/selfie/
  await fs.writeFile(`uploads/selfie/${userId}_${Date.now()}.jpg`, file.buffer);
  
  // 2. Liveness Detection (Google Vision Face Detection)
  const [result] = await this.visionClient.faceDetection({
    image: { content: file.buffer },
  });
  
  const faces = result.faceAnnotations || [];
  
  // 3. Verificar: Exatamente 1 rosto + Confiança > 80%
  const livenessOk = (faces.length === 1 && faces[0].detectionConfidence > 0.8);
  
  // 4. Guardar no PostgreSQL
  user.fotoSelfie = outputPath;
  await this.userRepository.save(user);
  
  return { livenessDetected: livenessOk };
}
```

**Liveness Detection:** Garante que é uma pessoa real, não foto de foto.

---

## ✅ 3. VALIDAÇÃO (Backend - Análise Automática)

### **Endpoint: POST /api/v1/kyc/analyze**

```typescript
async analyzeWithAI(userId: string) {
  // 1. Ler BI e Selfie do disco
  const biBuffer = await fs.readFile(user.fotoBI);
  const selfieBuffer = await fs.readFile(user.fotoSelfie);
  
  // 2. Re-executar OCR no BI para extrair nome
  const dadosBI = await this.extractBIData(biBuffer);
  
  // 3. VALIDAÇÃO 1: Comparar nome do BI com nome da conta
  const nomeCoincide = this.compareNames(user.nome, dadosBI.nome);
  // Normaliza: Remove acentos, lowercase
  // "João Silva" ≈ "SILVA, JOÃO" → true ✅
  
  // 4. VALIDAÇÃO 2: Comparar rostos (BI vs Selfie)
  const [biResult] = await this.visionClient.faceDetection({ image: { content: biBuffer } });
  const [selfieResult] = await this.visionClient.faceDetection({ image: { content: selfieBuffer } });
  
  const biFaces = biResult.faceAnnotations || [];
  const selfieFaces = selfieResult.faceAnnotations || [];
  
  // Verificar se ambos têm landmarks (nariz, olhos, boca)
  const rostosCorrespondem = (
    biFaces.length === 1 && 
    selfieFaces.length === 1 && 
    biFaces[0].landmarks.length > 5 && 
    selfieFaces[0].landmarks.length > 5
  );
  
  // 5. APROVAÇÃO AUTOMÁTICA
  if (nomeCoincide && rostosCorrespondem) {
    user.kycStatus = 'aprovado';
    user.seloVerificado = true; // 🟢 Selo Verde ativado
    await this.userRepository.save(user);
    
    return {
      message: '✅ Verificação aprovada! Selo verde atribuído.',
      aprovado: true,
    };
  } else {
    user.kycStatus = 'rejeitado';
    await this.userRepository.save(user);
    
    return {
      message: '❌ Verificação rejeitada. Dados não coincidem.',
      aprovado: false,
    };
  }
}
```

---

## 🧪 4. APROVAÇÃO (Resultado Final)

### **Cenário 1: ✅ Aprovado**

```json
{
  "message": "✅ Verificação aprovada! Selo verde atribuído.",
  "validacoes": {
    "nomeCoincide": true,
    "rostosCorrespondem": true,
    "aprovado": true
  },
  "seloVerificado": true
}
```

**No Flutter:** Mostrar badge verde "Verificado ✓" ao lado do nome do vendedor.

---

### **Cenário 2: ❌ Rejeitado**

```json
{
  "message": "❌ Verificação rejeitada. Dados não coincidem.",
  "validacoes": {
    "nomeCoincide": false,
    "rostosCorrespondem": true,
    "aprovado": false
  },
  "seloVerificado": false
}
```

**No Flutter:** Permitir nova tentativa ou enviar para validação manual.

---

## 🔐 Segurança do Sistema

### **1. Marca d'água Automática**
- Toda foto do BI recebe watermark "TudoAqui - KYC"
- Impede reutilização de documentos roubados

### **2. Comparação de Nome (Normalizado)**
```javascript
normalize('João Silva') → 'joao silva'
normalize('SILVA, JOÃO') → 'silva joao'

// Match: Se um contém o outro
'joao silva'.includes('joao') → true ✅
```

### **3. Liveness Detection**
- Verifica exatamente 1 rosto
- Confiança > 80%
- Previne "foto de foto"

### **4. Comparação de Rostos**
- Ambos devem ter > 5 landmarks
- Em produção: Calcular distância euclidiana

---

## 🛠️ Instalação e Configuração

### **1. Instalar Dependências:**
```bash
npm install @google-cloud/vision sharp
```

### **2. Configurar Google Cloud Vision:**
```bash
# 1. Ir para console.cloud.google.com
# 2. Ativar "Cloud Vision API"
# 3. Criar Service Account e baixar chave JSON
# 4. Definir variável de ambiente:

export GOOGLE_APPLICATION_CREDENTIALS="/path/to/key.json"
```

### **3. Adicionar ao `.env`:**
```env
GOOGLE_APPLICATION_CREDENTIALS=./tudoaqui-kyc-key.json
```

---

## 📊 Fluxo Completo (Diagrama)

```
┌─────────────────────────────────────────────────────────┐
│                  1️⃣ CAPTURA (Flutter)                   │
│  Utilizador tira foto do BI + Selfie                   │
└───────────────────┬─────────────────────────────────────┘
                    │
                    ▼
┌─────────────────────────────────────────────────────────┐
│              2️⃣ PROCESSAMENTO (Node.js)                 │
│  • Upload BI → Marca d'água → OCR (extrair nome + nº)  │
│  • Upload Selfie → Liveness (1 rosto, confiança > 80%) │
└───────────────────┬─────────────────────────────────────┘
                    │
                    ▼
┌─────────────────────────────────────────────────────────┐
│               3️⃣ VALIDAÇÃO (Google Vision)              │
│  • Comparar nome do BI com nome da conta (normalizado) │
│  • Comparar rosto do BI com selfie (landmarks)         │
└───────────────────┬─────────────────────────────────────┘
                    │
                    ▼
┌─────────────────────────────────────────────────────────┐
│                  4️⃣ APROVAÇÃO AUTOMÁTICA                │
│  SE nomeCoincide && rostosCorrespondem:                │
│    → kycStatus = 'aprovado'                            │
│    → seloVerificado = true 🟢                          │
│  SENÃO:                                                 │
│    → kycStatus = 'rejeitado'                           │
└─────────────────────────────────────────────────────────┘
```

---

## 🚀 Como Testar Agora

### **1. Configurar Google Cloud:**
- Ir para [console.cloud.google.com](https://console.cloud.google.com)
- Ativar "Cloud Vision API"
- Baixar chave JSON do Service Account
- Colocar em `backend/tudoaqui-kyc-key.json`
- Definir `GOOGLE_APPLICATION_CREDENTIALS` no `.env`

### **2. Reiniciar Backend:**
```bash
cd backend
npm run start:dev
```

### **3. Testar no Postman:**
```bash
# 1. Registar utilizador → Guardar JWT token
POST /api/v1/auth/register

# 2. Upload BI com foto real
POST /api/v1/kyc/upload-bi
- Header: Authorization: Bearer {token}
- Body: file=bi-frente.jpg, userId={uuid}

# 3. Upload Selfie
POST /api/v1/kyc/upload-selfie
- Body: file=selfie.jpg, userId={uuid}

# 4. Analisar e aprovar automaticamente
POST /api/v1/kyc/analyze
- Body: { "userId": "{uuid}" }
```

---

**✅ Sistema KYC Completo Implementado!**

**Arquivo principal:** `backend/src/modules/kyc/kyc.service.ts`  
**Documentação detalhada:** `backend/KYC_GOOGLE_VISION.md`
