From 651ab2363a927849a20eb4eeca69850336f03020 Mon Sep 17 00:00:00 2001 From: Armando Soares Date: Wed, 16 Sep 2026 05:13:10 +0000 Subject: [PATCH] texto sem traco longo --- .cursor/rules/arquitetura.mdc | 2 +- .cursor/rules/seguranca.mdc | 2 +- .env.example | 2 +- README.md | 6 ++---- RULES.md | 6 +++--- api/src/files/files.service.ts | 2 +- docs/ARCHITECTURE.md | 2 +- docs/DECISIONS.md | 6 +++--- docs/TESTING.md | 2 +- package.json | 2 +- web/AGENTS.md | 4 ++-- web/src/app/[tenant]/(panel)/clientes/page.tsx | 6 +++--- web/src/app/[tenant]/(panel)/historico/page.tsx | 2 +- web/src/app/[tenant]/(panel)/page.tsx | 4 ++-- web/src/app/[tenant]/(panel)/simular/page.tsx | 2 +- web/src/app/admin/(panel)/page.tsx | 2 +- web/src/app/layout.tsx | 2 +- web/src/components/landing/sinka-landing.tsx | 2 +- web/src/components/landing/site-footer.tsx | 2 +- web/src/components/landing/site-header.tsx | 2 +- 20 files changed, 29 insertions(+), 31 deletions(-) diff --git a/.cursor/rules/arquitetura.mdc b/.cursor/rules/arquitetura.mdc index 92b48c1..b581874 100644 --- a/.cursor/rules/arquitetura.mdc +++ b/.cursor/rules/arquitetura.mdc @@ -1,5 +1,5 @@ --- -description: Stack e pastas da Sinka — NestJS + Next.js, sem PHP +description: Stack e pastas da Sinka: NestJS + Next.js alwaysApply: true --- diff --git a/.cursor/rules/seguranca.mdc b/.cursor/rules/seguranca.mdc index 51437db..09fc4ec 100644 --- a/.cursor/rules/seguranca.mdc +++ b/.cursor/rules/seguranca.mdc @@ -6,7 +6,7 @@ alwaysApply: true # Tenant e segurança - Isolamento: **um database MySQL por empresa** (`sinka_t_`). Catálogo em `sinka_platform`. -- Queries de operação usam o PrismaClient do tenant autenticado — nunca o banco de outra empresa. +- Queries de operação usam o PrismaClient do tenant autenticado, nunca o banco de outra empresa. - Auth desta etapa: JWT + refresh em cookie httpOnly, papéis ADMIN / MANAGER / OPERATOR. Google, GitHub e TOTP na seguinte. - Segredos só em `.env`; nunca commitar - Rate limit de login com Redis diff --git a/.env.example b/.env.example index 68db916..c019c8c 100644 --- a/.env.example +++ b/.env.example @@ -27,7 +27,7 @@ FIREBASE_PROJECT_ID= FIREBASE_DATABASE_URL= NEXT_PUBLIC_FIREBASE_DATABASE_URL= -# Arquivos da operação (CSV/XLSX) — pasta local por empresa +# Arquivos da operação (CSV/XLSX), pasta local por empresa UPLOAD_DIR= # WEB diff --git a/README.md b/README.md index 7a0d960..ae9a74f 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,6 @@ # Sinka -SaaS de inteligência logística. Cada operação simula frete, compara transportadoras e acompanha custo — com os dados de uma empresa isolados dos das outras. - -**Demo:** [armandosoares.tech](https://armandosoares.tech) · código: [git.armandosoares.tech/armando/sinka](https://git.armandosoares.tech/armando/sinka) +SaaS de inteligência logística. Cada operação simula frete, compara transportadoras e acompanha custo, com os dados de uma empresa isolados dos das outras. ## O que faz @@ -19,7 +17,7 @@ Dois produtos no mesmo sistema: o **admin da Sinka** (`/admin`) cria e suspende Um database MySQL por empresa (`sinka_t_`). O catálogo fica em `sinka_platform`. -O JWT carrega o tenant. As queries de operação usam o PrismaClient daquele banco — um `WHERE` errado não cruza empresa. Backup, restore e exclusão também são por tenant. +O JWT carrega o tenant. As queries de operação usam o PrismaClient daquele banco: um `WHERE` errado não cruza empresa. Backup, restore e exclusão também são por tenant. ## Stack diff --git a/RULES.md b/RULES.md index b09b12b..4d20a79 100644 --- a/RULES.md +++ b/RULES.md @@ -1,4 +1,4 @@ -# RULES — Sinka +# RULES: Sinka Stack obrigatório do desafio. **Não usar PHP.** Não reintroduzir Laravel, Blade, `public/index.php` nem pasta `app/` no estilo PHP. @@ -6,7 +6,7 @@ Stack obrigatório do desafio. **Não usar PHP.** Não reintroduzir Laravel, Bla - Backend: Node.js + **NestJS** + TypeScript (`api/`) - Frontend: **Next.js** + TypeScript (`web/`) -- Banco: **MySQL** — `sinka_platform` + um database por empresa +- Banco: **MySQL**, `sinka_platform` + um database por empresa - Infra: **Docker**, **Docker Compose**, **Redis** ## Pastas @@ -22,7 +22,7 @@ Stack obrigatório do desafio. **Não usar PHP.** Não reintroduzir Laravel, Bla 1. Modelar no Prisma tenant (`api/prisma/tenant`) se for dado da empresa; no platform se for catálogo 2. Módulo NestJS: controller → use case/service → DTO + validação -3. Abrir o PrismaClient do tenant do JWT — nunca consultar outro database +3. Abrir o PrismaClient do tenant do JWT, nunca consultar outro database 4. Tela em `web/src/app` (App Router) 5. Teste no módulo da API quando a regra for importante diff --git a/api/src/files/files.service.ts b/api/src/files/files.service.ts index fdac39b..3091dfd 100644 --- a/api/src/files/files.service.ts +++ b/api/src/files/files.service.ts @@ -31,7 +31,7 @@ export class FilesService { return rows.map((row) => ({ id: row.id, name: row.originalName, - type: fileExtension(row.originalName).toUpperCase() || '—', + type: fileExtension(row.originalName).toUpperCase() || '-', sizeBytes: row.sizeBytes, createdAt: row.createdAt, })); diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index c21414c..720ea4e 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -1,4 +1,4 @@ -# Arquitetura — Sinka +# Arquitetura: Sinka ``` [Next.js :3000] → [NestJS :3001/api] → [MySQL sinka_platform] diff --git a/docs/DECISIONS.md b/docs/DECISIONS.md index 98e5466..0fdf1ba 100644 --- a/docs/DECISIONS.md +++ b/docs/DECISIONS.md @@ -4,7 +4,7 @@ Cada empresa recebe o próprio database (`sinka_t_`). 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. +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. @@ -28,8 +28,8 @@ Fila de importação (próxima etapa), rate limit de login, cache de CEP/geocodi ## Integrações externas -1. **ViaCEP** — cidade/UF a partir do CEP de origem e destino -2. **OpenStreetMap Nominatim** — coordenadas; distância por haversine +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). diff --git a/docs/TESTING.md b/docs/TESTING.md index 0a4ed15..c768af3 100644 --- a/docs/TESTING.md +++ b/docs/TESTING.md @@ -2,7 +2,7 @@ Estratégia: **testes de unidade Jest na API**, um `*.spec.ts` ao lado do código. Sem banco, Redis, Firebase ou browser. -O desafio avalia cobertura, qualidade e organização. A regra de negócio (frete, papéis, isolamento, chat, dashboard, OAuth) vive em funções puras e serviços com dependências mockadas — é o caminho mais estável e o que um avaliador consegue rodar com `npm test`. +O desafio avalia cobertura, qualidade e organização. A regra de negócio (frete, papéis, isolamento, chat, dashboard, OAuth) vive em funções puras e serviços com dependências mockadas. É o caminho mais estável e o que um avaliador consegue rodar com `npm test`. ```bash npm test diff --git a/package.json b/package.json index b3e16ef..f23b977 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "sinka", "private": true, - "description": "Plataforma SaaS de inteligência logística — NestJS + Next.js", + "description": "Plataforma SaaS de inteligência logística: NestJS + Next.js", "scripts": { "docker:up": "docker compose up -d", "docker:down": "docker compose down", diff --git a/web/AGENTS.md b/web/AGENTS.md index 643577d..ec8346a 100644 --- a/web/AGENTS.md +++ b/web/AGENTS.md @@ -2,8 +2,8 @@ # This is NOT the Next.js you know -This version has breaking changes — APIs, conventions, and file structure may all differ from your training data. Read the relevant guide in `node_modules/next/dist/docs/` (resolved from this file's directory; in monorepos the `next` package may not be visible from the repo root) before writing any code. Heed deprecation notices. +This version has breaking changes. APIs, conventions, and file structure may all differ from your training data. Read the relevant guide in `node_modules/next/dist/docs/` (resolved from this file's directory; in monorepos the `next` package may not be visible from the repo root) before writing any code. Heed deprecation notices. -This block is written and re-added by `next dev` — verify at `node_modules/next/dist/server/lib/generate-agent-files.js`. Removing it from a diff only re-creates the uncommitted change; committing it with your work keeps the tree clean. +This block is written and re-added by `next dev`. Verify at `node_modules/next/dist/server/lib/generate-agent-files.js`. Removing it from a diff only re-creates the uncommitted change; committing it with your work keeps the tree clean. diff --git a/web/src/app/[tenant]/(panel)/clientes/page.tsx b/web/src/app/[tenant]/(panel)/clientes/page.tsx index 29f5c5e..fa84efe 100644 --- a/web/src/app/[tenant]/(panel)/clientes/page.tsx +++ b/web/src/app/[tenant]/(panel)/clientes/page.tsx @@ -127,9 +127,9 @@ export default function ClientesPage() { {rows.map((row) => ( {row.name} - {row.document || "—"} - {[row.city, row.state].filter(Boolean).join(" / ") || "—"} - {row.email || row.phone || "—"} + {row.document || "-"} + {[row.city, row.state].filter(Boolean).join(" / ") || "-"} + {row.email || row.phone || "-"} {canWrite ? (