Pular para conteúdo

Operadores: acesso e disponibilidade

A autorização é vinculada ao número de WhatsApp na whitelist efetiva. O webhook intercepta mensagens desses números antes do fluxo de clientes: elas viram comandos operacionais ou a resposta fixa de ajuda, sem criar atendimento de cliente nem invocar o LLM.

Comandos reais

parse_whitelist_command(), em src/core/application/whitelist_command.py, aceita maiúsculas/minúsculas, espaços externos, barra inicial opcional e acento em “disponível”. O comando deve ocupar a mensagem inteira.

Mensagem Efeito Resposta esperada
disponivel Registra disponibilidade para hoje, gera acesso e consulta total pendente Confirma disponibilidade, quantidade aguardando se houver e link
entrar Também marca disponível hoje e gera novo acesso Mesmo fluxo de acesso e disponibilidade
indisponivel Remove registro da disponibilidade Confirma pausa das notificações
Outro texto de operador Nenhuma ação de conversa Lista os três comandos atuais

Comandos antigos como encerrar <telefone> e /assumir <telefone> não executam ações. Assumir e finalizar são feitos no painel. indisponivel não revoga automaticamente um cookie já emitido: disponibilidade para receber avisos e autenticação do navegador têm ciclos próprios. Use Sair para invalidar a sessão do navegador.

Whitelist e disponibilidade

effective_whitelist() em src/core/application/admin_tools.py resolve a configuração operacional antes do fallback WHITELIST_PHONE_NUMBERS. available_whitelisted_operators() sempre cruza essa lista com o mapa operator_availability persistido por OperationalConfigRepository.

A disponibilidade é válida somente na data local configurada em BUSINESS_HOURS_TZ, com idade não negativa e no máximo HANDOFF_OPERATOR_AVAILABILITY_TTL_HOURS (default 24). À meia-noite ela vence mesmo que ainda não tenham passado 24 horas. Dias e horários comerciais não bloqueiam notificações: enviar disponivel é a manifestação explícita de disponibilidade naquele dia.

O mapa é atualizado com comparação de updated_at e até 20 tentativas em contenção. O código evita sobrescrever a disponibilidade registrada simultaneamente por outro operador. Erro persistente gera Could not update operator availability under contention.

Login sem senha

  1. O operador envia entrar ao WhatsApp do agente.
  2. issue_login_link() gera token aleatório de 32 bytes, armazena somente SHA-256 e monta <OPERATOR_UI_BASE_URL>/acesso/<TOKEN>.
  3. O link expira em 10 minutos ou à meia-noite local, o que chegar primeiro.
  4. O GET apenas mostra a confirmação. O POST consome o grant atomicamente, para que previews automáticos não gastem o acesso.
  5. exchange_login_link() emite um novo token de sessão e um token CSRF. A sessão expira na próxima meia-noite local.

Configure a base já terminando em /atendimento, por exemplo https://atendimento.example.invalid/atendimento. Informar somente a raiz gera um caminho /acesso/... diferente da rota implementada.

O cookie gogenetic_operator_session tem HttpOnly, SameSite=Lax e caminho /atendimento; é Secure em produção, e também em desenvolvimento acessado por HTTPS. A whitelist é reavaliada no login e nas requisições autenticadas, de modo que remover um número impede o uso posterior do acesso.

DynamoOperatorAuthRepository persiste grants e sessões com TTL e confere expiração no consumo/leitura. A autorização não depende da remoção física imediata pelo mecanismo TTL do DynamoDB. Ler uma sessão de autenticação já expirada também solicita sua remoção.

As mutações exigem csrf_token comparado com hmac.compare_digest. As respostas protegidas usam Cache-Control: no-store, Pragma: no-cache, Referrer-Policy: no-referrer, X-Frame-Options: DENY e X-Content-Type-Options: nosniff. Não envie links de acesso, cookies ou HTML contendo token CSRF a terceiros.

Configuração relacionada

Variável Uso
WHITELIST_PHONE_NUMBERS Números autorizados, separados por vírgula; pode ter override operacional
OPERATOR_UI_BASE_URL Base pública completa do painel para compor acesso
BUSINESS_HOURS_TZ Data local e expiração diária
HANDOFF_OPERATOR_AVAILABILITY_TTL_HOURS Limite adicional de idade da disponibilidade
HANDOFF_NOTIFIER_ENABLED, HANDOFF_NOTIFIER_TYPE Escolha e ativação do notificador
WHATSAPP_CLOUD_ENABLED e credenciais Meta Envio de respostas e acessos reais
DEV_UI_ENABLED Exposição das ferramentas de desenvolvimento; também influencia o cookie local

Tipos, defaults e diferenças SAM estão na referência de variáveis.

Falhas e manutenção

Sintoma Verificação
“Este acesso expirou ou já foi utilizado” Gerar outro com entrar; não reutilizar o POST antigo
“Este número não está mais autorizado” Conferir whitelist operacional e ambiente do link
Disponível ontem, sem avisos hoje Enviar disponivel novamente; conferir fuso operacional
Link não é gerado Conferir OPERATOR_UI_BASE_URL e repository de autenticação
Login funciona, envio dá 403 Recarregar sessão e formulário; conferir CSRF
Login em HTTP de produção não persiste Usar o endpoint HTTPS, pois o cookie é Secure

Testes: tests/unit/application/test_whitelist_command.py, test_operator_auth.py, test_operator_availability.py; tests/unit/integrations/test_operator_auth_repository.py; e os cenários test_whitelist_entrar_issues_single_use_access_link e test_legacy_whitelist_commands_return_help_without_mutating_session em tests/unit/lambdas/test_webhook_handler.py.