# Linha do tempo de ações de agentes: compare carimbos sem distorções

Uma linha do tempo de ações de um agente pode contar uma mentira convincente mesmo quando todos os sistemas registraram um horário correto. A mentira surge quando o investigador trata a exibição do relógio local, o recebimento no servidor da API e o registro de auditoria como evidências intercambiáveis de um único momento.

Armazene os horários como foram observados, com deslocamentos numéricos e sua fonte. Depois, compare-os como relógios separados, cada um com seu próprio significado. Isso exige um pouco mais de dados do que um único campo `created_at`, mas evita o relatório de incidente comum em que o agente aparentemente agiu antes de receber aprovação, ou em que uma solicitação de API parece terminar antes de começar.

## Um único carimbo não descreve uma ação

Uma ação tem mais de um horário relevante. Um agente pode decidir chamar uma API em um instante, enviar os bytes depois, chegar ao servidor mais tarde e receber um resultado após o servidor concluir o trabalho. Cada evento pode ser importante quando alguém pergunta se o agente ultrapassou sua autoridade.

Um registro típico contém pelo menos estas afirmações:

- O processo do agente informa quando iniciou a ação.
- O servidor receptor informa quando aceitou a solicitação.
- O servidor receptor pode informar quando confirmou ou concluiu o trabalho.
- O gateway de ações informa quando recebeu e liberou a solicitação.
- Uma pessoa pode ver um horário local em uma interface de usuário.

Esses não são versões concorrentes de um único campo. Eles descrevem pontos diferentes em uma sequência causal. Se você os juntar em um único carimbo normalizado no momento da coleta, perderá a distinção que explica filas, atrasos de rede, novas tentativas, esperas por aprovação e chamadas longas.

Já vi equipes identificarem uma entrada de auditoria de API como o horário em que um agente «fez a coisa», quando a entrada mostrava apenas a aceitação da solicitação. Esse erro fica caro quando o endpoint coloca o trabalho em fila e realiza a alteração muito depois. O agente pode ter parado antes de a alteração ocorrer, mas sua solicitação ainda a causou.

Use nomes que indiquem o evento. `agent_action_started_at`, `gateway_received_at`, `server_received_at` e `server_completed_at` obrigam o leitor a perguntar o que aconteceu em cada ponto. Um campo vago chamado `timestamp` incentiva as pessoas a inventar uma resposta mais tarde.

## Um deslocamento preserva um instante, um fuso explica a exibição

Um deslocamento numérico em relação ao UTC transforma uma leitura do relógio de parede em um instante específico. Um fuso horário nomeado explica as regras civis que produziram aquela leitura. Muitas vezes você precisa dos dois, mas eles resolvem problemas diferentes.

Considere estes dois valores:

```text
2025-11-02T01:30:00-04:00
2025-11-02T01:30:00-05:00
```

O mostrador do relógio indica 1h30 nos dois casos. Eles estão separados por uma hora. Na volta do horário de verão na América do Norte, o horário local se repete, e um valor sem contexto como `2025-11-02 01:30:00` deixa o investigador sem saber qual instante ocorreu.

A RFC 3339 trata disso diretamente. Seu formato de carimbo usa data e hora completas, além de `Z` para UTC ou de um deslocamento numérico. A RFC também permite o deslocamento `-00:00` para indicar que a fonte conhece o horário, mas não conhece o deslocamento local. Essa distinção é uma evidência útil. Não reescreva silenciosamente `-00:00` como `Z`, pois UTC afirma um fato que a fonte não afirmou.

Um identificador de fuso como `America/Los_Angeles` ainda vale a pena quando uma aprovação humana, um chamado de suporte ou uma gravação de tela se refere ao horário local do escritório. Ele permite reproduzir as regras de calendário em vigor naquele lugar. Não substitui o deslocamento. As regras dos fusos podem mudar, e o mesmo fuso tem deslocamentos diferentes ao longo do ano.

Armazene o carimbo recebido como texto, mantenha seu deslocamento original e derive um instante UTC para ordenação. Não guarde apenas uma string local renderizada. A renderização pertence à borda do sistema, onde uma pessoa escolhe o fuso de exibição.

## Relógios local, do servidor e de auditoria respondem a perguntas diferentes

O horário local informa o que o operador ou o host do agente acreditava ser o horário. O horário do servidor informa quando um serviço remoto observou ou realizou o trabalho. O horário de auditoria informa quando o sistema de registro aceitou um evento. Os investigadores devem comparar os três, sem eleger um deles como verdade universal.

Comece pelo limite do evento. Se um agente solicita `POST /deployments`, o horário local da ação pode ajudar a descrever a intenção. O horário de recebimento no servidor pode estabelecer quando o serviço remoto se tornou responsável pela solicitação. O horário de conclusão no servidor pode estabelecer quando o estado de uma implantação mudou. Uma entrada de auditoria pode estabelecer quando seu ponto de controle observou a tentativa e se a aprovou.

A latência de rede cria intervalos normais entre esses valores. Filas criam intervalos maiores. Novas tentativas complicam a situação porque um cliente pode usar um identificador de ação para várias tentativas, enquanto o servidor registra cada tentativa separadamente. Uma linha do tempo que mostra apenas o primeiro horário local oculta tudo isso.

Não use a exibição de um navegador, o prompt de um terminal ou o relógio de uma captura de tela como critério de desempate, a menos que saiba como aquele dispositivo sincroniza o horário. Essas exibições ajudam a explicar o que uma pessoa acreditava, mas raramente resolvem uma disputa de ordenação apertada.

Uma comparação prática usa três colunas na planilha de investigação:

| Fonte da evidência | Preserve | Use para responder |
|---|---|---|
| Host do agente | Carimbo local bruto, deslocamento, fuso e identidade do processo | Quando esse processo afirmou ter começado ou recebido um resultado? |
| Serviço remoto | ID da solicitação, horário de recebimento, horário de conclusão e status da resposta | Quando o serviço aceitou e realizou o trabalho? |
| Sistema de auditoria | ID do evento, horário registrado, prova de integridade e resultado da autorização | Quando o ponto de controle observou e permitiu ou negou a chamada? |

As linhas devem manter seus próprios horários mesmo depois que você adicionar uma coluna UTC calculada para ordenação. Uma planilha limpa com uma única coluna de horário parece conveniente, mas esconde a trilha da evidência.

## Mudanças no horário de verão criam horas duplicadas e horas inexistentes

As transições do horário de verão expõem atalhos de carimbo porque quebram uma suposição humana: todo minuto local ocorre uma vez e todos os dias têm a mesma duração. Nenhuma das duas suposições é válida.

Durante a transição de outono, uma hora local se repete. Durante a transição de primavera, uma hora não existe. Um analisador que aceita um carimbo local sem contexto precisa escolher uma regra, rejeitar a entrada ou adivinhar. Adivinhar é inaceitável em um caminho de auditoria.

O registro a seguir é utilizável porque contém tanto um instante preciso quanto o contexto civil que gerou a leitura:

```json
{
  "event_id": "act_8f3c",
  "event": "authorization_granted",
  "observed_at": "2025-11-02T01:14:22-04:00",
  "zone": "America/New_York",
  "instant_utc": "2025-11-02T05:14:22Z",
  "clock_source": "agent_host"
}
```

O campo `instant_utc` é derivado, portanto preserve também a string original `observed_at`. Se um analisador mudar depois, ou se um erro afetar a conversão, você poderá refazer a derivação e explicar a diferença. Trate valores derivados como resultado de análise, não como substitutos da evidência original.

Uma abreviação de fuso como `EST` piora a situação. Abreviações são ambíguas entre regiões e não informam de modo confiável se o horário de verão estava em vigor. Use um identificador de fuso IANA para o contexto civil e um deslocamento numérico para o instante. Se uma fonte emitir apenas uma abreviação, registre-a exatamente e informe que seu significado continua sem resolução.

Agendamentos recorrentes precisam de uma regra própria. Armazene o agendamento como horário local mais um fuso IANA e calcule cada ocorrência segundo as regras desse fuso. Armazene uma ação que realmente foi executada como um carimbo com deslocamento. Um agendamento diz quando um trabalho deveria ocorrer; um registro de evento diz quando ele ocorreu.

## A deriva do relógio transforma uma ordem aparentemente precisa em falsa certeza

Precisão em milissegundos não significa exatidão em milissegundos. Um laptop não sincronizado pode produzir carimbos com seis casas decimais enquanto está vários minutos distante de um servidor. Suspensão, perda de rede, máquinas virtuais e sincronização defeituosa produzem esse problema.

Separe precisão de incerteza no modelo de dados. Precisão é o número de dígitos registrados. Incerteza é o intervalo em que você acredita que o instante real se encontra. Um horário do host de `10:00:00.123Z` com incerteza de dois segundos não deve resolver uma disputa de ordenação de um segundo com uma API remota.

Meça o deslocamento do relógio quando puder. Capture o horário de uma referência confiável antes de uma execução do agente e novamente depois, armazenando a diferença observada. Se a referência for remota, considere o tempo de trânsito da solicitação. Uma estimativa simples pelo ponto médio funciona para operações aproximadas quando você preserva a medição, em vez de apresentá-la como uma correção exata.

Por exemplo, um coletor envia uma solicitação às `10:00:00.000` no horário local, recebe uma resposta confiável às `10:00:00.200` no horário local, e a resposta informa `10:00:00.150Z`. O horário do servidor ocorreu em algum momento durante a ida e a volta. O ponto médio local é `10:00:00.100`, portanto o host parece estar cerca de 50 milissegundos atrasado sob a suposição usual de trânsito simétrico. Essa suposição pode falhar, por isso o resultado útil é um intervalo, não uma declaração de verdade.

Relógios monotônicos resolvem um problema mais específico. Um relógio monotônico mede o tempo decorrido dentro de um processo em execução e não salta quando o horário de parede muda. Registre um valor monotônico inicial e a duração junto com o horário de parede quando precisar provar que a ação B ocorreu depois da ação A dentro do mesmo processo. Não converta valores monotônicos para UTC nem os compare entre hosts.

A documentação do NTP faz uma distinção prática semelhante: a sincronização estima deslocamento e dispersão, em vez de conceder um horário perfeito. Trate essas estimativas como parte da evidência quando a ordem for próxima o suficiente para importar.

## Mantenha a evidência bruta e o horário normalizado no mesmo registro

Um esquema de eventos defensável preserva o que cada participante realmente informou e torna a análise reproduzível. O formato JSON a seguir funciona para uma ação de agente sem fingir que todos os campos vêm de um único relógio.

```json
{
  "action_id": "a91c2d7e",
  "attempt": 2,
  "agent": {
    "process_id": "p_4b71",
    "started_at": "2025-04-18T14:07:12.481-07:00",
    "zone": "America/Los_Angeles",
    "monotonic_start_ms": 9184421,
    "clock_uncertainty_ms": 750
  },
  "gateway": {
    "received_at": "2025-04-18T21:07:12.661Z",
    "authorized_at": "2025-04-18T21:07:14.034Z",
    "result_released_at": "2025-04-18T21:07:14.882Z",
    "audit_event_id": "aud_3e90"
  },
  "server": {
    "request_id": "req_7c19",
    "received_at": "2025-04-18T21:07:14.301Z",
    "completed_at": "2025-04-18T21:07:14.649Z",
    "status": 201
  },
  "normalization": {
    "sort_instant_utc": "2025-04-18T21:07:12.481Z",
    "method": "RFC3339 offset conversion"
  }
}
```

Esse esquema define um limite que as equipes costumam confundir: um identificador de ação conecta registros, enquanto um carimbo ordena um evento dentro daquela ação. Reutilizar um identificador após uma nova tentativa faz sentido. Reutilizar um único carimbo para todas as etapas, não.

Registre o ID da solicitação do servidor mesmo quando já tiver um ID de ação interno. Durante uma investigação, o identificador do próprio servidor muitas vezes é a única maneira confiável de distinguir uma solicitação que expirou de uma solicitação que nunca saiu do cliente.

Evite armazenar apenas milissegundos desde a época Unix, a menos que o produtor garanta UTC e documente sua fonte de relógio. Valores de época são fáceis de ordenar, mas perdem o deslocamento original, o contexto de exibição e, às vezes, a unidade. Se você os aceitar de terceiros, registre a unidade explicitamente e preserve a representação recebida.

## Uma linha do tempo precisa de intervalos quando as evidências se sobrepõem

Quando duas fontes têm incerteza, calcule intervalos em vez de forçar uma ordem. Isso evita um erro conhecido: o investigador vê `10:03:01.010` e `10:03:01.400`, ordena os valores e afirma que o primeiro evento causou o segundo, apesar de os deslocamentos dos dois computadores serem desconhecidos.

Suponha que o agente informe o início de uma ação às `21:07:12.481Z`, com 750 milissegundos de incerteza. Seu intervalo possível vai de `21:07:11.731Z` a `21:07:13.231Z`. O gateway informa o recebimento às `21:07:12.661Z`, com incerteza de 20 milissegundos. Os intervalos se sobrepõem, portanto os carimbos sozinhos não podem provar que o gateway recebeu a chamada depois do início informado. A sequência do protocolo ainda pode sustentar essa conclusão, mas os relógios de parede não.

Declare o motivo de cada afirmação de ordenação. Estas são conclusões diferentes:

- «O gateway registrou o recebimento depois que o agente emitiu a solicitação» resulta de evidência do protocolo ou de um rastreamento de solicitação correlacionado.
- «O carimbo de recebimento do gateway é posterior» resulta apenas dos horários de parede exibidos.
- «Os registros estabelecem a ordem dentro da incerteza informada» resulta quando os intervalos não se sobrepõem.
- «Os registros não conseguem estabelecer a ordem» é o resultado correto quando os intervalos se sobrepõem e nenhuma evidência causal preenche a lacuna.

As pessoas não gostam da quarta conclusão porque os relatórios de incidentes querem uma história organizada. Inventar precisão não melhora a história. Isso dá ao próximo revisor um motivo para questionar todas as conclusões ao redor dela.

Isso também muda o desenho dos alertas. Não sinalize um agente apenas porque um evento do gateway parece ocorrer algumas centenas de milissegundos antes do início local do agente. Sinalize um tempo decorrido negativo somente depois de aplicar os limites conhecidos do deslocamento, ou marque o caso para investigação da saúde do relógio.

## Aprovação e execução precisam manter carimbos separados

Uma aprovação humana prova que alguém permitiu uma capacidade em determinado momento. Ela não prova que o agente enviou uma solicitação naquele mesmo instante e certamente não prova que um sistema remoto concluiu o trabalho solicitado naquele momento.

Mantenha eventos de aprovação separados das chamadas. Um registro de aprovação deve incluir o ator, o escopo concedido, o processo ou sessão a que se aplicava, o horário observado e o ID do evento do sistema de autorização. Um registro de chamada deve referenciar essa autorização quando aplicável e manter seus próprios horários de recebimento e liberação.

Essa distinção é mais importante na autorização de sessões. Uma aprovação pode abranger várias ações durante a vida de um processo. Se uma ação posterior causar dano, o investigador precisará responder a duas perguntas separadas: quando a autorização ocorreu e o processo ainda estava dentro da sessão aprovada quando fez essa chamada? Um único campo `approved_at` não responde às duas.

A aprovação por chamada cria uma sequência mais precisa, mas ainda deixa uma lacuna. O usuário pode aprovar às 14:07:14, o gateway pode despachar às 14:07:14.1 e o serviço remoto pode confirmar às 14:08:02. Um tempo limite remoto depois do despacho não elimina a possibilidade de o serviço ter concluído a ação.

Em um fluxo controlado por gateway, registre também eventos de negação. Uma chamada negada estabelece que um agente tentou realizar uma ação, mesmo que nenhuma solicitação remota devesse ter ocorrido. Se o agente tentar novamente depois de mudanças na permissão, a linha do tempo precisará de tentativas separadas com evidências separadas. Não substitua uma negação por um sucesso posterior.

## Analise uma implantação contestada sem nivelar as evidências

Suponha que um agente tenha solicitado uma implantação depois que um desenvolvedor aprovou uma sessão. Mais tarde, o desenvolvedor diz que a aprovação ocorreu após o horário comercial, enquanto o registro do serviço remoto diz que a implantação começou antes da aprovação. A aparente contradição costuma surgir da comparação entre o horário local exibido e o horário UTC do servidor.

As evidências contêm estes registros:

| Evento | Horário informado | Fonte |
|---|---|---|
| Aprovação da sessão | `2025-04-18T17:58:40-07:00` | Registro de autorização local |
| Agente inicia a chamada de implantação | `2025-04-18T17:59:02-07:00` | Host do agente |
| Gateway recebe a chamada | `2025-04-19T00:59:02.410Z` | Registro de auditoria do gateway |
| Serviço remoto aceita a solicitação | `2025-04-19T00:59:04Z` | Registro de auditoria do serviço |
| Serviço remoto conclui a implantação | `2025-04-19T01:01:18Z` | Registro de auditoria do serviço |

Converta os dois primeiros registros, mas preserve as formas recebidas. A aprovação ocorreu às `00:58:40Z`, e o agente começou às `00:59:02Z`. Os registros do gateway e do serviço seguem uma sequência causal plausível. Nada ocorreu antes da aprovação; alguém apenas leu `17:58` ao lado de `00:59` como se os dois valores usassem a mesma exibição de relógio.

Agora vem a parte incômoda. Suponha que o host do agente tenha uma incerteza estimada de 90 segundos porque estava em suspensão. Você ainda pode dizer que o gateway recebeu uma chamada depois de o sistema de autorização registrar a aprovação, porque esses registros usam a trilha do gateway e da autorização. Você não pode usar o horário local do agente para estabelecer uma segunda afirmação de ordenação dentro desse intervalo.

A investigação deve preservar as duas conclusões. Uma é forte e a outra é limitada. Isso é melhor do que fazer toda a linha do tempo parecer igualmente precisa.

## Verifique a integridade da auditoria antes de confiar em sua posição no tempo

Um registro de auditoria só pode informar se alguém alterou, reordenou ou removeu evidências quando você verifica seu mecanismo de integridade. Faça essa verificação antes de usar as entradas de auditoria para sustentar uma sequência. Depois, faça a pergunta separada sobre qual relógio marcou cada entrada.

Os projetos do Sallyport exportam diários de sessões e chamadas de um único registro de auditoria criptografado e encadeado por hash, e `sp audit verify` pode verificar essa cadeia offline sobre o texto cifrado. Essa verificação permite ao investigador testar a continuidade do registro sem expor os segredos armazenados.

A integridade não transforma um carimbo de auditoria em um relógio globalmente perfeito. Uma entrada válida prova que o registro contém o evento registrado em sua cadeia. Ela ainda precisa de uma fonte de relógio documentada, de um formato de deslocamento e de uma política de incerteza se você quiser compará-la de perto com um servidor externo.

Execute a verificação contra a cópia das evidências e salve o resultado do comando junto com o material do caso. Um registro útil inclui o comando, o identificador do artefato de entrada, o resultado da verificação e a pessoa ou tarefa automatizada que a executou. Não cole apenas uma linha verde de status em um chamado. O próximo investigador precisa reproduzir a mesma verificação.

O encadeamento por hash também muda a maneira de lidar com lacunas. Se a cadeia indicar que entradas estão faltando ou foram alteradas, não prossiga silenciosamente com uma linha do tempo normalizada. Marque o intervalo afetado como incompleto e procure registros independentes do servidor. Um segmento de auditoria ausente pode dizer mais sobre o incidente do que as entradas ao redor dele.

## Construa a visão da investigação a partir de premissas declaradas

Uma boa visão de investigação mostra os carimbos brutos, as conversões para UTC, a identidade da fonte e a incerteza. Ela não esconde a conversão atrás de um rótulo de painel como «horário do evento». O leitor deve conseguir ver por que a exibição ordena dois eventos.

Use esta sequência ao montar uma linha do tempo de ações:

1. Colete os registros imutáveis das fontes e preserve suas strings originais de horário, identificadores e deslocamentos.
2. Identifique o evento marcado por cada carimbo: decisão, aprovação, recebimento no gateway, aceitação pelo servidor, conclusão ou liberação do resultado.
3. Converta os carimbos com deslocamento para UTC em um campo separado, registrando o analisador ou método usado.
4. Estime a incerteza do relógio de cada fonte que possa afetar a ordem contestada.
5. Ordene pelos instantes normalizados e depois examine os intervalos de incerteza sobrepostos e os IDs de solicitação antes de escrever afirmações causais.

Não converta um horário local anexando o deslocamento atual do próprio investigador. Esse erro altera eventos históricos sempre que o investigador trabalha em outro fuso ou quando as regras de horário de verão são diferentes. Analise o deslocamento fornecido com o registro. Se o registro não tiver deslocamento, marque-o como não resolvido até estabelecer uma fonte de fuso e as regras aplicáveis.

As equipes devem testar isso antes de um incidente. Crie uma ação perto de uma transição de horário de verão em um ambiente que não seja de produção. Altere o relógio de um cliente dentro de um limite de teste seguro. Force uma nova tentativa e uma resposta atrasada do servidor. Depois, peça a alguém que não tenha criado o registro para reconstruir a ordem. Se essa pessoa precisar de contexto verbal para explicar as evidências, o formato do registro está incompleto.

O tempo raramente é a única evidência em um incidente envolvendo agentes. Identificadores de solicitação, escopo de autorização, identidade do processo, corpos de resposta e verificações contra adulteração muitas vezes estabelecem fatos que os relógios não conseguem. Mantenha esses fatos ligados aos próprios eventos. A próxima ação contestada será mais fácil de explicar porque você registrou o que cada sistema sabia, em vez de obrigar todos os sistemas a concordar com um único carimbo fictício.
