43 lines
2.1 KiB
Markdown
43 lines
2.1 KiB
Markdown
# Decisões técnicas
|
||
|
||
## Multi-tenant: um banco MySQL por empresa
|
||
|
||
Cada empresa recebe o próprio database (`sinka_t_<slug>`). O catálogo de empresas e o administrador da plataforma ficam em `sinka_platform`.
|
||
|
||
A API resolve o banco no login (slug da empresa) e reutiliza um `PrismaClient` por database. Dados de operação (usuários, clientes, simulações) nunca compartilham tabela com outra empresa.
|
||
|
||
**Por quê:** o desafio pede isolamento entre empresas. Database-per-tenant é o isolamento mais forte no MySQL: backup, restore e exclusão por empresa; um vazamento de `WHERE` não cruza tenant. O custo extra (provisionar database + `db push` no onboarding) cabe no desafio e deixa a justificativa explícita.
|
||
|
||
O `PLATFORM_ADMIN` não mora no banco da empresa. Ele só cria/suspende tenants e não lê operação.
|
||
|
||
Papéis **dentro** da empresa: `ADMIN` (Administrador), `MANAGER`, `OPERATOR`.
|
||
|
||
## Auth
|
||
|
||
JWT de acesso (cookie httpOnly, 15 min) + refresh (cookie httpOnly, 7 dias, hash no banco da empresa). Login com slug + e-mail + senha. Rate limit no Redis. Google, GitHub e TOTP ficam para a etapa seguinte; os campos já existem no usuário.
|
||
|
||
Auditoria: login, provisionamento de empresa, mudança de papel e CRUD de usuários.
|
||
|
||
## Prisma + NestJS
|
||
|
||
Dois schemas Prisma: `platform` (catálogo) e `tenant` (cópia idêntica em cada database de empresa). Módulos Nest por domínio.
|
||
|
||
## Redis
|
||
|
||
Fila de importação (próxima etapa), rate limit de login, cache de CEP/geocoding.
|
||
|
||
## Integrações externas
|
||
|
||
1. **ViaCEP**: cidade/UF a partir do CEP de origem e destino
|
||
2. **OpenStreetMap Nominatim**: coordenadas; distância por haversine
|
||
|
||
Se o Nominatim falhar, a simulação usa uma distância de fallback (mesmo município / mesmo estado / interestadual).
|
||
|
||
## Cálculo de frete
|
||
|
||
Peso cobrado = máximo entre peso real e peso cubado `(L × A × C) / 6000`.
|
||
|
||
Preço = taxa base + (R$/kg × peso cobrado) + (R$/km × distância) + (ad valorem × valor da carga).
|
||
|
||
Cada transportadora ativa da empresa gera uma cotação; a simulação grava o ranking no histórico.
|