Didata

Plataforma onde professores brasileiros geram aula, atividade, prova e slides com IA, corrigem prova por foto e acompanham a turma. Está em produção em usedidata.com.br, com plano gratuito e pago, sem lançamento divulgado.

Papel
Autor único, do produto ao deploy
Contexto
Kyber Tech, carro-chefe
Situação
Em produção, com plano gratuito e pago
Acesso
usedidata.com.br ↗

O problema

O usuário é professor da Educação Infantil ao Superior, com peso no Fundamental e no Médio, mais professor particular, de cursinho e de idiomas. O contexto de uso é pouca familiaridade técnica e trabalho feito entre uma aula e outra, à noite, no fim de semana. O que ele precisa é transformar um tema em material pronto, corrigir prova e acompanhar a turma.

Sobre onde exatamente o tempo do professor vai embora, não há pesquisa de campo no repositório. Não existe entrevista, questionário nem nota de conversa com professor real. O que existe é a descrição de usuário do documento de produto, que é posicionamento, não dado coletado. Prefiro escrever isso do que apresentar posicionamento como pesquisa.

O rastro verificável de contato com usuário é pequeno e está no código. Houve um programa beta, desativado em julho de 2026, e duas decisões carregam a data do feedback nos comentários: prova de várias folhas, com até cinco fotos por aluno numa correção, e o envio de todas as páginas numa chamada só, para montar o gabarito completo.

A IA sugere, o professor confirma

Nenhuma decisão pedagógica, nota, correção ou feedback é fechada pela máquina. Toda resposta lida pela IA nasce com status sugerida, sem exceção, inclusive as de confiança alta.

É escolha, não limitação. O modelo devolve uma alternativa por questão e um número de confiança de 0 a 100. Seria trivial gravar a nota direto quando a confiança passasse de um limiar. O sistema não faz isso: sugerida e confirmada são estados distintos no banco, e a nota do boletim oficial só conta célula que o professor confirmou.

O custo em conveniência é real e foi pago de propósito. Numa prova de 30 alunos por 10 questões são 300 leituras para aceitar. A mitigação não foi afrouxar a regra, foi reduzir o esforço de aceitar: confirmação em lote das de alta confiança, e uma fila que prioriza o que pede atenção. O viés da fila é declarado e pró-cautela, questão sem leitura nenhuma conta como incerta.

A mesma regra amarra a geração de material. Todo prompt carrega a instrução de revisar e adaptar antes de aplicar em sala.

Currículo brasileiro, e o limite do que ele garante

É o ponto onde o case precisa ser honesto, porque o mecanismo é mais modesto do que a promessa deixaria supor.

O contexto da turma resolve a faixa de códigos

Série, disciplina e tipo de professor resolvem uma faixa BNCC. Para 9º ano de matemática, devolve EF09MA01 a EF09MA24, com os temas. Essa linha entra no prompt do usuário, nunca no sistema, porque o system é constante e serve ao cache dos providers.

Os casos que quebrariam uma regex ingênua

Ensino Superior não recebe código nenhum, porque não segue BNCC. Educação Infantil recebe campos de experiência em vez de habilidades. E 3º ano só é tratado como Médio quando a série ou o tipo de professor dizem Médio, porque 3º ano do Fundamental também existe.

Seis currículos estaduais sobre uma espinha só

GO, SP, MG, RJ, RS e BA têm módulo próprio. O desenho parte de um fato jurídico: currículo estadual adota os códigos da BNCC, e o que muda é o eixo de contextualização regional. Então a espinha fica num arquivo só e cada estado contribui o cabeçalho e o eixo, como a Goianidade no documento de Goiás.

A fonte vai junto, para conferência

Cada módulo declara fonte e versão, e o bloco injetado no prompt carrega a linha citável: órgão, documento, ano, e a instrução de citar o código BNCC porque é o mesmo do documento estadual e permite conferência no PDF oficial.

O que isso não garante

Não há validação determinística do código citado contra uma base oficial. Os dois validadores pós-geração checam marcador de gabarito, soma de pontos, contagem de questões e paleta de slides. Nenhum olha código BNCC. Uma validação por lista oficial é trabalho em aberto, e o repositório registra o motivo de não ter sido feito: falta corpus real.

Então o diferencial real é outro

Série, disciplina, faixa de códigos, eixo regional e fonte citável entram no prompt sem o professor digitar nada, em toda geração daquela turma. Contra usar ChatGPT direto, o ganho é esse, e não verificação formal de citação. Vale dizer qual é.

Da foto até a nota

  1. 01 Compressão no cliente 2048px no maior lado, JPEG 0.82, só acima de 1,5MB e nunca amplia. Câmera de celular gera de 4 a 12MB e o servidor rejeitava com erro genérico.
  2. 02 Guardas no servidor Teto de 8MB por foto, até 5 por aluno, MIME restrito e verificação de magic bytes antes de qualquer processamento.
  3. 03 Partição por status O que já está sugerido ou confirmado não é tocado. Reenviar foto não apaga trabalho feito, e se tudo já foi processado o Vision nem é chamado.
  4. 04 Vision com tool use forçada Claude Haiku 4.5, todas as páginas do aluno numa chamada. A saída sai por schema de ferramenta, não JSON em texto livre, porque prosa em volta derrubava a foto inteira no parse.
  5. 05 Persistência conservadora Uma resposta por questão, com alternativa da IA e confiança. A nota final lê outro campo, o único que o professor escreve.

Quando a leitura falha, três caminhos separados por tipo de falha. Erro passível de nova tentativa cai para GPT-4o com schema idêntico e registra alerta com as tags de primário e fallback; erro 4xx e schema inválido propagam sem tentar. Questão que voltou sem leitura vira status de erro e entra num contador de faltantes. E confiança ausente é tratada como baixa: ausência de sinal conta contra a IA, não a favor.

O acerto é medido pela discordância do professor, e só sobre respostas que ele confirmou, porque contar o não confirmado como concordância inflaria o resultado a favor da IA. Duas leituras: por questão, o percentual de leituras que o professor mudou, sinalizado acima de 20%; e por faixa de confiança, para responder se a IA erra mais onde disse ter menos confiança. Se a divergência for igual nas duas faixas, o sinal não discrimina e a fila de incertas dá falsa segurança. Isso só aparece a partir de 10 confirmações, para não mostrar percentual sobre amostra pequena.

Números de acurácia não existem. Não há conjunto de teste com fotos rotuladas nem relatório de avaliação. O mock de Vision diz, no próprio cabeçalho, que exercita a máquina em volta da IA e não testa se ela lê manuscrito. A instrumentação de divergência é o que existe no lugar da métrica offline: ela mede em uso, não antes.

Arquitetura

Next.js 16 em rota única na Vercel, sem serviço separado, sem fila e sem worker. O trabalho longo é streaming dentro da request; o periódico são quatro crons.

Autorização na aplicação, RLS como profundidade

O oposto do Kyber CRM, e de propósito. O Prisma conecta como role que ignora RLS, então a autorização é do aplicativo. O RLS existe para o caso de alguém falar com o Postgres pelo cliente Supabase, com force e deny all explícito nas tabelas sem policy.

Isolamento por professor e por escola

Toda query de professor filtra pelo dono. Escola é multi-tenant por organização, com contexto resolvido num lugar só e considerando apenas membro aprovado. A invariante que proíbe a superfície de escola de ler conteúdo alheio não publicado é teste, não parágrafo: quebra o CI.

Quatro controles de custo de IA

Reserva de cota em transação serializable, que fecha a corrida entre contar e criar; throttle de rajada; roteamento por complexidade com classificador determinístico, sem chamar IA para decidir; e cache de prompt mais dedupe de fonte por hash. Cada chamada grava o modelo real da resposta, nunca fixo no código.

Exportação que respeita o papel

PDF, DOCX, PPTX e CSV. Equação passa por KaTeX na web e por MathJax mais conversão SVG para PNG no PDF. Texto vindo da IA é limpo antes de imprimir, porque o renderizador não interpreta markdown e comentário HTML vazava para a folha do aluno.

Governança que custa CI

Constituição com invariantes numeradas, ADRs imutáveis e specs com critérios de aceite. As invariantes caras são testes: o CI falha se uma rota nova de IA não reservar cota, ou se um builder de prompt não neutralizar injeção.

Um MCP somente leitura para operar

Sete ferramentas de saúde, uso, custo, falhas, correção, negócio e feedback. Local, por stdio, fora do deploy. O cron do resumo semanal reusa as mesmas consultas em vez de ter query própria.

O que existe hoje

Testes unitários
1.595
Modelos de dados
34
Currículos estaduais
6
Migrations
86

Também: 111 páginas, 32 route handlers, 60 arquivos de Server Action, 906 arquivos TypeScript, 33 blocos de teste end to end em 9 specs, 33 dependências de produção e 798 commits desde maio de 2026. Cobertura de testes não existe: nenhum script coleta, então citar percentual seria inventar.

Números de uso não existem, e este case não publica nenhum. Não há contagem de professores ativos, materiais gerados, escolas ou receita. O produto está no ar com plano gratuito e pago, mas não teve lançamento divulgado. O medidor de custo de Vision e a instrumentação de divergência já estão implementados: a escolha é medir em uso, não publicar estimativa. O documento de produto do Didata proíbe prova social fabricada, e a mesma regra vale aqui.

  • Next.js 16
  • React
  • TypeScript
  • Prisma 7
  • PostgreSQL
  • Supabase
  • pgvector
  • Anthropic
  • OpenAI
  • Vision
  • RAG
  • Vercel

O que quebrou, em três atos

O melhor caso documentado é de infraestrutura, não de produto, e os três atos são encadeados.

A migration que nunca rodou. O Prisma Client é reconstruído a cada deploy a partir do schema, então passou a esperar colunas que duas migrations criariam. As duas ficaram no disco, nunca aplicadas em produção, e o dashboard quebrou pedindo uma coluna inexistente. A parte que interessa não é o erro: a documentação afirmava que a Vercel rodava migrate deploy no build, e isso nunca tinha sido configurado. Um pressuposto escrito, nunca verificado, sustentado por dias de deploys que por acaso não tocavam nas colunas novas.

Sete deploys mortos aos 45 minutos. Com o migrate deploy no build, os deploys passaram a morrer no timeout sem mensagem de erro. O pooler de transação do Supabase, que é o correto para runtime serverless, não suporta as transações DDL longas do migrate deploy, e o comando trava em vez de falhar. A correção foi separar a URL de runtime da URL do CLI. O detalhe que só aparece quando dói: a mesma variável precisa existir na Vercel e nos secrets do CI, porque o CI roda o mesmo build.

A config que quebra só na infra da plataforma. Depois disso, aumentar o limite de corpo das Server Actions passou a quebrar o build com um erro de tipo, logo após a plataforma aplicar a própria modificação de config. O build local não reproduzia. Foram cerca de seis horas de bisect até isolar. A consequência ficou: o limite segue no default de 1MB e nenhuma Server Action pode receber arquivo, então todo upload do produto é route handler.

O que eu faria diferente: migrate deploy no pipeline desde o primeiro deploy, porque aplicar migration como passo manual falha em silêncio; e tratar a diferença entre o build local e o da plataforma como fato conhecido, rodando o build da plataforma antes de mesclar mudanças de configuração. O contorno do terceiro ato continua sendo dívida, não desenho: a regra vale porque um bug de terceiro não foi resolvido.

Quer ver o resto do trabalho, ou conversar sobre uma vaga?

Atualizado em 5 de agosto de 2026