Skip to content

Captura Rapida multimodal, fluxo completo de incidentes e reorganizacao de integracoes - #11

Merged
janeiaraujo merged 13 commits into
mainfrom
feat/quick-capture-e-incidentes
Aug 3, 2026
Merged

Captura Rapida multimodal, fluxo completo de incidentes e reorganizacao de integracoes#11
janeiaraujo merged 13 commits into
mainfrom
feat/quick-capture-e-incidentes

Conversation

@janeiaraujo

Copy link
Copy Markdown
Owner

Resumo

Captura Rápida multimodal

  • Ditado por voz (Web Speech API do navegador) para os campos de problema e solução
  • Colar/anexar screenshots (clique, arrastar ou Ctrl+V), com legenda automática via IA (visão, gpt-4o-mini)
  • Campo dedicado para logs/stack trace, aproveitado no prompt de geração do KB
  • Seção "Evidências" anexada automaticamente ao artigo com as imagens reais (não depende da IA reproduzir URLs)
  • Criação rápida de tag/categoria direto no seletor (TagSelector/CategorySelector), refletindo também em Criar KB e Editar KB

Fluxo completo de incidentes

  • Corrigido bug real: POST /events/:id/convert-to-incident quebrava com ReferenceError (variável nunca definida)
  • IncidentList/IncidentView/EventList reescritas — eram stubs sem nenhuma função real
  • Máquina de estados do incidente: aberto → reconhecido → resolvido, com transições validadas (PATCH /incidents/:id/status)
  • Ingestão de eventos (Zabbix, Grafana, Datadog, Sentry) com abertura automática de incidente, opt-in por token e piso de severidade configurável
  • Ao resolver um incidente, sugestão (não forçada) de criar KB e/ou post-mortem, pré-preenchidos e vinculados de volta

Integrações reorganizadas em Entrada/Saída

  • Gestão de tokens de ingestão movida de Eventos para Integrações → Entrada, com cards no mesmo padrão visual da Saída
  • PagerDuty e Datadog migrados de Saída para Entrada (eram os únicos sem envio de notificação implementado, e sua descrição já era de recebimento de alerta)
  • Exemplo de curl pronto para copiar, com token e URL reais após criar o token

Correções e infraestrutura

  • CI (GitHub Actions) + smoke test do backend (boot, /health, login, rota protegida)
  • README traduzido para inglês (README.en.md)
  • <ToastContainer /> nunca estava montado — 9 arquivos chamando toast.*() não mostravam nada ao usuário
  • Bug de case-sensitivity (pages/auth vs pages/Auth) que quebrava o build em Linux
  • Versão exibida na UI dessincronizada do package.json
  • Botão de recolher/expandir da sidebar sumindo em modo claro (vazamento de layout no estado colapsado)
  • Endpoint de ingestão quebrava com tenant sem assinatura ativa (comum em self-hosted sem billing)
  • backend/scripts/seed-sample-data.js agora também popula incidentes/eventos de exemplo

Versão: 2.0.02.1.0 (backend e frontend).

Test plan

  • cd backend && npm install && npm run migrate && npm run seed && npm test
  • cd frontend && npm install && npm run build
  • Rodar local, testar Captura Rápida: ditado por voz, colar uma imagem, colar um log
  • node backend/scripts/seed-sample-data.js e conferir os incidentes/eventos de exemplo em /incidents e /events
  • Criar um token em Integrações → Entrada e enviar o curl de exemplo para /api/events/ingest
  • Testar transições de status de um incidente (reconhecer → resolver → reabrir) e as sugestões de KB/post-mortem ao resolver

Fecha as 3 lacunas apontadas antes de divulgar o projeto: build/CI
visivel via badge, smoke test do backend (boot, /health, login e rota
protegida) rodando a cada push/PR, e traducao completa do README para
ampliar a base de contribuidores.
App.jsx importava de "./pages/auth/..." (minusculo), mas o diretorio
estava como "Auth" (maiusculo) no disco. Funcionava por acaso em
sistemas de arquivos case-insensitive (macOS/Windows), mas quebrava
o build/dev server em Linux com "Failed to resolve import". Renomeado
para "auth", em linha com o padrao das demais pastas (kb, incidents,
gps, postmortem, settings).
A sidebar mostrava "v2.0" como string fixa, dessincronizada do
package.json (que estava em 1.0.0) — o badge de versao do README, que
le o backend/package.json, mostrava um numero diferente do que
aparecia na tela. Agora a versao e injetada em build time a partir do
package.json do frontend (vite.config.js define __APP_VERSION__), e
os dois package.json (backend e frontend) foram alinhados em 2.0.0,
que e a versao real do estado atual do projeto.
A causa nao era de cor por tema, e sim de layout: com a sidebar
colapsada (70px), o icone (40px) e o botao (28px) nao cabiam lado a
lado no espaco disponivel, entao o botao vazava para fora da caixa
escura da sidebar e caia sobre o fundo do conteudo principal. Em modo
escuro esse fundo tambem e escuro (o vazamento passava despercebido);
em modo claro o fundo e branco, escondendo o botao translucido.

Corrigido empilhando icone e botao em coluna quando colapsado, para
que os dois caibam dentro da largura reduzida da sidebar.
A acao ja existia escondida no dropdown mobile, mas nao tinha atalho
visivel no desktop -- ficava a dois cliques (abrir menu do usuario ou
navegar pela sidebar) para uma funcionalidade central do produto
(capturar incidente durante a emergencia). Agora aparece ao lado do
"Novo KB" no header, com estilo outline para nao competir com a acao
primaria.
… de tags/categorias

A Captura Rapida so aceitava texto. Agora tambem aceita:
- Ditado por voz (Web Speech API do navegador) para os campos de
  problema e solucao, com preview do trecho ainda nao finalizado.
- Colar/anexar uma ou mais capturas de tela do erro (clique, arrastar
  ou Ctrl+V), com descricao automatica via IA (visao, gpt-4o-mini) que
  o usuario pode editar.
- Colar logs/stack traces num campo dedicado.

O backend usa esses dados para gerar um KB mais assertivo: logs e
descricoes de imagem entram no prompt da IA, e uma secao de
Evidencias e anexada automaticamente ao artigo com os links reais das
imagens (nao dependendo da IA reproduzir URLs).

Tambem: TagSelector e CategorySelector (usados na Captura Rapida, em
KBCreate e em KBEdit) agora permitem criar uma tag ou categoria nova
direto no seletor quando ela ainda nao existe, em vez de precisar sair
do fluxo para cadastrar em Configuracoes.

Novos endpoints: POST /api/ai/describe-image (legenda de screenshot
via visao). Quick-capture agora aceita logs e images no corpo.
… paginas reais

As paginas de Incidentes e Eventos eram stubs (botao "New Incident" nao
fazia nada, listas sempre vazias), e o endpoint de conversao de evento
em incidente tinha um bug real: referenciava uma variavel `objectId`
nunca definida, quebrando com erro toda chamada.

Reescrito seguindo o modelo de lifecycle mais comum em ferramentas de
on-call (PagerDuty/Opsgenie):

- Ingestao de eventos (Zabbix, Grafana, Datadog, Sentry, etc.) via
  POST /api/events/ingest, agora com gestao de tokens de verdade:
  criar/listar/revogar por fonte, cada um com um piso de severidade
  opcional para abrir incidente automaticamente (opt-in, evita fadiga
  de alerta abrindo incidente para todo ruido). O valor do token so e
  mostrado uma vez na criacao.
- Maquina de estados do incidente: aberto -> reconhecido (pausa a
  notificacao enquanto alguem trabalha nele) -> resolvido, com
  timestamps e validacao de transicao (PATCH /:id/status).
- Ao resolver, sugere (sem forcar) criar KB e, se a severidade
  justificar, criar post-mortem - ambos pre-preenchidos a partir do
  incidente e linkados de volta a ele.
- IncidentList/IncidentView/EventList reescritas do zero: listagem
  real, criacao, timeline, notas, e o painel de fontes de eventos.

Corrigido de quebra: <ToastContainer /> nunca estava montado - os 9
arquivos que chamam toast.success()/error() nao mostravam nada ao
usuario. Endpoint de ingestao tambem nao tratava tenant sem assinatura
ativa (comum em instancias self-hosted sem billing) - quebrava com
TypeError em vez de simplesmente nao aplicar limite.
Cobre os tres estados do lifecycle de incidente (aberto, reconhecido,
resolvido), um incidente aberto automaticamente a partir de um evento
critico (simulando o /api/events/ingest de verdade), um incidente
resolvido com KB vinculado (simulando o resultado da Captura Rapida
disparada a partir dele), e 3 eventos ainda nao convertidos para
testar o botao "Converter em incidente" na tela de Eventos.

Reestruturado para checar cada colecao (records/incidents) de forma
independente, em vez de um unico early-return que pulava tudo se o
tenant ja tivesse KBs - agora da pra rodar de novo so pra popular
incidentes numa instancia que ja tem KBs seedadas.

Documentado no README (PT/EN), que nunca mencionava esse script.
…rada/Saida

A gestao de tokens de ingestao (Zabbix/Grafana/Datadog/Sentry) estava
na tela de Eventos, meio deslocada do resto da configuracao de
integracoes. Movida para Integracoes, que agora tem duas abas:

- Entrada: fontes que enviam dados PARA DENTRO da plataforma (o que
  antes era "Fontes de Eventos" em Eventos).
- Saida: para onde a plataforma envia notificacoes (Slack, Teams,
  Email, Jira, PagerDuty - o que ja existia na aba unica anterior).

Eventos agora so lista os eventos recebidos, com um link para
Integracoes -> Entrada para configurar fontes.

Tambem adicionado exemplo de `curl` pronto para copiar (com token e
URL reais apos criar o token, e um exemplo generico com placeholder na
descricao da secao) - antes so tinha o JSON do payload, sem o comando
completo para testar via terminal ou colar na config de webhook da
ferramenta de origem.
…/Datadog

A aba Entrada tinha um card unico e generico de "Fontes de Eventos",
destoando do catalogo em cards (icone, cor, descricao, lista de
recursos, badge de status) usado na aba Saida. Reescrita para o mesmo
padrao: um card por fonte (Zabbix, Grafana, Datadog, Sentry,
PagerDuty, Customizado), badge com a contagem de tokens ativos, e os
tokens daquela fonte listados dentro do proprio card.

PagerDuty e Datadog saem da lista de integracoes de Saida e entram
como fontes em Entrada - la, o "sendNotification" so tinha
implementacao real para Slack/Teams; PagerDuty e Datadog so validavam
credenciais (test connection) sem nenhum envio de fato, e a descricao
de ambos ja era essencialmente de ingestao de alerta/monitoramento
("Criar incidentes automaticamente", "Alertas baseados em dados"),
que e exatamente o papel de Entrada.
Minor version para a leva de mudancas desta sessao: Captura Rapida
multimodal (voz, logs, imagens), fluxo completo de incidentes
(ingestao automatica, lifecycle, paginas reais), integracoes
reorganizadas em Entrada/Saida, CI/smoke test, README em ingles e
correcoes de bugs (case-sensitivity no build, versao dessincronizada
na UI, botao sumindo em modo claro, conversao de evento quebrada).
Copilot AI review requested due to automatic review settings August 3, 2026 14:49

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Not ready to approve

Há pelo menos um problema de segurança confirmado (URLs de imagens não validadas sendo persistidas/embutidas no Markdown) e alguns ajustes necessários para evitar falhas/leaks em runtime.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

This review doesn't count toward merge requirements. Sign up for the private preview to control whether Copilot approvals count.

Pull request overview

Atualiza a plataforma para suportar captura rápida multimodal (voz + logs + imagens), completar o fluxo de incidentes (status + conversão de eventos + sugestões pós-resolução) e reorganizar integrações em Entrada/Saída, além de adicionar CI com smoke test.

Changes:

  • Expande a Captura Rápida para incluir ditado por voz, anexos de imagem com legenda automática e campo de logs, vinculando KBs a incidentes.
  • Implementa fluxo funcional de Incidentes/Eventos (listas, visualização, conversão e máquina de estados com transições validadas).
  • Adiciona CI com smoke test do backend e build do frontend; inclui README em inglês e ajustes de UI (ToastContainer, versão dinâmica, sidebar).
File summaries
File Description
README.md Link para versão em inglês + badge de CI + scripts de seed/smoke test documentados.
README.en.md Novo README em inglês com onboarding, configuração e scripts.
frontend/vite.config.js Injeta __APP_VERSION__ via package.json no build.
frontend/src/services/api.js Expande APIs de incidentes/eventos e adiciona ai.describeImage.
frontend/src/pages/postmortem/PostMortemList.jsx Prefill via navigation state e auto-abertura do modal de criação.
frontend/src/pages/kb/QuickCapture.jsx Quick Capture multimodal (voz/logs/imagens) + selectors reutilizáveis + vínculo a incidente.
frontend/src/pages/Integrations.jsx Reorganiza UI em abas Entrada/Saída e inclui InboundEventSources.
frontend/src/pages/incidents/IncidentView.jsx Tela de incidente completa (timeline, notas, transições de status, sugestões KB/postmortem).
frontend/src/pages/incidents/IncidentList.jsx Lista funcional com filtro por status e modal de criação.
frontend/src/pages/events/EventList.jsx Lista funcional de eventos + conversão para incidente e link para integrações de entrada.
frontend/src/pages/auth/Register.jsx Nova tela de registro.
frontend/src/pages/auth/MagicLink.jsx Nova tela de verificação de magic link.
frontend/src/pages/auth/Login.jsx Nova tela de login com opção de magic link.
frontend/src/components/VoiceRecorderButton.jsx Botão de ditado por voz via Web Speech API.
frontend/src/components/tags/TagSelector.jsx Quick-create de tags/categorias no seletor.
frontend/src/components/Sidebar.jsx Exibe versão via __APP_VERSION__.
frontend/src/components/Sidebar.css Corrige layout do botão de colapsar em modo colapsado/tema claro.
frontend/src/components/Layout.jsx Adiciona botão de acesso rápido à Captura Rápida no header.
frontend/src/components/integrations/InboundEventSources.jsx Novo catálogo/gerenciamento de tokens para ingestão de eventos (Entrada).
frontend/src/components/ImageAttachments.jsx Novo componente de anexos de imagem com upload + legenda via IA.
frontend/src/App.jsx Monta ToastContainer globalmente.
frontend/package.json Atualiza versão do frontend para 2.1.0.
CONTRIBUTING.md Passo de smoke test (npm test) no backend antes de abrir PR.
backend/src/seeds/index.js Seed atualiza token de ingestão para novo schema (label/source/...).
backend/src/modules/integrations/integrations.routes.js Remove PagerDuty/Datadog da lista de “saída” (agora são “entrada”).
backend/src/modules/incidents/incidents.routes.js Quick Capture passa a aceitar logs/imagens e adiciona status lifecycle + endpoint de transição.
backend/src/modules/events/events.routes.js Ingestão por token + tokens CRUD + auto-abertura de incidente por threshold + conversão robusta.
backend/src/modules/ai/ai.routes.js Adiciona endpoint de visão para descrever imagens (/ai/describe-image).
backend/scripts/smoke-test.js Novo smoke test de boot/health/auth/rota protegida.
backend/scripts/seed-sample-data.js Seed adicional agora inclui incidentes/eventos de exemplo cobrindo o lifecycle.
backend/package.json Atualiza versão do backend para 2.1.0 e adiciona npm test/smoke-test.
backend/.env.example Adiciona BACKEND_PUBLIC_URL para URLs públicas (uploads/ingest).
.github/workflows/ci.yml Novo CI: backend (mongo+migrate+seed+smoke) e frontend (build).
Review details

Suppressed comments (1)

frontend/src/components/ImageAttachments.jsx:111

  • Ao remover uma imagem, o blob URL (preview) não é revogado. Isso mantém o objeto em memória mesmo após remoção do item.
  const handleRemove = (localId) => {
    setImages(prev => {
      const img = prev.find(i => i.localId === localId);
      if (img?.fileId) fileAPI.delete(img.fileId).catch(() => {});
      return prev.filter(i => i.localId !== localId);
  • Files reviewed: 30/33 changed files
  • Comments generated: 6
  • Review effort level: Lite

We're testing this review assessment. Please use 👍 or 👎 to tell us if it's correct.

Comment on lines +37 to +39
const cleanImages = Array.isArray(images)
? images.filter(img => img && typeof img.url === 'string').slice(0, 10)
: [];
Comment on lines +205 to +207
affected_services: affected_services || '',
logs: cleanLogs || undefined,
images: cleanImages.length ? cleanImages : undefined
Comment on lines +55 to +62
try {
const { data } = await fileAPI.upload(file);
updateImage(entry.localId, {
fileId: data.fileId,
url: data.url,
uploading: false,
describing: true
});
Comment on lines +87 to +89
<td className="text-muted small">
{formatDistanceToNow(new Date(ev.created_at), { addSuffix: true, locale: ptBR })}
</td>
Comment on lines +117 to +120
<p className="text-muted small">
Incidentes também podem ser abertos automaticamente a partir de eventos monitorados.
Veja <a href="/events">Eventos</a> para configurar as fontes.
</p>
Comment on lines +3 to +4
import { formatDistanceToNow } from 'date-fns';
import { ptBR } from 'date-fns/locale';
Adiciona um job rapido que falha o CI se backend/package.json e
frontend/package.json estiverem com versoes diferentes - pega o
esquecimento antes do merge, nao so na hora de tagear a release.
Espelha o que foi adicionado ao README.md (PT) no PR de automacao de
release: badge de "release" e a secao explicando o fluxo de tag/release
automatico.
@janeiaraujo
janeiaraujo merged commit 94da45d into main Aug 3, 2026
2 of 3 checks passed
@janeiaraujo
janeiaraujo deleted the feat/quick-capture-e-incidentes branch August 3, 2026 18:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants