# Gestão de Permissões — Resumo

> Módulo: `V2/Modules/Infraestrutura/GestaoPermissoes`
> Grupo: `Infraestrutura`
> Camada de plataforma acoplada: `V2/Core/Services/PermissionService.php`,
> `V2/Core/Middleware/V2PermissionMiddleware.php`, `V2/Core/Models/V2Role.php`,
> `V2/Core/Helpers/helpers.php` (`v2_can`).
> Índice desta pasta: `00` a `09` (ver "Mapa do dossiê" ao final).
> Raiz de referência dos caminhos: `/home/one/projects/maxima/v7/lotep`.

## Objetivo

Administrar o **controle de acesso do CMS da V2**: perfis de acesso (`v2_roles`),
a matriz de permissões por módulo (`permissions_v2`, jsonb) e o vínculo de cada
usuário administrativo a **um único perfil** (`users.v2_role_id`).

O módulo entrega duas telas operacionais:

1. **Perfis de Acesso V2** — CRUD de perfis e edição da matriz
   `módulo × {none, read, write}`.
2. **Permissões e Usuários** — listagem e edição de usuários do CMS, incluindo a
   troca de perfil V2 e a troca da senha.

A decisão efetiva de acesso, porém, **não vive no módulo**: ela é tomada pelo
`V2PermissionMiddleware` (a partir do `active_pattern` declarado em cada
`ModuleProvider`), pelo helper `v2_can()` (chamadas explícitas em controllers e
Blade) e pelo `PermissionService` (resolução da chave e do nível).

## Efeito / impacto

| Faixa | Efeito |
|---|---|
| Operador do CMS | Recebe um perfil; vê apenas os módulos liberados na sidebar e só executa POST/PUT/DELETE nos módulos com nível `write`. |
| Administrador | Cria perfis, distribui níveis por módulo e associa usuários; gerencia credenciais e o papel Sentinel V1. |
| Segurança | Barreira dupla: middleware por rota + `v2_can()` dentro do controller/Blade. O e-mail de suporte e o papel Sentinel `super-admin` têm bypass total. |
| Transparência | Toda criação/edição/exclusão de perfil e edição de usuário é enviada ao `V2AuditLogger` (`v2_audit_logs`). |
| Portal público | Nenhum efeito: o módulo é exclusivamente CMS. |

## Comportamento observável

### Níveis e resolução

- Cada módulo do sistema tem **um** valor em `permissions_v2`:
  `none`, `read` ou `write`.
- `read` permite requisições **GET e HEAD** no módulo; qualquer outro método é
  barrado (`V2/Core/Middleware/V2PermissionMiddleware.php:102-121`).
- `write` permite tudo dentro do módulo (`:124-126`).
- `none` (ou ausência da chave) redireciona para o dashboard com mensagem de
  erro; requisições AJAX/JSON recebem `403` (`:84-100`).
- A chave é resolvida tolerando divergências entre o nome canônico do diretório
  e slugs legados: chave exata → aliases explícitos nos dois sentidos →
  comparação normalizada (minúsculas, sem separadores). Ver
  `V2/Core/Services/PermissionService.php:105-183`.
- Valor inválido (por exemplo `"super"`) é tratado como `none`
  (`PermissionService.php:185-188`).

### Como o middleware associa rota a módulo

Não existe um mapa explícito `rota → módulo`. O middleware percorre todos os
`ModuleProvider` registrados e usa o campo `active_pattern` como glob de path:

```php
foreach ($moduleConfigs as $moduleKey => $config) {
    $pattern = $config['active_pattern'] ?? null;
    if ($pattern && $request->is($pattern)) {
        $currentModuleKey = $moduleKey;
        $currentModuleConfig = $config;
        $matched = true;
        break;
    }
}
```

(`V2/Core/Middleware/V2PermissionMiddleware.php:40-48`)

Para este módulo, o `ModuleProvider` declara:

```php
'active_pattern' => ['cms/permissoes/permissions*', 'cms/permissoes/roles*'],
```

(`V2/Modules/Infraestrutura/GestaoPermissoes/ModuleProvider.php:22`)

### Proteções especiais

| Regra | Onde |
|---|---|
| E-mail `config('v2.support.email')` tem bypass total em `v2_can()` e no middleware | `V2/Core/Helpers/helpers.php:21`, `V2PermissionMiddleware.php:70` |
| Papel Sentinel `super-admin` tem bypass total no middleware e no serviço | `V2PermissionMiddleware.php:70`, `PermissionService.php:72` |
| Grupo de módulos `Support` é visível/acessível apenas para o e-mail de suporte | `V2PermissionMiddleware.php:51-67`, `SidebarComposer.php:43-49` |
| Perfis com `restricted` (e-mail) são removidos da matriz e não podem ser atribuídos | `GestaoPermissoesRolesController.php:96-100,136-146` |
| Slug `super-admin` não pode ser criado nem renomeado em `v2_roles` | `GestaoPermissoesRolesController.php:125-133,218-226` |
| `isHighAdmin()` reserva a organização do dashboard a suporte, `super-admin` e `administrador` | `PermissionService.php:197-210` |

### Telas

- **Perfis**: lista com busca por nome/slug, contagem de usuários por perfil,
  ordenação por nome/slug, paginação de 15 itens
  (`GestaoPermissoesRolesController.php:37-86`).
- **Edição de perfil**: matriz de rádio por módulo, com três opções — “Sem
  Acesso”, “Leitura”, “Leitura & Escrita” — e badges de grupo
  (`V2/Modules/Infraestrutura/GestaoPermissoes/Views/roles/edit.blade.php:100-140`).
- **Usuários**: lista com busca por nome/e-mail, badge do papel V1 e do perfil
  V2, e edição inline da conta (`V2/Modules/Infraestrutura/GestaoPermissoes/Views/permissions/index.blade.php:1-127`).
- **Edição de usuário**: nome, e-mail, nova senha (opcional) e seleção de perfil
  V2 (`V2/Modules/Infraestrutura/GestaoPermissoes/Views/permissions/edit.blade.php:45-100`).

## Detalhes e particularidades técnicas

- **Um perfil por usuário**: `users.v2_role_id` é um UUID nullable com índice e
  FK `nullOnDelete` (`V2/Core/Migrations/2026_06_01_000005_create_v2_roles_and_add_role_id_to_users_table.php:41-43`;
  `V2/Modules/Support/SupportConfigs/Migrations/2026_07_02_000001_add_v2_foreign_keys.php:22-28`).
- **`permissions_v2` é jsonb** e o model `V2Role` faz cast para `array`
  (`V2/Core/Models/V2Role.php:73-75`). O serviço ainda aceita string JSON por
  compatibilidade (`PermissionService.php:238-240`).
- **Dois RBACs coexistem**: o Sentinel V1 (`roles`, `role_users`,
  `inRole('super-admin')`) e o RBAC V2 (`v2_roles`, `users.v2_role_id`). O
  cadastro de usuário exige um papel V1 (`role_id`) e aceita um perfil V2
  opcional (`GestaoPermissoesPermissionsController.php:207-213`).
- **O parâmetro do middleware é ignorado**: as rotas declaram
  `v2.permission:gestao-permissoes`, `v2.permission:Operators,read` e
  `v2.permission:Operators,write`, mas `handle($request, Closure $next)` não
  recebe o parâmetro. O nível efetivo vem do método HTTP
  (`V2PermissionMiddleware.php:22`).
- **Fail-open para rota fora de módulo**: se nenhum `active_pattern` casar, a
  requisição segue (`V2PermissionMiddleware.php:74-77`).
- **Falha de leitura de perfil não bloqueia**: `getUserPermissions()` devolve
  `[]` em exceção e o middleware trata ausência como `none` apenas quando a rota
  pertence a um módulo; em módulo, `[]` → `none`, portanto bloqueia.
- **Dupla execução do middleware**: `CmsAuthenticate` chama o
  `V2PermissionMiddleware` no fim do seu `handle()`
  (`V2/Core/Middleware/CmsAuthenticate.php:40`), e as rotas do módulo também
  declaram `v2.permission` explicitamente
  (`V2/Modules/Infraestrutura/GestaoPermissoes/Routes/cms.php:10`).

## Estrutura de dados (resumo)

| Objeto | Papel |
|---|---|
| `v2_roles.id` (uuid, PK) | Identificador do perfil. |
| `v2_roles.name` (string) | Nome exibido. |
| `v2_roles.slug` (string, unique) | Identificador estável; `super-admin` é reservado. |
| `v2_roles.permissions_v2` (jsonb, nullable) | Mapa `{ "Modulo": "none|read|write" }`. |
| `v2_roles.deleted_at` | Soft delete. |
| `users.v2_role_id` (uuid, nullable, indexed, FK) | Perfil do usuário. |
| `users.permissions_v2` (jsonb, legado) | Coluna criada pela migration `000004`; **não é lida** pelo serviço atual. |
| `v2_audit_logs` | Destino da auditoria de criação/edição/exclusão. |

## Como testar (resumo)

```bash
vendor/bin/phpunit tests/Unit/V2/Core/Services/PermissionServiceTest.php
vendor/bin/phpunit tests/Unit/V2/Modules/Infraestrutura/GestaoPermissoes/
vendor/bin/phpunit tests/Feature/V2/Rbac/CommonUserModuleAccessE2ETest.php
vendor/bin/phpunit tests/Feature/V2/PermissionsTest.php
```

Casos cobertos: bypass de suporte, `isHighAdmin`, níveis `read`/`write`/`none`,
aliases e normalização, CRUD de perfil com auditoria, CRUD de usuário com
Sentinel e acesso HTTP de usuário comum por chave canônica e por slug legado.
Detalhes em `07-TESTES.md`.

## Migração para base moderna (resumo)

No V7 o modelo é **`{modulo}.{acao}` com quatro ações fixas** (`ver`, `editar`,
`aprovar`, `arquivar`), perfil único por usuário (`core_roles.permissoes` como
lista jsonb de tokens), `Gate` nativo do Laravel, **negação por padrão** e
**sem bypass por e-mail** (ADR-033). A matriz `none|read|write` deve ser
**traduzida**, não copiada: `read → ver`; `write → editar` (e, conforme o
módulo, `aprovar`/`arquivar`). O `active_pattern` deve virar o próprio prefixo
de rota do módulo, com guard declarado no manifesto. Detalhes em
`06-MIGRACAO-MODERNA.md` e o julgamento de portabilidade em
`09-APROVEITAMENTO-V7.md`.

## Resumo geral

O módulo é a interface administrativa de um RBAC de três níveis por módulo
(`none`, `read`, `write`) montado sobre duas tabelas: `v2_roles` (perfil com
mapa jsonb de permissões) e `users.v2_role_id` (um perfil por usuário). A
autorização real é distribuída entre um middleware que casa a URL com o
`active_pattern` do módulo, o helper `v2_can()` e o `PermissionService`, que
tolera aliases e variações de caixa/separador. O desenho funciona no caminho
feliz, mas tem quatro fragilidades estruturais: o parâmetro do middleware é
ignorado (o nível é inferido pelo verbo HTTP), rotas fora de módulo passam
livremente, qualquer GET passa com `read` mesmo quando a ação muta estado, e
existe bypass por e-mail fixo. Além disso, o RBAC V2 convive com o Sentinel V1,
o que duplica conceitos de papel. Para o V7, o valor aproveitável é a **UX da
matriz de permissões** e a **resolução tolerante de chaves**; o modelo de dados
e o mecanismo de autorização devem ser substituídos pelo vocabulário de quatro
ações do ADR-033, com `Gate`, negação por padrão e auditoria nativa.

## Mapa do dossiê

| Arquivo | Conteúdo |
|---|---|
| `00-RESUMO.md` | Este documento |
| `01-ARQUITETURA.md` | Camadas, fluxo de request, classes e dependências |
| `02-MODELAGEM.md` | `v2_roles`, `users.v2_role_id`, jsonb, migrations e seeds |
| `03-ROTAS-E-CONTROLADORES.md` | Rotas, middleware, validações e ações |
| `04-VIEWS-E-UX.md` | Blades, matriz de rádio, JS e estados de tela |
| `05-REGRAS-E-PORTABILIDADE.md` | Regras, armadilhas e acoplamentos |
| `06-MIGRACAO-MODERNA.md` | Plano de reconstrução no V7 |
| `07-TESTES.md` | Estratégia e casos de teste |
| `08-GAPS-E-DIVIDAS.md` | Riscos, dívidas e perguntas em aberto |
| `09-APROVEITAMENTO-V7.md` | Portar / adaptar / rejeitar com base nas ADRs |
