diff --git a/docs/progress.md b/docs/progress.md index cddc26b..5c44021 100644 --- a/docs/progress.md +++ b/docs/progress.md @@ -94,9 +94,15 @@ Estratégia: 4 subagentes (`general-purpose`, atuando com a persona `eden-commer - **Resellers** (`apps/api/src/resellers/` + migration `resellers`): CRUD operacional + vínculo usuário↔revenda (`users.reseller_id`). Leitura aberta, escrita via `resellers:edit` — desvio deliberado do legado (que travava em `requireAdmin`), documentado em comentário. - **Adapters S3/SMTP** (`packages/integrations/`): portados fielmente do legado — S3 falha alto (erro claro se não configurado), SMTP falha silencioso (nunca quebra um fluxo de negócio por causa de e-mail). -**2 bugs reais encontrados em teste manual e corrigidos antes do commit final:** +- **CRM** (`apps/api/src/leads/`, `apps/api/src/opportunities/` + migration `crm`): leads e oportunidades com conversão transacional (`convertLeadToOpportunity`, `FOR UPDATE` + `withTransaction`). Diferente de Companies/Products, leitura também exige permissão (`leads:view`/`opportunities:view`) por conter PII de prospect. + +**4 bugs reais encontrados em teste manual e corrigidos antes do commit final:** 1. `assertCanAssignRole`/`assertCanActOnUser` pulavam a validação de existência do papel quando o ator era `super_admin` (o bypass de peso pulava a checagem inteira) — convidar usuário com `role_key` inexistente estourava a constraint FK do banco como 500 não tratado em vez de 400 claro. 2. `PATCH /v1/resellers/:id/assign-user` aceitava um `resellerId` diferente no corpo, que na prática era o valor usado — o `:id` da URL virava só uma checagem de existência, não o alvo real da atribuição. Corrigido para o `:id` da URL ser a única fonte de verdade; desatribuição virou endpoint próprio (`POST /v1/resellers/unassign-user`). +3. Os controllers de Leads/Opportunities liam `req.user?.id` em vez de usar `@CurrentUser()`/`request.edenUser` (o padrão real do `JwtAuthGuard`) — todo evento de auditoria de lead/oportunidade estaria gravando `actorId: null` sempre. O agente que os escreveu não tinha o módulo de auth disponível no worktree dele para testar isso de verdade (só stubou e reverteu antes de commitar). +4. As chamadas `appendAuditEvent()` de leads/opportunities omitiam o campo obrigatório `actorType` (6 ocorrências). + +Também precisou renomear o timestamp da migration de CRM, que o agente gerou com valor anterior ao da migration de `resellers` (já aplicada por outro agente/merge) — `node-pg-migrate` recusa migration fora de ordem. Todos os módulos testados ao vivo contra a stack real (não só typecheck): convite de usuário, papel inexistente (400 após o fix), CRUD de produto com preços NUMERIC corretos, CRUD de revenda, atribuição/desatribuição de usuário à revenda.