Skip to content

About

Triagem inteligente de atendimentos com IA: recebe mensagens de marketplaces, classifica em segundo plano e prioriza em um dashboard Blazor. .NET 10, Transactional Outbox, MySQL e modo demo sem dependências externas.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

TriageFlow

Triagem inteligente de atendimentos com IA — .NET 10, Blazor, MySQL e arquitetura orientada a eventos.

CI .NET 10 Blazor MySQL 8 Licença

O TriageFlow recebe mensagens de clientes vindas de vários canais de venda (Mercado Livre, Amazon, Shopee, TikTok Shop, Magalu e e-commerce próprio), protege o conteúdo, classifica cada atendimento em segundo plano com IA e organiza tudo em um quadro priorizado para a equipe de SAC.

A IA não decide sozinha: ela devolve sinais estruturados e a prioridade é calculada por uma regra determinística, auditável e coberta por testes. O sistema também nunca responde ao cliente automaticamente — uma falha de IA não pode gerar uma resposta insegura.

Projeto de portfólio. Todas as mensagens exibidas no modo demonstração são fictícias.

Quadro de prioridades do TriageFlow em modo demonstração

Experimente em 1 minuto

Pré-requisito: .NET SDK 10. Não é necessário instalar banco de dados, criar conta na nuvem ou ter chave da OpenAI.

# Windows (PowerShell)
./run-demo.ps1
# Linux / macOS
./run-demo.sh

Depois abra http://localhost:5131/classificacoes.

Windows: alguns arquivos têm nomes longos. Clone em uma pasta curta (por exemplo, C:\dev\triageflow) ou habilite caminhos longos antes de clonar: git config --global core.longpaths true.

Prefere rodar manualmente? Use dois terminais:

dotnet run --project TriageFlow.Api --launch-profile demo
dotnet run --project TriageFlow.Web --launch-profile demo

O que o modo demonstração faz

Componente Modo completo Modo demonstração
Banco de dados MySQL 8 com migrations e procedures Banco em memória (Persistence:Provider=InMemory)
Dados Mensagens reais dos canais 35 mensagens fictícias embutidas na solução
Login Microsoft Entra ID com roles Visitante fictício (Authentication:Mode=Demo)
Classificador OpenAI (Responses API) Fake, baseado em palavras-chave
Processamento assíncrono Worker separado lendo a Outbox Despachante da Outbox dentro da API
Criptografia Chave no Azure Key Vault Chave AES-256 efêmera gerada na inicialização

As mensagens fictícias não são gravadas direto como classificações: na inicialização, cada uma percorre o pipeline real — validação, criptografia, Outbox, sanitização de dados sensíveis, classificador, validação do resultado e cálculo da prioridade. Os dados são recriados a cada execução.

Por segurança, o banco em memória e o login fictício são rejeitados na inicialização fora do ambiente Development.

Veja o pipeline funcionando ao vivo

Com a demonstração rodando, envie uma nova mensagem. Ela aparece classificada no quadro em cerca de dois segundos:

$agora = (Get-Date).ToUniversalTime().ToString('o')
Invoke-RestMethod -Method Post -Uri http://localhost:5213/api/v1/messages/inbound `
  -ContentType 'application/json; charset=utf-8' -Body (@{
    eventId = [guid]::NewGuid(); channel = 'shopee'; channelAccountId = 'loja-demo'
    externalMessageId = "teste-$([guid]::NewGuid())"
    content = 'Meu pedido está atrasado e a data prometida já passou.'
    occurredAtUtc = $agora; receivedAtUtc = $agora
  } | ConvertTo-Json)

Também há exemplos prontos em TriageFlow.Api/TriageFlow.Api.http.

Destaques técnicos

  • Transactional Outbox: ticket, mensagem cifrada e evento são gravados na mesma transação; o recebimento nunca espera a IA.
  • Worker com reserva concorrente de lotes (FOR UPDATE SKIP LOCKED), retry exponencial só para falhas transitórias, dead letter e fila de revisão humana.
  • Idempotência ponta a ponta: reenvios do mesmo evento devolvem o recibo existente, sem duplicar tickets ou classificações.
  • Privacidade por padrão: AES-GCM no conteúdo, mascaramento de CPF, e-mail, telefone e cartão antes da IA, contratos de leitura sem texto do cliente e auditoria com identidades pseudonimizadas por SHA-256.
  • Prioridade determinística calculada em C#, fora do modelo de IA.
  • IA substituível atrás de ITicketClassifier, com circuit breaker, saída estruturada por JSON Schema e proteção contra prompt injection.
  • Segurança operacional: Entra ID com roles por endpoint, rate limiting, TLS obrigatório no MySQL fora de Development e segredos no Key Vault.
  • Observabilidade com OpenTelemetry: métricas de Outbox, latência, disponibilidade do classificador e consumo de tokens, sem dados sensíveis (catálogo).
  • Arquitetura verificada por testes: a direção das dependências entre projetos é validada automaticamente.
  • Integrações de marketplaces: OAuth do Mercado Livre, webhooks com idempotência e adaptadores para Shopee e Amazon.

Fluxo principal

Canal de venda
    |
    v
POST /api/v1/messages/inbound
    |
    +--> autentica, valida e normaliza
    +--> cifra o conteúdo original (AES-GCM)
    +--> grava ticket + mensagem + evento Outbox (mesma transação)
    |
    v
Worker consulta a Outbox
    |
    +--> reserva um lote de forma concorrente
    +--> lê e decifra a mensagem
    +--> sanitiza dados sensíveis
    +--> chama ITicketClassifier
    +--> valida, prioriza e grava a classificação
    |
    +--> sucesso: conclui o evento
    +--> falha transitória: agenda retry
    +--> falha definitiva: dead letter + revisão humana
    |
    v
GET /api/v1/tickets/classifications
    |
    v
TriageFlow.Web (quadro priorizado, somente leitura)

Uma explicação didática, com analogias e o fluxo classe a classe, está em docs/architecture.md.

Prioridades

A IA devolve sinais estruturados; a prioridade é calculada pela Application:

Condição Valor da API Exibição no Web
existe flag de risco critical Crítica
existe sinal de urgência high Alta
existe contexto obrigatório pendente medium Média
nenhuma condição anterior normal Normal

A taxonomia inicial ainda não define flags de risco, por isso a coluna "Crítica" permanece vazia na demonstração.

Projetos

Projeto Responsabilidade
TriageFlow.Domain Conceitos e regras puras, sem dependências técnicas
TriageFlow.Application Casos de uso, validações, taxonomia e abstrações
TriageFlow.Contracts Contratos HTTP e eventos de integração versionados
TriageFlow.AI Classificadores Fake e OpenAI
TriageFlow.Infrastructure MySQL, banco em memória, criptografia, Key Vault e Outbox
TriageFlow.Integrations.* Adaptadores de Mercado Livre, Shopee e Amazon
TriageFlow.Api Endpoints, autenticação, autorização e rate limiting
TriageFlow.Worker Processamento da Outbox, retry e revisão humana
TriageFlow.Web Dashboard Blazor somente leitura
TriageFlow.Evaluation Avaliação do classificador com datasets sintéticos, incluindo prompt injection
TriageFlow.*Tests Testes unitários, de integração, contrato e arquitetura
Domain         -> nenhuma dependência interna
Application    -> Domain
Contracts      -> nenhuma dependência interna
AI             -> Application
Infrastructure -> Application, Domain e Contracts
Api            -> Application, Contracts, Infrastructure e AI
Worker         -> Application, Contracts, Infrastructure e AI
Web            -> Contracts

Modo completo (MySQL, Entra ID e OpenAI)

Pré-requisitos: MySQL 8 com as migrations de database/migrations aplicadas em ordem, um app registrado no Microsoft Entra ID e, opcionalmente, uma chave da OpenAI.

Configure com User Secrets (nunca no repositório):

ConnectionStrings:SacDatabase
Security:MessageEncryption:Development:KeyId
Security:MessageEncryption:Development:KeyBase64
AzureAd:TenantId / AzureAd:ClientId
SacApi:BaseAddress / SacApi:Scopes
OPENAI_API_KEY (variável de ambiente, somente com o provedor OpenAI)

Execute API, Worker e Web com o perfil http ou https:

dotnet run --project TriageFlow.Api --launch-profile https
dotnet run --project TriageFlow.Worker
dotnet run --project TriageFlow.Web --launch-profile https

Convenções de banco: tabelas TB_, chaves ID_ e procedures UP_SEL_, UP_INS_ e UP_UPD_.

Testes

dotnet build .\TriageFlow.slnx --configuration Release -warnaserror
dotnet test .\TriageFlow.slnx --configuration Release --no-build

A suíte executa por padrão testes unitários, de integração (incluindo a API real em modo demonstração), de contrato para o JSON público V1 e de arquitetura. Os testes que exercitam um MySQL real são opt-in:

$env:TRIAGEFLOW_RUN_LOCAL_MYSQL_TESTS = "true"
dotnet test .\TriageFlow.IntegrationTests --filter "FullyQualifiedName~Database"

Roadmap em fases

  1. Classificar — centralizar, proteger, classificar, priorizar e exibir para triagem humana (implementado).
  2. Assistir — resumir conversas e sugerir respostas para aprovação.
  3. Automatizar com supervisão — responder casos autorizados e de baixo risco.
  4. Automatizar com controle — executar ações determinísticas, auditáveis e reversíveis, sempre com fallback humano.

Licença

© 2026 Ivan Massanares. Todos os direitos reservados.

O código está público somente para avaliação de portfólio: você pode ler e executar o projeto localmente para conhecer o trabalho. Copiar, modificar, redistribuir ou reutilizar qualquer parte exige autorização prévia por escrito. Veja LICENSE.

About

Triagem inteligente de atendimentos com IA: recebe mensagens de marketplaces, classifica em segundo plano e prioriza em um dashboard Blazor. .NET 10, Transactional Outbox, MySQL e modo demo sem dependências externas.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages