#!/bin/sh
#
# A apuracao do dia 0 e o inventario do aplicativo leem o log do site, e dizem
# quando nao leram? (D332)
#
#     sh scripts/ensaiar-varredura-dos-logs.sh
#     sh scripts/ensaiar-varredura-dos-logs.sh <copia do remediacao-dia0.sh> <copia do inventariar-versoes-app.php>
#
# Sai com 0 quando todo caso abaixo da o esperado; 1 quando algum nao da, e diz
# qual; 2 quando nao consegue medir (sem `php`, `gzip` ou `zgrep`). Os
# argumentos apontam o ensaio para COPIAS dos dois roteiros -- e como se
# falsifica sem tocar nos de verdade.
#
# ---------------------------------------------------------------------------
# POR QUE ISTO EXISTE (08/11/2026, a fatia 128; o D332)
#
# A apuracao do incidente LGPD (`scripts/remediacao-dia0.sh`, os passos 2 e 6
# de `docs/dia0-remediacao-producao.md`) procurava so em `access.log*`, e o
# site tem log proprio por vhost: o D36 achou zero pedidos a /api/versao/app
# no `access.log*` e 11.032 em `*.log`. O "nenhum acesso externo" que sustenta
# nao notificar a ANPD podia ser o arquivo errado -- a comparacao contra o
# vazio, onde ela mais custa. O `inventariar-versoes-app.php --dir=` tinha o
# mesmo glob. Agora os dois leem todo `*.log` e `*.log.*` (o `.gz` tambem), e
# exigem o controle positivo: /api/versao/app tem de aparecer.
#
# COMO: logs INVENTADOS num diretorio temporario, no formato do nginx, com
# enderecos de documentacao (198.51.100.0/24, 203.0.113.0/24); uma raiz de
# mentira com `public/` vazio, e o relatorio vai para o `docs/` dela. Nada le o
# /var/log de verdade. Os casos:
#
#   o log do vhost, o rotacionado   a apuracao acha o clientes.txt no log do
#   em .gz e o de erro              vhost e o migrar-senhas no .gz, ignora o
#                                   127.0.0.1 e o log de erro, e o controle
#                                   positivo e maior que zero; o inventario
#                                   le os tres arquivos de acesso e sai 0
#   so o access.log, sem o site     a apuracao diz "NAO LI O LOG DO SITE", nao
#                                   escreve "Nenhum acesso externo" e sai 2; o
#                                   inventario diz o mesmo e sai 1
#   o diretorio que nao existe      (a correcao da 128) a apuracao sai 2, troca
#                                   o relatorio velho pelo "nao li" e o resumo
#                                   nao diz "Nada pendente"
#   o .gz truncado e o .bz2         (a correcao da 128) os dois saem na lista
#                                   "Arquivos que NAO li", fora dos lidos; a
#                                   conclusao nao conclui e a apuracao sai 2

set -u

cd "$(dirname "$0")/.." || exit 2

nao_medi() { echo "NAO CONSEGUI MEDIR: $1" >&2; exit 2; }

REMEDIACAO="${1:-scripts/remediacao-dia0.sh}"
INVENTARIO="${2:-scripts/inventariar-versoes-app.php}"
[ -r "$REMEDIACAO" ] || nao_medi "nao li $REMEDIACAO"
[ -r "$INVENTARIO" ] || nao_medi "nao li $INVENTARIO"
for c in php gzip zgrep; do
    command -v "$c" > /dev/null 2>&1 || nao_medi "sem $c."
done

T=$(mktemp -d 2>/dev/null) || nao_medi "mktemp -d falhou."
trap 'rm -rf "$T"' EXIT INT TERM

# linha <ip> <alvo>: uma linha no formato `combined` do nginx.
linha() {
    printf '%s - - [02/Nov/2026:10:%02d:00 -0300] "GET %s HTTP/1.1" 200 120 "-" "okhttp/4.9.2"\n' "$1" "${3:-0}" "$2"
}

# A raiz de mentira: `public/` sem nada exposto, sem a rota do migrar-senhas.
mkdir -p "$T/raiz/public" "$T/raiz/module" "$T/raiz/config"

# O DIRETORIO COM O LOG DO SITE: o access.log do servidor padrao sem o site, o
# do vhost com o aplicativo e um acesso externo ao clientes.txt, o rotacionado
# em .gz com um acesso externo ao migrar-senhas, e o de erro (fora da busca).
mkdir -p "$T/com-site"
{
    linha 203.0.113.5 / 1
    linha 203.0.113.6 /favicon.ico 2
} > "$T/com-site/access.log"
{
    linha 198.51.100.20 '/api/versao/app?plataforma=android' 3
    linha 198.51.100.21 '/api/versao/app?plataforma=ios' 4
    linha 198.51.100.7 /clientes.txt 5
    linha 127.0.0.1 /clientes.txt 6
} > "$T/com-site/franquiabv.com.br.access.log"
{
    linha 198.51.100.22 /api/versao/app 7
    linha 198.51.100.9 /autenticacao/migrar-senhas 8
} | gzip -c > "$T/com-site/franquiabv.com.br.access.log.2.gz"
echo '2026/11/02 10:09:00 [error] 12#12: *1 open() "/var/www/public/clientes.txt" failed, client: 198.51.100.99' \
    > "$T/com-site/franquiabv.com.br.error.log"

# O DIRETORIO SEM O LOG DO SITE: so o access.log do servidor padrao, com uma
# chamada a /api que nao e a do aplicativo.
mkdir -p "$T/sem-site"
{
    linha 203.0.113.5 / 1
    linha 203.0.113.7 /api/agendas/getAgenda 2
} > "$T/sem-site/access.log"

falhas=0
casos=0
caso=''
falhou() { echo "  - $caso: $1"; falhas=$((falhas + 1)); }
tem() { grep -qF -- "$2" "$3" || falhou "$1 (faltou: $2)"; }
nao_tem() { ! grep -qF -- "$2" "$3" || falhou "$1 (veio: $2)"; }

# apurar <dir>: a apuracao sobre a raiz de mentira; o codigo em $codigo.
apurar() {
    rm -rf "$T/raiz/docs"
    codigo=0
    RAIZ="$T/raiz" LOGS_NGINX="$T/$1" QUARENTENA="$T/quarentena" sh "$REMEDIACAO" > "$T/saida.txt" 2>&1 || codigo=$?
    : >> "$T/raiz/docs/incidente-lgpd-dia0.md" 2>/dev/null || true
}

# A secao de um termo no relatorio, ate a seguinte.
secao() { sed -n "/^## $1\$/,/^## /p" "$T/raiz/docs/incidente-lgpd-dia0.md"; }

# 1. O diretorio com o log do site.
casos=$((casos + 1)); caso='a apuracao com o log do vhost, o .gz e o de erro'
apurar com-site
[ "$codigo" = 0 ] || falhou "saiu $codigo, e devia sair 0 ($(tail -n 1 "$T/saida.txt"))"
R="$T/raiz/docs/incidente-lgpd-dia0.md"
secao clientes.txt > "$T/clientes.txt"
tem 'o acesso externo ao clientes.txt no log do vhost' '**1 requisição externa.**' "$T/clientes.txt"
tem 'com o IP' '198.51.100.7' "$T/clientes.txt"
nao_tem 'o 127.0.0.1 nao conta' '127.0.0.1' "$T/clientes.txt"
nao_tem 'o log de erro nao entra' '198.51.100.99' "$R"
secao migrar-senhas > "$T/migrar.txt"
tem 'o acesso ao migrar-senhas no .gz rotacionado' '198.51.100.9' "$T/migrar.txt"
secao phpinfofile > "$T/phpinfo.txt"
tem 'o termo sem acesso, com o controle positivo, diz "nenhum"' 'Nenhum acesso externo registrado.' "$T/phpinfo.txt"
tem 'o controle positivo vai ao relatorio' 'aparece 3 vez(es)' "$R"
tem 'os arquivos lidos vao ao relatorio' '`franquiabv.com.br.access.log.2.gz`' "$R"
nao_tem 'o de erro nao e lido' '`franquiabv.com.br.error.log`' "$R"
nao_tem 'nada de "nao li"' 'NÃO LI O LOG DO SITE' "$R"

casos=$((casos + 1)); caso='o inventario com o log do vhost e o .gz'
codigo=0
php "$INVENTARIO" --dir="$T/com-site" > "$T/inventario.txt" 2>&1 || codigo=$?
[ "$codigo" = 0 ] || falhou "saiu $codigo, e devia sair 0 ($(grep -m1 -E 'NAO LI|Nenhuma chamada' "$T/inventario.txt"))"
grep -qE 'Arquivos lidos +3$' "$T/inventario.txt" || falhou "le os tres de acesso, sem o de erro: $(grep 'Arquivos lidos' "$T/inventario.txt")"

# O DIRETORIO COM UM ARQUIVO QUE NAO SE LE: o log do vhost com o aplicativo e
# nenhum acesso externo; o rotacionado em .gz TRUNCADO (o comeco de um gzip
# maior: o zgrep do macOS sai 0 com o que leu ate o corte), com um acesso
# externo ao clientes.txt depois do corte; e um .bz2, que o zgrep nao abre.
mkdir -p "$T/truncado"
{
    linha 198.51.100.20 /api/versao/app 3
    linha 198.51.100.21 /api/versao/app 4
} > "$T/truncado/franquiabv.com.br.access.log"
{
    i=0
    while [ "$i" -lt 4000 ]; do
        linha "198.51.100.$((i % 200 + 1))" "/api/versao/app?n=$i" $((i % 60))
        i=$((i + 1))
    done
    linha 198.51.100.77 /clientes.txt 9
} | gzip -c > "$T/inteiro.gz"
tamanho=$(wc -c < "$T/inteiro.gz" | tr -d ' ')
head -c $((tamanho / 2)) "$T/inteiro.gz" > "$T/truncado/franquiabv.com.br.access.log.2.gz"
! gzip -t "$T/truncado/franquiabv.com.br.access.log.2.gz" > /dev/null 2>&1 || nao_medi 'o .gz do caso truncado se le inteiro.'
linha 198.51.100.78 /clientes.txt 1 > "$T/truncado/franquiabv.com.br.access.log.3.bz2"

# 2. O diretorio sem o log do site.
casos=$((casos + 1)); caso='a apuracao sem o log do site'
apurar sem-site
[ "$codigo" = 2 ] || falhou "saiu $codigo, e devia sair 2 ($(tail -n 1 "$T/saida.txt"))"
R="$T/raiz/docs/incidente-lgpd-dia0.md"
tem 'o relatorio diz que nao leu o log do site' 'NÃO LI O LOG DO SITE' "$R"
nao_tem 'e nao diz "nenhum acesso externo"' 'Nenhum acesso externo' "$R"
tem 'cada termo sai como nao apurado' 'Não apurado: o log do site não foi lido' "$R"
tem 'a conclusao nao conclui' 'Nenhuma conclusão: o log do site não foi lido.' "$R"
tem 'a saida diz o mesmo' 'NAO LI O LOG DO SITE' "$T/saida.txt"

casos=$((casos + 1)); caso='o inventario sem o log do site'
codigo=0
php "$INVENTARIO" --dir="$T/sem-site" > "$T/inventario.txt" 2>&1 || codigo=$?
[ "$codigo" = 1 ] || falhou "saiu $codigo, e devia sair 1"
tem 'diz que nao leu o log do site' 'NAO LI O LOG DO SITE' "$T/inventario.txt"

# 3. O diretorio que nao existe, com o relatorio de uma rodada anterior no lugar.
casos=$((casos + 1)); caso='a apuracao com o diretorio que nao existe'
apurar com-site
[ "$codigo" = 0 ] || falhou "a rodada anterior saiu $codigo"
codigo=0
RAIZ="$T/raiz" LOGS_NGINX="$T/nao-existe" QUARENTENA="$T/quarentena" sh "$REMEDIACAO" > "$T/saida.txt" 2>&1 || codigo=$?
[ "$codigo" = 2 ] || falhou "saiu $codigo, e devia sair 2 ($(tail -n 1 "$T/saida.txt"))"
R="$T/raiz/docs/incidente-lgpd-dia0.md"
tem 'o relatorio novo diz que nao leu o log do site' 'NÃO LI O LOG DO SITE' "$R"
tem 'e que o diretorio nao existe' 'não existe ou não está acessível' "$R"
nao_tem 'o relatorio da rodada anterior nao fica' '198.51.100.7' "$R"
nao_tem 'o resumo nao diz "nada pendente"' 'Nada pendente' "$T/saida.txt"

# 4. O .gz truncado e o .bz2: fora dos lidos, e a conclusao nao conclui.
casos=$((casos + 1)); caso='a apuracao com o .gz truncado e o .bz2'
apurar truncado
[ "$codigo" = 2 ] || falhou "saiu $codigo, e devia sair 2 ($(tail -n 1 "$T/saida.txt"))"
R="$T/raiz/docs/incidente-lgpd-dia0.md"
sed -n '/^Arquivos lidos/,/^\*\*Arquivos que NÃO li/p' "$R" > "$T/lidos.txt"
sed -n '/^\*\*Arquivos que NÃO li/,/^\*\*Controle positivo/p' "$R" > "$T/nao-lidos.txt"
tem 'a lista dos que nao li existe' 'Arquivos que NÃO li: 2.' "$R"
tem 'o .gz truncado esta nela' '`franquiabv.com.br.access.log.2.gz`' "$T/nao-lidos.txt"
tem 'o .bz2 esta nela' '`franquiabv.com.br.access.log.3.bz2`' "$T/nao-lidos.txt"
nao_tem 'o .gz truncado nao conta como lido' 'log.2.gz' "$T/lidos.txt"
tem 'o log do vhost conta como lido' '`franquiabv.com.br.access.log`' "$T/lidos.txt"
tem 'o controle positivo vem so do lido' 'aparece 2 vez(es)' "$R"
nao_tem 'a conclusao nao diz "nenhum acesso externo nos logs retidos"' 'Nenhum acesso externo nos logs retidos' "$R"
tem 'a conclusao diz que nao cobre o periodo' 'Nenhuma conclusão sobre o período inteiro' "$R"
secao phpinfofile > "$T/phpinfo.txt"
tem 'o termo diz "nos arquivos lidos"' 'Nenhum acesso externo nos arquivos lidos' "$T/phpinfo.txt"
tem 'a saida nomeia o arquivo' 'franquiabv.com.br.access.log.2.gz' "$T/saida.txt"
nao_tem 'o resumo nao diz "nada pendente"' 'Nada pendente' "$T/saida.txt"

if [ "$falhas" -gt 0 ]; then
    echo "O ENSAIO DA VARREDURA DOS LOGS FALHOU: $falhas conferencia(s) em $casos casos."
    exit 1
fi

echo "A varredura dos logs do dia 0 e do inventario: $casos casos, todos como deviam."
exit 0
