O menu usa a mesma policy da tela, e nenhum perfil vê um link que dá 403
[!NOTE] Resumo Executivo (DEV-2026-105): O operador via no menu telas que devolviam 403, porque o menu tinha uma regra e a tela outra. Com as duas usando a mesma policy, um teste percorre o menu de cada perfil e garante que elas continuem iguais.
🚨 O Desafio Técnico / Contexto
Em um sistema de 148 telas, abrir cada módulo com cada perfil mostrou o operador vendo Usuários, Empresas e Licenças no menu, todas com 403. A diretoria também pediu ambiente com menu lateral ou com blocos e cards, ajustável por perfil.
💡 Principais Lições Aprendidas & Descobertas
- 💡 Meça antes de mexer: abrir tudo com cada perfil revelou o problema real, que uma revisão visual do menu não mostraria.
- 💡 ModuleAccess pergunta ao Gate usando viewAny, a mesma permissão da tela. Assim, o menu acompanha qualquer mudança de permissão sem manutenção à parte.
- 💡 A limpeza roda ao gravar e ao ler o layout. Gravar barra requisição forjada, e ler tira da tela salva o que perdeu permissão ou licença depois.
- 💡 Num sistema grande, trocar o shell primeiro melhora todas as telas de uma vez. O interior de cada uma fica para a etapa seguinte, e a nota do guia deixa isso à vista: 4,5 para 8,5 de 15.
- 💡 Esconder um item do menu não retira a permissão, e a tela de configuração avisa isso. Sem o aviso, o administrador pensa que bloqueou o acesso.
🛠️ Especificação Técnica & Código-Chave
public function roleAllows(User $user, string $moduleName): bool
{
$model = config("ui_shell.module_policies.{$moduleName}");
return $model === null || Gate::forUser($user)->allows('viewAny', $model);
}
📈 Impacto no Ecossistema & Valor Prático
Em 20 testes dedicados, nenhum item do menu leva a tela recusada, e um perfil de uma empresa não afeta outra.
- Projetos Relacionados:
omnichannel-system - Registro de Origem:
_data/daily.dev-17.yml
Publicado originalmente como parte do Diário de Desenvolvimento 2026 do ecossistema Artes do Sul & Araguaci.