Módulo de Documentos¶
Este documento descreve o módulo de gerenciamento de documentos do MeAjudaAi, incluindo arquitetura, configuração e melhorias futuras.
Visão Geral¶
O módulo Documents permite que prestadores de serviço façam upload de documentos necessários para validação (RG, CPF, CNH, comprovante de residência, certificados), com processamento automático via OCR e verificação assíncrona.
Tecnologias Utilizadas¶
- Azure Blob Storage: Armazenamento de arquivos
- Azure Document Intelligence: OCR e extração de dados
- Hangfire: Processamento assíncrono de verificação
- PostgreSQL: Persistência com schema isolado
Arquitetura¶
Camadas¶
src/Modules/Documents/
├── Api/ # Endpoints HTTP
│ ├── Endpoints/ # Minimal APIs
│ └── Extensions.cs # Configuração do módulo
├── Application/ # Use cases (CQRS)
│ ├── Commands/ # Upload, MarkAsVerified, MarkAsRejected
│ ├── Queries/ # GetStatus, GetProviderDocuments
│ └── Jobs/ # DocumentVerificationJob (Hangfire)
├── Domain/ # Regras de negócio
│ ├── Entities/ # Document aggregate
│ ├── Enums/ # EDocumentStatus, EDocumentType
│ ├── Events/ # Domain events
│ └── Repositories/ # Interfaces
└── Infrastructure/ # Implementações técnicas
├── Data/ # EF Core, migrations
└── Repositories/ # Implementação IDocumentRepository
Fluxo de Processamento¶
1. Upload
├─> POST /api/v1/documents/upload
├─> UploadDocumentCommandHandler
├─> Azure Blob Storage (salvamento)
├─> PostgreSQL (metadados)
└─> Hangfire (enfileira verificação)
2. Verificação Assíncrona
├─> DocumentVerificationJob (background)
├─> Azure Document Intelligence (OCR)
├─> Validação de dados extraídos
└─> MarkAsVerified/MarkAsRejected
3. Consulta
├─> GET /api/v1/documents/status/{id}
└─> GetDocumentStatusQueryHandler
Tipos de Documento¶
| Tipo | Enum | Modelo Azure |
|---|---|---|
| RG | IdentityDocument |
prebuilt-idDocument |
| CPF | IdentityDocument |
prebuilt-idDocument |
| CNH | DriverLicense |
prebuilt-idDocument |
| Comprovante de Residência | ProofOfAddress |
prebuilt-document |
| Certificado | Certificate |
prebuilt-document |
Estados do Documento¶
Uploaded (1)
↓
PendingVerification (2)
↓
├─> Verified (3)
├─> Rejected (4)
└─> Failed (5) [erro técnico]
Configuração¶
1. Azure Blob Storage¶
Desenvolvimento Local (Azurite)¶
# Instalação
npm install -g azurite
# Executar
azurite --silent --location c:\azurite --debug c:\azurite\debug.log
Configuração em appsettings.Development.json:
{
"Azure": {
"Storage": {
"ConnectionString": "UseDevelopmentStorage=true",
"BlobContainerName": "documents"
}
}
}
Produção (Azure Storage Account)¶
# Via user-secrets (recomendado)
dotnet user-secrets set "Azure:Storage:ConnectionString" "DefaultEndpointsProtocol=https;AccountName=...;AccountKey=...;EndpointSuffix=core.windows.net"
# Via variável de ambiente
$env:Azure__Storage__ConnectionString = "DefaultEndpointsProtocol=https;..."
Passos no Portal Azure: 1. Criar Storage Account 2. Obter connection string em Access keys → Connection string 3. Configurar via user-secrets ou variáveis de ambiente
2. Azure Document Intelligence¶
# User-secrets
dotnet user-secrets set "Azure:DocumentIntelligence:Endpoint" "https://your-resource.cognitiveservices.azure.com/"
dotnet user-secrets set "Azure:DocumentIntelligence:ApiKey" "your-api-key-here"
# Variáveis de ambiente
$env:Azure__DocumentIntelligence__Endpoint = "https://your-resource.cognitiveservices.azure.com/"
$env:Azure__DocumentIntelligence__ApiKey = "your-api-key-here"
Passos no Portal Azure: 1. Criar recurso Azure AI Document Intelligence 2. Obter Endpoint e API Key em Keys and Endpoint
3. Hangfire (Background Jobs)¶
{
"Hangfire": {
"DashboardEnabled": true,
"DashboardPath": "/hangfire",
"WorkerCount": 5,
"PollingIntervalSeconds": 15,
"RetryAttempts": 3,
"AutomaticRetryDelaySeconds": 60
}
}
Dashboard: Disponível em http://localhost:5000/hangfire (dev) ou https://api.meajudaai.com/hangfire (prod)
⚠️ Segurança: Adicione autenticação ao dashboard do Hangfire em produção.
4. Database (PostgreSQL)¶
# Connection string via user-secrets
dotnet user-secrets set "ConnectionStrings:DocumentsDb" "Host=localhost;Database=meajudaai;Username=documents_owner;Password=your-password"
Schema criado automaticamente:
- Schema: documents
- Roles: documents_owner, documents_role, hangfire_role
- Tabelas: documents, hangfire_*
Exemplo Completo - User Secrets¶
cd src/Bootstrapper/MeAjudaAi.ApiService
# Azure Storage (Desenvolvimento)
dotnet user-secrets set "Azure:Storage:ConnectionString" "UseDevelopmentStorage=true"
# Azure Document Intelligence
dotnet user-secrets set "Azure:DocumentIntelligence:Endpoint" "https://meajudaai-docs.cognitiveservices.azure.com/"
dotnet user-secrets set "Azure:DocumentIntelligence:ApiKey" "your-32-char-api-key"
# Database
dotnet user-secrets set "ConnectionStrings:DocumentsDb" "Host=localhost;Database=meajudaai;Username=documents_owner;Password=SecurePass123!"
Verificação de Configuração¶
# Listar secrets
cd src/Bootstrapper/MeAjudaAi.ApiService
dotnet user-secrets list
# Testar Azure Storage
# Use Azure Storage Explorer: https://azure.microsoft.com/features/storage-explorer/
# Testar Document Intelligence
# Use: https://formrecognizer.appliedai.azure.com/studio
Custos Azure (Estimativa)¶
| Serviço | Free Tier | Custo Standard | Estimativa Mensal |
|---|---|---|---|
| Storage Account | 5 GB | ~R$ 0,10/GB | 1000 docs (~500MB) = ~R$ 0,05 |
| Document Intelligence | 500 páginas/mês | ~R$ 5,00/1000 páginas | 500 docs/mês = ~R$ 2,50 |
| Total | - | - | ~R$ 2,55/mês |
Troubleshooting¶
Erro: "Unable to connect to Azurite"¶
# Verificar se está rodando
netstat -an | findstr "10000"
# Reiniciar
azurite --silent --location c:\azurite
Erro: "Azure Document Intelligence unauthorized"¶
# Verificar API Key
dotnet user-secrets list | findstr "DocumentIntelligence"
# Regenerar no Portal Azure se necessário
Erro: "Hangfire schema not found"¶
# Executar migrations
dotnet ef database update --project src/Modules/Documents/Infrastructure --context DocumentsDbContext
# Verificar schema
psql -U postgres -d meajudaai -c "\dn"
Melhorias Futuras¶
1. Type-Safety no Repositório¶
Sugestão: Usar DocumentId ao invés de Guid nas assinaturas:
// Atual
Task<Document?> GetByIdAsync(Guid id, ...);
// Proposto
Task<Document?> GetByIdAsync(DocumentId id, ...);
Status: ⏸️ Adiado para v2
Razão: Manter consistência com outros módulos (Users, Providers usam Guid). Revisar em refatoração cross-module.
2. IDateTimeProvider no Domain¶
Sugestão: Injetar IDateTimeProvider ao invés de DateTime.UtcNow:
// Atual
public static Document Create(...)
{
UploadedAt = DateTime.UtcNow
}
// Proposto
public static Document Create(..., IDateTimeProvider dateTimeProvider)
Status: ⏸️ Adiado para v2
Razão:
- Viola princípios DDD (agregados devem ser self-contained)
- Testes atuais já validam timestamps com tolerância (BeCloseTo)
- Alternativa: usar factories se necessário
3. Domain Event para Falhas¶
Sugestão: Adicionar DocumentFailedDomainEvent e separar FailureReason de RejectionReason.
Status: ⏸️ Adiado para v2
Razão: MVP não requer rastreamento detalhado de falhas técnicas. Implementar quando houver dashboard de monitoramento ou SLA tracking.
4. Azurite em Testes de Integração¶
Sugestão: Configurar Azurite no TestContainerTestBase para eliminar fallback error-tolerant:
private AzuriteContainer _azuriteContainer;
public override async Task InitializeAsync()
{
_azuriteContainer = new AzuriteBuilder().Build();
await _azuriteContainer.StartAsync();
}
Status: ✅ TODO criado
Prioridade: Alta - melhora confiabilidade de CI/CD
5. Input Guards no Agregado¶
Sugestão: Adicionar validações no factory method Document.Create().
Status: ❌ Não implementar
Razão: Validação já ocorre em UploadDocumentCommandHandler (Application layer). Command validation é responsabilidade da camada de aplicação (padrão CQRS).
Resumo de Status¶
| Melhoria | Status | Prioridade | Revisar quando |
|---|---|---|---|
| DocumentId no Repository | ⏸️ Adiado | Baixa | Refatoração cross-module |
| IDateTimeProvider no Domain | ⏸️ Adiado | Baixa | Time travel testing necessário |
| DocumentFailedDomainEvent | ⏸️ Adiado | Média | Dashboard de monitoramento |
| Azurite em E2E tests | ✅ TODO | Alta | Sprint atual |
| Input guards no agregado | ❌ Não implementar | N/A | Se factory ficar público |
Referências¶
- Azure Blob Storage Documentation
- Azure Document Intelligence Documentation
- Hangfire Documentation
- Azurite Emulator
Última atualização: 2025-11-14
Próxima revisão: 2025-12-01