Jesse Daniel Brown commited on
Commit
2bc83bf
·
1 Parent(s): 77e2ec1

Add audit findings and next steps

Browse files
Files changed (2) hide show
  1. docs/CODEBASE_AUDIT.md +57 -0
  2. docs/NEXT_STEP_PROMPTS.md +44 -0
docs/CODEBASE_AUDIT.md ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # CODEBASE AUDIT
2
+
3
+ ## Executive summary
4
+ Status: **Amarelo** — há boas bases de segurança (hash de senha, validação com Zod, limiter) e fluxos iniciais de áudio/consentimento, mas a instalação está bloqueada por 403 no registry, build/lint/test não rodam por falta de dependências, e a geração de planos via IA ainda não existe (501). O armazenamento local é só um placeholder e não protege os arquivos.
5
+
6
+ ## O que funciona agora
7
+ - Autenticação com NextAuth + credenciais, adaptador Prisma e hashing de senha com bcrypt, populando org/role no token e sessão.【F:src/lib/auth.ts†L10-L96】
8
+ - Rate limiting em memória para login, registro e geração de planos, retornando 429 e cabeçalhos Retry-After.【F:src/lib/rate-limit.ts†L3-L93】
9
+ - CRUD básico de estudantes (criação com código pseudonimizado) e listagem/registro de gravações com validação de tipos e datas via Zod.【F:src/app/api/students/route.ts†L1-L96】【F:src/app/api/recordings/route.ts†L8-L129】
10
+ - Pipeline de captura de áudio no cliente com bloqueio por consentimento, checagem de MIME/size (10 MB) e upload assinado seguido de POST para registro.【F:src/app/capture/CaptureClient.tsx†L176-L336】【F:src/lib/upload-validation.ts†L1-L30】
11
+ - Middleware protegendo `/dashboard` e `/capture` com redirecionamento para login.【F:middleware.ts†L5-L25】
12
+
13
+ ## O que falha agora (erros exatos)
14
+ - `npm install` falha por 403 ao baixar `@auth/prisma-adapter`.【32d7a4†L1-L7】
15
+ - `npm run build` falha: `next: not found` (ausência de dependências instaladas).【4704ff†L1-L7】
16
+ - `npm run lint` falha: `next: not found`.【075119†L1-L7】
17
+ - `npm run test -- --reporter=verbose` falha: `vitest: not found`.【ca289a†L1-L7】
18
+ - Geração de planos IA retorna 501 “não disponível neste ambiente”.【F:src/app/api/plans/generate/route.ts†L5-L14】
19
+
20
+ ## Mapa de arquitetura
21
+ - **Rotas App Router**: home pública `/` com call-to-action; login `/login`; registro `/register`; painel `/dashboard` (layouts e páginas de settings, students, recordings, plans); captura móvel `/capture`.【F:src/app/page.tsx†L1-L92】【F:src/app/dashboard/layout.tsx†L1-L200】【F:src/app/capture/page.tsx†L1-L57】
22
+ - **APIs**: NextAuth (`/api/auth/[...nextauth]`), registro `/api/auth/register`, estudantes CRUD `/api/students` e `/api/students/[id]`, consentimento `/api/students/[id]/consent`, gravações `/api/recordings`, storage presign `/api/storage/sign-upload` e `/sign-download`, geração de planos `/api/plans/generate` (placeholder).【F:src/app/api/auth/[...nextauth]/route.ts†L1-L14】【F:src/app/api/auth/register/route.ts†L1-L62】【F:src/app/api/students/route.ts†L1-L96】【F:src/app/api/students/[id]/route.ts†L1-L95】【F:src/app/api/students/[id]/consent/route.ts†L10-L41】【F:src/app/api/recordings/route.ts†L8-L129】【F:src/app/api/storage/sign-upload/route.ts†L13-L66】【F:src/app/api/storage/sign-download/route.ts†L13-L61】【F:src/app/api/plans/generate/route.ts†L5-L14】
23
+ - **Autenticação/autorização**: NextAuth credenciais com JWT; memberships ligam usuário a organização e papel (ADMIN/TEACHER). Middleware protege rotas, mas RBAC fino depende de uso manual de `requireRole`.【F:src/lib/auth.ts†L10-L96】【F:middleware.ts†L5-L25】【F:src/lib/rbac.ts†L1-L13】
24
+ - **Modelos Prisma**: Organization, User, Membership (role ADMIN/TEACHER), Student (código único por org, campos opcionais), Consent (audioAllowed/shareForResearch), Plan (needsJson/planJson), Recording (storageKey, mimeType, duration).【F:prisma/schema.prisma†L3-L103】
25
+ - **Armazenamento de áudio**: driver S3 com presign (Put/Get) ou fallback local (URL query sem assinatura); chaves de objeto derivadas de org/estudante e MIME. Upload assinado chamado pelo cliente, depois gravação salva no DB. Download exige orgId e chave prefixada.【F:src/lib/storage/index.ts†L31-L124】【F:src/lib/storage/key.ts†L10-L20】【F:src/app/api/storage/sign-upload/route.ts†L13-L66】【F:src/app/api/storage/sign-download/route.ts†L13-L61】【F:src/app/api/recordings/route.ts†L82-L127】
26
+ - **Geração de planos**: schema de plano pedagógico definido com Zod, mas endpoint retorna 501 e não chama OpenAI.【F:src/lib/schemas/activity-plan.ts†L1-L34】【F:src/app/api/plans/generate/route.ts†L5-L14】
27
+ - **Captura/consentimento**: `/capture` carrega estudantes da org e último consentimento; checa no cliente antes de gravar; API de consentimento só lê (não grava).【F:src/app/capture/page.tsx†L15-L55】【F:src/app/capture/CaptureClient.tsx†L176-L336】【F:src/app/api/students/[id]/consent/route.ts†L10-L41】
28
+
29
+ ## Achados de segurança e privacidade
30
+ - Senhas são hashadas com bcrypt na criação e verificadas no login.【F:src/app/api/auth/register/route.ts†L32-L53】【F:src/lib/auth.ts†L34-L41】
31
+ - Rate limiting aplicado a login, registro e geração (memória, sem redis), protegendo contra brute force básico.【F:src/app/api/auth/[...nextauth]/route.ts†L5-L13】【F:src/app/api/auth/register/route.ts†L8-L20】【F:src/lib/rate-limit.ts†L3-L93】
32
+ - RBAC: há enum de papéis e helper `requireRole`, mas APIs de estudantes/gravações não checam papel — qualquer usuário autenticado da org pode operar.【F:prisma/schema.prisma†L12-L47】【F:src/lib/rbac.ts†L1-L13】【F:src/app/api/students/route.ts†L21-L96】
33
+ - Validação de entrada com Zod em registro, estudantes, gravações, storage e plano (schema); uso consistente de mensagens.【F:src/app/api/auth/register/route.ts†L9-L20】【F:src/app/api/students/route.ts†L7-L17】【F:src/app/api/recordings/route.ts†L8-L19】【F:src/app/api/storage/sign-upload/route.ts†L13-L26】【F:src/lib/schemas/activity-plan.ts†L1-L34】
34
+ - Consentimento: UI bloqueia sem consentimento e consulta último registro, mas API de upload/recording não valida consentimento server-side; não há endpoint para registrar consentimento (somente leitura).【F:src/app/capture/CaptureClient.tsx†L176-L336】【F:src/app/api/students/[id]/consent/route.ts†L10-L41】【F:src/app/api/storage/sign-upload/route.ts†L13-L66】
35
+ - Armazenamento: fallback automático para driver local sem autenticação (URL com query param), inadequado para produção; S3 exige credenciais completas, sem criptografia/TTL configurado.【F:src/lib/storage/index.ts†L31-L124】
36
+ - OpenAI: nenhuma chamada no cliente, evitando vazamento de chave, mas recurso ainda não implementado.【F:src/app/api/plans/generate/route.ts†L5-L14】
37
+ - PII: estudantes podem ter `displayName` e `notes` opcionais; códigos pseudonimizados reforçam privacidade. Nenhuma coleta de analytics.【F:prisma/schema.prisma†L49-L62】【F:src/app/api/students/route.ts†L7-L96】
38
+ - Segredos: `.env.local.example` vazio; não há chaves versionadas. Apenas falha de instalação por registry (não por credenciais expostas).
39
+
40
+ ## Testes e CI
41
+ - Scripts: build/lint/test/vitest/playwright definidos em `package.json`.【F:package.json†L5-L56】
42
+ - Vitest: ambiente Node, cobertura text+lcov, alias `@` para `src`.【F:vitest.config.ts†L1-L16】
43
+ - Playwright: baseURL via `E2E_BASE_URL` (default localhost), único projeto Chromium; não há gate `E2E_RUN`, então `npm run test:e2e` rodaria sempre se chamado.【F:playwright.config.ts†L1-L15】
44
+ - CI GitHub Actions: Node 20, `npm ci`, lint, `npm run test -- --runInBand`, build. E2E não incluído.【F:.github/workflows/ci.yml†L1-L33】
45
+ - Estado atual: nenhum teste rodou por ausência de dependências (instalação 403).【32d7a4†L1-L7】【4704ff†L1-L7】【075119†L1-L7】【ca289a†L1-L7】
46
+
47
+ ## Top 10 correções priorizadas (menor esforço primeiro)
48
+ 1. Corrigir acesso ao registry npm para instalar `@auth/prisma-adapter` e demais deps (pode exigir proxy ou mirror).【32d7a4†L1-L7】
49
+ 2. Ajustar `DATABASE_URL` para usar Postgres (como no schema) ou trocar o provider para SQLite conforme `.env.local` gerado, evitando mismatch.【F:prisma/schema.prisma†L3-L103】
50
+ 3. Adicionar verificação de consentimento no servidor ao criar gravações (em `sign-upload` ou `/api/recordings`) para não depender só do cliente.【F:src/app/api/recordings/route.ts†L82-L127】【F:src/app/api/storage/sign-upload/route.ts†L13-L66】
51
+ 4. Implementar endpoint para registrar/atualizar consentimento de áudio (com auditoria de quem assinou) e UI correspondente.【F:src/app/api/students/[id]/consent/route.ts†L10-L41】
52
+ 5. Introduzir RBAC efetivo nas rotas de estudantes/gravações/planos, usando `requireRole` para limitar ações de TEACHER vs ADMIN.【F:src/lib/rbac.ts†L1-L13】【F:src/app/api/students/route.ts†L21-L96】
53
+ 6. Endurecer driver de armazenamento local (auth temporária, expiração de URL, caminhos isolados) ou removê-lo em produção.【F:src/lib/storage/index.ts†L81-L124】
54
+ 7. Finalizar implementação da geração de planos com schema `ActivityPlan`, validação de entrada e chamada server-side à OpenAI Responses API (sem expor chave).【F:src/lib/schemas/activity-plan.ts†L1-L34】【F:src/app/api/plans/generate/route.ts†L5-L14】
55
+ 8. Adicionar validação de tamanho/tipo no backend de storage/download além do cliente (defesa em profundidade).【F:src/app/api/storage/sign-upload/route.ts†L13-L52】
56
+ 9. Ampliar limites e persistência do rate limit (Redis/Upstash) para múltiplas instâncias e logs de abuso.【F:src/lib/rate-limit.ts†L3-L93】
57
+ 10. Criar testes automatizados para consentimento, RBAC e storage (Vitest) e, opcionalmente, fluxos E2E condicionais por `E2E_RUN`.【F:vitest.config.ts†L1-L16】【F:playwright.config.ts†L1-L15】
docs/NEXT_STEP_PROMPTS.md ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # NEXT STEP PROMPTS
2
+
3
+ Use estes prompts pequenos no GitHub Copilot/Codex para avançar com segurança.
4
+
5
+ 1. **Desbloquear instalação npm 403**
6
+ ```
7
+ Revise .npmrc e variáveis de proxy para garantir acesso ao registry npmjs.org; reproduza `npm install` e registre o pacote que falha (@auth/prisma-adapter). Adicione logs e, se preciso, force `npm config delete proxy`/`https-proxy` no script de CI local (não commitar segredos).
8
+ ```
9
+ 2. **Corrigir DATABASE_URL vs provider**
10
+ ```
11
+ Abra prisma/schema.prisma e alinhe `datasource db` ao banco real: usar Postgres local (compose) ou trocar provider para sqlite se o objetivo for arquivo .tmp/dev.db. Atualize .env.local.example com valor compatível e descreva no README.
12
+ ```
13
+ 3. **Aplicar consentimento no backend de gravação**
14
+ ```
15
+ Em /api/storage/sign-upload e /api/recordings, antes de criar URL ou registro, carregue o último consentimento do estudante e recuse se audioAllowed for falso ou ausente. Retorne 403 com mensagem clara.
16
+ ```
17
+ 4. **Criar endpoint de registro de consentimento**
18
+ ```
19
+ Adicione POST/PATCH em /api/students/[id]/consent para salvar Consent com audioAllowed/shareForResearch/signedAt/signedByUserId. Valide com Zod e restrinja a membros da org.
20
+ ```
21
+ 5. **Enforçar RBAC nas rotas protegidas**
22
+ ```
23
+ Use requireRole em /api/students*, /api/recordings e geração de planos para limitar operações de cadastro a ADMIN; TEACHER apenas leitura. Retorne 403 quando papel não autorizado.
24
+ ```
25
+ 6. **Endurecer driver de armazenamento local**
26
+ ```
27
+ No lib/storage/index.ts, adicione assinatura temporária (token/HMAC com expiração) às URLs do driver local, evitando acesso público. Documente que só é para desenvolvimento.
28
+ ```
29
+ 7. **Implementar geração de planos via OpenAI Responses API**
30
+ ```
31
+ No endpoint /api/plans/generate, valide entrada (targetIpa, idade, necessidades) com o schema ActivityPlan, chame o cliente OpenAI no servidor usando model configurável e retorne JSON estruturado. Mantenha a chave apenas server-side.
32
+ ```
33
+ 8. **Validar uploads no backend**
34
+ ```
35
+ Em sign-upload e sign-download, revalide tamanho/tipo do arquivo (MAX_AUDIO_FILE_BYTES, ALLOWED_AUDIO_MIME_TYPES) e negue chaves que não pertençam à org. Adicione logs de auditoria mínimos.
36
+ ```
37
+ 9. **Gating opcional para E2E**
38
+ ```
39
+ Atualize package.json e CI para rodar `npm run test:e2e` somente quando E2E_RUN=true, mantendo playwright.config.ts intacto.
40
+ ```
41
+ 10. **Cobertura de testes para consentimento/RBAC**
42
+ ```
43
+ Adicione testes Vitest cobrindo requireRole (roles permitidos/negados) e novos endpoints de consentimento, mockando Prisma e auth(). Garanta reset do rate limit nos testes.
44
+ ```