# Operações — Sistema de Chamados (Prod)

Este documento consolida as mudanças recentes, o racional por trás delas e o procedimento de operação/deploy (Web e Convex self‑hosted) do ambiente em produção.

## 1) Mudanças Funcionais (Front + Server)

- Empresas (admin)
  - “Slug” renomeado para “Apelido” (mensagens e placeholders ajustados).

- Fila padrão ao criar tickets
  - Todo novo ticket entra na fila “Chamados”.
  - Implementado no backend (fallback) e pré‑seleção na UI.

- Status de tickets e interações
  - Nomes/cores atualizados:
    - Pendente (cinza), Em andamento (azul), Pausado (amarelo), Resolvido (verde).
  - Transições automáticas:
    - Iniciar (play) → status “Em andamento”.
    - Pausar → status “Pausado”.
  - “Encerrar” permanece manual. O dropdown foi substituído por badge + botão “Encerrar”.
  - Diálogo de encerramento: botão “Cancelar” adicionado (além de “Limpar mensagem”/“Encerrar ticket”).

- Dashboard — Últimos chamados
  - Prioridade: sem responsável primeiro (dos mais antigos para os mais recentes), depois demais chamados.

- Filtros de tickets
  - Filtro por “Responsável” (agente/admin) adicionado.
  - Salvar filtro como padrão por usuário (localStorage) + “Limpar padrão”.
  - Empresas no filtro: lista completa via API admin (não só empresas presentes em tickets).
  - Produção: filtro “Responsável” agora é feito no servidor (assigneeId); o front não envia mais parâmetros inválidos.

- Editor de comentários (Tiptap)
  - Correção: reativar edição quando um responsável é atribuído (o editor agora reflete mudanças em `disabled` via `setEditable`).

## 2) Convex (Self‑Hosted) — Ajustes e Motivo

- Problema observado: deploy do Convex falhava no CI por:
  - Ausência de `convex.json` (link do projeto) no servidor.
  - Uso incorreto de `CONVEX_DEPLOYMENT` junto a `CONVEX_SELF_HOSTED_URL` + `CONVEX_SELF_HOSTED_ADMIN_KEY` (não suportado pelo CLI ao usar self‑hosted).
  - Divergência de schema (campo `provisioningCode` já existente nos dados, mas ausente no schema do Convex no servidor).

- Medidas aplicadas:
  - Atualização do schema do Convex no servidor: inclusão de `provisioningCode?: string` na tabela `companies` (e índice opcional `by_provisioning_code`).
  - Criação do link de projeto (`convex.json`) no servidor via wizard do CLI (ver Passo a passo abaixo).
  - Ajustes no workflow do GitHub Actions para self‑hosted:
    - Adicionado passo “Acquire Convex admin key” no job de deploy do Convex.
    - Removido `CONVEX_DEPLOYMENT` quando `CONVEX_SELF_HOSTED_URL` + `CONVEX_SELF_HOSTED_ADMIN_KEY` estão definidos.
    - Cópia automática do `convex.json` de `/srv/apps/sistema` para o diretório de build temporário.
  - Forçar redeploy das funções: tocar arquivos sob `convex/**` para acionar o filtro do job “Deploy Convex functions”.

## 3) CI/CD — Visão Geral

- Pipeline “CI/CD Web + Desktop” (GitHub Actions)
  - Job “Detect changes” usa filtros por paths.
  - Job “Deploy (VPS Linux)” cuida do Web (Next.js) e stack do Swarm.
  - Job “Deploy Convex functions” roda quando há mudanças em `convex/**` ou via `workflow_dispatch`.
    - Passos relevantes:
      - “Acquire Convex admin key” (via container `sistema_convex_backend`).
      - “Bring convex.json from live app if present” (usa o arquivo de link do projeto em `/srv/apps/sistema`).
      - “convex env list” e “convex deploy” com `CONVEX_SELF_HOSTED_URL` + `CONVEX_SELF_HOSTED_ADMIN_KEY`.

## 4) Troca de colaborador / reaproveitamento de dispositivo

Quando um computador muda de dono (ex.: João entrega o equipamento antigo para Maria e recebe uma dispositivo nova), siga este checklist para manter o inventário consistente:

1. **No painel (Admin → Dispositivos)**
   - Abra os detalhes da dispositivo que será reaproveitada (ex.: a “amarela” que passará da TI/João para a Maria).
   - Clique em **Resetar agente**. Isso revoga todos os tokens gerados para aquele equipamento; ele precisará ser reprovisionado antes de voltar a reportar dados.
   - Abra **Ajustar acesso** e altere o e-mail para o do novo usuário (Maria). Assim, quando o agente se registrar novamente, o painel já mostrará a responsável correta.

2. **Na dispositivo física que ficará com o novo colaborador**
   - Desinstale o desktop agent (Painel de Controle → remover programas).
   - Instale novamente o desktop agent. Use o mesmo **código da empresa/tenant** e informe o **e-mail do novo usuário** (Maria). O backend emite um token novo e reaproveita o registro da dispositivo, mantendo o histórico.

3. **Dispositivo nova para o colaborador antigo**
   - Instale o desktop agent do zero na dispositivo que o João vai usar (ex.: a “azul”). Utilize o mesmo código da empresa e o e-mail do João.
   - A dispositivo azul aparecerá como um **novo registro** no painel (inventário/tickets começarão do zero). Renomeie/associe conforme necessário.

4. **Verificação final**
   - A dispositivo antiga (amarela) continua listada, agora vinculada à Maria, com seus tickets históricos.
   - A dispositivo nova (azul) aparece como um segundo registro para o João. Ajuste hostname/descrição para facilitar a identificação.

> Não é necessário excluir registros. Cada dispositivo mantém seu histórico; o reset garante apenas que o token antigo não volte a sobrescrever dados quando o hardware mudar de mãos.
    - Importante: não usar `CONVEX_DEPLOYMENT` em conjunto com URL + ADMIN_KEY.

- Como forçar o deploy do Convex
  - Faça uma alteração mínima em `convex/**` (ex.: comentário em `convex/tickets.ts`) ou rode o workflow em “Run workflow” (workflow_dispatch).

## 4) Convex — Provisionamento inicial (self‑hosted)

Executar apenas 1x na VPS para criar o link do projeto (`convex.json`):

```bash
cd /srv/apps/sistema
export CONVEX_SELF_HOSTED_URL="https://convex.esdrasrenan.com.br"
CID=$(docker ps --format '{{.ID}} {{.Names}}' | awk '/sistema_convex_backend/{print $1; exit}')
export CONVEX_SELF_HOSTED_ADMIN_KEY="$(docker exec -i "$CID" /bin/sh -lc './generate_admin_key.sh' | tr -d '\r' | grep -o 'convex-self-hosted|[^ ]*' | tail -n1)"

npx convex dev --once --configure=new
# Siga o wizard (self-hosted) e vincule/crie o projeto/deployment (ex.: "sistema" / "default").
# Isso gera /srv/apps/sistema/convex.json
```

Depois disso, o job “Deploy Convex functions” funciona em modo não interativo.

## 5) VPS — Acesso e Serviços

- Acesso
  - Host: `31.220.78.20`
  - Usuário: `root`
  - Chave SSH (repo raiz): `./codex_ed25519` (Atenção: manter permissões 600)
    - Exemplo: `ssh -i ./codex_ed25519 root@31.220.78.20`
  - Opcional (endurecimento): desabilitar login por senha após validar a chave.

- Diretórios principais
  - Código do app: `/srv/apps/sistema`
  - Arquivo do projeto Convex: `/srv/apps/sistema/convex.json`
  - Stack do Swarm: `stack.yml` (no repositório; aplicado no servidor via CI).

- Serviços (Docker Swarm + Traefik)
  - Web (Next.js): serviço `sistema_web`, exposto em `tickets.esdrasrenan.com.br`.
  - Convex backend: serviço `sistema_convex_backend`, exposto em `convex.esdrasrenan.com.br`.
  - Convex dashboard: `convex-admin.esdrasrenan.com.br`.
  - Comandos úteis:
    - `docker service ls`
    - `docker service ps sistema_web`
    - `docker service update --force sistema_web` (reiniciar)
    - `docker service update --force sistema_convex_backend` (reiniciar Convex)

- Convex admin key (diagnóstico)
  - `docker exec -i $(docker ps | awk '/sistema_convex_backend/{print $1; exit}') /bin/sh -lc './generate_admin_key.sh'`
  - Usada no CI para `convex env list` e `convex deploy`.

## 6) Notas de Segurança

- A chave privada `codex_ed25519` está na raiz do repo (ambiente atual). Em produção, recomenda‑se:
  - Remover a chave do repositório ou armazená‑la em Secrets/Deploy keys do provedor.
  - Desabilitar login por senha no SSH (apenas chave).
  - Manter permissões: `chmod 600 ./codex_ed25519`.

## 7) Testes, Build e Lint

- Local
  - `bun run build:bun` (Next + typecheck)
  - `bun run lint`
  - `bun test`

- CI garante build, lint e testes antes do deploy.

## 8) Troubleshooting Rápido

- “No CONVEX_DEPLOYMENT set” durante o deploy do Convex
  - Certifique‑se de que `/srv/apps/sistema/convex.json` existe (rodar wizard `npx convex dev --once --configure=new`).
  - Não usar `CONVEX_DEPLOYMENT` com `CONVEX_SELF_HOSTED_URL` + `CONVEX_SELF_HOSTED_ADMIN_KEY`.

- Login quebrando com erro de `better_sqlite3` (NODE_MODULE_VERSION)
  - Sintoma: HTTP 500 em `/api/auth/sign-in/email` e logs do `sistema_web` com “Could not locate the bindings file” ou “compiled against NODE_MODULE_VERSION 115”.
  - Causa: o `better-sqlite3` precisa ser recompilado para a versão de Node em uso (rodamos Node 22 dentro do container).
  - Correção (uma vez, após trocar versão de Node/Bun ou limpar `node_modules`):
    ```
    docker run --rm -v /apps/sistema:/app sistema_web:node22-bun \
      bash -lc "cd /app && npm rebuild better-sqlite3"
    docker service update --force sistema_web
    ```
    Isso grava o binário em `/apps/sistema/node_modules/.bun/better-sqlite3@11.10.0/...` (path montado pelo serviço).
  - Flags no serviço (stack.yml):
    - `SKIP_APT_BOOTSTRAP=true` evita apt-get no boot (imagem já tem toolchain).
    - `SKIP_SQLITE_REBUILD=true` deixa o boot rápido; deixe como `true` depois de recompilar manualmente como acima.

- “Schema validation failed” (campo extra `provisioningCode`)
  - Atualize o schema do Convex no servidor para incluir `provisioningCode?: string` em `companies`.
  - Refaça o deploy.

- Filtro “Responsável” não funciona
  - Front envia `assigneeId` e o backend Convex deve aceitar esse parâmetro (função `tickets.list`).
  - Se necessário, forçar redeploy das funções (`convex/**`).

- Admin ▸ Dispositivos travado em skeleton infinito
  - Abra o DevTools (console) e filtre por `admin-machine-details`. Se o log mostrar `machineId: undefined`, o componente não recebeu o parâmetro da rota.
  - Verifique se o `page.tsx` está passando `params.id` corretamente ou se o componente client-side usa `useParams()` / `machineId` opcional.
  - Deploys antigos antes de `fix(machines): derive machine id from router params` precisam desse patch; sem ele o fallback nunca dispara e o skeleton permanece.
- Export do Convex em loop (`application::exports::worker`)
  - Sintoma: WebSocket `1006`, logs com `Caught error ... shape_inference`, `Export <id> beginning...` repetindo.
  - Solução completa documentada em `docs/convex-export-worker-loop.md` (backup do SQLite, limpeza dos registros defeituosos e rerun do export).

---

Última atualização: sincronizado após o deploy bem‑sucedido do Convex e do Front (20/10/2025).

## 9) Admin ▸ Usuários e Dispositivos — Unificação e UX

Resumo das mudanças aplicadas no painel administrativo para simplificar “Usuários” e “Agentes de dispositivo” e melhorar o filtro em Dispositivos:

- Unificação de “Usuários” e “Agentes de dispositivo”
  - Antes: abas separadas “Usuários” (pessoas) e “Agentes de dispositivo”.
  - Agora: uma só aba “Usuários” com filtro de tipo (Todos | Pessoas | Dispositivos).
  - Onde: `src/components/admin/admin-users-manager.tsx:923`, aba `value="users"` em `:1147`.
  - Motivo: evitar confusão entre “usuário” e “agente”; agentes são um tipo especial de usuário (role=machine). A unificação torna “Convites e Acessos” mais direta.

- Dispositivos ▸ Filtro por Empresa com busca e remoção do filtro de SO
  - Adicionado dropdown de “Empresa” com busca (Popover + Input) e removido o filtro por Sistema Operacional.
  - Onde: `src/components/admin/devices/admin-devices-overview.tsx:1038` e `:1084`.
  - Motivo: fluxo real usa empresas com mais frequência; filtro por SO era menos útil agora.

- Windows ▸ Rótulo do sistema sem duplicidade do “major”
  - Exemplo: “Windows 11 Pro (26100)” em vez de “Windows 11 Pro 11 (26100)”.
  - Onde: `src/components/admin/devices/admin-devices-overview.tsx` (função `formatOsVersionDisplay`).
  - Motivo: legibilidade e padronização em chips/cartões.

- Vínculos visuais entre dispositivos e pessoas
  - Cards de dispositivos mostram “Usuário vinculado” quando disponível (assignment/metadata): `src/components/admin/devices/admin-devices-overview.tsx:3198`.
  - Editor de usuário exibe “Dispositivos vinculadas” (derivado de assign/metadata): `src/components/admin/admin-users-manager.tsx` (seção “Dispositivos vinculadas” no sheet de edição).
  - Observação: por ora é leitura; ajustes detalhados de vínculo permanecem em Admin ▸ Dispositivos.

### Identidade, e‑mail e histórico (reinstalação)

- Identificador imutável: o histórico (tickets, eventos) referencia o `userId` (imutável). O e‑mail é um atributo mutável.
- Reinstalação do desktop para o mesmo colaborador: reutilize a mesma conta de usuário (mesmo `userId`); se o e‑mail mudou, atualize o e‑mail dessa conta no painel. O histórico permanece, pois o `userId` não muda.
- Novo e‑mail como nova conta: se criar um usuário novo (novo `userId`), será considerado um colaborador distinto e não herdará o histórico.
- Caso precise migrar histórico entre contas diferentes (merge), recomendamos endpoint/rotina de “fusão de contas” (remapear `userId` antigo → novo). Não é necessário para a troca de e‑mail da mesma conta.

### Vínculos múltiplos de usuários por dispositivo (Fase 2)

- Estrutura (Convex):
  - `machines.linkedUserIds: Id<"users">[]` — lista de vínculos adicionais além do `assignedUserId` (principal).
  - Mutations: `machines.linkUser(machineId, email)`, `machines.unlinkUser(machineId, userId)`.
  - APIs admin: `POST /api/admin/devices/links` (body: `{ machineId, email }`), `DELETE /api/admin/devices/links?machineId=..&userId=..`.
- UI:
  - Detalhes da dispositivo mostram “Usuários vinculados” com remoção por item e campo para adicionar por e‑mail.
  - Editor de usuário mostra “Dispositivos vinculadas” consolidando assignment, metadata e `linkedUserIds`.
- Racional: permitir que uma dispositivo tenha mais de um colaborador/gestor associado, mantendo um “principal” (persona) para políticas e contexto.

### Onde editar

- Usuários (pessoas): editar nome, e‑mail, papel, tenant e empresa; redefinir senha pelo painel. Arquivo: `src/components/admin/admin-users-manager.tsx`.
- Agentes (dispositivos): provisionamento automático; edição detalhada/vínculo principal em Admin ▸ Dispositivos. Arquivo: `src/components/admin/devices/admin-devices-overview.tsx`.

> Observação operacional: mantivemos o provisionamento de dispositivos inalterado (token/e‑mail técnico), e o acesso web segue apenas para pessoas. A unificação é de UX/gestão.
