Monitoramento de Processos em Segredo de Justiça#

Esta seção descreve como o cliente pode configurar o webhook de segredo de justiça, cadastrar processos para monitoramento contínuo e descriptografar os dados recebidos.

Nota

O monitoramento exige uma credencial previamente cadastrada e habilitada. Consulte Gerenciamento de Credenciais para o passo a passo de cadastro.

Módulos necessários#

Os módulos abaixo devem estar habilitados para a empresa antes de usar este fluxo. Entre em contato com o suporte para ativá-los.

Módulo

Finalidade

api.credenciais.proc.segredo-justica

Associar e dissociar credenciais de processos monitorados em segredo de justiça.

api.monitoramento.proc.segredo-justica

Criar, listar, visualizar e arquivar processos monitorados em segredo de justiça.

Configuração do webhook de segredo#

Importante

A configuração do webhook é um pré-requisito para o cadastro de processos. Sem uma URL de destino ativa e uma chave pública registrada, a criação de monitoramentos não é permitida. Configure o webhook antes de registrar qualquer processo monitorado.

Para receber eventos de segredo de justiça, o cliente precisa:

  1. Gerar um par de chaves RSA-4096.

  2. Registrar a chave pública e a URL de destino via PATCH /api/webhook_config/{id} ou pelo painel.

  3. Habilitar a entrega com is_segredo_active: true.

A configuração também pode ser feita pelo painel em Configurações → Webhook — Segredo de Justiça:

Painel de configuração do Webhook — Segredo de Justiça

Formulário do painel com os campos URL, habilitação e Chave Pública (RSA/PEM).#

Nota

Permissões (POST e PATCH): além das roles do módulo listadas acima (que controlam o acesso às credenciais/processos), os endpoints POST /api/webhook_config e PATCH /api/webhook_config/{id} exigem também a role companyadmin ou admin — é um requisito adicional, não substituído pelas roles de segredo de justiça. Ao setar qualquer campo de segredo (segredo_url, is_segredo_active ou public_key), a API também verifica se o módulo api.monitoramento.proc.segredo-justica está habilitado para a empresa — retornando 403 Forbidden caso contrário.

Gerando o par de chaves:

# Chave privada — guarde em segurança, nunca compartilhe
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:4096 \
  -out chave_privada.pem

# Chave pública para envio ao OP
openssl rsa -pubout -in chave_privada.pem -out chave_publica.pem

Aviso

Formato do PEM no JSON: o campo public_key precisa conter quebras de linha reais (\n) separando o cabeçalho, o corpo em Base64 e o rodapé — sem isso, a validação do PEM falha com 400 Bad Request. Se você gerou a chave com openssl (comando acima), o arquivo já vem com as quebras de linha; ao colar o conteúdo em uma string JSON, troque cada quebra de linha real por \n (a maioria das bibliotecas HTTP faz isso automaticamente ao serializar uma string multi-linha — o problema costuma aparecer só ao montar o JSON manualmente, como num curl -d).

Criando a configuração pela primeira vez (POST):

Se a empresa ainda não tem nenhum webhook_config cadastrado (verifique com um GET /api/webhook_config), use POST — note que user_company_id é obrigatório no corpo e não é preenchido automaticamente a partir do usuário autenticado:

POST /api/webhook_config
Authorization: Bearer <token>
Content-Type: application/json

{
  "user_company_id": 123,
  "segredo_url": "https://seu-servidor.com/webhooks/segredo-justica",
  "is_segredo_active": true,
  "public_key": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkq...\n-----END PUBLIC KEY-----\n"
}

A resposta traz o id gerado para essa configuração — guarde-o, é o valor usado no {id} das próximas atualizações via PATCH.

Atualizando uma configuração existente (PATCH):

Se a empresa já tem um webhook_config (o caso comum após o cadastro inicial), use PATCH no id retornado pelo POST — ou obtido via GET /api/webhook_config:

PATCH /api/webhook_config/{id}
Authorization: Bearer <token>
Content-Type: application/json

{
  "segredo_url": "https://seu-servidor.com/webhooks/segredo-justica",
  "is_segredo_active": true,
  "public_key": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkq...\n-----END PUBLIC KEY-----\n"
}

Nota

O {id} acima é o identificador da própria linha de webhook_confignão é o user_company_id nem qualquer outro identificador. Diferente do fluxo de webhook regular (que expõe o atalho current_webhook_config para a empresa não precisar descobrir esse id), o canal de segredo de justiça exige o id explícito.

Campo

Tipo

Descrição

segredo_url

string

URL do endpoint do cliente que receberá os eventos de segredo.

is_segredo_active

boolean

Habilita (true) ou desabilita (false) a entrega de eventos.

public_key

string

Chave pública RSA-4096 do cliente em formato PEM (-----BEGIN PUBLIC KEY-----). Usada pelo OP para cifrar o payload antes da entrega.

Nota

Eventos de segredo de justiça são entregues exclusivamente ao segredo_url, nunca ao url padrão do webhook. Os demais eventos (não-segredo) continuam sendo entregues ao url configurado normalmente.

Resumo de roles#

A tabela abaixo lista todas as roles específicas de segredo de justiça e o endpoint que cada uma desbloqueia.

Role

O que libera

api.monitoramento.proc.segredo-justica.gerenciar

POST /api/monitoramento/proc, PATCH /api/monitoramento/proc/{id} e DELETE /api/monitoramento/proc/{id} (arquivamento). Também libera GET — não é preciso a role listar além desta.

api.monitoramento.proc.segredo-justica.listar

GET /api/monitoramento/proc e GET /api/monitoramento/proc/{id}, sem poder criar, alterar ou arquivar.

api.monitoramento.proc.segredo-justica.eventos

GET /api/monitoramento/monitored_event — inclui eventos dos tipos 22, 23 e 24 (ocultados sem esta role)

Criando um processo monitorado#

Nota

Role necessária (POST): api.monitoramento.proc.segredo-justica.gerenciar.

Além disso, a API valida que o webhook já está configurado: se is_segredo_active não for true ou public_key não estiver preenchida, a requisição retorna 400 Bad Request. Esse comportamento reforça a obrigatoriedade do webhook como pré-requisito.

Para registrar um processo em segredo de justiça, utilize POST /api/monitoramento/proc informando o número CNJ e a credencial que será usada na coleta.

Requisição:

POST /api/monitoramento/proc
Authorization: Bearer <token>
Content-Type: application/json

{
  "numero": "0001234-56.2024.8.26.0100",
  "credencial_id": 42
}

Resposta (200):

{
  "$uri": "/api/monitoramento/proc/98765",
  "numero": "0001234-56.2024.8.26.0100",
  "credencial_id": 42,
  "is_monitored_diario": false,
  "is_monitored_tribunal": false
}

Nota

Processos em segredo de justiça têm is_monitored_diario e is_monitored_tribunal sempre false — a coleta é disparada pela credencial cadastrada, não pelo fluxo diário ou de tribunal. O campo credencial_id deve ser o id inteiro retornado pelo endpoint de criação de credencial. O mesmo CNJ pode ser monitorado por credenciais distintas (cada par numero + credencial_id é um monitoramento independente). Não é possível converter um processo regular em segredo de justiça via PATCH.

A coleta é executada automaticamente por um job diário (0 2 * * *) que percorre os processos monitorados e enfileira uma consulta para cada credencial ativa. O resultado chega ao cliente via webhook.

Listando e visualizando monitoramentos#

Nota

Role necessária (GET): api.monitoramento.proc.segredo-justica.listar ou .gerenciar (quem gerencia também pode visualizar). Sem nenhuma das duas, tentativas de acessar GET /api/monitoramento/proc/{id} retornam 404 Not Found — propositalmente, para não confirmar que aquele ID corresponde a um monitoramento em segredo de justiça.

Para listar todos os monitoramentos ativos:

GET /api/monitoramento/proc
Authorization: Bearer <token>

Para visualizar um monitoramento específico:

GET /api/monitoramento/proc/{id}
Authorization: Bearer <token>

Resposta (200):

{
  "$uri": "/api/monitoramento/proc/98765",
  "numero": "0001234-56.2024.8.26.0100",
  "credencial_id": 42,
  "is_monitored_diario": false,
  "is_monitored_tribunal": false,
  "archived_at": null
}

Alterando um monitoramento#

Nota

Role necessária (PATCH): api.monitoramento.proc.segredo-justica.gerenciar.

Restrições:

  • Não é possível transformar um processo regular em segredo de justiça via PATCH (adicionar credencial_id onde antes era nulo retorna 403).

  • Os campos is_monitored_diario e is_monitored_tribunal não podem ser alterados para true em processos de segredo de justiça.

O principal uso do PATCH é trocar a credencial associada ao monitoramento (por exemplo, ao renovar um certificado A1):

PATCH /api/monitoramento/proc/{id}
Authorization: Bearer <token>
Content-Type: application/json

{
  "credencial_id": 99
}

Resposta (200): retorna o objeto atualizado no mesmo formato do GET /api/monitoramento/proc/{id}.

Arquivando um monitoramento#

Nota

Role necessária (DELETE): api.monitoramento.proc.segredo-justica.gerenciar.

A operação é um arquivamento soft-delete — o monitoramento recebe um archived_at e deixa de ser processado, mas o registro permanece acessível via filtro archived_at!=null.

DELETE /api/monitoramento/proc/{id}
Authorization: Bearer <token>

Resposta: 204 No Content.

Listando eventos monitorados#

Os eventos gerados pelo monitoramento de processos em segredo de justiça (tipos 22, 23 e 24) são entregues via webhook, mas também ficam disponíveis para consulta no endpoint de eventos monitorados.

Nota

Role necessária (GET): api.monitoramento.proc.segredo-justica.eventos. Sem esta role, os eventos dos tipos 22, 23 e 24 são automaticamente removidos da listagem — a resposta retorna 200 mas omite silenciosamente esses tipos. Os demais tipos de evento continuam visíveis normalmente.

GET /api/monitoramento/monitored_event
Authorization: Bearer <token>

É possível filtrar por tipo de evento usando o parâmetro where:

GET /api/monitoramento/monitored_event?where={"evt_type":23}
Authorization: Bearer <token>

Eventos gerados#

O monitoramento gera três tipos de evento, todos entregues ao segredo_url configurado:

Tipo

Nome

Quando é gerado

22

VALIDACAO_LOGIN

Ao final de uma validação de login (sucesso ou falha) para a credencial.

23

COLETA_SEGREDO_JUSTICA

Quando a consulta retorna dados de um processo. O campo data contém o payload criptografado (ver Descriptografia do payload).

24

COLETA_SEGREDO_JUSTICA_ERROR

Quando a coleta termina com erro (ex: credencial inválida, tribunal indisponível).

VALIDACAO_LOGIN (tipo 22)#

O campo data não é criptografado. Exemplo de login bem-sucedido:

{
  "credencial_id": "999",
  "status": "CONECTADO",
  "acesso_id": 2001
}

Exemplo de falha de login:

{
  "credencial_id": "999",
  "status": "FALHOU",
  "acesso_id": 2001,
  "erro": "Descrição técnica do erro"
}

Os valores possíveis de status são CONECTADO e FALHOU. O campo acesso_id contém o ID da execução de um dos nossos workers para o login da credencial.

COLETA_SEGREDO_JUSTICA (tipo 23)#

O campo data contém o payload criptografado em base64. Consulte Descriptografia do payload para o formato e o exemplo de código.

Após a descriptografia, o JSON resultante é uma lista com um elemento no seguinte formato:

[
  {
    "id": "123456",
    "data": "2024-01-15T10:30:00",
    "tipo": "Intimação",
    "magistrado": "Dr. Fulano de Tal",
    "processo": {
      "id": 98765,
      "numero": "0001234-56.2024.8.26.0100",
      "instancia": "1",
      "codigo_classe_natureza_tribunal": "456",
      "classe_natureza": "Ação Ordinária",
      "assunto": "Responsabilidade Civil",
      "vara": "3ª Vara Cível",
      "orgao": null,
      "parte_interessada": "Empresa XYZ Ltda",
      "valor": "R$ 50.000,00",
      "processos_relacionados": null,
      "perfil": null,
      "partes": null,
      "estado_sigla": "SP",
      "tribunal": "TJSP",
      "audiencia": null,
      "sessao_julgamento": null,
      "numero_processo_antigo": null,
      "situacao": null,
      "sistema": {
        "nome": "esaj",
        "id": 3
      }
    }
  }
]

COLETA_SEGREDO_JUSTICA_ERROR (tipo 24)#

Gerado quando a coleta termina com status_job = 'error' — por exemplo, credencial expirada ou tribunal indisponível. Quando a consulta é bem-sucedida mas não retorna notificações, nenhum evento é criado.

O campo data não é criptografado:

{
  "credencial_id": "a1b2c3d4-...",
  "erro": "Descrição técnica do erro (ex: credencial expirada)"
}

Descriptografia do payload#

O payload do evento COLETA_SEGREDO_JUSTICA é cifrado com criptografia híbrida RSA-4096-OAEP + AES-256-GCM, garantindo que apenas o cliente — detentor da chave privada RSA — consiga acessar o conteúdo.

Formato do blob (após decodificação base64)#

[ dek_ct (512 bytes) | nonce (12 bytes) | ciphertext (variável) ]
  • dek_ct — A data encryption key (DEK) AES-256 cifrada com a chave pública RSA-4096 do cliente via RSA-OAEP (SHA-256). Sempre 512 bytes (tamanho da chave RSA-4096).

  • nonce — 12 bytes aleatórios gerados para cada mensagem, usados no AES-GCM.

  • ciphertext — Dados da notificação cifrados com AES-256-GCM usando a DEK e o user_company_id (em string) como AAD (additional authenticated data).

Exemplo de descriptografia em Python#

import base64
import json
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
from cryptography.hazmat.backends import default_backend


def descriptografar_payload(
    payload_b64: str,
    chave_privada_pem: bytes,
    user_company_id: int,
) -> list:
    """
    Descriptografa o campo ``data`` de um evento COLETA_SEGREDO_JUSTICA.

    :param payload_b64: Valor do campo ``data`` do evento (base64).
    :param chave_privada_pem: Chave privada RSA em PEM (bytes).
    :param user_company_id: ID da empresa no OP (mesmo valor do evento).
    :returns: Lista de notificações (JSON decodificado).
    """
    raw = base64.b64decode(payload_b64)

    dek_ct = raw[:512]     # DEK cifrada com RSA-4096
    nonce  = raw[512:524]  # 12 bytes
    ct     = raw[524:]     # ciphertext AES-GCM

    private_key = serialization.load_pem_private_key(
        chave_privada_pem,
        password=None,
        backend=default_backend(),
    )

    # Decifra a DEK com RSA-OAEP
    dek = private_key.decrypt(
        dek_ct,
        padding.OAEP(
            mgf=padding.MGF1(algorithm=hashes.SHA256()),
            algorithm=hashes.SHA256(),
            label=None,
        ),
    )

    # Decifra os dados com AES-256-GCM
    # AAD = str(user_company_id) vincula o blob ao tenant
    aesgcm = AESGCM(dek)
    plaintext = aesgcm.decrypt(
        nonce,
        ct,
        str(user_company_id).encode(),
    )

    return json.loads(plaintext)


# Exemplo de uso:
#
# with open('chave_privada.pem', 'rb') as f:
#     chave_privada_pem = f.read()
#
# notificacoes = descriptografar_payload(
#     payload_b64=event['data'],
#     chave_privada_pem=chave_privada_pem,
#     user_company_id=event['user_company_id'],
# )
# print(notificacoes[0]['processo']['numero'])

Nota

O user_company_id está presente no corpo do evento entregue ao webhook. Usar um valor incorreto resulta em InvalidTag (falha na autenticação AES-GCM), indicando que AAD não confere — verifique o ID da empresa antes de tentar novamente.