Documentação · versão 2.0.1
SaguiDesk 2.0.1
Help desk em PHP puro e MySQL, sem Composer e sem framework. Você descompacta, abre o instalador no navegador e em um minuto tem uma central de atendimento com painel da equipe, área do cliente, e-mails automáticos e relatórios.
Requisitos
| Item | Mínimo | Observação |
|---|---|---|
| PHP | 7.4 | Testado até 8.3 |
| Banco | MySQL 5.7 ou MariaDB 10.3 | utf8mb4 |
| Extensões PHP | pdo_mysql, openssl, mbstring, fileinfo | zip é opcional (exportação .xlsx) |
| Servidor web | Apache ou LiteSpeed com mod_rewrite, Nginx, ou php -S | Exemplo de Nginx incluído |
| Permissão de escrita | Pasta raiz, storage/, assets/brand/ | O instalador verifica tudo |
Instalar na hospedagem
- Baixe o
sagui_desk_v2.0.1.zipe envie o conteúdo da pastasaguideskparapublic_html/(ou para uma subpasta ou subdomínio) pelo Gerenciador de Arquivos. - No painel da hospedagem, crie um banco MySQL e um usuário com acesso total a ele. Anote nome do banco, usuário e senha.
- Acesse
https://seudominio.com.br/install/. O instalador confere os requisitos e mostra em vermelho o que faltar. - Preencha o banco, o nome do sistema, a URL e o administrador. Clique em Instalar SaguiDesk.
- Pronto: entre com o e-mail e a senha do administrador.
Depois de instalar
- Apague a pasta
/install. Ela já fica bloqueada pelo arquivostorage/installed.lock, mas apagar é a prática recomendada. - Guarde uma cópia da
APP_KEYdo.env.php. Sem ela os dados criptografados (telefones, senha SMTP) não podem ser lidos. - Ative o HTTPS: o cookie de sessão passa a ser
Secureautomaticamente.
Rodar localmente
Para testar no seu computador antes de publicar. No instalador há botões de atalho que preenchem os dados do banco de cada pacote.
MAMP (macOS)
- Copie a pasta
saguideskpara/Applications/MAMP/htdocs/e clique em Start no MAMP. - Abra
http://localhost:8888/saguidesk/. - No bloco do banco, clique em MAMP: servidor
127.0.0.1, porta8889, usuário e senharoot.
XAMPP, WAMP ou Laragon
Copie para htdocs (XAMPP) ou www (WAMP/Laragon), abra http://localhost/saguidesk/ e use o atalho XAMPP / WAMP / Laragon: porta 3306, usuário root, senha vazia.
Servidor embutido do PHP
Com PHP e MySQL instalados (no Mac, brew install php mysql):
cd saguidesk
php -S localhost:8000 router.php
O router.php faz o papel do .htaccess: rotas amigáveis e bloqueio das pastas internas.
Dados de demonstração
Marque Criar dados de demonstração no instalador para já começar com tickets, um atendente e dois clientes. Senha de todas as contas: Demo1234.
| Perfil | |
|---|---|
| Atendente | atendente@demo.local |
| Cliente | cliente@demo.local |
| Cliente | fernanda@demo.local |
Exclua essas contas em Admin → Usuários antes de colocar o sistema em produção.
Instalação manual
Para quem prefere não usar o instalador:
- Crie o banco e importe
saguidesk.sqlpelo phpMyAdmin. - Copie
.env.example.phppara.env.phpe preencha os dados. - Gere a chave de criptografia e cole em
APP_KEY. - Crie o administrador na tabela
userscomrole = 'admin'e a senha gerada porpassword_hash(). - Crie o arquivo vazio
storage/installed.lock.
# chave AES-256 (32 bytes em base64)
php -r "echo base64_encode(random_bytes(32)), PHP_EOL;"
# hash da senha do admin
php -r "echo password_hash('SuaSenha123', PASSWORD_DEFAULT), PHP_EOL;"
Arquivo .env.php
Gerado pelo instalador na raiz do sistema. Guarda credenciais e nunca deve ser versionado (já está no .gitignore).
| Chave | Para que serve |
|---|---|
APP_URL | Endereço do sistema, sem barra no final. Usado nos links dos e-mails. |
APP_DEBUG | true mostra erros na tela. Use só em desenvolvimento. |
APP_TIMEZONE | Fuso padrão (o painel pode sobrescrever). |
APP_KEY | Chave AES-256 dos dados criptografados. Trocar a chave torna esses dados ilegíveis. |
DB_HOST, DB_PORT, DB_NAME, DB_USER, DB_PASS | Conexão MySQL. |
SMTP_* | Padrões de e-mail. O que for preenchido em Admin → Configurações tem prioridade. |
SESSION_REGENERATE | Regenera o ID da sessão no login. Mude para false se algum LiteSpeed antigo derrubar a sessão logo após entrar. |
Configurações do painel
Em Admin → Configurações, dividido em cinco abas:
| Aba | O que dá para ajustar |
|---|---|
| Geral | Nome do sistema, empresa, fuso horário e se clientes podem criar conta sozinhos. |
| Aparência | Logotipo (PNG, JPG ou WEBP até 2 MB), cor de destaque com prévia ao vivo, tema padrão claro ou escuro, frase do login e texto do rodapé. |
| E-mail / SMTP | Servidor, porta, segurança, usuário, senha (gravada com AES-256), remetente e quais notificações enviar. Botão de envio de teste. |
| Segurança | Tempo de sessão por inatividade, tamanho mínimo de senha, tentativas de login e tempo de bloqueio. |
| Tickets e anexos | Tamanho máximo por arquivo, arquivos por mensagem, extensões permitidas e fechamento automático de tickets resolvidos. |
E-mail e SMTP
O SaguiDesk tem cliente SMTP próprio, sem bibliotecas externas. Com o SMTP desligado (padrão), cada e-mail é gravado em storage/logs/mail.log, inclusive o link de recuperação de senha. É assim que você testa tudo em localhost.
| Provedor | Servidor | Porta / segurança |
|---|---|---|
| Hostinger | smtp.hostinger.com | 465 / SSL |
| Gmail / Google Workspace | smtp.gmail.com | 587 / STARTTLS (senha de app) |
| Microsoft 365 | smtp.office365.com | 587 / STARTTLS |
| cPanel genérico | mail.seudominio.com.br | 465 / SSL |
Notificações automáticas (cada uma pode ser desligada):
- Abertura: confirmação para o cliente e aviso para a equipe (o responsável, ou os atendentes do departamento, ou os administradores).
- Resposta: quando a equipe responde, o cliente recebe; quando o cliente responde, a equipe recebe. Notas internas nunca geram e-mail.
- Fechamento: o cliente é avisado e convidado a avaliar o atendimento.
Perfis e permissões
Administrador
Acesso total, inclusive criar outros administradores.
Atendente
Atende tickets com as permissões que você escolher.
Cliente
Abre e acompanha somente os próprios chamados.
Permissões atribuíveis a cada atendente em Admin → Usuários:
| Permissão | Libera |
|---|---|
tickets.view_all | Ver tickets de todos os clientes. Sem ela, o atendente vê os atribuídos a ele e os sem responsável do seu departamento. |
tickets.manage | Alterar status, prioridade, departamento e responsável; ações em massa. |
tickets.delete | Excluir tickets e seus anexos. |
users.manage | Gerenciar usuários (um atendente nunca concede permissões que não tem). |
departments.manage | Criar, editar e excluir departamentos. |
reports.view | Relatórios e exportação PDF/Excel. |
logs.view | Logs de atividade. |
settings.manage | Configurações do sistema. |
Tickets
Cada ticket recebe um código público curto, como SD-4F7K2Q, que não revela quantos chamados existem.
Status
| Status | Quando acontece |
|---|---|
| Aberto | Ticket novo, ainda sem resposta da equipe. |
| Em andamento | A equipe está trabalhando, ou o cliente respondeu depois de uma resposta da equipe. |
| Aguardando cliente | Padrão após uma resposta da equipe. |
| Resolvido | Marcado pela equipe. Fecha sozinho após N dias (configurável). |
| Fechado | Encerrado pela equipe ou pelo cliente. Pode ser reaberto. |
Na tela do ticket
- Responder ou nota interna: a nota fica destacada em amarelo e o cliente nunca a vê.
- Depois de responder: escolha se o ticket vai para "Aguardando cliente", fica "Em andamento" ou vira "Resolvido".
- Quem responde primeiro assume o ticket se ele estiver sem responsável.
- Mudanças de status, prioridade, departamento e responsável viram eventos na linha do tempo.
- Na lateral: dados do cliente, tempos de 1ª resposta e resolução e os outros chamados dele.
- Ctrl/⌘ + Enter envia a resposta.
Lista e ações em massa
Filtre por status, prioridade, departamento e responsável, busque por assunto, código, nome ou e-mail e ordene por prioridade. Marque vários tickets para mudar status, atribuir ou excluir de uma vez. Tickets aguardando a equipe aparecem com um ponto colorido.
Anexos
Arraste arquivos para o formulário. O sistema confere a extensão, o tamanho e o conteúdo real do arquivo; um .php renomeado para .jpg é recusado. Os arquivos ficam em storage/uploads, fora do alcance da web, e só são entregues a quem pode ver o ticket.
Painel do cliente
O cliente vê quantos chamados estão com a equipe, quantos aguardam resposta dele e o histórico completo. Respostas novas da equipe ganham o selo Nova resposta. Ao encerrar, ele avalia o atendimento com 1 a 5 estrelas e um comentário opcional; a média aparece no dashboard e nos relatórios.
Dashboard
Atualiza sozinho a cada 20 segundos e pausa quando a aba fica em segundo plano. Mostra:
- Em aberto, aguardando a equipe, urgentes e sem responsável
- Novos e resolvidos hoje
- Tempo médio de 1ª resposta e de resolução (30 dias)
- Satisfação média (CSAT) e número de avaliações
- Gráfico de abertos x resolvidos dos últimos 14 dias
- Distribuição por status, prioridade e departamento, e ranking da equipe
O sino do topo conta, para a equipe, os tickets esperando resposta; para o cliente, os que a equipe respondeu.
Relatórios PDF e Excel
Em Admin → Relatórios, filtre por período (atalhos de 7, 30 e 90 dias e mês atual), status, prioridade, departamento e responsável. A tela mostra o resumo, o desempenho por responsável e a lista de tickets.
- PDF: A4 paisagem, com cabeçalho na cor do sistema, cartões de resumo, tabela paginada e "Página X de Y".
- Excel (.xlsx): cabeçalho fixo, autofiltro e números como número. Sem a extensão
zipno servidor, gera.xls.
Logs de atividade
Registra logins, falhas e bloqueios de login, abertura, resposta, alteração e exclusão de tickets, mudanças em usuários e configurações, exportações e falhas de e-mail, com usuário, data e IP. Filtre por tipo, pessoa, período ou texto.
Segurança
| Camada | Como o SaguiDesk protege |
|---|---|
| Senhas | password_hash() com rehash automático e política de tamanho mínimo com letras e números. |
| Força bruta | Bloqueio por e-mail e por IP após N tentativas, pelo tempo configurado. |
| Recuperação de senha | Token de uso único com validade de 60 min; só o hash SHA-256 fica no banco; a resposta não revela se o e-mail existe. |
| Dados sensíveis | AES-256-GCM (autenticado) para telefone e senha SMTP. |
| SQL Injection | Prepared statements reais em 100% das consultas. |
| XSS | Escape de toda saída e Content-Security-Policy sem scripts inline. |
| CSRF | Token em todos os formulários; requisições sem token são recusadas. |
| Sessão | Cookie HttpOnly, SameSite e Secure; ID regenerado no login; vínculo com o navegador; expiração por inatividade e tempo máximo de 12 h. |
| Anexos | Lista branca de extensões, verificação de MIME, nome aleatório, pasta bloqueada e download com checagem de permissão. |
| Exportações | Proteção contra formula injection no Excel. |
Estrutura e rotas
saguidesk/
├── index.php front controller
├── router.php roteador para php -S
├── .htaccess rotas amigáveis e bloqueios
├── nginx.conf.example
├── .env.example.php
├── saguidesk.sql
├── AGENTS.md guia para agentes de código (Codex etc.)
├── install/ instalador web
├── app/
│ ├── bootstrap.php configuração, erros, cabeçalhos, sessão
│ ├── routes.php todas as rotas
│ ├── helpers.php e(), url(), flash(), icon()…
│ ├── Core/ DB, Auth, Session, Crypto, Csrf, Mailer, PdfReport, XlsxWriter…
│ ├── Controllers/
│ └── Views/
├── assets/ css, js, logotipo enviado
└── storage/ anexos, logs, lock (bloqueado na web)
| Rota | Tela | Acesso |
|---|---|---|
/login, /register, /forgot | Entrar, criar conta, recuperar senha | Público |
/dashboard | Dashboard (equipe) ou Início (cliente) | Logado |
/tickets, /tickets/new, /tickets/{id} | Lista, novo chamado, conversa | Logado |
/admin | Atalho para o dashboard da equipe | Equipe |
/admin/users | Usuários | users.manage |
/admin/departments | Departamentos | departments.manage |
/admin/reports | Relatórios e exportação | reports.view |
/admin/logs | Logs | logs.view |
/admin/settings | Configurações | settings.manage |
/profile | Meu perfil e troca de senha | Logado |
/api/stats, /api/notifications | JSON do dashboard e do sino | Logado |
Banco de dados
Nove tabelas InnoDB em utf8mb4, com chaves estrangeiras:
| Tabela | Conteúdo |
|---|---|
users | Contas, papel, permissões (JSON), telefone criptografado |
departments | Áreas de atendimento |
tickets | Chamados, código público, tempos, avaliação |
ticket_replies | Mensagens, notas internas e eventos |
attachments | Metadados dos anexos |
password_resets | Hash dos tokens de recuperação |
login_attempts | Tentativas para o bloqueio de força bruta |
activity_logs | Auditoria |
settings | Configurações do painel (chave/valor) |
Personalizar o código
O pacote traz um AGENTS.md com a arquitetura e as regras do projeto, lido automaticamente por agentes de código como Codex e Claude Code. As regras que valem para qualquer alteração:
- Manter compatibilidade com PHP 7.4 (nada de
match, union types ou?->). - SQL só pela classe
DB, com placeholders. - Escapar toda saída com
e(); nenhum JavaScript inline (a CSP bloqueia). - Todo formulário POST com
csrf_field().
| Quero… | Onde mexer |
|---|---|
| Nova rota | app/routes.php |
| Nova configuração do painel | Settings::DEFAULTS, aba em Views/admin/settings.php e AdminController::saveSettings |
| Nova permissão | Auth::PERMISSIONS (aparece sozinha no formulário de usuário) |
| Nova métrica no dashboard | Core/Stats.php e assets/js/app.js |
| Novo e-mail automático | Core/Notifier.php e Views/emails/layout.php |
| Cores e layout | assets/css/app.css (variáveis de tema) |
Vindo da 1.x
A 2.0 é uma reescrita completa, com outro banco de dados. Não existe atualização automática:
- Instale a 2.0.1 em uma pasta ou subdomínio novo, com um banco novo.
- Recrie departamentos e atendentes; clientes podem se cadastrar sozinhos.
- Mantenha a 1.x no ar, só para consulta, até encerrar os chamados antigos.
A base de conhecimento da 1.x não existe na 2.0.
Solução de problemas
| Sintoma | Solução |
|---|---|
404 em /login no Apache | Ative o mod_rewrite e AllowOverride All. |
| "Não conectou no MySQL" no MAMP | Servidor 127.0.0.1 (não localhost), porta 8889, usuário e senha root. |
| Logout logo depois de entrar | No .env.php, 'SESSION_REGENERATE' => false. |
| "Sessão expirada" ao enviar formulário | A página ficou aberta além do tempo de sessão. Recarregue e envie de novo. |
| Anexo grande falha | Aumente upload_max_filesize e post_max_size no php.ini. |
| E-mails não chegam | Use Enviar teste em Configurações → E-mail; o erro do servidor aparece na tela e em Logs. |
| Datas com horário errado | Ajuste o fuso em Configurações → Geral. |
| Ver o erro real de uma tela branca | 'APP_DEBUG' => true no .env.php ou leia storage/logs/php-error.log. |
Changelog
2.0.1 · outubro de 2026
- Reescrita completa, compatível com PHP 7.4 a 8.3
- Dashboard com atualização automática, CSAT e gráfico de 14 dias
- Papéis Admin/Atendente/Cliente e 8 permissões granulares
- Departamentos, notas internas, eventos na linha do tempo e ações em massa
- Anexos com verificação de conteúdo e download protegido
- Avaliação de atendimento de 1 a 5 estrelas
- Cliente SMTP próprio, notificações e envio de teste
- Relatórios PDF e Excel sem bibliotecas externas
- Logotipo, cor de destaque e tema claro/escuro
- AES-256-GCM, CSP, recuperação de senha com token de uso único
- Instalador com detecção de MAMP e dados de demonstração
1.0.0 · dezembro de 2025
Primeira versão estável. Baixar 1.0.0
Pronto para instalar?
Grátis, open source (licença MIT) e sem mensalidade.
Baixar SaguiDesk 2.0.1sagui_desk_v2.0.1.zip · 134 KB