# LGPD (Barra de Privacidade) — Arquitetura

> **Versão analisada:** `v6` (Laravel 5.5.50 / PHP 7.2.34 / PostgreSQL 10)
> **Slug do módulo:** `lgpd`

---

## 1. Visão geral

O módulo **não possui classes próprias**. Ele é um *perfil de configuração*
sobre a infraestrutura genérica de configurações do CMS. Isso significa que
qualquer mudança na configuração da infraestrutura de configurações impacta
este módulo. O dossiê dos módulos irmãos descreve a estrutura comum:

- `../configuracoes-da-instituicao/` — categoria `site`
- `../temas-e-cores/` — categoria `temas`
- `../outras-configuracoes/` — categoria `outros`

Aqui documentamos **apenas** o que é próprio da LGPD.

## 2. Classes envolvidas

| Classe | Arquivo | Papel no módulo LGPD |
|---|---|---|
| `App\Http\Controllers\Prefecture\ConfigurationController` | `v6/app/Http/Controllers/Prefecture/ConfigurationController.php` | Controller único do CMS: `editByCategory('barra-privacidade')` monta a tela; `updateByCategory()` grava as 4 chaves. |
| `App\Http\Requests\ConfigurationRequest` | `v6/app/Http/Requests/ConfigurationRequest.php` | Validação dinâmica: monta regras por chave consultando `configurations`. |
| `App\Prefecture\Configuration` | `v6/app/Http/Model/Prefecture/Configuration.php` | Model da tabela `configurations` (`use SoftDeletes`, `$fillable` com `key`, `value`, `type`, `title`, `category_configurations_id`, `max_input`, `min_input`, `notnull`, `order`). |
| `App\Http\Model\Prefecture\CategoryConfiguration` | `v6/app/Http/Model/Prefecture/CategoryConfiguration.php` | Model de `category_configurations` (slug `barra-privacidade`). |
| `App\Http\Model\Admin\Modulos` | `v6/app/Http/Model/Admin/Modulos.php` | Model de `modulos`; o `status` do slug `lgpd` decide se a barra existe no portal. |
| `App\Http\Controllers\Portal\HelperController` | `v6/app/Http/Controllers/Portal/HelperController.php` | Endpoint público `getPrivacyBar()` que devolve o prazo de expiração. |
| `App\Providers\ConfigHeaderServiceProvider` | `v6/app/Providers/ConfigHeaderServiceProvider.php` | Composer que injeta `$configurations` (3 chaves da barra) nas views do portal. |
| `App\Providers\ModulosServiceProvider` | `v6/app/Providers/ModulosServiceProvider.php` | Composer que injeta `$modulos` (cache `modulos`). |
| `App\Http\Views\Composers\ConfigurationsComposer` | `v6/app/Http/Views/Composers/ConfigurationsComposer.php` | **Código morto**: foi criado para as 3 chaves da barra, mas não é registrado em nenhum provider. |
| `App\Http\Traits\GetInformationsPrefectureTrait` | `v6/app/Http/Traits/GetInformationsPrefectureTrait.php` | Fornece `getConfiguration($reference)` usado pelo controller para listar as configurações da categoria. |
| `App\Http\Traits\DataMaskTrait` | `v6/app/Http/Traits/DataMaskTrait.php` | Mascaramento de dados pessoais (escopo mais amplo de LGPD, tratado na seção 6). |

### Trecho real do trait de leitura

```php
public function getConfiguration($reference)
{
    return Configuration::whereHas('categoryConfiguration', function ($query) use ($reference) {
        $query->where('slug', '=', $reference);
    })->orderBy('order')->get();
}
```

## 3. Fluxo 1 — CMS (leitura da tela)

```
GET /cms/configuracoes/editar/barra-privacidade
        |
        +- middleware check.logged
        v
Prefecture\ConfigurationController@editByCategory('barra-privacidade')
        |
        +- $reference = 'barra-privacidade' ; $acess = 'barra-privacidade'
        +- $configurations = $this->getConfiguration('barra-privacidade')
        +- $category = CategoryConfiguration::where('slug','barra-privacidade')->first()
        +- if (!has_access(['barra-privacidade.edit'])) -> redirect dashboard.index
        +- switch: case 'barra-privacidade'
              -> view('prefecture.configurations.barra-privacidade.edit',
                    compact('configurations','title','category'))
                    |
                    +- @include('prefecture.configurations.barra-privacidade.form')
                          +- @foreach($configurations as $configuration) -> 4 campos
```

Trecho real do controller (`v6/app/Http/Controllers/Prefecture/ConfigurationController.php`):

```php
case 'barra-privacidade':
    $title = 'LGPD';
    $this->configurationLog('Acessou edição de barra de privacidade');
    return view("prefecture.configurations.{$slug}.edit", compact("configurations", 'title', 'category'));
```

## 4. Fluxo 2 — CMS (gravação)

```
POST /cms/update/configuration  (name: update.configurations.by.category)
        |
        +- sem middleware check.logged; guarda interna has_access(['configuracoes.edit'])
        v
ConfigurationController@updateByCategory(ConfigurationRequest $request)
        |
        +- $category = CategoryConfiguration::find($request->get('category_configurations_id'))
        +- $dataForm = $request->except('_token','category_configurations_id','display')
        +- foreach ($dataForm as $key => $value):
        |     $config = Configuration::where('key', $key)->first();
        |     $config->value = $value; $config->save();
        |     activity()->performedOn($config)->causedBy(Sentinel::getUser())->log('Edição de configuração');
        |     Cache::pull('structureType');
        +- redirect()->route('edit.configuracoes.by.category', $category->slug)
```

## 5. Fluxo 3 — Portal (exibição e aceite)

```
GET / (qualquer página do portal, modelo1..modelo6)
        |
        +- ModulosServiceProvider    -> $modulos  (cache 'modulos')
        +- ConfigHeaderServiceProvider -> $configurations (3 chaves)
        v
portal/layouts/modeloN/layout/layout.blade.php
        +- @include('portal.layouts.barra-privacidade.head')    -> CSS inline + variaveis de cor
        +- @include('portal.layouts.barra-privacidade.scripts') -> <script src="assets/js/custom/portal/barra-privacidade.js">
        v
portal/layouts/modeloN/layout/footer.blade.php
        +- @include('portal.layouts.barra-privacidade.barra-privacidade')
              +- @if(isset($modulos['lgpd']) && $modulos['lgpd'] && demais condicoes)
                    +- <div class="barradeprivacidade"> texto: {!! $configurations['barra-privacidade'] !!}
                          +- <button class="btn btn-success acceptcookies bg-color-1 botao-privacidade-color">Ok, entendi!</button>
        v
barra-privacidade.js (IIFE)
        +- if (!getCookie('acceptCookies')) cookieAlert.classList.add('show');
        +- acceptCookies.onclick:
              +- let bar_config = await myFetch('/getPrivacyBar');
              +- setCookie('acceptCookies', true, bar_config.value ? bar_config.value : 7)
              +- remove classe 'show' após 1000ms
              +- window.dispatchEvent(new Event('cookieAlertAccept'))
        v
GET /getPrivacyBar  ->  Portal\HelperController@getPrivacyBar()
        +- Configuration::where('key','barra-privacidade-expiracao')->orderBy('id')->first(['key','value'])
```

### Diagrama (Mermaid)

```mermaid
flowchart TD
    CMS[Operador no CMS] -->|GET /cms/configuracoes/editar/barra-privacidade| R1[Rota basepro.php:241]
    R1 --> C1[ConfigurationController@editByCategory]
    C1 --> M1[(configurations / category_configurations)]
    C1 --> V1[prefecture.configurations.barra-privacidade.edit + form]

    V1 -->|POST /cms/update/configuration| R2[Rota basepro.php:246]
    R2 --> C2[ConfigurationController@updateByCategory]
    C2 --> FR[ConfigurationRequest::rules] --> M1

    CID[Visitante] --> P1[Views do portal modelo1..6]
    MP[ModulosServiceProvider] --> P1
    CP[ConfigHeaderServiceProvider] --> P1
    P1 --> BV[barra-privacidade.blade.php]
    BV -->|show| JS[barra-privacidade.js]
    JS -->|GET /getPrivacyBar| HC[Portal\HelperController@getPrivacyBar]
    HC --> M1
    JS -->|document.cookie acceptCookies| CK[(Cookie do navegador)]
```

## 6. Relações com outros módulos (âmbito LGPD mais amplo)

O módulo `lgpd` do CMS é restrito à barra de privacidade. Outras
implementações de LGPD no sistema, fora do escopo do módulo `lgpd`:

| Peça | Arquivo | Papel |
|---|---|---|
| Mascaramento determinístico + refino por IA | `v6/app/Http/Traits/DataMaskTrait.php` | `maskTextDeterministic()` (CPF, CNPJ, RG, telefone, CEP, e-mail, credenciais, CID-10, dicionário sensível) e `maskTextWithAi()` (Gemini, chave `gemini_api_key` da categoria `site`). |
| Mascaramento exposto no model | `v6/app/Http/Model/Prefecture/InformationsRequest.php` | Campo `mask_request` (protocolo/nome mascarados) do e-SIC. |
| Backfill histórico | `v6/database/seeds/UpdateRequestToMaskRequestInInformationRequest.php`, `v6/database/seeds/UpdateRequestToMaskRequestInOmbudsmanRequest.php`, `v6/database/seeds/UpdateAnswerToMaskAnswerInOmbudsmanAnswer.php` | Chamados por `v6/database/seeds/ExtrasSeeder.php:17-19` com o comentário "Precisa rodar sempre. NUNCA remover." |
| Listagem completa desabilitada | `v6/database/seeds/AddToConfigurationDisabledFullListRequests.php` | Chave `full_list_requests_disabled` (categoria `site`) lida em `v6/app/Http/Controllers/Portal/OmbudsmanController.php:306` e `v6/app/Http/Controllers/Portal/TransparencyController.php:169`. |
| Manual e cadastro da LGPD | `v6/database/migrations/2023_02_01_083626_add_itens_to_archives.php:512` e `:722` | Itens de menu "Manual da LGPD" e "Cadastro da LGPD". |

## 7. Dependências externas

| Dependência | Uso | Origem |
|---|---|---|
| Summernote (`summernote.min.js`, `summernote-pt-BR.js`) | editor do texto da barra | `v6/public/assets/plugins/summernote/` |
| `v6/public/assets/js/custom/utilities/richtext/summernote.js` | inicialização do Summernote | asset local |
| bootstrap-colorpicker 2.5.2 | campo de cor do botão | `v6/public/assets/plugins/colorpicker-2.5.2/dist/css/bootstrap-colorpicker.min.css` e `v6/public/assets/plugins/colorpicker-2.5.2/dist/js/bootstrap-colorpicker.js` |
| `v6/public/assets/js/custom/utilities/functions.js` | helper `myFetch()` (linha 64) usado pelo JS da barra | asset local |
| `laravel/framework` 5.5.50, `cartalyst/sentinel` (permissões), log de atividade | framework | `v6/composer.json` |

## 8. Onde a v6 introduziu arquitetura nova

- Tabela `modulos` (`v6/database/migrations/2024_11_01_150206_create_modulos_table.php`),
  com `resources.modulo_id` e `menu_orders.modulo_id`.
- Composer `ModulosServiceProvider` que faz da barra uma feature **ativável**.
- Composer `ConfigurationsComposer` (morto) que centralizaria a leitura das 3
  chaves da barra.
- A v5 não tinha nenhuma checagem de módulo na renderização da barra — ela era
  exibida sempre que `barra-privacidade-exibir` estivesse ligada.
