Repository navigation
Open
Description
Contexto
O Ask ApplyWell utiliza Gemini (Google AI Studio) para o chat com SSE e ferramentas de consulta. Hoje é necessário proteger a cota compartilhada do provedor contra uso excessivo, rajadas de mensagens, múltiplas requisições simultâneas e retries sem controle.
Os limites do Gemini são aplicados por projeto, não individualmente por usuário. Portanto, limitar apenas o frontend não protege a API nem impede que um usuário esgote a capacidade de todos.
Relacionadas: #81 (chatbot), #87 (tratamento de 429/quota do provedor), #93 (memória/contexto).
Objetivo
Implementar cota diária por usuário autenticado + proteção anti-flood no backend, com limites configuráveis e observabilidade, impedindo novas chamadas ao Gemini antes de exceder o orçamento.
Escopo backend
- Aplicar os controles no ponto central de entrada do Ask ApplyWell, antes de chamar o modelo, incluindo requests SSE, independentemente de quantas abas ou clientes estejam abertos.
- Cota diária por usuário em número de mensagens/chamadas ao assistente (valor por configuração, com sugestão inicial de 30 mensagens/dia). Explicitar timezone e horário do reset; não confundir com o reset diário do Google.
- Rate limit por usuário em janela curta (sugestão inicial: 5 solicitações/minuto), além de uma geração em andamento por usuário para evitar flood e corridas de execução.
- Limite global configurável para proteger a chave/projeto Gemini compartilhado; garantir que o limite por usuário não seja a única barreira contra estouro de RPM/RPD/TPM do provedor.
- Validação, reserva e contabilização atômicas no backend, seguras contra requests simultâneos e múltiplas instâncias. Preferir mecanismo simples usando a persistência já existente; não adicionar Redis apenas para isso sem justificativa.
- Definir política para contabilização e estorno de tentativas bloqueadas, falhas antes de chamar o modelo, falhas do provedor e interrupções de streams. Nenhum erro deve permitir burlar a cota; bloqueios locais não devem consumir cota.
- Limitar tamanho de prompt/contexto e, quando suportado, tokens de saída, para uma única solicitação não drenar os recursos. Registrar métricas de uso/tokens retornadas pelo Spring AI/Gemini, considerando tool-calls.
- Bloquear novas solicitações ao alcançar a cota, sem atingir o Gemini. Retornar HTTP 429 com código de erro estável e
Retry-After/horário de liberação quando possível; para SSE, manter contrato de erro estruturado já discutido em feat: expose Gemini 429 retry delay and failed-message retry state #87. - Disponibilizar informação de uso diário, limite, restante e próximo reset para exibição futura no frontend (endpoint autenticado ou contrato existente). Não expor consumo de outros usuários.
- Logs e métricas de requests autorizadas, bloqueadas, em curso, tokens e erros 429 locais vs. 429 Gemini; nunca logar conteúdo sensível de prompts.
- Adicionar configurações via propriedades/variáveis de ambiente (cotas, janela, concorrência, limite global, habilitação), documentadas para operação.
Critérios de aceite
- Um usuário que atinge o limite diário não consegue disparar chamadas adicionais ao Gemini até a renovação da cota.
- Rajadas, solicitações paralelas e diferentes sessões/abas não burlam os limites.
- Cota e limite global permanecem corretos em concorrência, reinícios e eventual escala horizontal.
- Rejeições retornam erro claro, estruturado e informação de quando tentar novamente, sem encerrar incorretamente uma geração já autorizada.
- Falhas de upstream e desconexões não criam consumo fantasma nem permitem bypass.
- Testes automatizados cobrem limite diário, reset, rate-limit, concorrência, global, isolamento por usuário, falhas e SSE.
- Os valores dos limites são ajustáveis em produção sem alteração de código.
Fora do escopo inicial
- Planos pagos, cobrança, painel administrativo avançado ou limites diferentes por assinatura.
- Alteração da UX do frontend nesta issue (apenas expor contrato para consumo posterior).
Referências
Metadata
Metadata
Assignees
Labels
No labels
Activity