feat(platform): Sistema > Usuários/Auditoria, Infraestrutura > Saúde

Três endpoints novos, todos platform-only: GET /platform/users (cross-
tenant, users não tem RLS) + PATCH .../status (desabilitar tem efeito
real — login() já checava status ACTIVE desde a PHASE 04); GET
/platform/audit-log (últimos 200 eventos, audit_logs também sem RLS,
linha imutável); GET /platform/health (Postgres/Redis + FreeSWITCH via
conexão ESL avulsa, sem manter estado).

Achado de arquitetura documentado explicitamente na própria tela: o check
de FreeSWITCH sempre falha neste ambiente porque apps/api roda no host e
a porta 8021 é deliberadamente não publicada (decisão da PHASE 01/05) —
não é um bug, é a rede isolada do jeito certo.

Frontend: /platform/sistema/usuarios, /auditoria, /platform/
infraestrutura/saude. Testado ponta a ponta contra dados reais (3
usuários da plataforma, audit log com eventos reais desta sessão,
inclusive uma referência órfã tratada corretamente). Smoke test nas 19
telas anteriores, todas 200.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BFaBaBSQGhyXGEgtTYZGV8
This commit is contained in:
2026-08-29 20:04:05 -03:00
parent 2c1269a83a
commit a23e68b011
17 changed files with 654 additions and 3 deletions

56
TODO.md
View File

@@ -1231,6 +1231,62 @@ novo) (agente.md secao 29, 56, 126, 141, 168)
- [ ] `Plan.key` não pode ser editado depois de criado (só os limites) —
não implementado, `key` normalmente não deveria mudar mesmo
## PHASE 34 — Platform: Sistema > Usuários/Auditoria, Infraestrutura >
Saúde (agente.md secao 148, 150-151, 168, 187)
- [x] `GET /platform/users` (novo) — lista TODOS os usuários da
plataforma, cross-tenant; `users` não tem RLS (identidade global,
secao 148), consulta direta sem `withTenantContext`.
`PATCH /platform/users/:id/status` desabilita/reativa (`login()`
já checava `status === "ACTIVE"` desde a PHASE 04 — o toggle tem
efeito real, não é só cosmético). Botão desabilitado na UI pra
qualquer usuário com role de plataforma, de propósito (evita se
trancar fora sem querer).
- [x] `GET /platform/audit-log` (novo) — últimos 200 eventos de
`audit_logs` (também sem RLS, linha imutável precisa sobreviver ao
tenant), nomes de usuário/tenant resolvidos numa segunda consulta
em lote.
- [x] `GET /platform/health` (novo) — Postgres/Redis (reusa a mesma
lógica de `/health/ready`) + FreeSWITCH via uma conexão ESL avulsa
(connect → espera até 2.5s → desconecta, sem manter estado — `apps/
api` não tem uma conexão ESL permanente como fs-events/fs-config).
- [x] **Achado de arquitetura, não um bug**: o check de FreeSWITCH
**sempre falha** neste ambiente — `apps/api` roda no host, e a
porta 8021 (Event Socket) é deliberadamente não publicada pro host
(secao 184, decisão da PHASE 01/05). Confirmado com `nc -zv
localhost 8021` → connection refused, apesar do container
`b2bcall-freeswitch` estar `healthy`. Documentado explicitamente na
própria tela (`/platform/infraestrutura/saude`) em vez de deixar
parecer que algo está quebrado — os serviços que falam com o
FreeSWITCH de verdade (fs-events/fs-config/predictive-dialer) rodam
dentro da rede Docker e não têm esse problema.
- [x] Frontend: `/platform/sistema/usuarios` (lista+busca+toggle),
`/platform/sistema/auditoria` (lista+busca, somente leitura),
`/platform/infraestrutura/saude` (3 cards com latência + botão
"verificar de novo").
- [x] Testado ponta a ponta contra a API real: os 3 usuários reais da
plataforma (Beta Corp, Acme, Platform Super Admin) listados
corretamente com tipo/status certos; audit log mostrando eventos
reais (LOGIN, LOGIN_FAILED, TENANT_CREATE) desta própria sessão de
testes, inclusive uma referência órfã a um usuário apagado numa
sessão anterior (fallback pro UUID cru confirmado, comportamento
correto de audit trail imutável); saúde mostrando Postgres/Redis OK
e FreeSWITCH "Falhou" com a explicação certa. Smoke test de
regressão nas 19 telas do tenant + tarifas, todas 200.
- [ ] "Sistema > Permissões" e "> Configurações" continuam "em breve" —
Permissões teria só leitura útil por ora (RBAC é system-defined,
sem UI de criar role customizada ainda); Configurações nunca teve
escopo definido na especificação além do nome
- [ ] "Infraestrutura > FreeSWITCH/SIP Profiles/Nodes" continuam "em
breve" — precisam de introspecção real via ESL
(`getChannels`/`getRegistrations`/`getGateways`/`getQueues` da
`TelephonyProvider`, todos tipados como `unknown` ainda) exposta
por endpoint; mais arriscado que o check de saúde (conexão avulsa
× dado estruturado de verdade), não tentado nesta fase
- [ ] "IA > Providers/Modelos/Uso/Custos" (visão de plataforma) continuam
"em breve" — o tenant já tem BYOK completo (PHASE 31); a versão
platform-wide (ver GLOBAL, agregar uso/custo entre tenants) não foi
construída ainda
---
## Riscos conhecidos