Pular para o conteúdo

Sigilo, e por que ele não é problema seu aqui

A Unidade 1 inteira foi construída em cima de uma linha:

TETO_SIGILO = 1   # 0 = Público  1 = Segredo de Justiça  2 = Sigilo Absoluto

E de uma regra: quem decide o que o agente pode ver é o seu código, não o modelo. O teto era uma constante no WHERE, nunca um argumento de Tool, porque um argumento é algo que o modelo escolhe — e o modelo obedece a quem escreveu a última linha do prompt.

Agora vem a pergunta natural: e na API do CNJ?

A resposta, medida

Duas consultas, feitas de forma independente uma da outra.

Primeiro, quantos processos do TJRJ existem no DataJud:

consultar({"size": 0, "track_total_hits": True, "query": {"match_all": {}}})
{'value': 23152022, 'relation': 'eq'}

Agora, a distribuição por nível de sigilo:

consultar({"size": 0,
           "aggs": {"s": {"terms": {"field": "nivelSigilo", "size": 10}}}})
{"s": {"doc_count_error_upper_bound": 0,
       "sum_other_doc_count": 0,
       "buckets": [{"key": 0, "doc_count": 23152022}]}}

Um único balde. sum_other_doc_count: 0 — nada ficou de fora da contagem. E o número bate, dígito por dígito, com o total do acervo.

23.152.022 processos, 23.152.022 com nivelSigilo 0. Não é uma amostra que por acaso deu tudo público: é o acervo inteiro.

Por que é assim

Porque a filtragem acontece antes da API existir.

Quando o TJRJ envia dados ao CNJ, o processo de extração marca o nível de sigilo de cada processo — e os que têm segredo de justiça ou sigilo absoluto não entram no índice público. Existem na base do CNJ; não existem no api_publica_tjrj.

Ou seja: o controle de acesso que na Unidade 1 você escreveu na cláusula WHERE aqui já foi executado por outra pessoa, num estágio anterior do caminho do dado.

Por que o filtro continua no código, então

Olhe a Tool do próximo capítulo:

TETO_SIGILO = 0

corpo = {
    "query": {"bool": {"filter": [
        {"term": {"assuntos.nome.keyword": assunto}},
        {"range": {"nivelSigilo": {"lte": TETO_SIGILO}}},
    ]}},
    ...
}

E, depois de receber a resposta:

for h in achados:
    p = h["_source"]
    # Cinto e suspensório: se algo com sigilo escapar da origem, para aqui.
    if p.get("nivelSigilo", 99) > TETO_SIGILO:
        continue

Duas verificações para uma coisa que já é garantida. Isso é desperdício?

Não, e a razão não é desconfiança do CNJ. São três:

1. A garantia é de terceiro, e pode mudar sem avisar. O que garante que só há nível 0 na API é uma decisão operacional do CNJ, não um contrato com você. Se amanhã o índice passar a incluir nível 1, seu código não fica sabendo. Com o filtro, ele simplesmente continua correto.

2. O .get("nivelSigilo", 99) protege contra o campo faltando. Você já viu sistema.nome vir "Inválido" no primeiro documento da primeira consulta. Um campo ausente vira 99, que é maior que o teto, e o processo é descartado. O padrão numa checagem de acesso é negar, não permitir.

3. É a linha que o leitor do seu código vai procurar. Quando alguém — o senhor mesmo, daqui a um ano — abrir essa Tool para adaptá-la ao sistema do Tribunal, a primeira pergunta vai ser "onde está o controle de acesso aqui?". Se a resposta for "não tem, porque a origem já filtra", a adaptação vai começar sem ele. E aí a origem não filtra mais.

Atenção

Este é o ponto da unidade que vale para além do curso.

A Unidade 1 usava dado inventado, e o teto de sigilo era um exercício. Esta unidade usa dado real e o teto é redundante. Nenhuma das duas te expõe a nada.

O dia em que a Tool apontar para o banco do Tribunal, ela vai ver os três níveis — e aí a mesma linha, que até então nunca tinha feito diferença nenhuma, passa a ser a única coisa entre um agente e os autos de um processo criminal com a vítima identificada.

Escreva-a agora, enquanto ela é inofensiva. Quem escreve o controle de acesso depois, escreve depois do incidente.

O que o CNJ não tem

Vale ser explícito sobre o que essa API não devolve, porque isso define o alcance do agente que você está construindo:

Existe no DataJud Não existe
Número do processo Nome das partes
Classe e assuntos (TPU) Petição inicial
Órgão julgador e comarca Sentenças e acórdãos
Data de ajuizamento Qualquer PDF
Lista completa de movimentos Valor da causa
Grau, formato, sistema de origem Advogados

É metadado processual. E é justamente por não ter nome de parte nem peça que ele pode ser público.

Para o uso que motivou este curso, isso basta: com número e órgão julgador, o magistrado abre o processo no sistema do Tribunal, onde tem — aí sim, com sua credencial nominal e o registro de acesso correspondente — tudo o que precisa.

Nota

Repare no desenho que se formou, quase sem querer.

O agente trabalha sobre metadado público e devolve ponteiros. O acesso ao conteúdo continua acontecendo no sistema do Tribunal, com a credencial do juiz e a trilha de auditoria dele.

Isso não é um contorno de limitação. É uma arquitetura melhor do que a alternativa — e é a resposta que você vai dar quando alguém, com toda razão, perguntar "mas esse agente aí vai ler os autos?".

A ponte para o acervo do Tribunal

O arquivo dados/MAPEAMENTO.md já descreve como as tabelas do TJRJ correspondem ao esquema da Unidade 1. Vale registrar o que muda quando a origem é interna:

API do CNJ Banco do Tribunal
Níveis de sigilo presentes Só 0 0, 1 e 2
Quem filtrou O CNJ, antes de publicar Ninguém. Você.
Sua credencial Chave pública, igual para todos Nominal, com trilha de auditoria
Consequência de um filtro esquecido Nenhuma Acesso indevido a processo protegido
Onde o teto entra Redundância defensiva Único controle existente

A coluna da direita é o segundo curso. A da esquerda é este.

O ponto pedagógico é que o código das duas colunas é o mesmo código. A linha nivelSigilo <= TETO_SIGILO não muda de forma ao trocar de origem: ela vira p.id_nivel_sigilo <= ? no SQLite, nivelSigilo no range do Elasticsearch, e uma cláusula equivalente no Oracle do EJUD. Muda a sintaxe; não muda a decisão.

Fixando o capítulo

Q1: A agregação mostrou 23.152.022 processos, todos com nivelSigilo: 0. Por quê?

Q2: Se a API só devolve processos públicos, por que a Tool mantém range em nivelSigilo e ainda confere cada documento recebido?

Q3: Um colega propõe: "já que a API é pública e não tem sigilo, vamos tirar o TETO_SIGILO e simplificar o código". Qual a melhor resposta?