{
  "id": "auditoria",
  "title": "Auditoria e logs",
  "description": "Rastreabilidade das mutações de negócio, autores, filtros, retenção e diferenças de atributos.",
  "type": "architecture",
  "status": "observed",
  "visibility": "public",
  "tags": [
    "auditoria",
    "logs",
    "activitylog",
    "rastreabilidade"
  ],
  "related": [
    "contatos",
    "acertos",
    "notificacoes",
    "decisoes",
    "arquitetura"
  ],
  "sourceRefs": [
    "https://github.com/james-suite/james/blob/master/routes/web.php",
    "https://github.com/james-suite/james/blob/master/app/Http/Controllers/AuditController.php",
    "https://github.com/james-suite/james/blob/master/app/Enums/AuditAction.php",
    "https://github.com/james-suite/james/blob/master/app/View/Components/ActivityLog.php",
    "https://github.com/james-suite/james/blob/master/config/activitylog.php",
    "https://github.com/james-suite/james/blob/master/database/migrations/2026_07_18_162729_create_activity_log_table.php"
  ],
  "authors": [],
  "updated": null,
  "diagram": null,
  "body": "## O que é registrado\n\nO painel autenticado `/audit` usa `spatie/laravel-activitylog` para registrar mutações em entidades de negócio. O log guarda o sujeito alterado, o autor, a ação, o nome do log e as mudanças de atributos.\n\n{{diagram:audit-flow}}\n\nO registro não é um log de todas as requisições HTTP. Ele acompanha eventos de modelos que optaram por `LogsActivity`, sempre priorizando o que mudou no dado de negócio.\n\n## Entidades monitoradas\n\nHoje participam do mecanismo de auditoria:\n\n- usuário;\n- contato e grupo de contatos;\n- acerto individual, divisão de conta e arquivamento de saldo;\n- conta financeira;\n- cartão de crédito e fatura;\n- transação e item de transação;\n- recorrência financeira;\n- tag financeira.\n\nO conjunto exato de eventos depende do modelo. Entidades com soft delete podem registrar exclusão lógica, restauração e exclusão permanente; entidades sem esse ciclo registram apenas criação, atualização e exclusão.\n\n## Ações e ciclo de vida\n\n| Descrição | Significado |\n| --- | --- |\n| `created` | Registro criado. |\n| `updated` | Um ou mais campos foram alterados. |\n| `deleted` | Registro enviado para a lixeira por soft delete. |\n| `restored` | Registro restaurado. |\n| `forceDeleted` | Registro removido fisicamente. |\n| `item_deleted` | Evento usado para marcar a remoção definitiva de um item de transação. |\n\nNa atualização, o log usa apenas atributos preenchíveis que ficaram sujos. Um `save()` sem alteração real não cria uma entrada vazia.\n\n## Quem realizou a mudança\n\nO `causer` normalmente é o usuário autenticado. Alterações disparadas por comandos do scheduler ou jobs sem sessão HTTP podem não ter `causer_id`; o painel as apresenta como **Sistema / Rotina Automática**.\n\nIsso permite diferenciar, por exemplo:\n\n- uma transação editada manualmente;\n- uma recorrência materializada pelo scheduler;\n- uma fatura avançada para o período seguinte;\n- uma alteração de dados feita por um job de importação.\n\n## Filtros do painel\n\nEm `/audit`, a consulta é paginada em até 100 registros e pode ser filtrada por:\n\n- **Módulo/sujeito** (`subject_type`);\n- **ID do sujeito** (`subject_id`);\n- **Ação** (`description`);\n- **Usuário** ou opção **Sistema** para registros sem autor;\n- **Data inicial** e **data final**;\n- ordem mais recente ou mais antiga.\n\nAs opções de módulo, ação e usuário são montadas a partir do próprio histórico existente. Isso evita uma lista fixa que fique desatualizada quando um novo modelo passa a registrar atividades.\n\n## Visualização do diff\n\nAo abrir `/audit/{activity}`, o James normaliza os dados da atividade e mostra:\n\n- valor anterior (`old`);\n- valor novo (`attributes`);\n- campos criados ou removidos;\n- autor, sujeito, ação, data e nome do log.\n\nO formatador trata arrays e objetos como JSON, datas com o timezone da aplicação, valores nulos como `null` e booleanos como `true`/`false`. Quando a entidade ainda está disponível, a tela tenta criar um link para seu registro.\n\nEm exclusões, o activity log pode guardar o estado anterior em `old` ou em `attributes`, dependendo do evento. O controller normaliza os dois formatos para que a tela mostre os dados que foram removidos.\n\n## Histórico dentro das telas\n\nAlém do painel global, o componente `ActivityLog` aparece nas telas de entidades que oferecem histórico contextual. Ele carrega os 20 eventos mais recentes do sujeito, junto com o avatar do autor quando existe.\n\nAssim, a investigação pode começar pelo detalhe de um contato, acerto ou entidade financeira e depois continuar no filtro global `/audit`.\n\n## Configuração e retenção\n\nAs opções principais estão em `config/activitylog.php`:\n\n| Configuração | Padrão | Efeito |\n| --- | --- | --- |\n| `ACTIVITYLOG_ENABLED` | `true` | Liga ou desliga a gravação. |\n| `clean_after_days` | `365` | Idade usada pelo comando de limpeza do pacote. |\n| `include_soft_deleted_subjects` | `false` | Define se a relação de sujeito inclui modelos apagados logicamente. |\n| `ACTIVITYLOG_BUFFER_ENABLED` | `false` | Permite buffer de atividades para inserção em lote, quando necessário. |\n\nO valor de 365 dias é a política padrão para uma futura execução de limpeza; não significa que cada requisição apague logs automaticamente. Se a limpeza for adotada em produção, ela deve ser executada de forma consciente porque reduz a capacidade de investigação histórica.\n\n## Como habilitar uma nova entidade\n\nUma nova model de negócio deve:\n\n1. usar `LogsActivity`;\n2. declarar em `$recordEvents` somente eventos relevantes;\n3. retornar `LogOptions::defaults()` com `logFillable()`;\n4. usar `logOnlyDirty()` e `dontLogEmptyChanges()`;\n5. escolher um nome de log específico com `useLogName()`;\n6. evitar registrar segredos, tokens ou campos técnicos que não pertençam ao histórico funcional.\n\nExemplo mínimo:\n\n```php\nuse Spatie\\Activitylog\\Models\\Concerns\\LogsActivity;\nuse Spatie\\Activitylog\\Support\\LogOptions;\n\nclass ExampleModel extends Model\n{\n    use LogsActivity;\n\n    protected static array $recordEvents = ['created', 'updated', 'deleted'];\n\n    public function getActivitylogOptions(): LogOptions\n    {\n        return LogOptions::defaults()\n            ->logFillable()\n            ->logOnlyDirty()\n            ->dontLogEmptyChanges()\n            ->useLogName('example_model');\n    }\n}\n```\n\n### Caso especial: itens de transação\n\nItens removidos durante a edição de uma transação financeira podem ser excluídos fisicamente para não continuar compondo cálculos. Antes da remoção, o James registra o evento com descrição `item_deleted`, preservando descrição, quantidade, preço unitário, total e vínculo com a transação no histórico.\n\n### Referências\n\n- [Contatos](doc:contatos) e [Acertos](doc:acertos) — exemplos de telas com histórico contextual.\n- [Rotinas automáticas](doc:automacoes) — explica por que o autor pode aparecer como sistema.\n- [Decisões arquiteturais](doc:decisoes) — escolhas de auditoria e dados.",
  "sections": [
    {
      "id": "o-que-e-registrado",
      "level": 2,
      "title": "O que é registrado",
      "text": "O painel autenticado `/audit` usa `spatie/laravel-activitylog` para registrar mutações em entidades de negócio. O log guarda o sujeito alterado, o autor, a ação, o nome do log e as mudanças de atributos.   O registro não é um log de todas as requisições HTTP. Ele acompanha eventos de modelos que optaram por `LogsActivity`, sempre priorizando o que mudou no dado de negócio.",
      "line": 1
    },
    {
      "id": "entidades-monitoradas",
      "level": 2,
      "title": "Entidades monitoradas",
      "text": "Hoje participam do mecanismo de auditoria:  - usuário; - contato e grupo de contatos; - acerto individual, divisão de conta e arquivamento de saldo; - conta financeira; - cartão de crédito e fatura; - transação e item de transação; - recorrência financeira; - tag financeira.  O conjunto exato de eventos depende do modelo. Entidades com soft delete podem registrar exclusão lógica, restauração e exclusão permanente; entidades sem esse ciclo registram apenas criação, atualização e exclusão.",
      "line": 9
    },
    {
      "id": "acoes-e-ciclo-de-vida",
      "level": 2,
      "title": "Ações e ciclo de vida",
      "text": "| Descrição | Significado | | --- | --- | | `created` | Registro criado. | | `updated` | Um ou mais campos foram alterados. | | `deleted` | Registro enviado para a lixeira por soft delete. | | `restored` | Registro restaurado. | | `forceDeleted` | Registro removido fisicamente. | | `item_deleted` | Evento usado para marcar a remoção definitiva de um item de transação. |  Na atualização, o log usa apenas atributos preenchíveis que ficaram sujos. Um `save()` sem alteração real não cria uma entrada vazia.",
      "line": 24
    },
    {
      "id": "quem-realizou-a-mudanca",
      "level": 2,
      "title": "Quem realizou a mudança",
      "text": "O `causer` normalmente é o usuário autenticado. Alterações disparadas por comandos do scheduler ou jobs sem sessão HTTP podem não ter `causer_id`; o painel as apresenta como **Sistema / Rotina Automática**.  Isso permite diferenciar, por exemplo:  - uma transação editada manualmente; - uma recorrência materializada pelo scheduler; - uma fatura avançada para o período seguinte; - uma alteração de dados feita por um job de importação.",
      "line": 37
    },
    {
      "id": "filtros-do-painel",
      "level": 2,
      "title": "Filtros do painel",
      "text": "Em `/audit`, a consulta é paginada em até 100 registros e pode ser filtrada por:  - **Módulo/sujeito** (`subject_type`); - **ID do sujeito** (`subject_id`); - **Ação** (`description`); - **Usuário** ou opção **Sistema** para registros sem autor; - **Data inicial** e **data final**; - ordem mais recente ou mais antiga.  As opções de módulo, ação e usuário são montadas a partir do próprio histórico existente. Isso evita uma lista fixa que fique desatualizada quando um novo modelo passa a registrar atividades.",
      "line": 48
    },
    {
      "id": "visualizacao-do-diff",
      "level": 2,
      "title": "Visualização do diff",
      "text": "Ao abrir `/audit/{activity}`, o James normaliza os dados da atividade e mostra:  - valor anterior (`old`); - valor novo (`attributes`); - campos criados ou removidos; - autor, sujeito, ação, data e nome do log.  O formatador trata arrays e objetos como JSON, datas com o timezone da aplicação, valores nulos como `null` e booleanos como `true`/`false`. Quando a entidade ainda está disponível, a tela tenta criar um link para seu registro.  Em exclusões, o activity log pode guardar o estado anterior em `old` ou em `attributes`, dependendo do evento. O controller normaliza os dois formatos para que a tela mostre os dados que foram removidos.",
      "line": 61
    },
    {
      "id": "historico-dentro-das-telas",
      "level": 2,
      "title": "Histórico dentro das telas",
      "text": "Além do painel global, o componente `ActivityLog` aparece nas telas de entidades que oferecem histórico contextual. Ele carrega os 20 eventos mais recentes do sujeito, junto com o avatar do autor quando existe.  Assim, a investigação pode começar pelo detalhe de um contato, acerto ou entidade financeira e depois continuar no filtro global `/audit`.",
      "line": 74
    },
    {
      "id": "configuracao-e-retencao",
      "level": 2,
      "title": "Configuração e retenção",
      "text": "As opções principais estão em `config/activitylog.php`:  | Configuração | Padrão | Efeito | | --- | --- | --- | | `ACTIVITYLOG_ENABLED` | `true` | Liga ou desliga a gravação. | | `clean_after_days` | `365` | Idade usada pelo comando de limpeza do pacote. | | `include_soft_deleted_subjects` | `false` | Define se a relação de sujeito inclui modelos apagados logicamente. | | `ACTIVITYLOG_BUFFER_ENABLED` | `false` | Permite buffer de atividades para inserção em lote, quando necessário. |  O valor de 365 dias é a política padrão para uma futura execução de limpeza; não significa que cada requisição apague logs automaticamente. Se a limpeza for adotada em produção, ela deve ser executada de forma consciente porque reduz a capacidade de investigação histórica.",
      "line": 80
    },
    {
      "id": "como-habilitar-uma-nova-entidade",
      "level": 2,
      "title": "Como habilitar uma nova entidade",
      "text": "Uma nova model de negócio deve:  1. usar `LogsActivity`; 2. declarar em `$recordEvents` somente eventos relevantes; 3. retornar `LogOptions::defaults()` com `logFillable()`; 4. usar `logOnlyDirty()` e `dontLogEmptyChanges()`; 5. escolher um nome de log específico com `useLogName()`; 6. evitar registrar segredos, tokens ou campos técnicos que não pertençam ao histórico funcional.  Exemplo mínimo:",
      "line": 93
    },
    {
      "id": "caso-especial-itens-de-transacao",
      "level": 3,
      "title": "Caso especial: itens de transação",
      "text": "Itens removidos durante a edição de uma transação financeira podem ser excluídos fisicamente para não continuar compondo cálculos. Antes da remoção, o James registra o evento com descrição `item_deleted`, preservando descrição, quantidade, preço unitário, total e vínculo com a transação no histórico.",
      "line": 127
    },
    {
      "id": "referencias",
      "level": 3,
      "title": "Referências",
      "text": "- [Contatos](doc:contatos) e [Acertos](doc:acertos) — exemplos de telas com histórico contextual. - [Rotinas automáticas](doc:automacoes) — explica por que o autor pode aparecer como sistema. - [Decisões arquiteturais](doc:decisoes) — escolhas de auditoria e dados.",
      "line": 131
    }
  ],
  "sourcePath": "content/auditoria.md",
  "visuals": [
    {
      "id": "audit-flow",
      "kind": "flowchart",
      "title": "Fluxo de auditoria",
      "description": "Mutações Eloquent são registradas e expostas no painel de auditoria.",
      "summary": "Uma ação do usuário altera um modelo de negócio; o LogsActivity registra a mutação na tabela activity_log e o painel mostra o diff da alteração.",
      "renderMode": "mermaid",
      "api": "api/diagrams/audit-flow.json",
      "human": "diagrams/audit-flow.html"
    }
  ],
  "apiVersion": 1
}
