# Os horários de auditoria dos agentes resistem a mudanças de relógio?

O horário do relógio de parede é uma evidência, não uma garantia de ordenação. Um agente pode fazer duas chamadas perfeitamente legítimas enquanto o relógio do host volta no tempo, repete uma hora durante o horário de verão ou é corrigido depois de sair de um longo período de suspensão. Se o visualizador de auditoria ordenar essas chamadas apenas pelo horário exibido, poderá contar uma história convincente, mas falsa.

Use um número de sequência para responder «qual registro este diário aceitou primeiro?». Use um registro de data e hora de parede para responder «qual horário do calendário o gravador informou?». São perguntas diferentes. As equipes têm problemas quando fingem que um único campo responde às duas.

Para agentes autônomos, essa distinção é importante. Um revisor talvez precise estabelecer se um comando SSH veio depois de uma aprovação, se uma chamada HTTP foi repetida ou se uma revogação ocorreu antes da próxima ação. A resposta precisa resistir a um relógio ruim no laptop e a uma mudança de horário inesperada, não apenas parecer organizada em uma tabela.

## Os registros de data e hora não estabelecem uma ordem confiável dos eventos

Um registro de data e hora de parede não pode provar que um evento ocorreu antes de outro quando o relógio pode mudar. Ele apenas informa a leitura observada pelo relógio quando o software gravou o registro.

Considere esta sequência de uma máquina que estava dez minutos adiantada até que a sincronização de horário a corrigiu:

```text
seq 841  2026-11-03T14:10:12.481Z  agent requested deploy status
seq 842  2026-11-03T14:00:13.107Z  agent requested deploy status
seq 843  2026-11-03T14:00:14.052Z  approval recorded
```

Uma ordenação por horário coloca 842 e 843 antes de 841. O diário aceitou 841 primeiro. Nenhuma das duas visões é um erro de digitação. Elas respondem a perguntas diferentes.

Isso importa mesmo quando os horários aumentam. Um relógio pode andar devagar, avançar de repente ou ser corrigido por um usuário. Dois registros com horários de calendário crescentes ainda podem estar mais distantes ou mais próximos do que seus valores sugerem. Um registro de data e hora fornece uma coordenada observada em uma escala de tempo civil. Ele não fornece uma medição contínua de duração.

A RFC 3339 deixa clara a parte relacionada ao armazenamento: os registros precisam de um deslocamento quando o horário local está envolvido, e o UTC expresso com `Z` remove a ambiguidade do deslocamento durante a troca de dados. Isso é uma boa prática, mas a RFC 3339 não transforma o relógio do host em uma testemunha infalível. Ela define uma notação, não a verdade.

Dê a todo fluxo de auditoria somente para anexação um `seq` monotonicamente crescente. Atribua-o no componente que serializa as gravações, não em cada processo do agente. Se dois processos de agente puderem alocar números localmente e enviar seus registros mais tarde, você terá criado duas ordens e chamado isso de uma só.

O número de sequência faz uma afirmação limitada, mas útil:

- Dentro de um diário, um `seq` menor entrou primeiro.
- Lacunas significam que o investigador precisa explicar registros ausentes, retidos ou excluídos intencionalmente.
- Uma duplicata significa que o gravador, importador ou armazenamento falhou.
- O valor, sozinho, não diz nada sobre um evento em outra máquina.

Esse último ponto é ignorado porque um número inteiro com aparência global parece ter autoridade. Não tem. Um número de sequência precisa de um namespace. `journal_id=macbook-17, seq=841` é uma declaração com limites. `seq=841` em uma planilha é um convite ao exagero.

## O horário de verão repete leituras do relógio local

O horário de verão faz o relógio local repetir uma hora em muitas regiões. Durante a transição de outono, 01:15 ocorre uma vez com um deslocamento UTC e novamente com outro. Um registro que armazena apenas `2026-11-01 01:15:00` descartou a informação necessária para distingui-los.

Não tente corrigir isso depois adivinhando qual ocorrência o operador quis dizer. Capture contexto suficiente quando o evento for gravado:

```json
{
  "journal_id": "build-mac-07",
  "seq": 842,
  "event_id": "01JXYZ...",
  "recorded_at_utc": "2026-11-01T08:15:00.000Z",
  "local_offset": "-07:00",
  "time_zone": "America/Los_Angeles",
  "event_type": "agent.http.requested"
}
```

Na ocorrência posterior, a mesma exibição do relógio local pode carregar `local_offset: "-08:00"` e um valor UTC uma hora mais tarde. O deslocamento numérico preserva o fato observado. O nome do fuso horário ajuda uma pessoa a explicar por que o deslocamento existia, mas não deve substituí-lo no registro.

As regras de fuso horário mudam. Governos já alteraram datas de início, datas de término e até a existência do horário de verão, sem muita preocupação com seu analisador de registros. Se você armazenar uma data local e o nome de um fuso e recalcular o deslocamento anos depois usando um banco de fusos mais recente, poderá exibir uma evidência histórica de forma diferente daquela registrada pela máquina na época. Preserve o valor UTC original e o deslocamento capturado. Use as regras atuais para exibição apenas quando o visualizador identificar claramente o resultado como uma conversão feita nos dias de hoje.

A transição de primavera produz um problema diferente. Alguns horários locais nunca acontecem. Um sistema que aceite um prazo local digitado por uma pessoa, como 02:30 durante uma hora que foi pulada, deve rejeitá-lo ou pedir uma resolução explícita. Movê-lo silenciosamente para 03:30 é uma decisão de produto disfarçada de aritmética de calendário.

Para registros de auditoria, o UTC deve ser canônico. Exiba o horário local quando isso ajudar o leitor, mas mostre o deslocamento no mesmo campo. `2026-11-01 01:15:00 -08:00` é menos simples que `01:15`, mas também é uma evidência.

## Uma correção manual deve criar um novo registro

As edições manuais mostram se uma trilha de auditoria mantém seu valor ou se transforma em um feed de atividades bem-apresentado. Se um administrador corrigir um horário no próprio registro, a observação original desaparece. O investigador deixa de saber se o relógio antigo estava errado, se o conteúdo do evento estava errado ou se alguém queria que o histórico parecesse diferente.

Mantenha o registro original imutável. Adicione um registro de correção que identifique o evento anterior, informe o campo em disputa, registre o valor corrigido proposto e explique sua base. A correção não apaga o primeiro registro. Ela acrescenta um fato posterior: alguém fez e justificou uma afirmação sobre o primeiro registro.

Um payload de correção pode ser pequeno e ainda cumprir sua função:

```json
{
  "seq": 913,
  "event_type": "audit.timestamp_corrected",
  "corrects_event_id": "01JXYZ...",
  "original_recorded_at_utc": "2026-11-03T14:10:12.481Z",
  "asserted_occurred_at_utc": "2026-11-03T14:00:12.481Z",
  "basis": "host time service report and neighboring journal entries",
  "actor": "admin-identifier"
}
```

Use `asserted_occurred_at_utc` apenas quando houver evidência para o horário revisado. Não renomeie o `recorded_at_utc` original. Ele descreve a leitura do relógio do gravador e continua historicamente correto mesmo quando essa leitura era imprecisa.

Separe estas três ideias tanto no esquema quanto na linguagem:

1. `occurred_at` é o horário em que uma ação aconteceu, se o agente puder estabelecê-lo.
2. `observed_at` é o horário em que um coletor específico viu a ação.
3. `recorded_at` é o horário em que o gravador de auditoria confirmou sua entrada.

Eles podem ser iguais. Muitas vezes são. Ainda assim, não merecem o mesmo nome de campo.

A recomendação popular de «simplesmente corrigir dados incorretos» vem de sistemas de relatórios, nos quais um número errado deve desaparecer do painel. Sistemas de auditoria têm outra função. Eles preservam o caminho entre a observação e a conclusão. Uma correção visível é menos conveniente para leitores ocasionais, mas impede que o sistema transforme incerteza em certeza.

## Correções do horário de rede podem mover o relógio de parede

A sincronização de horário pela rede melhora a precisão do relógio, mas a própria correção pode tornar os registros surpreendentes. Um cliente pode ajustar gradualmente sua velocidade ou avançar o relógio de uma só vez quando o deslocamento é grande o bastante ou quando a política permite. Um usuário ajustando o relógio manualmente, uma máquina virtual retomando a execução e um relógio de firmware com um valor incorreto podem produzir o mesmo resultado visível: o horário do calendário muda entre duas entradas de auditoria.

A documentação de `clock_gettime` do POSIX distingue o relógio de tempo real do relógio monotônico. `CLOCK_REALTIME` acompanha o horário do calendário e pode ser configurado. `CLOCK_MONOTONIC` não tem uma origem útil no calendário, mas não é configurado por `clock_settime`; ele é o tipo certo de fonte para medir um intervalo dentro de um único sistema em execução.

Essa distinção produz uma regra prática de dados. Registre o horário de parede para o investigador. Registre uma amostra monotônica quando precisar analisar tempo decorrido, comportamento de timeout ou ordenação em torno de uma correção. Não serialize um valor monotônico como se fosse uma data. Seu valor absoluto só tem significado em relação ao boot e ao domínio de relógio correspondentes.

A RFC 8633, orientação da IETF para operações NTP, discute explicitamente grandes mudanças de horário e afirma que os operadores não devem ignorar cegamente o limite de pânico do NTP em inicializações a frio. A tentação habitual é tratar toda correção como uma tarefa administrativa inofensiva. Ela não é inofensiva quando o horário controla a validade de tokens, a retenção, a reconstrução de incidentes ou a detecção de repetição.

Seu sistema de auditoria deve informar anomalias de horário como fatos de auditoria. Não deve tentar escondê-las com uma regra de ordenação. Um evento útil pode conter o último valor do relógio de parede, o novo valor, a diferença estimada, a origem da mudança, se conhecida, e o processo que a detectou. Se o sistema operacional não expuser uma causa, diga isso. Uma explicação falsa é pior que uma explicação ausente.

Mantenha uma pequena tolerância para variações normais. Não crie um evento dramático de mudança de relógio porque valores adjacentes diferem alguns milissegundos em uma direção inesperada entre gravadores concorrentes. O `seq` serializado fornece a ordem. Marque uma descontinuidade quando o relógio de parede retroceder além da precisão declarada ou quando um salto para frente entrar em conflito com a atividade esperada e precisar de análise.

## Os números de sequência precisam de um escopo definido

Um número de sequência só funciona dentro do registro que o atribuiu. Tratá-lo como uma ordem global depois que os registros saem desse diário produz conclusões erradas em sistemas distribuídos de agentes.

Suponha que um agente de programação em um Mac solicite uma ação de API e que um host de build remoto grave uma ação SSH. Cada host tem seu próprio diário:

```text
build-mac-07  seq 842  14:00:13Z  HTTP action requested
build-host-2  seq  91  14:00:14Z  SSH action accepted
build-mac-07  seq 843  14:00:15Z  HTTP result received
```

Você pode dizer que 842 precede 843 em `build-mac-07`. Pode dizer que 91 foi registrado por `build-host-2` no horário informado. Não pode provar, apenas com esses campos, se o host remoto aceitou a ação SSH antes ou depois da primeira solicitação HTTP em tempo real.

Para estabelecer relações entre sistemas, adicione um vínculo explícito. Um identificador de solicitação propagado do chamador ao receptor pode conectar o evento da solicitação ao evento de recebimento. Um recibo assinado pelo receptor pode fornecer evidências mais fortes. Um coletor central pode atribuir uma sequência de coleta quando recebe os registros, mas essa sequência prova a ordem de chegada ao coletor, não a ordem de ocorrência nas fontes.

Não exagere o que cada elemento prova:

- Um ID de solicitação comprova correlação quando os dois lados o preservam. Ele não comprova o horário de entrega.
- Uma sequência central de ingestão comprova a ordem de ingestão. O atraso da rede pode reordenar a chegada.
- Um relógio sincronizado reduz a incerteza. Ele não a elimina.
- Um relógio lógico distribuído pode expressar causalidade se todos os participantes o carregarem corretamente. Ele não fornece o horário de parede.

Para muitas trilhas de auditoria de agentes, não é necessário um grande sistema de ordenação distribuída. É preciso manter limites honestos. Tenha uma sequência local para cada diário confiável, inclua IDs de correlação nos limites das ações e mostre o diário de origem em toda exportação. Assim, o revisor consegue ver onde a evidência é forte e onde ela passa a ser uma inferência.

## Armazene evidências temporais suficientes para explicar uma divergência

Um campo `timestamp` isolado não é um esquema de auditoria. É uma preferência de exibição que escapou para o armazenamento.

Use uma estrutura de registro que mantenha separadas a ordem, a hora do calendário, a identidade da fonte e os dados de integridade. Os nomes exatos dos campos são sua escolha, mas os conceitos devem sobreviver à exportação e à retenção:

```json
{
  "journal_id": "build-mac-07",
  "seq": 842,
  "event_id": "01JXYZ...",
  "recorded_at_utc": "2026-11-03T14:00:13.107Z",
  "recorded_offset": "-08:00",
  "time_zone": "America/Los_Angeles",
  "monotonic_ns": 3982188001123,
  "boot_id": "boot-identifier",
  "event_type": "agent.http.requested",
  "correlation_id": "request-identifier",
  "actor_process": "process-identifier",
  "previous_hash": "hex-value",
  "record_hash": "hex-value"
}
```

`boot_id` evita um erro comum com valores monotônicos. Um contador monotônico pode reiniciar depois de um reboot, portanto `3982188001123` de um boot não pode ser comparado ao mesmo valor de outro sem contexto adicional. Armazene-o apenas se for usá-lo e documente sua unidade. Um campo chamado `monotonic_time` que deixa o leitor tentando descobrir se significa nanossegundos, milissegundos ou ciclos do sistema desperdiça o campo.

`recorded_offset` é o deslocamento em vigor quando o gravador registrou o evento. Ele não substitui o UTC. Permite que uma pessoa veja o contexto do horário local da fonte e que um formatador preserve a interpretação civil original. Inclua um fuso horário nomeado apenas se a plataforma puder fornecê-lo de maneira confiável. Um deslocamento fixo é suficiente para ordenação e reconstrução.

Os campos de hash precisam de regras igualmente claras. Calcule um hash do registro sobre uma representação canônica de todos os campos cuja alteração mudaria seu significado, incluindo `seq`, os horários, o tipo de evento, a identidade do agente e o resumo do payload. Não faça o hash de um bloco JSON formatado se diferentes serializadores puderem alterar espaços em branco, ordem das propriedades ou formatação dos números. Faça a canonização primeiro.

Uma cadeia de hashes detecta um registro alterado quando a verificação começa em uma âncora confiável e cada registro confirma o registro anterior. Ela não prova que o relógio da fonte estava correto. Não prova que um evento aconteceu fora da máquina. Ela comprova uma afirmação mais restrita, mas ainda importante: o histórico verificado preservou as relações criptográficas produzidas pelo gravador.

É por isso que uma cadeia e uma sequência devem andar juntas. A sequência fornece a ordem local. A cadeia torna visível uma reescrita posterior. O horário acrescenta contexto de calendário. Nenhum deles pode fazer o trabalho dos outros.

## Investigue reversões de horário sem inventar uma história

Quando uma sequência posterior tem um horário anterior, comece pelas evidências que você já possui. Não comece chamando isso de repetição, bug do agente ou adulteração.

Use esta breve sequência de investigação:

1. Verifique a continuidade da sequência do diário e o resultado da verificação de integridade antes de interpretar os valores de horário.
2. Compare os valores UTC anterior e posterior, os deslocamentos locais, os identificadores de boot e quaisquer amostras monotônicas.
3. Verifique se o host atravessou uma transição de horário de verão, reiniciou, retomou a execução ou registrou uma correção do serviço de horário.
4. Siga os IDs de correlação até os diários adjacentes, mas trate o horário entre hosts como uma estimativa, a menos que um recibo ou mecanismo de ordenação compartilhado o comprove.
5. Adicione um registro de anotação se as evidências sustentarem uma correção ou uma conclusão de anomalia temporal.

Veja uma falha que aparece em revisões reais. Um agente solicita uma ação de API às `09:02:04`, a máquina desperta, o horário de rede recua quatro minutos e o resultado da ação é registrado às `08:58:07`. Um painel ordena cronologicamente e mostra o resultado antes da solicitação. Um operador conclui que o resultado foi repetido, bloqueia o agente e começa a trocar as credenciais.

A sequência e os valores monotônicos contam uma história mais simples. A solicitação é a sequência 117. O resultado é a sequência 118. Os dois têm o mesmo identificador de boot. O contador monotônico avança cerca de três segundos. O relógio de parede mudou entre as entradas. O resultado veio depois da solicitação nesse diário, e a exibição do calendário está incorreta durante a correção.

Essa conclusão ainda deixa perguntas úteis. Por que o relógio diferia quatro minutos? A ação dependia de uma credencial com expiração limitada por tempo? Outro sistema recebeu a solicitação antes da correção? A investigação deve responder a essas perguntas separadamente. Não deve tentar forçar uma ordem temporal limpa apenas porque o visualizador prefere uma.

Se uma verificação de integridade falhar, pare de tratar o diário como uma linha do tempo estabelecida. Preserve a exportação, registre a falha de verificação fora do diário afetado, se possível, e obtenha uma cópia nova por um caminho independente. Uma cadeia com falha não identifica a pessoa ou o processo que alterou os dados. Ela informa que as evidências já não sustentam a afirmação de um histórico sem modificações.

## Uma trilha evidente contra adulteração precisa de verificação offline

Um registro de auditoria tem pouco valor forense se sua única prova de integridade depender do serviço ativo que o produziu. Um revisor precisa exportar os registros, levá-los a outra máquina e verificar a cadeia sem usar o cofre nem perguntar ao agente que realizou as ações.

O Sallyport projeta seus diários Sessions e Activity a partir de um único registro de auditoria criptografado e encadeado por hashes, e `sp audit verify` pode verificar a cadeia offline sobre o texto cifrado, sem uma chave do cofre.

Esse design trata de um problema diferente da precisão do relógio. A verificação offline informa se o histórico criptografado continua internamente consistente segundo o design da auditoria. Ela não certifica o relógio de parede do host. Mantenha as duas afirmações separadas nos relatórios: «a cadeia de auditoria foi verificada» e «o horário do evento foi corroborado por uma fonte independente» são declarações úteis, e nenhuma implica a outra.

Os procedimentos de exportação devem preservar a identidade do diário, o intervalo de sequências, o resultado da verificação e a versão do software que realizou a verificação. Um CSV apenas com horário e texto da ação é um relatório, não uma evidência de auditoria. Ele perde os campos que permitiriam a alguém contestar ou confirmar o relatório mais tarde.

## Construa o visualizador em torno das divergências, não apenas da ordenação ideal

Um bom visualizador de auditoria não esconde anomalias de relógio. Ele ordena por sequência do diário por padrão dentro de um único diário, mostra o UTC ao lado do horário local quando o usuário expande uma linha e marca uma reversão temporal como uma descontinuidade de horário, em vez de reorganizar o histórico.

Ofereça aos leitores diferentes visões, mas dê a cada uma um nome preciso. «Ordem do diário» significa ordem da sequência. «Horário de calendário informado» significa ordem dos registros de data e hora e pode colocar registros causalmente posteriores antes dos anteriores. «Ordem de chegada ao coletor» significa a ordem em que outro serviço recebeu os dados. Evite uma ordenação genérica por «horário», pois ela torna invisível uma escolha forense relevante.

A interface também deve mostrar o alcance de sua certeza. Quando os eventos vierem de diários diferentes, agrupe-os por origem ou mostre um rótulo claro da origem ao lado de cada número de sequência. Se um ID de solicitação conectar os registros, mostre essa relação como um vínculo no modelo de dados e na interface. Não desenhe uma linha contínua na linha do tempo entre hosts a menos que seu sistema possa defendê-la.

A primeira ação é simples: examine uma das exportações existentes em busca de um horário local sem deslocamento, de um número de sequência sem identidade do diário ou de um caminho de edição no próprio registro. Qualquer um desses elementos basta para criar uma linha do tempo de incidente enganosa. Corrigir isso agora custa menos do que explicá-lo depois que uma ação do agente se tornar evidência.
