sistema-de-chamados/docs/DEV.md
rever-tecnologia 2682b6e8ac Adiciona endpoint de arquivamento e ajustes de infra
- Adiciona rota API para arquivar tickets por ID
- Atualiza configuracao do Prisma para PostgreSQL
- Simplifica workflow CI/CD
- Adiciona src/generated ao gitignore
- Atualiza documentacao e dependencias

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-11 13:25:36 -03:00

208 lines
11 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Guia de Desenvolvimento — 18/10/2025
Este documento consolida o estado atual do ambiente de desenvolvimento, descreve como rodar lint/test/build localmente (e no CI) e registra erros recorrentes com as respectivas soluções.
## Resumo rápido
- **Bun (runtime padrão)**: 1.3+ já instalado no runner e VPS (`bun --version`). Após instalar localmente, exporte `PATH="$HOME/.bun/bin:$PATH"` para tornar o binário disponível. Use `bun install`, `bun run dev:bun`, `bun run convex:dev:bun`, `bun run build:bun` e `bun test` como fluxo principal (scripts Node continuam disponíveis como fallback).
- **Node.js**: mantenha a versão 20.9+ instalada para ferramentas auxiliares (Prisma CLI, scripts legados em Node) quando não estiver usando o runtime do Bun.
- **Next.js 16**: Projeto roda em `next@16.0.8` com Turbopack como bundler padrão (dev e build); webpack continua disponível como fallback.
- **Lint/Test/Build**: `bun run lint`, `bun test`, `bun run build:bun`. O test runner do Bun já roda em modo não interativo; utilize `bunx vitest --watch` apenas quando precisar do modo watch manualmente.
- **Banco DEV**: PostgreSQL local (Docker recomendado). Defina `DATABASE_URL` apontando para seu PostgreSQL.
- **Desktop (Tauri)**: fonte em `apps/desktop`. Usa Radix tabs + componentes shadcn-like, integra com os endpoints `/api/machines/*` e suporta atualização automática via GitHub Releases.
- **CI**: Workflow `Quality Checks` roda lint/test/build para pushes e PRs na `main`, além do pipeline de deploy existente.
## Banco de dados (Prisma + PostgreSQL)
1. Suba um PostgreSQL local (Docker recomendado):
```bash
docker run -d --name postgres-dev -p 5432:5432 -e POSTGRES_PASSWORD=dev -e POSTGRES_DB=sistema_chamados postgres:18
```
2. Configure a `DATABASE_URL` no seu `.env`:
```
DATABASE_URL=postgresql://postgres:dev@localhost:5432/sistema_chamados
```
3. Gere/atualize o schema local:
```bash
bun install
bunx prisma db push
bun run prisma:generate
bun run auth:seed
```
4. Rode o app Next.js:
```bash
bun run dev:bun
```
> Alternativas: `bun run dev` (Node) ou `bun run dev:webpack` se precisar do fallback oficial.
5. Credenciais padrao (seed): `admin@sistema.dev / admin123`.
6. Herdou dados antigos? Execute `node scripts/remove-legacy-demo-users.mjs` para limpar contas demo legadas.
## Next.js 16 (estável)
- Mantemos o projeto em `next@16.0.8`, com React 19 e o App Router completo.
- **Bundlers**: Turbopack permanece habilitado no `next dev`/`bun run dev:bun` e agora também no `next build --turbopack`. Use `next build --webpack` somente para reproduzir bugs ou comparar saídas.
- **Whitelist de hosts**: o release estável continua sem aceitar `server.allowedHosts` (vide [`invalid-next-config`](https://nextjs.org/docs/messages/invalid-next-config)), portanto bloqueamos domínios exclusivamente via `middleware.ts`.
### Editor rich text (TipTap) — menções de ticket
- Menções (`ticketMention`) agora têm prioridade maior (`priority: 1000`) e um Link seguro (`SafeLinkExtension`) foi introduzido para ignorar `<a data-ticket-mention="true">`. Isso evita que o `Link` do StarterKit capture as âncoras na hidratação, garantindo que as menções continuem como nodes (não como marks) durante a edição.
- O mesmo helper `normalizeTicketMentionHtml` é aplicado ao carregar/atualizar conteúdo no editor, dentro dos fluxos de comentários e no Convex. Esse helper reescreve qualquer HTML legado (`#123•Assunto`) no formato de chip completo (datasets, spans, dot).
- Resultado: o chip mantém layout e comportamento ao editar (Backspace/Delete removem o node inteiro, node view continua ativo) sem exigir reload.
- Se precisar adicionar novos comportamentos, importe `SafeLinkExtension` e mantenha a ordem `[TicketMentionExtension, StarterKit (link:false), SafeLinkExtension, Placeholder]` para que o parser continue estável.
## Comandos de qualidade
- `bun run lint`: executa ESLint (flat config) sobre os arquivos do projeto.
- `bun test`: roda a suíte de testes utilizando o runner nativo do Bun. Para modo watch, use `bunx vitest --watch` manualmente.
- `bun run build:bun`: `next build --turbopack` usando o runtime Bun (Turbopack).
- Scripts com Bun (padrão atual): `bun run dev:bun`, `bun run convex:dev:bun`, `bun run build:bun`, `bun run start:bun`. Eles mantêm os scripts existentes, apenas forçando o runtime do Bun via `bun run --bun`. O `cross-env` garante `NODE_ENV` consistente (`development`/`production`).
- `bun run build:webpack`: build com o bundler oficial do Next (fallback).
- `bun run dev:webpack`: fallback do Next em dev quando o Turbopack apresentar problemas.
- `bun run prisma:generate`: necessário antes do build quando o client Prisma muda. Para migrações use `bunx prisma migrate deploy`.
### Automação no CI
Arquivo: `.github/workflows/quality-checks.yml`
Etapas:
1. Instala dependências (`bun install --frozen-lockfile`).
2. `bun run prisma:generate`.
3. `bun run lint`.
4. `bun test`.
5. `bun run build:bun`.
O workflow dispara em todo `push`/`pull_request` para `main` e fornece feedback imediato sem depender do pipeline de deploy.
## Testes rápidos via curl (Convites & acessos)
1. Rode `bun run dev:bun` (ou `bun run dev` se preferir Node) e autentique-se em `http://localhost:3000/login` usando `admin@sistema.dev / admin123`.
2. Copie o valor do cookie `BETTER_AUTH_SESSION` e exporte no shell: `export COOKIE="BETTER_AUTH_SESSION=<valor>"`.
### Usuários
```bash
# Listar usuários com acesso web
curl -s http://localhost:3000/api/admin/users \
-H "Cookie: $COOKIE" \
-H "Accept: application/json" | jq '.users | map({ id, email, role })' # remova o pipe se não tiver jq
# Criar usuário gestor (ajuste o e-mail se necessário)
NEW_EMAIL="api.teste.$(date +%s)@sistema.dev"
curl -s -X POST http://localhost:3000/api/admin/users \
-H "Cookie: $COOKIE" \
-H "Content-Type: application/json" \
-d "{\"name\":\"Usuário via curl\",\"email\":\"$NEW_EMAIL\",\"role\":\"manager\",\"tenantId\":\"tenant-atlas\"}" \
| tee /tmp/user-created.json
# Remover o usuário recém-criado
USER_ID=$(jq -r '.user.id' /tmp/user-created.json)
curl -i -X DELETE http://localhost:3000/api/admin/users/$USER_ID \
-H "Cookie: $COOKIE"
```
> Os exemplos acima utilizam `jq` para facilitar a leitura. Se não estiver disponível, remova os pipes e leia o JSON bruto.
### Convites
```bash
# Criar convite válido por 7 dias
INVITE_EMAIL="convite.$(date +%s)@sistema.dev"
curl -s -X POST http://localhost:3000/api/admin/invites \
-H "Cookie: $COOKIE" \
-H "Content-Type: application/json" \
-d "{\"email\":\"$INVITE_EMAIL\",\"name\":\"Convite via curl\",\"role\":\"collaborator\",\"tenantId\":\"tenant-atlas\",\"expiresInDays\":7}" \
| tee /tmp/invite-created.json
# Revogar convite pendente
INVITE_ID=$(jq -r '.invite.id' /tmp/invite-created.json)
curl -i -X PATCH http://localhost:3000/api/admin/invites/$INVITE_ID \
-H "Cookie: $COOKIE" \
-H "Content-Type: application/json" \
-d '{"reason":"Revogado via curl"}'
# Reativar (até 7 dias após a revogação)
curl -i -X PATCH http://localhost:3000/api/admin/invites/$INVITE_ID \
-H "Cookie: $COOKIE" \
-H "Content-Type: application/json" \
-d '{"action":"reactivate"}'
```
> Dica: ao receber `409` na criação de convite, há outro convite pendente/aceito para o mesmo e-mail. Revogue ou remova o usuário antes.
## Desktop (Tauri)
- Tabs Radix + estilos shadcn: `apps/desktop/src/components/ui/tabs.tsx`.
- Painel principal: `apps/desktop/src/main.tsx` — abas Resumo/Inventário/Diagnóstico/Configurações, envio manual de inventário, seleção de persona (colaborador/gestor) e vínculo com usuário.
- Coleta/hardware: `apps/desktop/src-tauri/src/agent.rs`.
- Variáveis de build:
- `VITE_APP_URL` (URL Web).
- `VITE_API_BASE_URL` (API).
### Build local
```bash
bun install
bun install --cwd apps/desktop
VITE_APP_URL=http://localhost:3000 \
VITE_API_BASE_URL=http://localhost:3000 \
bun run --cwd apps/desktop tauri build
```
Artefatos: `apps/desktop/src-tauri/target/release/bundle/`.
#### Ícone do instalador (NSIS)
- O Windows espera que `apps/desktop/src-tauri/icons/icon.ico` contenha sprites em 16, 24, 32, 48, 64, 128 e 256px, todos com fundo transparente. Sem esses tamanhos o Explorer gera uma miniatura reduzida com bordas acinzentadas.
- Para atualizar o ícone a partir do `icon-512.png`, execute:
```bash
cd apps/desktop/src-tauri
python3 - <<'PY'
from PIL import Image
img = Image.open("icons/icon-512.png")
img.save("icons/icon.ico", sizes=[(16,16),(24,24),(32,32),(48,48),(64,64),(128,128),(256,256)])
PY
```
- Depois de regerar `icon.ico`, faça o commit e rode novamente `bun run --cwd apps/desktop tauri build` para empacotar o instalador com o ícone correto.
### Atualizações OTA
1. Gere chaves (`bun run --cwd apps/desktop tauri signer generate`).
2. Defina `TAURI_SIGNING_PRIVATE_KEY` (+ password) no ambiente de build.
3. Publique os pacotes e um `latest.json` em release GitHub.
4. O app verifica ao iniciar e pelo botão “Verificar atualizações”.
## Erros recorrentes e soluções
| Sintoma | Causa | Correção |
| --- | --- | --- |
| `ERR_BUN_LOCKFILE_OUTDATED` no pipeline | Dependências do desktop alteradas sem atualizar o `bun.lock` | Rodar `bun install` (raiz e `apps/desktop`) e commitar o lockfile. |
| Prisma falha com `P2021` / tabelas Better Auth inexistentes | Banco nao foi inicializado | Rodar `bunx prisma db push` e `bun run auth:seed`. |
| Vitest trava em modo watch | Script `bun test` sem `--run` e CI detecta TTY | Ajustado para `vitest --run --passWithNoTests`. Localmente, use `bun test -- --watch` se quiser. |
| Desktop não encontra updater | Falta `latest.json` ou assinatura inválida | Publicar release com `*.sig` e `latest.json` apontando para os pacotes corretos. |
## Cronômetro dos tickets
- A UI e o backend agora compartilham um relógio real alinhado via `serverNow`. Toda resposta de `tickets.workSummary`, listagens de tickets e mutations `startWork/pauseWork` envia `serverNow` (epoch UTC).
- O frontend (`ticket-summary-header` e tabela) calcula um deslocamento (`offset = Date.now() - serverNow`) e projeta `Date.now()` para a linha do tempo do servidor usando `toServerTimestamp`. Isso elimina drift quando o navegador está adiantado/atrasado.
- Durante o `startWork`, se a mutation retornar `status = already_started` sem `startedAt`, a UI usa `getServerNow()` como fallback, e assim que o Convex reenviar a sessão ativa, o reconciliador (`reconcileLocalSessionStart`) substitui o valor local.
- O tempo em execução exibido “ao vivo” torna-se idêntico ao acumulado após pausar, com tolerância de ±1s por conta do tick do cronômetro. Ao depurar inconsistências, verifique se `serverNow` está chegando (painel de rede) e se o offset em `ticket-timer.utils.ts` está sendo calibrado.
## Referências úteis
- **Deploy (Swarm)**: veja `docs/DEPLOY-RUNBOOK.md`.
- **Plano do agente desktop / heartbeat**: `docs/plano-app-desktop-maquinas.md`.
- **Histórico de incidentes**: `docs/historico-agente-desktop-2025-10-10.md`.
> Última revisão: 18/10/2025. Atualize este guia sempre que o fluxo de DEV ou automações mudarem.
- **Next.js 16 (beta)**: comportamento sujeito a mudanças. Antes de subir para stable, acompanhe o changelog oficial (quebra: `revalidateTag` com segundo argumento, params assíncronos, etc.). Já estamos compatíveis com os breaking changes atuais.