# Perfis de Acesso / Usuários (telas administrativas) > Movido do `CLAUDE.md` da raiz em 2026-08-26 para reduzir conflito de edição entre aplicações. Ver `CLAUDE.md` na raiz para o **modelo de permissões em si** (formato do JSON de `PerfilAcesso.permissoes`, padrão visualizar/editar, `permissoes_efetivas()`) — esse conteúdo é transversal e continua lá porque toda aplicação do Portal depende dele. Este arquivo cobre só as telas administrativas (`perfis-acesso.html`/`usuarios.html`) em si. Não é auto-carregado pelo Claude Code — leia manualmente ao mexer nessas duas telas. ## Popup "Nova Aplicação" (gerenciar acesso por aplicação, entre perfis) Botão `#pa-app-search-btn` ao lado de "Novo Perfil" (`perfis-acesso.html`) abre `#pa-app-search-modal` — o caminho inverso da árvore de permissões: em vez de abrir um perfil e marcar módulo por módulo, o usuário busca uma aplicação/ferramenta pelo nome e vê/gerencia **todos os perfis** que têm acesso a ela numa tabela só. - **Fonte dos dados — 100% reaproveitado, sem endpoint novo**: `pidFlattenAplicacoes()` (`profiles.js`) achata `PID_MODULES` × `PID_MODULE_APPS` (já carregados de `GET /api/catalogo/` no load da página) numa lista plana de "aplicações" — uma por entrada de `MODULE_APPS`, seja ela um app simples ou um subgrupo com `tools` aninhadas (mesma unidade usada em `renderEntry()` da árvore). A busca (`renderAppSearchResults()`) casa o termo contra o label da aplicação, o label do módulo **e** o label de cada `tool` aninhada — esse último é o que permite achar, por exemplo, "Controle Simples Nacional" (o `tool` real dentro do subgrupo "Consultoria Tributária" de Auditorias) mesmo a unidade selecionável sendo o subgrupo inteiro. - **Painel de gerenciamento** (`renderAppManageTable()`): ao clicar num resultado, mostra uma tabela com uma linha por perfil (`profiles`, o mesmo array já carregado pela tela) e uma coluna de checkbox por `tool` — para app simples sem subgrupo, uma coluna única "Acesso". O cabeçalho de cada coluna usa `tool.label.split(" (")[0]` (corta o parêntese explicativo tipo "Editar (reordenar, incluir e remover cartões)" → "Editar"), sem precisar de um label curto dedicado no catálogo. - **Salva na hora, por checkbox** (decisão explícita do usuário — sem botão "Salvar" no popup): cada `change` dispara `PATCH /api/perfis/{codigo}/` só com `{permissoes: perfil.permissions}` (`pidUpdatePerfilPermissoes`, PATCH parcial — o `ModelViewSet` já aceita, `PerfilAcessoSerializer` não exige os outros campos fora de `partial_update`). Erro de rede reverte o checkbox e o estado em memória, com `pidAlert()` (ver "Modal de confirmação genérico" no `CLAUDE.md` da raiz — mesmo padrão de outros toggles imediatos do app, ex. inativar usuário). - **Conceder acesso habilita o módulo automaticamente** (decisão explícita do usuário): se o checkbox marcado pertence a um módulo com `enabled=false` naquele perfil, o toggle também vira `perm.enabled = true` no mesmo PATCH — sem isso, o perfil ganharia a chave em `apps` mas o item continuaria escondido no menu (`access.js` esconde o `nav-group`/`nav-subitem` inteiro por `enabled`, não só por app). **Revogar não desabilita o módulo de volta** (outras aplicações dele podem seguir em uso por aquele perfil). - Perfis inativos (`ativo=False`) aparecem na tabela com o selo `.status-pill--inativo` (mesmo componente da coluna "Status" de `usuarios.html`), sem serem excluídos da lista — nada nesse popup impede gerenciar o acesso deles. ## Aba "Usuários do Escritório" (dentro da edição de um perfil) — duas tabelas com seleção múltipla Substituiu o antigo `