8. Conceitos transversais
Autenticação e autorização
Seção intitulada “Autenticação e autorização”- Sessão em cookie gerida pelo Better Auth, configurado uma vez em
@moldape/auth(createMoldapeAuth) e instanciado emapps/web/src/lib/auth/auth.ts, com os pluginsadminejwt(oopenAPIsó fora de produção). O prefixo do cookie émoldape, a validade é de 30 dias e o cookie vale entre subdomínios demoldape.com. - No Fastify,
requireAuth()lêmoldape.session_token(ou a variante__Secure-), busca a sessão no Redis e, se não achar, no PostgreSQL.requireAdmin()exige tambémrole = admin. - No Next.js, em duas camadas:
- o
proxy.ts(antigo middleware) roda só em/home,/studio,/partiale/admine redireciona para o login quando não há cookie de sessão — sem I/O; - os layouts protegidos validam a sessão de verdade no servidor
(
@/server/session:requireUser()em(customer)/layout.tsxerequireAdmin()emadmin/(panel)/layout.tsx, que também confere o papel). Cookie expirado ou de não-admin cai no login antes de qualquer HTML ser gerado.
- o
- A autorização dos dados continua na API (
requireAuth/requireAdmin).
Validação
Seção intitulada “Validação”| Camada | Ferramenta |
|---|---|
| Formulários (web) | Zod 4 + TanStack Form (lib/schemas.ts) |
| Entrada HTTP (API) | JSON Schema do Fastify (presentation/schemas) |
| Domínio | Value objects (CustomerName, Email, Quantity, códigos de entidade) |
Tratamento de erros
Seção intitulada “Tratamento de erros”- Exceções de domínio em
domain/exceptionssão convertidas em respostas HTTP no handler global de erro doserver.ts. - As respostas seguem um envelope (
ResponseFactory.success/error) comsuccess,dataemessage. - Efeitos colaterais não bloqueiam o fluxo principal: falha ao gerar PDF ou enviar e-mail é registrada em log, mas não reverte a mudança de status.
Logs e observabilidade
Seção intitulada “Logs e observabilidade”@moldape/logger(wrapper isomórfico) ebusiness-event-loggerpara eventos de negócio.- Log de requisições ativado por
ENABLE_REQUEST_LOGGING=true, que remove os headersauthorizationex-api-key. - Health checks:
/health,/health/detailed,/health/redis,/health/cache/info. - Atenção: há muitos
console.logem produção, incluindo um no checkout que imprime nome, endereço e valor do pagamento no console do navegador. Ver Riscos.
Renderização e busca de dados (web)
Seção intitulada “Renderização e busca de dados (web)”O web é SSR primeiro: as páginas (page.tsx) são Server Components que
buscam os dados no servidor e entregam o HTML já preenchido; a parte
interativa fica em componentes 'use client' colocados ao lado
(*-view.tsx).
sequenceDiagram
participant B as Navegador
participant N as Next (servidor)
participant A as order-lifecycle
B->>N: GET /home/drafts (cookie)
N->>N: requireUser() — sessão no Better Auth
N->>A: GET /me/drafts (mesmo cookie repassado)
A-->>N: rascunhos
N-->>B: HTML + estado do React Query (dehydrate)
Note over B: hidrata sem nova requisição;<br/>mutations e polling seguem no cliente
- Uma definição por consulta:
lib/query/queries.tsdefine chave e função de cada consulta (queryOptions). O servidor usa com os serviços autenticados por cookie (@/server/api), o cliente comclientServices. Como a chave é a mesma, o dado pré-carregado é exatamente o que o hook procura. - Prefetch e hidratação:
prefetch()+<HydrateClient>(@/server/query). Só consultas concluídas com sucesso vão para o cliente; uma falha no servidor não derruba a página, o cliente tenta de novo. - Usuário logado: a consulta
currentUseré semeada a partir da sessão no layout da área do cliente; oAuthProviderlê dela (o usuário não é mais guardado nolocalStorage). - HTTP:
@moldape/api-client(fetch nativo). No navegador o cookie vai comcredentials: include; no servidor ele é repassado no headercookie, pela URL internaORDER_LIFECYCLE_INTERNAL_URLquando definida.
Cache e limites
Seção intitulada “Cache e limites”| Camada | O que guarda | Invalidação |
|---|---|---|
Data Cache do Next (fetch com next.tags) |
Só conteúdo público: slide show do login, documentos (termos, catálogo) e itens de ajuda (@/server/public-data) |
Tags slide-shows, documents, help-info: a server action revalidatePublicData chama updateTag após cada edição no admin; senão, expira em 1 h |
| TanStack Query (navegador) | Dados do usuário e do admin | invalidateQueries nas mutations |
| Redis (API) | Sessões e, com ENABLE_CACHING=true, respostas públicas |
TTL |
| Vetorização do estúdio | Estado do canvas e imagens (vectorization-store, image-cache) |
Inalterado nesta versão, para não afetar o salvamento |
Dados de usuário nunca entram no Data Cache do Next: o cliente HTTP do
servidor usa cache: 'no-store' e um QueryClient por requisição.
- Redis guarda sessões e, com
ENABLE_CACHING=true, respostas públicas. - Rate limit com
@fastify/rate-limit, ativado porENABLE_RATE_LIMITING(RATE_LIMIT_MAX,RATE_LIMIT_WINDOW_MS).
Arquivos
Seção intitulada “Arquivos”- Upload multipart (
@fastify/multipart) ou em partes (/upload/chunk,/upload/chunk/complete) para arquivos grandes. - Tipos aceitos para plantigrafia: JPEG, PNG, WebP e PDF, até 5 MB. PDFs são
convertidos em imagem no servidor (
pdf2pic+ GraphicsMagick). - Tudo fica em
UPLOAD_DIRECTORY, em subpastas por tipo:plantigraphies,vectorized-plantigraphies,creation-images,pdfs,products,pieces,coverages,coverage-logos,banners,temp. A pasta é servida em/uploads/.
Dinheiro
Seção intitulada “Dinheiro”- Valores monetários são
Decimalno Prisma edecimal.jsno domínio, para evitar erro de ponto flutuante. - Para o gateway, o total é convertido em centavos inteiros
(
Math.round(total * 100)). - Na interface, o formato deveria ser sempre
Intl.NumberFormat('pt-BR', { style: 'currency', currency: 'BRL' }). O checkout hoje mostraR$ 196.07(com ponto); ver Avaliação heurística.
Estado no front-end
Seção intitulada “Estado no front-end”| Tipo de estado | Ferramenta |
|---|---|
| Estado do servidor (rascunhos, catálogo, sacola, pedidos) | TanStack Query 5: pré-carregado no servidor e hidratado; hooks de query e mutation por recurso (hooks/use*.ts) sobre lib/query/queries.ts |
| Usuário logado | Consulta currentUser (hidratada pela sessão) exposta por useAuth() |
| Estado local do estúdio (seleção, zoom, elementos) | Zustand 4 (stores/) |
| Canvas | Konva / react-konva |
| Notificações | sonner e o toast do @moldape/ui |
Códigos de entidade
Seção intitulada “Códigos de entidade”Os identificadores legíveis seguem padrões definidos em
domain/value-objects/codes.ts, por exemplo ORD-<timestamp>-<n> para
pedidos e TX001, EN001 para taxas. As chaves primárias são cuid().

Desenvolvido e documentado porNós Tecnologia · Desenvolvimento Criativo

