Sistema de Resultados de Campeonatos (Chronosat)
Em que ordem construir e como verificar
Sistema de Resultados de Campeonatos (Chronosat): Roadmap de Implementação
| Campo | Valor |
|---|---|
| Projeto | Sistema de Resultados de Campeonatos (integração Chronosat) |
| Cliente | Sertões |
| Agência / Autor | Modulareasy |
| Documento | Roadmap de Implementação (companheiro do DRS) |
| Data de revisão | 2026-09-18 |
Documentos da família
- DRS (resultados-chronosat), o que o sistema faz.
- Inventário de Artefatos (resultados-chronosat-inventario), tudo que precisa existir e como cada item deve ser.
- Jornadas dos Atores (resultados-chronosat-jornadas), como cada papel opera o sistema.
- Plano de Testes (Alfa e Beta) (resultados-chronosat-tests), o que validar antes de entregar.
- Questionário de Elicitação (resultados-chronosat-questionario), decisões de negócio já reconciliadas no DRS.
Este é o roteiro de construção do sistema, em ordem, com verificação primeiro: para cada tarefa, o observável que prova que ela está pronta é declarado antes do como construir. A ordem vem das ondas de entrega do DRS (bloco 9, J.1) e de suas dependências. Cada tarefa cobre um ou mais requisitos funcionais (RF) do DRS.
Estado da implementação (2026-07-07, S84). Fase F6 em andamento, vertical Kitesurf no ar por configuração (F6-01): a tabela, o pódio e o modal de um evento de Kitesurf (verde #88BD23, logo próprio) exibem um único atleta por competidor (regra de tripulação solo), e as modalidades Kite e Wing aparecem com suas próprias categorias, lidas dinamicamente, tudo por configuração, sem alteração de código, com dados fictícios de demonstração (mesmo padrão das demais verticais fora a Series). As verticais Series (piloto e navegador), Petrobras (encerrada) e MTB (dupla) seguem sem regressão. Fases F0 (servidor e SSL), F1 (motor de leitura e persistência), F2 (site público completo da Series), F3 (painel único, incluindo o super admin multiusuário F3-13 a F3-17) e F4 (no que é autônomo: múltiplos eventos por vertical F4-01, Petrobras por configuração F4-02, home global F4-03 e endurecimento de pico F4-05) estão completas. Os testes de prontidão F5-GATE (Bike/dupla) e F6-GATE (Kite/solo e divergência por pontos) já absorvem o primeiro pacote real de cada esporte, com armazenamento não-bloqueante e tabela genérica sinalizada na divergência (ADR-012). Fronteiras declaradas, ainda não entregues: a validação com o primeiro pacote de dados REAIS da Bike (F5-02) e do Kite (F6-02), ambas dependentes do dado real de terceiros chegar, e, no caso do Kite, a exibição da classificação por PONTOS com os rótulos de coluna próprios (Atleta/Pontos), que é o adaptador contido de métrica (ADR-012) e entra junto do dado real; e a publicação no subdomínio com vínculo a partir do site institucional (F4-04, adiado por decisão do cliente para o fim do projeto, quando o sistema inteiro estiver validado). Ocultação por origem (RF-REGRA-006), LIGADA (F2-14, S82): competidor marcado como oculto na origem pela Chronosat (_status="O") agora não aparece na página pública (pódio, tabela, contador, busca, modais e recortes por categoria e trecho), lendo tanto o crews quanto o racetimes; smoke visual real com um competidor oculto confirmou a remoção (líder some do pódio e da tabela, contador 27 para 26), sem regressão nos demais, e o operador continua vendo o competidor no painel. Estendida à API interna de leitura em F2-15 (S83): o competidor oculto na origem também não aparece nos endpoints públicos da API (/api/events; o detalhe dele responde não encontrado), e o /meta não lista competidor. O DRS foi ampliado e republicado (RF-REGRA-006 cobre página pública e API interna de leitura). Home global agora 100% conforme (F4-03 / RF-PUB-016, S84): a vertical Series passou a exibir seu logotipo quadrado laranja no card da raiz, como as demais verticais (antes herdava o logotipo genérico do Sertões): as quatro verticais aparecem com a própria marca oficial; smoke visual real (desktop e celular) confirmou os quatro tiles coloridos consistentes e o cabeçalho da Series sem regressão. Correção de diagnóstico (S84): NÃO há overflow horizontal no celular, verificado com emulação real de dispositivo (360 e 390 px) na home global e nas páginas de evento; o alerta anterior de "overflow mobile system-wide" vinha de captura por tamanho de janela, que dá falso positivo em páginas com viewport responsivo. Polish real remanescente, de nicho, não bloqueia nenhuma fatia: numa faixa estreita de tablet (por volta de 768 px) a última coluna da tabela de classificação fica cortada porque o contêiner da tabela recorta o excedente em vez de permitir rolagem horizontal, a corrigir em ciclo dedicado de polish do base.css (recorte para rolagem no contêiner da tabela). Correção e ampliação pontuais (2026-09-17): o filtro de categoria agora vale dentro do recorte de trecho (F2-16, RF-PUB-004), e o grupo Parciais passou a ser uma coluna ocultável por evento junto das demais dez (F3-18, RF-PAINEL-014). Onda AUD entregue e provada em produção (2026-09-19), audiência: 20 de 20 cartões. O sistema foi usado ao vivo no primeiro evento grande e ninguém soube dizer quantas pessoas acompanharam, porque ele não mede nada: o retrato de partida está no cartão AUD-00, com o placar fechado (3 tipos de página pública, 0 com medição, 3 sem). O DRS foi ampliado antes de qualquer linha de código, com o módulo MEDIR (RF-MEDIR-001 a 017), sete decisões de arquitetura novas (ADR-013 a ADR-019), a série de acessos no modelo de dados (E.4) e o catálogo da medição (Ap.6). A onda tem duas metades: a medição externa, que alimenta as plataformas do cliente, e o painel de audiência dentro da própria ferramenta, que é a verdade operacional e não depende de consentimento nem de bloqueador. Nenhum identificador e nenhuma credencial de medição vivem em código: quem liga é o administrador, pela tela nova de integrações (AUD-01), e por isso ela é o primeiro cartão da fila. Reconciliação do gate da onda (2026-09-18, mesma data): sete pontos de divergência entre o documento e o código foram corrigidos antes de a onda abrir, e o mais grave era o critério do próprio retrato: "carrega recurso de terceiro" devolveria 3 de 3, porque as páginas públicas carregam a tipografia oficial de domínio externo desde a construção do site; o critério passou a ser "dispara chamada de medição ou grava linha na série", medido pelos dois lados. Também mudaram: a exclusão do que não é audiência passou a ser por origem da requisição e nunca por rota (a lista do monitor inclui páginas públicas reais); a série ganhou a rota e a proveniência da linha; a repetibilidade da importação passou a ser por proveniência e não por identificador de visitante; o envio pelo servidor declarou o dado de correspondência que a plataforma exige; o momento da prova é nulo nas homes; e a contagem do catálogo de textos foi corrigida para 39 chaves, 41 com as duas do aviso de medição (o texto e o endereço da política, confirmado no ADR-019). Prova de fechamento (2026-09-19, main 3a2f16e, gates plano aprovado / qa aprovado / revisão aprovada): o par invertido do retrato de AUD-00 fechou, 3 páginas medidas e 0 não medidas, com etiqueta e pixel únicos em cada uma; os sete eventos de interação chegaram com os nomes exatos no relatório de tempo real do GA4 (troca_de_trecho, troca_de_modalidade, troca_de_categoria, busca_de_competidor, parciais_abertas, documento_oficial_aberto, atualizacao_ao_vivo); a CAPI aceitou 2 PageView na condição "Servidor, Processado" com identificador de evento no Eventos de Teste da Meta; a série gravou 696 acessos na primeira hora sem descarte; a importação do registro do servidor absorveu 51.248 linhas de 10 a 18 de setembro de forma repetível (reimportar o mesmo arquivo não soma linha); e a carga de prova ficou dentro do limite do RNF-PERF-003 (p95 1586 ms contra 2191 ms de referência, 0 erro em 531 pedidos).
Atualização de 2026-09-19, duas correções medidas. (1) O ADR-019 deixou de ser pendência: o cliente publicou a sua política de privacidade, com seção própria sobre o Sistema de Resultados declarando a medição anônima e o uso da mesma propriedade de análise e do mesmo pixel do site institucional; o ADR passou a confirmado, com endereço, controlador e data, e o aviso do rodapé aponta para ela. A confirmação também dá respaldo público ao ADR-014 e ao RNF-PRIV-001. (2) O AUD-17 fechou (2026-09-19): o gate de QA provou o H1 inteiro em produção, as duas metades positivas (valor de fábrica, vínculo para a política) e as duas negativas (esvaziar a chave do texto remove o aviso inteiro, esvaziar só a do endereço mantém o aviso sem vínculo), mais a ausência confirmada em toda tela do painel. O cartão foi marcado com o H1 completo. Essa medição corrigiu, de quebra, um número deste próprio roadmap: o aviso virou duas chaves e não uma, então o grupo de cabeçalho e rodapé foi de 12 a 14 e o catálogo de 39 a 41, e não a 40 como estava escrito aqui ontem. As fases F0 a F4 seguem completas, F5-02 e F6-02 seguem dependentes do primeiro pacote real de terceiros, e F4-04 segue adiado por decisão do cliente.
Como usar
Cada tarefa é um cartão com um código curto e estável (ex.: F1-03), o RF que cobre, o que implementar, como verificar (o teste, declarado primeiro) e o critério de aceite H1. Marque a tarefa como feita quando o teste passar. As fases são sequenciais; dentro de uma fase, siga a ordem dos cartões. Ao fim de cada fase há uma Definição de Pronto: a fase só fecha quando todos os seus critérios estão verdes.
Mapa de cobertura
| Fase | Onda do DRS | Módulo do DRS | RFs cobertos |
|---|---|---|---|
| F0 Infraestrutura | Preparação | Arquitetura (G), Operação (K) | ADR-006, ADR-007, RNF-ISO-001, RNF-ESC-001 |
| F1 Motor de leitura e persistência | Onda 1 | INGEST, API | RF-INGEST-001 a 005, RF-API-001 a 005, ADR-012 |
| F2 Página pública e site Series | Onda 2 | PUB, REGRA | RF-PUB-001 a 015, RF-REGRA-001 a 006 |
| F3 Painel único de gestão (com contas nominais) | Onda 3 | PAINEL, CONFIG | RF-PAINEL-001 a 013, RF-CONFIG-001 a 003, RF-CONFIG-005, RNF-ARQ-001, RNF-SEG-002 a 005 |
| F4 Petrobras por configuração e home global | Onda 4 | CONFIG, PUB, borda | RF-CONFIG-002, RF-CONFIG-004, RF-PUB-016, RNF-COMP-001, RNF-PERF-001, RNF-PERF-002, RNF-ESC-001 |
| F5 Vertical MTB (Bike) | Onda 5 | CONFIG, PUB | RF-CONFIG-001 (perfil dupla), validação do primeiro pacote real |
| F6 Vertical Kitesurf | Onda 6 | CONFIG, PUB | RF-CONFIG-001 (perfil solo), validação do primeiro pacote real |
| PET Plantão do Petrobras 2026 | Evento ao vivo | PUB, REGRA, INGEST, API, PAINEL | RF-PUB-001, RF-PUB-004, RF-PUB-005, RF-PUB-014, RF-REGRA-001, RF-REGRA-002, RF-REGRA-004, RF-INGEST-001, RF-INGEST-003, RF-INGEST-005, RF-API-001, RF-API-002, RF-API-005, RF-PAINEL-013, ADR-012 |
| Planejamento (Fase 0) | Preparação | Elicitação, especificação, companheiros, validação, aprovação | Pré-concluída na aprovação do DRS |
| M Mockup Navegável | Preparação | Referência visual de todo o sistema (Ap.4, Ap.5) | Concluída: mockup completo publicado e aprovado (guia do desenvolvimento) |
| AUD Audiência | Onda AUD | MEDIR, PAINEL, PUB, CONFIG | RF-MEDIR-001 a 017, RF-PAINEL-012, RF-CONFIG-006, RNF-PERF-003, RNF-PRIV-001, RNF-SEG-006, ADR-013 a ADR-019 |
Planejamento
Concluída na aprovação do DRS. Vale 40% do projeto (seção Planejamento). Estas etapas cobrem tudo que aconteceu antes de codar.
0.1 Entendimento e Elicitação
0.2 Especificação (o DRS)
0.3 Documentos companheiros
0.4 Validação e Qualidade
0.5 Publicação e Aprovação
Fase M, Mockup Navegável (pós-Planejamento, gate de aprovação)
Dependência: DRS aprovado (Planejamento fechado). A construção (F0 em diante) não começa com esta fase aberta. Concluída em 2026-07-03: mockup completo publicado em modulareasy.com/sertoes/pagina-de-resultados e aprovado.
DRS (bloco Artefatos de apoio), Ap.4 e Ap.5. Home global, home e página de evento das quatro verticais (cada uma com a sua regra de exibição: piloto e navegador, dupla em negrito, solo por pontos), painel do operador em três telas (eventos, novo evento com o fluxo de colar as URLs, verticais), logotipos e cores oficiais 2026, base compartilhada e Mapa do mockup flutuante.
Como verificar (teste primeiro): todas as páginas respondem 200 na URL publicada; cada vertical exibe a própria marca e cor oficial; o cadastro demonstra a classificação dos arquivos pelo nome; smoke visual página a página em desktop e mobile.
Aceite (H1): Dado o mockup publicado, Quando o cliente navega pelo Mapa do mockup, Então alcança toda tela do sistema, E cada vertical aparece com a identidade oficial.
Gate. Apresentado e aprovado; ajustes de identidade (nomes e logos oficiais das verticais) aplicados no próprio mockup.
Como verificar (teste primeiro): aprovação registrada; DRS atualizado no bloco "Artefatos de apoio e protótipo" declarando o mockup REFERÊNCIA VISUAL APROVADA e GUIA DO DESENVOLVIMENTO.
Aceite (H1): Dado o mockup aprovado, Quando a construção de uma tela começar, Então a página correspondente do mockup será o guia, E divergência visual se resolverá consultando o mockup.
Definição de Pronto M: mockup completo no ar, aprovado, e vinculado no DRS como guia do desenvolvimento. CUMPRIDA.
Fase F0, Infraestrutura
DRS J.3, ADR-006, RNF-ISO-001. Adquirir e configurar o servidor próprio, separado dos demais produtos.
O que implementar: provisionar uma máquina de pequeno porte com Ubuntu e contêineres, isolada de outros sistemas; preparar o runtime do aplicativo único.
Como verificar (teste primeiro): o aplicativo sobe no servidor novo e responde a um health check; o servidor não compartilha processos com nenhum outro produto.
Aceite (H1): Dado o servidor provisionado, Quando a sustentação consulta a saúde do sistema, Então o health check responde OK, E o servidor não hospeda nenhum outro produto.
DRS ADR-007, RNF-ESC-001. Apontar o domínio ao servidor dedicado e terminar o SSL nele.
O que implementar: publicar resultados.sertoes.com.br no servidor dedicado como proxy reverso para o aplicativo único (127.0.0.1:3000), com redirecionamento de HTTP para HTTPS e certificado automático Let's Encrypt. O cache de respostas de leitura repetidas é o cache de janela curta do próprio aplicativo (F1-02, RF-INGEST-002), servido através deste proxy quando os endpoints de leitura existirem. Uma camada de rede (CDN) à frente fica como evolução, se o volume exigir.
Como verificar (teste primeiro): a página abre em HTTPS com certificado válido no domínio (sem aviso de segurança); a requisição é roteada ao aplicativo único (o health check e a página respondem pelo domínio).
Aceite (H1): Dado o domínio apontado ao servidor, Quando o público acessa https://resultados.sertoes.com.br, Então a conexão é HTTPS com certificado válido, E a requisição é roteada ao aplicativo único (a página e o health check respondem pelo domínio), E o acesso por HTTP é redirecionado para HTTPS.
Definição de Pronto F0: servidor isolado no ar com health check verde; domínio de resultados no ar com HTTPS e certificado válido (SSL terminado no próprio servidor), com redirecionamento de HTTP para HTTPS; nenhum recurso compartilhado com outros produtos.
Fase F1, Motor de leitura e persistência (Onda 1: INGEST e API)
Dependência: nenhuma além das URLs de um evento de referência (Rally do Jalapão). Esta fase entrega o motor único que sustenta todas as verticais.
RF-INGEST-001. Buscar do lado do servidor os arquivos JSON (crews, stagetimes, racetimes) das URLs configuradas e servir ao front.
O que implementar: um endpoint de servidor que recebe a referência do arquivo, busca em satcron.com/stages/cache, e devolve o JSON com cabeçalho de origem cruzada para o domínio da página.
Como verificar (teste primeiro): o navegador do público obtém os dados via servidor, sem chamar satcron.com diretamente; a resposta traz o cabeçalho de origem cruzada.
Aceite (H1): Dado um evento com URLs válidas de crews, stagetimes e racetimes, Quando o front solicita os dados ao servidor, Então o servidor responde com os JSON da Chronosat sem que o navegador chame a origem, E a resposta inclui cabeçalho de origem cruzada permitindo o domínio da página.
RF-INGEST-002. Manter em cache a resposta de cada arquivo por uma janela curta (padrão 30 a 60 segundos) e buscar a origem no máximo uma vez por minuto por arquivo.
O que implementar: camada de cache por chave de arquivo com expiração configurável; coalescência de requisições concorrentes numa única busca à origem.
Como verificar (teste primeiro): múltiplas requisições ao mesmo arquivo dentro da janela são servidas do cache; a origem é chamada no máximo uma vez por minuto por arquivo (medido nos logs).
Aceite (H1): Dado um arquivo buscado há menos de 30 segundos, Quando chegam múltiplas requisições do público para o mesmo arquivo, Então todas são servidas do cache sem nova chamada à origem, E a chamada à origem ocorre no máximo uma vez por minuto por arquivo.
RF-INGEST-005, ADR-003, ADR-009, RNF-ARQ-001. Gravar cada leitura bem-sucedida de um arquivo da Chronosat no banco (entidade DADOS_EVENTO) como o estado mais recente daquela fonte, com o payload bruto preservado como veio da origem; a página pública passa a ser servida sempre do banco, nunca da origem diretamente.
O que implementar: ao fim de cada busca bem-sucedida à origem (F1-01), gravar o payload bruto em DADOS_EVENTO (chave evento, modalidade, tipo, trecho), com o momento da leitura; a leitura de dados para servir o front passa a ler do banco, não da resposta ao vivo do proxy.
Como verificar (teste primeiro): após uma leitura bem-sucedida, o registro aparece no banco com o payload bruto; retirar a URL de origem do ar depois disso e confirmar que a leitura seguinte continua servindo o último payload salvo, sem erro.
Aceite (H1): Dado um evento ao vivo com leituras bem-sucedidas, Quando a Chronosat retira os arquivos do ar (com ou sem o evento ter sido encerrado no painel), Então a página continua exibindo o último estado salvo no banco, E nenhum dado exibido anteriormente se perde.
RF-INGEST-003. Servir o último conteúdo válido salvo no banco quando a Chronosat responder erro ou ficar indisponível, sinalizando o estado; e tratar o caso de a origem estar indisponível já no primeiro acesso, antes de qualquer leitura bem-sucedida (sem nada salvo ainda).
O que implementar: ao falhar a busca à origem, servir o último payload salvo em DADOS_EVENTO (F1-03) com um marcador de atualização suspensa; quando não houver nenhum registro salvo ainda para aquela fonte (cold-start), devolver um estado de "aguardando dados" em vez de erro.
Como verificar (teste primeiro): simular erro da origem após uma leitura boa; a página exibe o último resultado válido salvo no banco com aviso, sem erro cru nem página em branco. Simular erro da origem no primeiro acesso, sem nada salvo ainda; a página exibe o estado de aguardando dados, sem erro cru nem página em branco.
Aceite (H1): Dado que a última leitura foi bem-sucedida e a origem passa a responder erro, Quando o público acessa a página, Então a página exibe o último resultado válido salvo no banco com indicação de atualização temporariamente suspensa, E não exibe erro cru nem página em branco. Dado que a origem está indisponível no primeiro acesso, sem nada salvo ainda, Quando o público acessa a página, Então a página exibe o estado de aguardando dados, E não exibe erro cru nem página em branco.
RF-INGEST-004. Relacionar crews, stagetimes e racetimes pela chave numeral, montando a visão consolidada de cada competidor, a partir dos dados salvos no banco.
O que implementar: normalizar cada payload salvo e juntar por numeral (identificação de crews, parciais e tempo do trecho de stagetimes, acumulado de racetimes); a normalização acontece na exibição, não na gravação (ADR-012).
Como verificar (teste primeiro): para um numeral presente nos três arquivos de teste, a visão consolidada reúne os três blocos, todos com o mesmo numeral.
Aceite (H1): Dado um competidor de numeral X presente em crews, stagetimes e racetimes, Quando o sistema consolida os dados, Então a visão do competidor reúne identificação, parciais, tempo do trecho e acumulado, todos com numeral X.
ADR-012. A leitura e a normalização não dependem de uma lista fixa de campos: modalidades, categorias, trechos e competidores são lidos dinamicamente; campos seriados (ssX, IX, posIX) são reconhecidos por padrão de nome em qualquer quantidade; um campo desconhecido é ignorado na exibição mas preservado no banco; um campo ausente apenas omite o elemento correspondente, sem quebrar a página.
O que implementar: o parser de normalização (usado por F1-05 e pela exibição em F2) reconhece campos seriados por padrão de nome (prefixo mais índice) em vez de uma lista fixa; campos fora do contrato conhecido são preservados no payload bruto e ignorados na montagem da visão; a ausência de um campo esperado não interrompe a montagem do competidor, apenas omite aquele dado.
Como verificar (teste primeiro): alimentar o parser com um arquivo de teste contendo um campo desconhecido (deve ser ignorado na visão e continuar presente no payload bruto salvo), um campo ausente do usual (o elemento correspondente some sem quebrar o restante) e mais parciais que o padrão atual (I8, I9; devem ser reconhecidas pelo padrão de nome).
Aceite (H1): Dado um payload com um campo desconhecido, um campo ausente e parciais além da quantidade usual, Quando o sistema normaliza para exibição, Então o campo desconhecido não aparece na tela mas permanece no banco, o campo ausente apenas omite o elemento sem quebrar a página, E as parciais extras são reconhecidas pelo padrão de nome.
ADR-012. Quando um pacote vier estruturalmente diferente do contrato conhecido (não é apenas campo a mais ou a menos, é uma forma diferente), o teste de conexão aponta ao operador exatamente o que divergiu, o dado é armazenado mesmo assim, e a página exibe uma tabela genérica sinalizada do que veio, até um adaptador específico entrar no módulo de ingestão. Sem inferência de layout por inteligência artificial.
O que implementar: uma verificação de forma no teste de conexão (usado por RF-PAINEL-003) que compara a estrutura do arquivo recebido ao contrato conhecido (crews, stagetimes, racetimes) e sinaliza divergência estrutural (não apenas campo a mais/a menos); quando divergente, salvar o payload do mesmo jeito e a exibição pública cair num modo de tabela genérica (chave e valor) sinalizada como "formato não reconhecido", em vez de quebrar ou tentar adivinhar o layout.
Como verificar (teste primeiro): alimentar o teste de conexão com um pacote de forma diferente do contrato (por exemplo, um esquema de bike de exemplo com blocos renomeados); o teste aponta a divergência ao operador; publicar mesmo assim e confirmar que a página exibe a tabela genérica sinalizada, sem erro cru.
Aceite (H1): Dado um pacote estruturalmente divergente do contrato conhecido, Quando o operador testa a conexão, Então o sistema aponta exatamente o que divergiu, E se publicado mesmo assim, o dado é armazenado e a página exibe uma tabela genérica sinalizada do que veio, sem quebrar e sem inferência de layout por IA.
Notas: este cartão constrói o mecanismo geral; a ativação de MTB (F5-GATE) e Kitesurf (F6-GATE) o exercita contra o primeiro pacote real de cada esporte.
RF-API-004. Expor os metadados de crews (título, subtítulo, trechos com atributos e status, modalidades, categorias) e o estado de publicação, a partir dos dados salvos no banco.
O que implementar: endpoint de leitura que devolve título, subtítulo, lista de trechos (nome, distância, origem, destino, status I ou NI), modalidades, categorias e estado ao vivo ou encerrado.
Como verificar (teste primeiro): o front carrega e recebe todos os metadados do evento de teste com os status corretos por trecho.
Aceite (H1): Dado um evento publicado, Quando o front carrega a página, Então recebe título, subtítulo, a lista de trechos com atributos e status, as modalidades, as categorias e o estado ao vivo ou encerrado.
RF-API-001. Expor a classificação geral (acumulado) de um evento e modalidade, cruzada e ordenada, a partir dos dados salvos no banco.
O que implementar: endpoint de leitura que devolve a lista ordenada pelo tempo total acumulado, cada competidor com numeral, tripulação, veículo, equipe, tempo total, penalidades e bônus.
Como verificar (teste primeiro): a lista do evento de teste vem ordenada pelo acumulado, com todos os campos exigidos.
Aceite (H1): Dado um evento e modalidade publicados, Quando o front solicita a classificação geral, Então a API retorna a lista ordenada pelo tempo total acumulado com numeral, tripulação, veículo, equipe, tempo total, penalidades e bônus.
RF-API-002. Expor a classificação de um trecho (stagetimes) com tempos e posições do trecho, a partir dos dados salvos no banco.
O que implementar: endpoint que devolve a lista do trecho com tempo da especial, posições parciais e tempo total do trecho.
Como verificar (teste primeiro): para um trecho iniciado do evento de teste, a lista vem com tempo da especial e posições.
Aceite (H1): Dado um evento, modalidade e trecho publicados, Quando o front solicita o trecho, Então a API retorna a lista de competidores com tempo da especial, posições parciais e tempo total do trecho.
RF-API-003. Expor as parciais I1 a I7 (ou mais, ver F1-06) de um competidor num trecho.
O que implementar: endpoint que devolve os horários de passagem, os deltas e as posições, omitindo indicadores nulos.
Como verificar (teste primeiro): para um competidor com parciais no evento de teste, o detalhe traz passagens, deltas e posições, sem os indicadores nulos.
Aceite (H1): Dado um competidor de numeral X num trecho, Quando o front solicita o detalhe, Então a API retorna os horários I1 a I7, os deltas tempo1 a tempo7 e as posições posI1 a posI7, omitindo os indicadores nulos.
RF-API-005. Expor a classificação recalculada dentro de uma categoria, com as posições renumeradas entre os competidores daquela categoria.
O que implementar: endpoint que filtra os competidores de uma categoria e recalcula a posição de 1 em diante, usando o tempo aplicável (acumulado no Geral, tempo do trecho quando um trecho está selecionado), a partir dos dados que a Chronosat já entrega.
Como verificar (teste primeiro): para uma categoria do evento de teste, a lista vem só com os competidores daquela categoria, ordenados e renumerados a partir de 1.
Aceite (H1): Dado um evento com categorias e uma categoria selecionada, Quando o front solicita a classificação da categoria, Então a API retorna apenas os competidores da categoria, ordenados pelo tempo aplicável, com a posição renumerada de 1 em diante.
Definição de Pronto F1: o proxy resolve CORS com cache e resiliência; cada leitura bem-sucedida fica persistida no banco e a página nunca depende da origem continuar no ar; o parser tolera campo desconhecido, campo ausente e parciais extras, e sinaliza divergência estrutural com fallback genérico; os cinco endpoints de leitura respondem com dados reais do evento de teste, servidos do banco; o cruzamento por numeral está validado contra os JSON reais.
Fase F2, Página pública e site da vertical Series (Onda 2: PUB e REGRA)
Dependência: Fase F1. As regras de interpretação (REGRA) são implementadas junto com a exibição, porque moldam o que a página mostra. Ficha completa das regras no Ap.2 do DRS. Esta fase entrega o primeiro site de vertical completo (Series), servindo de referência para F4, F5 e F6.
RF-REGRA-001 a 006. Aplicar valor ausente, posição nula, prólogo fora do acumulado, abandono e teto, horários de auditoria e oculto na origem.
O que implementar: camada de interpretação que trata " *" como traço, posIx nulo como oculto, prólogo (ss0) fora do acumulado, 9000.00/27000.00 como "Não completou", L/C decimais como auditoria, _status=O como não exibido.
Como verificar (teste primeiro): cada regra é conferida contra os exemplos de JSON reais; o comportamento bate com o Ap.2 do DRS.
Aceite (H1): Dado os dados reais do evento de teste, Quando a página os interpreta, Então cada uma das seis regras se comporta como no Ap.2 do DRS (traço no valor ausente, posição nula oculta, prólogo fora do acumulado, "Não completou" para abandono e teto, auditoria interpretada, oculto na origem removido).
RF-PUB-011. Barra na cor da marca, logotipo oficial, navegação e selo "Ao Vivo" pulsante quando ao vivo.
O que implementar: cabeçalho que reproduz a identidade do site (Ap.5), com o selo de estado ligado ao estado do evento.
Como verificar (teste primeiro): num evento ao vivo o selo pulsa; num evento encerrado o selo não pulsa.
Aceite (H1): Dado um evento ao vivo, Quando o público abre a página, Então o cabeçalho exibe a barra na cor da marca, o logotipo do Sertões, a navegação e o selo "Ao Vivo" pulsante; Quando encerrado, o selo não pulsa.
RF-PUB-012, RF-PUB-003, RF-PUB-005. Nome e subtítulo do evento, abas de modalidade com contador, faixa de etapas com distância e estado, indicador "atualizado há X".
O que implementar: o hero do Ap.5, com as abas trocando a modalidade exibida e a faixa de etapas selecionando o trecho.
Como verificar (teste primeiro): trocar de aba muda a modalidade exibida; selecionar um trecho na faixa muda a tabela; o indicador de frescor aparece.
Aceite (H1): Dado um evento publicado, Quando o público abre a página, Então o hero mostra nome, subtítulo, abas de modalidade com contador, faixa de etapas com nome, distância e estado (incluindo Prólogo) e o indicador "atualizado há X"; Quando troca de aba, a página reflete aquela modalidade.
Nota (2026-07-04): hero SSR 100% no ar, incluindo a reação de troca de aba e de trecho: com os filtros de F2-06 no ar, selecionar uma aba de modalidade ou um trecho da faixa reflete no recorte exibido (classificação, pódio e trechos), fechando a 2ª sentença do H1.
RF-PUB-001, RF-REGRA-004. Tabela no desktop e cartões no celular, com as colunas na ordem do Ap.5; "Não completou" para abandono e teto; a coluna Tripulação exibe conforme a regra da vertical (piloto e navegador em destaque no rally).
O que implementar: a tabela com Posição, Numeral, Tripulação, Equipe e Veículo, Categoria, Penalidades, Tempo total, Diferença; no celular vira cartão; o texto da tripulação é montado por um formatador que lê regra_tripulacao do perfil da vertical (RF-CONFIG-001) e no caso da Series aplica piloto em destaque e navegador.
Como verificar (teste primeiro): no celular cada competidor é um cartão legível; no desktop as colunas aparecem na ordem do Ap.5; abandono exibe "Não completou"; a tripulação aparece no formato piloto e navegador.
Aceite (H1): Dado um evento com classificação, Quando o público abre no celular, Então cada competidor é um cartão com todos os campos; no desktop os mesmos dados em tabela na ordem do Ap.5; quem abandonou ou atingiu o teto exibe "Não completou"; E a tripulação é exibida conforme a regra da vertical do evento.
Notas: o formatador de tripulação é construído genérico (piloto_navegador / dupla / solo) nesta fase para já sustentar F5 e F6 sem retrabalho, mesmo que só a regra piloto_navegador seja exercitada aqui.
RF-PUB-002. Os cinco primeiros do recorte, em ordem sequencial de 1º a 5º (da esquerda para a direita no desktop, de cima para baixo no celular), cada lugar com posição, numeral, tripulação (conforme regra da vertical), equipe, tempo total e diferença.
O que implementar: o pódio do Ap.5, refletindo o recorte selecionado (geral, categoria ou etapa), sempre na ordem sequencial 1 a 5, inclusive no celular (não a disposição clássica 2, 1, 3); reusa o formatador de tripulação de F2-04.
Como verificar (teste primeiro): num recorte com cinco ou mais competidores, o pódio mostra os cinco primeiros na ordem sequencial de 1 a 5 com todos os campos, no desktop e no celular; com menos de cinco, mostra os que houver na mesma ordem.
Aceite (H1): Dado um recorte com ao menos cinco competidores, Quando o público vê o pódio, Então os cinco primeiros aparecem em destaque na ordem sequencial de 1º a 5º, cada lugar exibindo posição, numeral, tripulação, equipe, tempo total e diferença, coerente com o recorte selecionado; Quando o recorte tem menos de cinco competidores, o pódio mostra os que houver, na mesma ordem.
RF-PUB-003, RF-PUB-004, RF-PUB-005, RF-API-005. Filtrar por modalidade, categoria (com ranking recalculado) e alternar geral por trecho.
O que implementar: os filtros que recortam classificação, pódio e trechos; ao selecionar uma categoria, a lista usa o endpoint de classificação por categoria (F1-12) e exibe a posição renumerada de 1 em diante dentro da categoria, não a posição da classificação geral.
Como verificar (teste primeiro): cada filtro recorta a exibição corretamente; selecionar uma categoria mostra só os competidores dela com posições renumeradas a partir de 1; selecionar Geral volta ao acumulado.
Aceite (H1): Dado um evento com mais de uma modalidade e categorias, Quando o público seleciona modalidade, categoria ou trecho, Então a classificação, o pódio e os trechos passam a refletir o recorte, E ao selecionar uma categoria a lista mostra apenas os competidores dela ordenados entre si com a posição renumerada de 1 em diante; ao selecionar Geral, volta ao acumulado.
RF-PUB-006, RF-PUB-013. Localizar competidor pelo numeral e exibir o contador do recorte ativo.
O que implementar: busca por numeral que destaca ou filtra o competidor; contador que reflete a quantidade exibida.
Como verificar (teste primeiro): buscar um numeral destaca o competidor; aplicar ou limpar filtro atualiza o contador.
Aceite (H1): Dado um competidor de numeral X, Quando o público busca por X, Então a tabela destaca ou filtra esse competidor; Quando aplica ou limpa um filtro, o contador reflete a quantidade exibida no recorte ativo.
RF-PUB-007, RF-REGRA-002. Ao tocar um competidor, abrir o detalhe com identificação, desempenho por especial (SS1 a SSN) e, quando há trecho selecionado, as parciais I1 a I7 (ou mais, ver F1-06).
O que implementar: o modal do Ap.5, com equipe, veículo, categoria, posição, penalidades, tempo total, tempo por especial e parciais (ocultando posIx nulo).
Como verificar (teste primeiro): abrir o detalhe mostra os dados por especial; com trecho selecionado, mostra as parciais sem as posições nulas; fecha sem recarregar.
Aceite (H1): Dado um competidor da classificação, Quando o público abre o detalhe, Então o modal mostra equipe, veículo, categoria, posição, penalidades, tempo total e tempo por especial SS1 a SSN; com trecho selecionado, mostra I1 a I7 com deltas e posições, ocultando as parciais sem posição, E fecha sem recarregar a página.
RF-PUB-008. Botões de download dos PDFs do evento; estado vazio sem erro quando não há documentos.
O que implementar: a central que lista os PDFs publicados pelo operador como botões com título e link; ausência não aparece.
Como verificar (teste primeiro): com PDFs publicados, cada um aparece como botão funcional; sem PDFs, a central mostra estado vazio.
Aceite (H1): Dado um evento com documentos publicados, Quando o público abre a central, Então cada documento aparece como botão de download com título e link funcional, E se não houver documentos, exibe estado vazio sem erro.
RF-PUB-008 (revisado), RF-PUB-009. Mover a Central de Documentos Oficiais do fim da página para uma barra compacta logo abaixo da faixa de etapas, antes do pódio e dos filtros; container sempre emitido (mesmo vazio) para que o refresh suave o preencha sem F5.
O que implementar: renderDocumentosBarra em src/lib/render-documents.ts; container #docbar entre o hero e o .wrap em render-page.ts; 5ª troca em public/assets/live-refresh.js; .docbar:empty{display:none} sem espaço/quebra de linha dentro do template; remoção de renderDocumentos() (código morto) e da chave evento.docs_vazio do catálogo (RF-CONFIG-006, agora 39 chaves).
Como verificar (teste primeiro): test/render-documents.test.ts (vazio = string vazia, ordem, escape, hostil isolado) e test/pages-route.test.ts (posição antes do <table class="res">, ausência quando 0 documentos, publicação ao vivo aparece no ciclo seguinte sem F5); suíte completa 1265/1265.
Aceite (H1): Dado um evento com documentos publicados, Quando o público abre a página, Então a barra aparece antes do pódio e dos filtros; Quando não há nenhum documento, Então a barra não aparece mas o container permanece vazio no HTML; E quando um documento é publicado ao vivo, o chip aparece no próximo ciclo do refresh sem recarregar.
RF-PUB-009. Indicar ao vivo ou encerrado e atualizar os dados automaticamente enquanto ao vivo.
O que implementar: consulta periódica do front (cerca de 30 segundos) enquanto ao vivo; indicador de estado; parada da atualização ao encerrar (coerente com RF-PAINEL-009: encerrar é o operador parar de buscar a origem, não apagar nada).
Como verificar (teste primeiro): num evento ao vivo os dados se atualizam sozinhos e o indicador diz "ao vivo"; ao encerrar, a atualização para e o indicador muda.
Aceite (H1): Dado um evento ao vivo, Quando o público permanece na página, Então os dados se atualizam a cada cerca de 30 segundos e um indicador "ao vivo" é exibido; Quando encerrado, o indicador muda para "encerrado" e a atualização para.
RF-PUB-010. Aplicar a cor e a marca da vertical Series sobre o tema escuro comum, conforme a configuração (Ap.4).
O que implementar: a cor de destaque vinda da config aplicada a realces, pódio, abas e estados ativos; o mecanismo lê o perfil da vertical (RF-CONFIG-001), não uma cor fixa em código, para já sustentar as demais verticais em F4, F5 e F6.
Como verificar (teste primeiro): um evento Series exibe o laranja oficial #E96409 da vertical; trocar a config muda a cor sem novo deploy.
Aceite (H1): Dado um evento da vertical Series, Quando o público abre a página, Então a cor de destaque é o laranja vivo da vertical sobre fundo escuro, conforme Ap.4, E a cor vem da configuração da vertical, não de um valor fixo no código.
RF-PUB-014. Crédito de cronometragem e de desenvolvimento no rodapé.
O que implementar: rodapé com "Cronometragem por Chronosat" e "Desenvolvido por Modulareasy".
Como verificar (teste primeiro): o rodapé exibe os dois créditos ao fim da página.
Aceite (H1): Dado qualquer página de resultados publicada, Quando o público chega ao fim, Então o rodapé exibe "Cronometragem por Chronosat" e "Desenvolvido por Modulareasy".
RF-PUB-015. A home em /series é a capa do site do esporte: hero com a identidade e a capa do perfil da vertical, o evento ao vivo em destaque quando houver, e o arquivo das edições por ano (como o índice de um blog), cada uma levando à sua página fixa em /series/<ano>/<evento>.
O que implementar: a página inicial da vertical, que lê os eventos configurados daquela vertical (RF-CONFIG-002) e monta a capa (hero_titulo, hero_subtitulo, hero_imagem do perfil) mais a lista por ano, com o link para cada endereço permanente (RF-CONFIG-005), destacando o evento ao vivo; o mecanismo é construído por vertical (não fixo para Series) para já sustentar F4, F5 e F6.
Como verificar (teste primeiro): com um evento ao vivo e um evento arquivado cadastrados na vertical Series, a home da vertical lista os dois, cada um levando à sua página fixa, o ao vivo aparece sinalizado, e nenhuma outra vertical aparece nessa home.
Aceite (H1): Dado uma vertical com um ou mais eventos publicados (ao vivo ou arquivados), Quando o público abre a home da vertical, Então vê a capa com a identidade do esporte, o evento ao vivo sinalizado em destaque quando houver, e a lista das edições por ano, e ao escolher uma é levado à página daquele evento, E nenhuma outra vertical aparece nessa home.
RF-REGRA-006. Competidor marcado como oculto na origem pela Chronosat (_status="O") não aparece na página pública. Reconcilia um gap declarado: a regra já existia pronta na biblioteca (F2-01) mas não estava ligada nas rotas.
O que implementar: chamar o filtro de ocultação por origem no caminho público, antes do filtro de ocultação manual do operador (canal ortogonal, F3-08), lendo tanto o crews quanto o racetimes (a Chronosat carimba o _status nas duas formas); a leitura de dados do operador segue intocada (o painel continua vendo o competidor).
Como verificar (teste primeiro): um evento com um competidor marcado _status="O" na origem não mostra esse competidor no pódio, na tabela, no contador, na busca nem nos modais, e os demais aparecem normalmente; o operador ainda o vê no painel.
Aceite (H1): Dado um competidor com _status igual a "O", Quando a classificação pública é montada, Então esse competidor não aparece na página pública, E os demais aparecem normalmente, E a ocultação manual do operador continua funcionando de forma independente.
RF-REGRA-006 (superfície da API), RF-API-001/002/003/005. A mesma regra da F2-14, agora também na API interna de leitura (/api/events), que servia os mesmos dados de classificação sem o filtro e expunha o competidor oculto no JSON (constatado pelo teste de aceitação da F2-14).
O que implementar: aplicar o mesmo filtro de ocultação por origem do caminho público nos endpoints da API que listam ou detalham competidor (classificação geral, por trecho, por categoria e detalhe do competidor); os metadados do evento (/meta, RF-API-004) não listam competidor e não são afetados; a leitura autenticada do operador segue intocada.
Como verificar (teste primeiro): semeando um competidor com _status="O", os endpoints de classificação da API não o trazem no JSON e o detalhe dele responde não encontrado; os demais competidores aparecem normalmente e o /meta segue completo.
Aceite (H1): Dado um competidor com _status igual a "O", Quando a classificação é montada na API interna de leitura, Então esse competidor não aparece em nenhum endpoint público de lista ou detalhe da API, E os demais aparecem normalmente, E os metadados do evento seguem completos.
RF-PUB-004. Corrige o filtro de categoria sendo ignorado quando um trecho está selecionado (defeito constatado no evento MTB Ibitipoca 2026); o H1 do RF-PUB-004 já exigia a combinação categoria dentro do trecho.
O que implementar: no ramo de trecho da rota pública, quando há categoria selecionada, filtrar a lista de competidores pela categoria (função única filtrarPorCategoria, mesma fonte de verdade do filtro Geral) antes de montar a classificação do trecho, sem reatribuir a lista completa usada pelo hero, pelas abas de modalidade, pelos modais e pela classificação Geral do modal.
Como verificar (teste primeiro): ?trecho=N&cat=X mostra só os competidores daquela categoria naquele trecho, com posição renumerada de 1 e pódio da categoria; sem categoria, o trecho segue mostrando todos; categoria sem ninguém naquele trecho mostra tabela vazia sem erro.
Aceite (H1): Dado um evento com trecho e categoria selecionados juntos, Quando o público filtra por categoria com um trecho ativo, Então a lista mostra só os competidores da categoria naquele trecho, com posição renumerada de 1 e o pódio refletindo os cinco primeiros da categoria, E os demais filtros e o modal (posição Geral) seguem intactos.
Prova: gate .claude/gates/plan/categoria-no-trecho-e-parciais-toggle.gate (planner, APPROVED); suite completa 1272 de 1272 (test/pages-route.test.ts, test/category-classification.test.ts, test/stage-classification.test.ts), medida diretamente antes desta publicação.
Definição de Pronto F2: o site da vertical Series reproduz o protótipo aprovado (Ap.5) em celular e desktop, com as seis regras de interpretação aplicadas, atualização automática ao vivo, identidade da vertical vinda da configuração (não fixa em código), a tripulação exibida pela regra da vertical, e a home da vertical funcionando como arquivo por ano; smoke visual real feito tela a tela.
Fase F3, Painel único de gestão (Onda 3: PAINEL e CONFIG)
Dependência: Fase F1. Esta fase entrega o painel que administra todas as verticais, e o perfil completo de vertical que F2 já consumia parcialmente (cor) passa a ser editável por inteiro. Inclui a sub-sequência de contas nominais com papel (F3-13 a F3-16), evolução do acesso de login único para administrador e operador nominais, com gestão de contas e auditoria.
RF-PAINEL-001 (primeira versão), RNF-SEG-001. Acesso ao painel só mediante autenticação; público barrado.
O que implementar: login com credencial única e barreira nas rotas do painel.
Como verificar (teste primeiro): quem tem a credencial entra; visitante sem credencial é barrado numa rota do painel.
Aceite (H1): Dado quem tem a credencial válida, Quando faz login, Então acessa as telas de gestão; Quando um visitante sem credencial tenta uma rota do painel, Então é barrado.
Nota: entregue como login único. Evolui para contas nominais com papel na sub-sequência F3-13 a F3-16 (ADR-011 revisado); a barreira das rotas continua valendo, o que muda é a credencial única virar contas nominais.
RF-CONFIG-001. Manter as verticais com o perfil completo do site de cada uma, editável: cor de destaque, marca, capa da home (hero_titulo, hero_subtitulo, hero_imagem), rótulos da hierarquia (modalidade, categoria, trecho, com valores padrão), regra de exibição da tripulação (piloto e navegador / dupla / solo) e ordem na home global; permitir adicionar uma nova vertical.
O que implementar: tela de verticais com edição de todos os campos do perfil e seleção da regra de tripulação; adicionar vertical sem código (Ap.4, bloco 11).
Como verificar (teste primeiro): editar a cor ou a capa de uma vertical muda a página e a home pública dela sem novo deploy; trocar a regra de tripulação muda o formato exibido na tabela e no pódio (F2-04, F2-05); adicionar uma vertical nova a torna selecionável no assistente (F3-03).
Aceite (H1): Dado o conjunto de verticais, Quando o operador consulta ou ajusta uma vertical, Então vê e edita todos os campos do perfil (cor, marca, capa, rótulos, regra de tripulação, ordem), E a mudança reflete no site daquela vertical sem novo deploy, E uma nova vertical pode ser adicionada sem alteração de código.
RF-PAINEL-002. Escolher a vertical e nomear o campeonato.
O que implementar: primeiro passo do assistente com seleção de vertical (lendo o cadastro de F3-02, incluindo verticais adicionadas depois) e campo de nome; habilita o passo 2.
Como verificar (teste primeiro): selecionar vertical e informar nome registra a vertical (com o seu perfil) e o nome e libera o passo 2.
Aceite (H1): Dado o operador iniciando um campeonato, Quando seleciona a vertical e informa o nome, Então o sistema registra a vertical (com o seu perfil de identidade) e o nome e habilita o passo 2.
RF-PAINEL-003, RF-CONFIG-003. O operador cola de uma vez o bloco de URLs que a Chronosat enviou (o documento de integração do evento inteiro); o sistema extrai e classifica cada URL automaticamente pelo padrão do nome do arquivo, sem o operador separar campo a campo, e testa a conexão com pré-visualização.
O que implementar: um campo único de colagem que recebe o bloco de URLs inteiro; um parser que reconhece cada arquivo pelo padrão do nome {evento}_{modalidade}_{tipo}_{trecho}_{controle}.json e o associa à modalidade, tipo e trecho corretos; botão "testar conexão" que usa o proxy (F1-01) e a verificação de forma (F1-07), e mostra "achei N modalidades, N trechos, N competidores" (ou o aviso de divergência estrutural, se houver); aceita um arquivo de trecho ainda não iniciado (que retorna vazio) e o mantém associado para passar a valer quando o trecho começar; guarda as fontes classificadas por modalidade. As modalidades são totalmente dinâmicas (uma ou várias, em qualquer quantidade, mudam de evento para evento); o rótulo de cada modalidade vem do arquivo crews quando disponível e pode ser confirmado ou ajustado pelo operador, sem lista fixa de modalidades no código.
Como verificar (teste primeiro): colar o bloco de URLs de teste e testar mostra a contagem de modalidades, trechos e competidores, sem o operador preencher campo a campo; uma URL inválida ou inacessível é apontada sem publicar; uma URL de trecho ainda vazio é aceita e não bloqueia o teste; uma URL cujo conteúdo diverge estruturalmente é apontada com o aviso de F1-07.
Aceite (H1): Dado o operador com o bloco de URLs do evento, Quando cola o bloco e aciona "testar conexão", Então o sistema reconhece cada arquivo pelo padrão do nome e o associa à modalidade, tipo e trecho corretos, e exibe a contagem de modalidades, trechos e competidores encontrados; se uma URL for inválida, inacessível ou estruturalmente divergente, exibe o que houve sem publicar; um arquivo de trecho ainda não iniciado (que retorna vazio) é aceito e passa a valer quando o trecho começar.
RF-PAINEL-004. Publicar o campeonato, que passa a aparecer na página pública e na home da vertical correspondente.
O que implementar: resumo e ação de publicar; define o estado inicial (ao vivo ou aguardando); aciona a geração do endereço permanente (F3-12).
Como verificar (teste primeiro): publicar um campeonato de teste o faz aparecer na página pública e na home da vertical certa, no estado inicial configurado.
Aceite (H1): Dado um campeonato com passos 1 e 2 concluídos e teste bem-sucedido, Quando o operador publica, Então o evento fica disponível na página pública da vertical, E o estado inicial é o configurado.
Nota (2026-07-05, S66): o evento publicado aparece de fato na página pública da vertical e como card na home dela ao lado do evento real, sem regressão. Limitação declarada, não bug: o poller de dados (F2-10) ainda é fixo no evento real; um evento novo entra em "aguardando dados" honesto até a F3-06 ligar o poller ao banco.
RF-PAINEL-005, RF-PAINEL-009. Alternar o estado do campeonato; ao marcar como encerrado, o sistema para de buscar a origem e marca o estado salvo no banco como final, sem copiar nada (a persistência contínua de F1-03 já guardou tudo).
O que implementar: alternância de estado que liga e desliga a atualização automática pública e a busca periódica à origem; ao marcar encerrado, apenas atualiza o campo estado do evento (não existe cópia separada de congelamento, ADR-003/ADR-009).
Como verificar (teste primeiro): marcar como encerrado para a busca à origem e a atualização pública, mostra o indicador de encerrado, e a página segue servindo do último estado salvo no banco; simular a origem fora do ar depois disso e confirmar que nada muda para o público; marcar como ao vivo retoma a busca e a atualização.
Aceite (H1): Dado um evento ao vivo com leituras persistidas, Quando o operador o encerra, Então o sistema para de consultar a origem e a página passa a exibir permanentemente o último estado salvo, mesmo depois de a Chronosat retirar os dados da origem, E o evento continua acessível no seu endereço e listado na home da vertical; E se o operador NÃO encerrar antes de a origem sair do ar, o último estado salvo continua sendo servido do mesmo jeito, sem perda.
Notas: este cartão substitui a ideia de "gerar um snapshot ao encerrar": o congelamento é somente parar de buscar, porque o dado já está salvo desde a primeira leitura (F1-03).
RF-PAINEL-006. Adicionar, nomear e remover os PDFs do evento por link ou upload de arquivo, com a arquitetura aberta a outras formas de entrada (por exemplo webhook) sem retrabalho.
O que implementar: tela de PDFs que aceita link e upload de arquivo; título por PDF; reflete na central pública; a gravação do PDF é desacoplada da forma de entrada, de modo que uma nova origem (ex.: recebimento automático por webhook) possa ser acrescentada depois sem mudar o modelo nem a central pública.
Como verificar (teste primeiro): adicionar um PDF por link ou por upload com título o faz aparecer na central pública; removê-lo o tira de lá.
Aceite (H1): Dado um campeonato publicado, Quando o operador adiciona um PDF com título por link ou por upload de arquivo, Então ele aparece na central pública; Quando o remove, deixa de aparecer.
RF-PAINEL-007. Ocultar e reexibir manualmente um competidor.
O que implementar: busca por numeral e alternância de visibilidade, reversível; distinto do oculto pela origem (RF-REGRA-006).
Como verificar (teste primeiro): ocultar um competidor o tira da página pública; reexibir o traz de volta.
Aceite (H1): Dado um competidor exibido, Quando o operador o oculta, Então ele deixa de aparecer na página pública, E pode ser reexibido.
RF-PAINEL-008. Listar os campeonatos com vertical, nome, estado e ações.
O que implementar: a lista com as ações de editar, publicar, alternar estado e gerenciar PDFs.
Como verificar (teste primeiro): com um ou mais campeonatos, a lista mostra vertical, nome, estado e as ações.
Aceite (H1): Dado um ou mais campeonatos, Quando o operador abre o painel, Então vê a lista com vertical, nome, estado (rascunho, ao vivo, encerrado) e as ações de editar, publicar, alternar estado e gerenciar PDFs.
RF-PAINEL-010. O caminho principal do histórico é o arquivamento contínuo: todo evento que o sistema publica fica guardado para sempre (F3-06), do mesmo jeito que um blog acumula posts, e a home da vertical cresce naturalmente a cada evento. O cadastro retroativo é o complemento, para trazer edições anteriores ao início do sistema, quando há dados disponíveis (o bloco de URLs, se a Chronosat ainda os servir, ou os arquivos que a Sertões tenha guardado).
O que implementar: reaproveitar o assistente de cadastro (F3-03 a F3-05) para uma edição passada, marcando-a como já encerrada.
Como verificar (teste primeiro): cadastrar uma edição passada de teste pelo assistente, marcando-a como encerrada, gera a página arquivada no endereço por vertical, ano e evento, e ela aparece na home da vertical junto às demais.
Aceite (H1): Dado o operador com os dados de uma edição passada, Quando cadastra o evento pelo assistente marcando-o como já encerrado, Então a página daquela edição é gerada e arquivada no endereço por vertical, ano e evento, E passa a aparecer na home da vertical junto às demais.
RF-CONFIG-003. Cada evento guarda suas URLs de origem por modalidade e por trecho; as modalidades de um evento são as que ele tiver, em qualquer quantidade, e mudam de um evento para outro.
O que implementar: o armazenamento das fontes classificadas por FONTE (evento, modalidade, tipo, trecho, url), alimentado pelo passo 2 do assistente (F3-04); a leitura de dados (F1) resolve a fonte correta conforme o filtro de modalidade ativo, sem depender de uma lista fixa de modalidades no código.
Como verificar (teste primeiro): um evento de teste com três modalidades guarda as URLs corretamente separadas por modalidade e trecho; a página exibe a modalidade selecionada lendo a fonte certa.
Aceite (H1): Dado um evento com uma ou mais modalidades quaisquer, Quando o operador cadastra as fontes, Então cada modalidade guarda suas URLs de crews, racetimes e stagetimes por trecho, com o seu rótulo, e o sistema lê a fonte correta conforme o filtro de modalidade, sem depender de uma lista fixa de modalidades no código.
RF-CONFIG-005. Cada evento recebe um endereço estável e permanente no padrão resultados.sertoes.com.br/<vertical>/<ano>/<evento> (ex.: /series/2026/sertoes-series-parana), com o nome do evento (o slug) na URL, definido no cadastro e imutável depois de publicado. O slug distingue dois eventos da mesma vertical no mesmo ano.
O que implementar: geração do endereço a partir da vertical, do ano e do slug do evento no momento da publicação (F3-05), com trava para não mudar depois de publicado; validação para que dois eventos da mesma vertical no mesmo ano não colidam no slug; a home da vertical (F2-13) e a home global (F4-03) apontam para esse endereço.
Como verificar (teste primeiro): publicar um evento de teste gera o endereço no padrão vertical, ano e evento; tentar alterá-lo depois de publicado é bloqueado; publicar um segundo evento da mesma vertical no mesmo ano gera um endereço distinto do primeiro.
Aceite (H1): Dado um evento cadastrado, Quando é publicado, Então recebe um endereço permanente no padrão vertical, ano e evento que não muda depois, E a home da vertical e a home global apontam para esse endereço, E dois eventos da mesma vertical no mesmo ano têm endereços distintos.
Entregue (S72 2026-07-06): endereço permanente verificado e travado por teste; imutabilidade estrutural, garantida pela ausência de qualquer caminho de código que mute a identidade do evento após publicado, e confirmada por teste estrutural que varre os módulos em busca desse caminho. Fix pego pelo próprio smoke visual: os links da home da vertical usavam a forma /<vertical>/ com barra final, que retornava 404 no roteador público (/:vertical sem barra); corrigido nos quatro pontos que apontavam para lá (logo, Início, Edições e a trilha de navegação) para a forma canônica sem barra final.
Sub-sequência F3, contas nominais com papel (evolução do ADR-011). Estes quatro cartões trocam o "login único" (credencial única em configuração, entregue em F3-01) por contas nominais com papel, para a equipe da Modulareasy administrar o sistema de forma declarada e auditável. Vêm em ordem: primeiro a entidade e as contas iniciais (F3-13), depois a autenticação passa a ler da tabela e a carregar o papel (F3-14, que substitui a barreira de F3-01 sem removê-la), depois a tela de gestão de contas (F3-15) e a auditoria (F3-16). F3-14 depende de F3-13; F3-15 e F3-16 dependem de F3-14. Não têm dependência com F3-02 a F3-12 e podem ser priorizados como primeira fatia da fila.
RF-PAINEL-001 (revisado), E.1, E.3. Criar a tabela de contas nominais e semear as contas iniciais, sem ainda trocar a autenticação.
O que implementar: entidade USUÁRIO (id, login único, hash_senha, papel enum administrador/operador, ativo, criado_em, atualizado_em) no banco; semear as contas de administrador iniciais da equipe que opera o sistema, cada uma com a sua senha própria hasheada (nunca em texto puro), e migrar o operador existente ("sertoes", hoje credencial única em configuração) para uma conta nominal com papel operador. Nenhuma senha em texto puro no código nem no banco.
Como verificar (teste primeiro): consultar a tabela mostra as contas semeadas com papel e situação corretos e sem senha em texto puro; o login único anterior continua funcionando enquanto F3-14 não entra (nenhuma regressão de acesso).
Aceite (H1): Dado o sistema com login único, Quando a migração roda, Então a tabela de contas existe com as contas de administrador da equipe que opera o sistema e a conta de operador da Sertões, cada uma com senha guardada apenas como hash e papel definido, E nenhuma senha aparece em texto puro em lugar nenhum.
RF-PAINEL-001 (revisado), RNF-SEG-002, RNF-SEG-003, RNF-SEG-005. Trocar a verificação da credencial única (F3-01) por consulta à tabela de contas (F3-13), carregando o papel do usuário na sessão; a barreira das rotas do painel permanece.
O que implementar: o login passa a validar login e senha contra USUÁRIO (comparando o hash), recusa conta desativada, e grava na sessão quem entrou e com qual papel; a barreira das rotas de gestão (já existente em F3-01) continua valendo e passa a distinguir papel para as telas exclusivas do administrador (base para F3-15 e F3-16). Registrar o login e o login negado na auditoria (F3-16) quando ela existir; até lá, deixar o ponto de registro preparado.
Como verificar (teste primeiro): entrar com uma conta de administrador dá acesso e a sessão carrega papel administrador; entrar com a conta de operador dá acesso com papel operador; senha errada ou conta desativada é recusada; visitante sem sessão continua barrado nas rotas do painel.
Aceite (H1): Dado um usuário com conta ativa, Quando entra com login e senha corretos, Então acessa o painel e a sua sessão fica associada ao seu usuário e papel; Quando a senha está errada ou a conta está desativada, Então o acesso é negado; Quando um visitante sem sessão tenta uma rota do painel, Então é barrado.
RF-PAINEL-011. O administrador cria, edita, desativa/reativa contas, define papel e redefine senha; a tela é barrada ao operador.
O que implementar: tela de gestão de contas com lista (login, papel, situação), criar conta (login, papel, senha inicial), editar papel, desativar/reativar, redefinir senha; toda senha informada é guardada só como hash; a rota é acessível apenas ao papel administrador (gate "é administrador?", F3-14); sem autocadastro público. Cada ação registra na auditoria (F3-16).
Como verificar (teste primeiro): um administrador cria uma conta de operador que passa a entrar; muda o papel de uma conta e o acesso muda de acordo; desativa uma conta e ela deixa de entrar sem perder o histórico, e reativa; redefine uma senha e a nova passa a valer; um operador que tenta abrir a tela é barrado.
Aceite (H1): Dado um administrador autenticado, Quando cria, edita o papel, desativa/reativa uma conta ou redefine uma senha, Então a mudança passa a valer no acesso daquela conta sem apagar o histórico; Quando um operador tenta abrir a gestão de contas, Então é barrado; E nenhuma senha é exibida nem guardada em texto puro.
RF-PAINEL-012, RNF-SEG-004. Registrar num log imutável e consultável as ações sensíveis do painel; a consulta é do administrador.
O que implementar: entidade AUDITORIA (usuario_id nulo em login negado, acao, alvo, detalhe sem a senha, registrado_em); gravar nos pontos preparados por F3-14 (login, login negado) e por F3-15 (criar/editar/desativar/reativar conta, mudar papel, redefinir senha); tela de consulta do mais recente ao mais antigo, acessível apenas ao papel administrador; o registro é só escrita e leitura, nunca editável pelo painel.
Como verificar (teste primeiro): executar uma ação sensível grava um registro com quem, o que, sobre o que e quando; a tela de auditoria lista os registros do mais recente ao mais antigo; a redefinição de senha registra a troca sem o valor da senha; um operador que tenta abrir a auditoria é barrado.
Aceite (H1): Dado um administrador que executa uma ação sensível, Quando ela acontece, Então fica gravado um registro imutável com quem fez, o que fez, sobre o que e quando (nunca a senha); Quando o administrador abre a auditoria, Então vê os registros do mais recente ao mais antigo; Quando um operador tenta abrir a auditoria, Então é barrado.
RF-PAINEL-013. Tela de sitemap que lista as rotas das páginas principais do sistema e do site (lista curada, uma rota por área, nunca por evento) e mostra, para cada uma, o código de resposta HTTP do servidor: no ar (200) ou com erro (4xx ou 5xx). Depende do gate de administrador (F3-14) e da moldura do painel; por isso vem depois de F3-16.
O que implementar: uma configuração curada de rotas monitoradas (uma entrada por área: home global quando existir, home de cada vertical, rotas do painel, verificação de saúde e âncoras do site), config-driven (nova vertical ou área é mais uma entrada, não código); uma verificação do lado do servidor que, ao carregar a página e ao acionar "verificar de novo", faz a requisição a cada rota da lista e coleta o código HTTP; a tela lista cada rota com o código, marcando 200 como no ar e 4xx ou 5xx como erro em destaque; a rota é acessível apenas ao papel administrador (gate "é administrador?", F3-14). Sem histórico, gráfico de uptime nem alerta nesta fatia (evolução futura). A verificação nunca lança: uma rota que não responde é reportada como erro, não derruba a página.
Como verificar (teste primeiro): abrir a tela como administrador mostra a lista curada de rotas com um código de status por linha; uma rota no ar aparece com 200; uma rota inexistente ou fora do ar aparece com o código de erro sinalizado; acionar "verificar de novo" reconsulta e atualiza os códigos; a lista não traz nenhuma rota por evento (só as principais curadas); um operador que tenta abrir a tela é barrado.
Aceite (H1): Dado um administrador na tela de monitor de status, Quando a página carrega ou ele aciona "verificar de novo", Então o sistema consulta cada rota da lista curada e exibe o código de resposta HTTP de cada uma (200 no ar, 4xx ou 5xx sinalizado como erro); Quando uma rota está no ar, Então aparece com 200; Quando uma rota responde com erro, Então aparece com o código do erro em destaque; Quando um operador tenta abrir a tela, Então é barrado; E a lista nunca inclui rotas por evento.
RF-CONFIG-006. Os textos fixos das páginas públicas (home global, cabeçalho, rodapé, home de vertical e página do evento) deixam de ser código e passam a ser configuração editável no painel, com remoção e restauração por campo.
O que implementar: catálogo src/config/textos.ts com as 40 chaves em 4 grupos (padrão igual ao literal exato de hoje, paridade 1:1); tabela texto_site (chave, valor, atualizado_em) e repositório src/db/textos.ts (ler, salvar, apagar a linha quando o valor volta ao padrão); renders consultando o texto por uma função t(chave) servida por um store em memória, sem I/O no render; tela /painel/textos (rota comum a operador e administrador, formulário único agrupado, valor atual, padrão como referência, restaurar por campo); auditoria com a ação editar_textos.
Como verificar (teste primeiro): alterar um texto e salvar reflete na página pública no carregamento seguinte, sem reiniciar o sistema; salvar em branco um texto removível apaga o elemento da página; salvar em branco um texto não removível volta ao padrão; restaurar padrão apaga o desvio salvo; a suite completa (1268 de 1268) permanece verde sem enfraquecer nenhuma asserção existente.
Aceite (H1): Dado um operador ou administrador autenticado no painel, Quando altera um texto em "Textos do site" e salva, Então a página pública exibe o novo texto no próximo carregamento sem reinício; Quando salva em branco um texto removível, Então o elemento some da página; E Quando marca "restaurar padrão", Então o texto volta exatamente ao valor de fábrica.
Prova: gates .claude/gates/plan/f3-textos-do-site.gate (planner, APPROVED), .claude/gates/qa/f3-textos-do-site.gate (qa, PASS, 1268/1268 e tsc limpo) e .claude/gates/review/f3-textos-do-site.gate (code-reviewer, APPROVED, check de regressão comparando byte a byte cada render alterado); branch feat/f3-textos-do-site, commit 575fa65, em produção.
RF-PAINEL-014. Amplia a config de colunas ocultáveis do evento (de 10 para 11), incluindo o grupo Parciais (Parc 1 a N, exclusivo do recorte de Trecho), fora da auto-ocultação por vazio (junto de Penalidades e Bônus) para não piscar durante o evento ao vivo.
O que implementar: incluir parc em COLUNAS_OCULTAVEIS (11o checkbox do hub, entre Largada e Chegada) e excluir de COLUNAS_AUTO_OCULTAVEIS; ajustar o seletor de visualização para não oferecer o preset "Parciais" e usar "completo" como padrão quando o grupo está oculto; eventos já salvos (CSV sem parc) nascem com o checkbox marcado (visível), sem mudar comportamento existente.
Como verificar (teste primeiro): hub mostra 11 checkboxes; desmarcar Parciais some o grupo Parc 1..N da tabela de Trecho; Parciais vazia no ao vivo não some sozinha; com Parciais oculta, o seletor de visualização não mostra o preset "Parciais" e abre em "completo".
Aceite (H1): Dado um evento, Quando o operador desmarca Parciais no hub, Então o grupo Parc 1..N some da tabela pública de Trecho e o preset "Parciais" some do seletor de visualização (padrão "completo"); Quando Parciais está vazia mas marcada, Então continua visível (nunca auto-oculta); E eventos existentes sem a coluna configurada nascem com Parciais visível.
Prova: gate .claude/gates/plan/categoria-no-trecho-e-parciais-toggle.gate (planner, APPROVED); suite completa 1272 de 1272 (test/render-table-colunas-ocultas.test.ts, test/render-table-auto-ocultar-vazias.test.ts, test/eventos-colunas-route.test.ts), medida diretamente antes desta publicação.
Definição de Pronto F3: um operador não técnico cadastra e publica um campeonato sozinho pelo assistente de três passos (colando o bloco de URLs de uma vez, com extração e classificação automática), com teste de conexão que também sinaliza divergência estrutural, e opera estado, PDFs (link e upload, arquitetura aberta a outras entradas) e ocultação; encerrar é apenas parar de buscar a origem, porque cada leitura já ficou salva desde o início; cada evento tem endereço permanente por vertical, ano e evento; o perfil completo de cada vertical (cor, marca, capa, rótulos, regra de tripulação, ordem) é editável no painel. O acesso é por conta nominal com papel: administrador (equipe Modulareasy) e operador (equipe Sertões) entram cada um com a sua credencial; o administrador cria e mantém contas, define papel, redefine senha, desativa/reativa, e consulta o log de auditoria das ações sensíveis, tudo declarado e rastreável.
Fase F4, Vertical Petrobras por configuração e home global (Onda 4)
Dependência: Fases F2 e F3. Esta fase prova o modelo multisite (RF-CONFIG-004): uma vertical nova nasce só como configuração, sem tocar código. Se algo aqui exigir código além do perfil (RF-CONFIG-001) e do cadastro de evento, é um sinal de que F2/F3 embutiram algo fixo da Series que deveria estar na configuração, e o achado deve ser corrigido na fonte antes de prosseguir para F5.
RF-CONFIG-002. Suportar o evento vigente de cada vertical de forma independente.
O que implementar: cada vertical exibe seu próprio evento publicado sem interferência entre elas (mecanismo já usado por F3-11; este cartão valida com duas verticais simultâneas).
Como verificar (teste primeiro): publicar um evento em Series e outro em Petrobras e abrir cada página mostra o evento certo com a identidade certa.
Aceite (H1): Dado um evento publicado em uma vertical e outro em outra, Quando o público abre cada vertical, Então cada uma exibe seu próprio evento com sua identidade, sem interferência.
RF-CONFIG-004, ADR-010. Cadastrar a vertical Sertões Petrobras com o seu perfil completo (marca própria e o mesmo laranja oficial da Series, RF-CONFIG-001) e publicar um evento dela, sem nenhuma alteração ou cópia de código.
O que implementar: usar exclusivamente as telas de F3-02 (cadastro de vertical) e F3-03 a F3-05 (assistente de evento) para criar a vertical Petrobras com seus logos e cores próprios (extraídos da midiateca dos sites da Sertões, ver Ap.4 do DRS) e publicar um evento de teste dela.
Como verificar (teste primeiro): cadastrar a vertical Petrobras pelo painel (sem deploy) e publicar um evento gera o site /petrobras com identidade, home e evento funcionando, idêntico em mecânica ao site Series mas com a marca própria; nenhuma linha de código foi alterada para isso.
Aceite (H1): Dado o motor no ar com a vertical Series publicada, Quando o operador cadastra a vertical Petrobras com o seu perfil e um evento dela, Então o site da vertical Petrobras fica no ar com identidade, home e eventos próprios, E nenhuma linha de código foi alterada nem copiada para isso.
RF-PUB-016. A raiz do subdomínio de resultados apresenta os sites das verticais (nome, marca e cor de cada uma) e leva à home de cada esporte, sem misturar classificações ou eventos de esportes diferentes.
O que implementar: a página raiz que lista as verticais cadastradas (lendo ordem_home do perfil de cada uma, RF-CONFIG-001) com link para a home de cada vertical (F2-13).
Como verificar (teste primeiro): com Series e Petrobras cadastradas, a raiz lista as duas na ordem configurada, cada uma levando à sua home; nenhuma classificação aparece na home global.
Aceite (H1): Dado o subdomínio publicado com uma ou mais verticais, Quando o público abre a raiz, Então vê a lista dos sites das verticais na ordem configurada e, ao escolher um, é levado à home daquela vertical.
RNF-COMP-001, RF-CONFIG-005, F.2, ADR-008. A página de resultados fica publicada no subdomínio próprio (resultados.sertoes.com.br), autônoma, e as páginas de cada vertical no site institucional apenas vinculam (linkam) para ela; não há incorporação (embed).
O que implementar: publicar o front no subdomínio de resultados; adicionar, nas páginas de vertical do site institucional, o link para a home da vertical correspondente (F2-13) ou para o endereço permanente do evento (F3-12).
Como verificar (teste primeiro): a página de resultados abre de forma independente no subdomínio, com todo o conteúdo, sem depender do hosting do site institucional; a página da vertical no site institucional leva até ela pelo link.
Aceite (H1): Dado um evento publicado no subdomínio de resultados, Quando o público acessa a página de uma vertical no site institucional, Então encontra o vínculo para a página de resultados, E ao acessá-la ela funciona de forma autônoma, com todo o conteúdo, sem incorporação.
RNF-PERF-001, RNF-PERF-002, RNF-ESC-001. Garantir que a página aguenta o pico ao vivo servindo do banco e do cache, sem sobrecarregar a origem, com duas ou mais verticais publicadas simultaneamente.
O que implementar: afinar o cache de borda e a janela do proxy; validar sob carga com o evento de teste em mais de uma vertical ao mesmo tempo.
Como verificar (teste primeiro): sob carga simulada de pico em duas verticais, a primeira tela carrega rápido no celular e a origem é chamada no máximo uma vez por minuto por arquivo, em cada vertical.
Aceite (H1): Dado o pico de acessos ao vivo em mais de uma vertical, Quando o público carrega a página no celular, Então a primeira tela útil carrega rápido servida do banco e do cache, E o servidor de origem é chamado no máximo uma vez por minuto por arquivo.
Definição de Pronto F4: a vertical Petrobras nasce e opera só por configuração, sem alteração de código, provando o modelo multisite; a home global lista as verticais sem misturar dados entre elas; o subdomínio funciona de forma autônoma vinculado a partir do site institucional; o sistema aguenta o pico de acessos ao vivo com duas verticais simultâneas.
Fase F5, Vertical MTB, Bike (Onda 5)
Dependência: Fase F4 apenas. Nada é aguardado de terceiros: a construção usa os dados reais já em mãos (rally) e a vertical MTB é ativada quando o primeiro pacote real da Bike chegar, validado no próprio teste de conexão do cadastro. Risco real mapeado no DRS (J.1): a dupla de bikers pode vir com dois numerais (um por atleta) ou com estrutura de prova diferente do rally; a tolerância de esquema garante exibição útil imediata e o ajuste fino entra como adaptador contido.
DRS J.1 (Onda 5), ADR-012. A validação dos dados da Bike acontece no momento da ativação da vertical, com o primeiro pacote real (URLs ou arquivos), usando o mecanismo de tolerância de esquema e detecção de divergência já construído (F1-06, F1-07). Nenhum arquivo de exemplo é pré-requisito nem é aguardado antes.
O que implementar: nada novo; rodar o teste de conexão (F3-04) com o primeiro pacote real da Bike. Se a estrutura bater com o contrato conhecido (um numeral por tripulação, mesmos três tipos de arquivo), seguir direto para F5-01; se divergir (dois numerais por dupla, ou estrutura de prova diferente), a página já exibe o fallback genérico útil e o adaptador contido (ADR-012) entra na sequência.
Como verificar (teste primeiro): o teste de conexão roda contra o primeiro pacote real da Bike e reporta match ou a divergência exata, sem quebrar e sem bloquear o armazenamento.
Aceite (H1): Dado o primeiro pacote real de um evento de MTB, Quando o teste de conexão é executado, Então o sistema reporta se a estrutura bate com o contrato conhecido ou exatamente o que diverge, E os dados são armazenados e exibidos de forma útil em qualquer um dos dois casos (renderização plena no match, fallback genérico sinalizado na divergência).
Notas: se houver divergência (dois numerais por dupla), o adaptador entra no módulo de ingestão (ADR-012), pequeno e contido, sem tocar no resto do sistema, como refinamento da exibição, não como desbloqueio.
RF-CONFIG-001, RF-CONFIG-004. Cadastrar a vertical Sertões MTB com o seu perfil (rosa oficial #E40E7F, marca, capa, rótulos) e a regra de exibição de tripulação dupla (os dois nomes em negrito, sem destaque de um sobre o outro).
O que implementar: usar as telas de F3-02 e o assistente (F3-03 a F3-05) para criar a vertical MTB; confirmar que o formatador de tripulação (F2-04, F2-05), já construído genérico, produz a exibição em dupla sem código novo.
Como verificar (teste primeiro): cadastrar a vertical MTB e publicar um evento de teste (com os dados validados no gate) mostra a tabela e o pódio com os dois nomes da dupla em negrito, sem um piloto em destaque sobre o outro.
Aceite (H1): Dado a vertical MTB cadastrada com regra de tripulação dupla, Quando o público abre a página de um evento de MTB, Então a tabela e o pódio exibem os dois nomes da dupla em negrito, conforme Ap.4, E o site da vertical tem identidade, home e evento próprios sem alteração de código.
DRS bloco 8. Validar a página completa da vertical MTB (classificação, pódio, filtros, parciais, downloads, identidade) contra os dados reais ou de exemplo validados no gate.
O que implementar: não aplicável (validação, não construção); usar o mesmo conjunto de telas de F2, já genéricas por vertical.
Como verificar (teste primeiro): abrir a página de MTB no celular e no desktop e conferir tela a tela contra os dados reais de um evento de Bike.
Aceite (H1): Dado um evento de MTB publicado com dados reais ou validados, Quando a página é percorrida tela a tela em celular e desktop, Então todas as seções do Ap.5 funcionam com a identidade e a regra de tripulação da vertical MTB, sem elemento quebrado.
Definição de Pronto F5: o primeiro pacote real da Bike foi validado no teste de conexão e seu resultado registrado (renderização plena no match, ou fallback útil mais adaptador contido na divergência); a vertical MTB opera por configuração com a regra de tripulação dupla; o smoke visual tela a tela passou com os dados reais de um evento de Bike.
Fase F6, Vertical Kitesurf (Onda 6)
Dependência: Fase F4 apenas. Nada é aguardado de terceiros: a vertical Kitesurf é ativada quando o primeiro pacote real do Kite chegar, validado no próprio teste de conexão do cadastro. Referência observada na página de resultados atual do kite da Sertões: classificação final por PONTOS somados por etapa (Geral mais Etapas 1 a 4), com divisões como Pro e Elite, Adventure Master e Jr, e Open; o acumulado do Kite tende a ser pontuação, não tempo, e o sistema exibe a métrica que o payload entregar (renderização orientada a dados, ADR-012).
DRS J.1 (Onda 6), ADR-012. A validação dos dados do Kite acontece no momento da ativação da vertical, com o primeiro pacote real (URLs ou arquivos), usando o mecanismo de tolerância de esquema e detecção de divergência já construído (F1-06, F1-07). Nenhum arquivo de exemplo é pré-requisito nem é aguardado antes.
O que implementar: nada novo; rodar o teste de conexão (F3-04) com o primeiro pacote real do Kite. Se a estrutura bater com o contrato conhecido (trechos), seguir direto para F6-01; se divergir (baterias em vez de trechos, classificação por pontos), a página já exibe o fallback genérico útil e o adaptador contido (ADR-012) entra na sequência, exibindo a métrica que o payload trouxer (pontos ou tempos).
Como verificar (teste primeiro): o teste de conexão roda contra o primeiro pacote real do Kite e reporta match ou a divergência exata, sem quebrar e sem bloquear o armazenamento.
Aceite (H1): Dado o primeiro pacote real de um evento de Kitesurf, Quando o teste de conexão é executado, Então o sistema reporta se a estrutura bate com o contrato conhecido ou exatamente o que diverge, E os dados são armazenados e exibidos de forma útil em qualquer um dos dois casos (renderização plena no match, fallback genérico sinalizado na divergência).
Notas: se houver divergência (baterias ou pontos), o adaptador entra no módulo de ingestão (ADR-012), pequeno e contido, sem tocar no resto do sistema, como refinamento da exibição, não como desbloqueio.
RF-CONFIG-001, RF-CONFIG-004. Cadastrar a vertical Sertões Kitesurf com o seu perfil (verde oficial #88BD23, marca, capa, rótulos ajustados à hierarquia do Kite) e a regra de exibição de tripulação solo (um único atleta, sem par).
O que implementar: usar as telas de F3-02 e o assistente (F3-03 a F3-05) para criar a vertical Kitesurf, incluindo as modalidades Kite e Wing com suas categorias (lidas dinamicamente, F3-11); confirmar que o formatador de tripulação produz a exibição solo sem código novo.
Como verificar (teste primeiro): cadastrar a vertical Kitesurf e publicar um evento de teste (com os dados validados no gate) mostra a tabela e o pódio com um único atleta por linha, nas modalidades Kite e Wing.
Aceite (H1): Dado a vertical Kitesurf cadastrada com regra de tripulação solo, Quando o público abre a página de um evento de Kitesurf, Então a tabela e o pódio exibem um único atleta por competidor, conforme Ap.4, E as modalidades Kite e Wing com suas categorias aparecem corretamente, E o site da vertical tem identidade, home e evento próprios sem alteração de código.
DRS bloco 8. Validar a página completa da vertical Kitesurf (classificação, pódio, filtros, downloads, identidade) contra os dados reais ou de exemplo validados no gate.
O que implementar: não aplicável (validação, não construção); usar o mesmo conjunto de telas de F2, já genéricas por vertical.
Como verificar (teste primeiro): abrir a página de Kitesurf no celular e no desktop e conferir tela a tela contra os dados reais de um evento de Kite.
Aceite (H1): Dado um evento de Kitesurf publicado com dados reais ou validados, Quando a página é percorrida tela a tela em celular e desktop, Então todas as seções aplicáveis do Ap.5 funcionam com a identidade e a regra de tripulação da vertical Kitesurf, sem elemento quebrado.
Definição de Pronto F6: o primeiro pacote real do Kite foi validado no teste de conexão e seu resultado registrado (renderização plena no match, ou fallback útil mais adaptador contido na divergência, exibindo a métrica que o payload trouxer, pontos ou tempos); a vertical Kitesurf opera por configuração com a regra de tripulação solo e a hierarquia Kite/Wing; o smoke visual tela a tela passou com os dados reais de um evento de Kitesurf.
Onda PET, Plantão do Sertões Petrobras 2026 (evento ao vivo)
Nasceu durante o primeiro evento grande no ar (21 a 26 de agosto de 2026), com a cronometragem e a organização olhando a página em tempo real. Cada cartão aqui veio de um relato do cliente durante a prova, não de um planejamento prévio, por isso a onda é registrada depois, com os cartões já entregues, para que o roadmap continue sendo a verdade do que existe. Todos foram medidos no dado real do evento antes de qualquer linha ser escrita, e verificados no ar contra a tabela oficial da própria Chronosat. Três cartões (PET-05, PET-06, PET-07) trouxeram informação que a página nunca tinha exibido; os demais corrigiram exibição ou precisão. Nenhum exigiu mudança de arquitetura: todos entraram pelo motor único e valem para as quatro verticais.
RF-API-001, RF-API-002, RF-API-005. A Chronosat pode publicar tempoTotal negativo quando a cronometragem sai inconsistente (chegada carimbada antes da largada) ou quando um bônus é aplicado antes de a especial fechar.
O que implementar: as três libs de classificação (geral, categoria e trecho) passam a tratar duração negativa como não-classificável, do mesmo modo que já tratam a ausente. O critério é único e explícito: o que a exibição não mostra como duração, a ordenação não trata como tempo. O data-v das células de duração segue o mesmo critério, senão o primeiro clique do público no cabeçalho refaz o defeito.
Como verificar (teste primeiro): um competidor com tempoTotal negativo aparece depois de todos os que têm tempo válido, e a célula continua mostrando o traço, sem sumir da lista.
Aceite (H1): Dado um competidor cujo tempo veio negativo da origem, Quando a classificação é montada em qualquer recorte, Então ele não assume a liderança nem entra no pódio, E a sua linha continua visível com o traço na coluna de tempo.
RF-REGRA-004, RF-API-001, RF-API-005. Enquanto o dia corre, a origem manda tempoTotal=999999 para todos; o código lia esse número como "não largou" e como chave de ordem.
O que implementar: o sentinela passa a significar "sem tempo acumulado", não "não largou": quem tem largada real vira NC (largou, ainda não completou) e só quem não tem sinal de largada segue NL. E, como chave de ordem, o sentinela sai de cena: sem tempo, a lista ordena por horário de LARGADA, que é a ordem em que a prova acontece na estrada e já era a regra do recorte de trecho.
Como verificar (teste primeiro): com o dia em andamento e ninguém com tempo fechado, a lista sai na ordem de largada e não na ordem dos numerais, e quem já largou não aparece como "não largou".
Aceite (H1): Dado um dia em andamento em que ninguém tem tempo acumulado, Quando o público abre a classificação geral, Então os competidores aparecem na ordem em que largaram, E quem já largou não é rotulado como "não largou".
RF-PUB-014. O rodapé trazia uma frase sobre o banco de dados, o crédito da agência sem vínculo e nenhum aviso de direitos.
O que implementar: sai a frase de bastidor (fala da nossa arquitetura para quem veio ver resultado de prova); o crédito de desenvolvimento vira link no padrão que já existe no site do cliente, com UTM para a visita chegar identificada; entra o aviso de direitos do cliente com o ano corrente. Vale para os dois rodapés do sistema, incluindo o da home global, que tem markup próprio.
Como verificar (teste primeiro): o rodapé de uma página de evento, de uma home de vertical e da home global mostram o mesmo conjunto, e o link de crédito leva ao site da agência.
Aceite (H1): Dado qualquer página pública do sistema, Quando o público chega ao fim, Então vê o crédito da cronometragem, o crédito de desenvolvimento como link e o aviso de direitos do cliente, sem nenhuma menção a detalhes internos do sistema.
RF-PUB-002. O número do primeiro colocado era maior que os demais, e como ele abre o cartão, empurrava o conteúdo para baixo e entortava a fileira.
O que implementar: os cinco números passam a ter o mesmo tamanho. A distinção do primeiro lugar continua existindo por cor e pela sombra do cartão, que é como as demais posições já se distinguem.
Como verificar (teste primeiro): os cinco cartões do pódio têm a mesma altura e o conteúdo de cada um começa na mesma linha.
Aceite (H1): Dado o pódio de qualquer recorte, Quando ele é exibido, Então os cinco cartões ficam alinhados entre si, E o primeiro lugar continua distinguível dos demais.
RF-PUB-004, RF-PAINEL-013, RF-CONFIG-001, ADR-012. A cronometragem pediu que a página dissesse em que quilômetro fica cada ponto medido.
O que implementar: a quilometragem aparece no cabeçalho da coluna, embaixo do rótulo (Largada, cada Parc e Chegada), que é onde a pergunta "esse tempo foi medido onde?" é feita, e ali a resposta vale para todas as linhas de uma vez, sobrevive à ordenação e ao filtro. O valor vive em tabela própria por evento, modalidade e ponto, alimentada por uma tela nova do painel (o operador informa a lista de quilômetros na ordem dos pontos, um campo por trecho).
Como verificar (teste primeiro): cadastrar a quilometragem de um trecho pelo painel e abrir a tabela daquele trecho mostra o quilômetro embaixo de cada coluna de ponto; trecho sem quilometragem cadastrada renderiza exatamente como antes.
Aceite (H1): Dado um trecho com a quilometragem dos pontos informada, Quando o público abre a tabela daquele trecho, Então cada coluna de ponto exibe o quilômetro em que ela foi medida, E um trecho sem essa informação não exibe placeholder nem espaço reservado.
RF-INGEST-001, RF-INGEST-005, ADR-012. A Chronosat publicou um arquivo novo com a quilometragem de todos os pontos, em outro endereço e com outro padrão de nome; o sistema recusava o cadastro.
O que implementar: o arquivo passa a ser um quarto tipo de fonte reconhecido, com base própria, e as duas bases seguem fixas no código, então a barreira contra endereço arbitrário não afrouxa. Cada leitura projeta o conteúdo na mesma tabela que a exibição já lia, e a quilometragem deixa de precisar ser digitada. A leitura é defensiva por desenho: arquivo que mude de forma não sobrescreve o que já está configurado, e valor fora do formato é ignorado e contado no log.
Como verificar (teste primeiro): colar a URL do arquivo no bloco de fontes do painel é aceito, o teste de conexão aprova, e a quilometragem aparece na tabela pública sem nenhuma digitação.
Aceite (H1): Dado o arquivo de parciais publicado pela cronometragem, Quando o operador o cadastra como fonte do evento, Então a quilometragem de todos os pontos passa a ser exibida automaticamente em todas as modalidades, E um arquivo fora da forma esperada não apaga a configuração existente.
RF-PUB-001, RF-API-001, RF-API-002. A geral mostrava só o tempo total acumulado; a organização pediu o resultado de cada dia.
O que implementar: uma coluna por etapa, com o tempo daquele dia e a posição do competidor nele, mais a coluna do tempo apurado (soma das especiais antes de penalidade e bônus), que fecha a conta que o público consegue conferir sozinho. As etapas saem dos metadados da cronometragem cruzados com o que já tem tempo lançado, então dia que ainda não correu não vira coluna vazia e o número de colunas cresce sozinho conforme o evento avança.
Como verificar (teste primeiro): a classificação geral mostra uma coluna por dia já corrido, com tempo e posição, e os números batem com a tabela oficial da cronometragem.
Aceite (H1): Dado um evento de várias etapas em andamento, Quando o público abre a classificação geral, Então vê o tempo e a posição de cada competidor em cada etapa já disputada, além do tempo apurado e do total.
RF-PUB-004, RF-REGRA-002. A posição de cada parcial já chegava da cronometragem e já era lida pelo motor, mas não era exibida.
O que implementar: a célula de cada parcial passa a mostrar a posição ao lado do tempo. A posição é passagem direta do que a cronometragem publica, não recálculo. Parcial sem posição informada não exibe nada, e ponto sem tempo não recebe posição.
Como verificar (teste primeiro): na tabela de um trecho, cada parcial mostra tempo e posição, e os valores conferem com o arquivo da origem.
Aceite (H1): Dado um trecho com as posições parciais informadas pela cronometragem, Quando o público abre a tabela daquele trecho, Então cada parcial exibe a posição do competidor naquele ponto, E parcial sem posição informada não exibe indicador algum.
RF-PUB-005, RF-INGEST-003, ADR-012. Duas informações que a cronometragem já mandava e a página não usava.
O que implementar: ao abrir um trecho, o percurso do dia (origem e destino) aparece embaixo da faixa de trechos; e o indicador de atualização passa a dizer também de quando é o dado da cronometragem, distinto da hora da nossa leitura; quando a origem trava, continuamos servindo o último estado salvo e só o instante do dado responde "de quando é isto". O instante é relativo, e não hora absoluta, porque a origem publica em outro fuso e a página exibe horas locais de prova.
Como verificar (teste primeiro): abrir um trecho mostra o percurso; o indicador ao vivo mostra a idade do dado da cronometragem; trecho sem esses campos renderiza como antes.
Aceite (H1): Dado que a cronometragem informa o percurso do trecho e o instante de geração do arquivo, Quando o público abre a página, Então vê de onde para onde vai a etapa aberta e de quando é o dado exibido, E a ausência de qualquer um desses campos não altera a página.
RF-PUB-001, RF-REGRA-001. A cronometragem apontou que penalidade e bônus saíam com milésimos, e que tempo total e diferenças precisavam de centésimos, porque já houve empate no décimo.
O que implementar: penalidade e bônus em segundo fechado; tempo total, tempo do trecho, tempo na especial, apurado, tempo de cada etapa e todas as diferenças em centésimos; bônus em azul, oposto do vermelho de penalidade, que é o padrão dos relatórios oficiais. As parciais seguem em segundo inteiro porque a origem nunca manda fração nelas.
Como verificar (teste primeiro): comparar os tempos e as diferenças da nossa tabela com a tabela oficial da cronometragem, competidor a competidor.
Aceite (H1): Dado um resultado publicado, Quando o público compara a nossa tabela com o relatório oficial da cronometragem, Então tempos e diferenças coincidem na casa do centésimo, E penalidade e bônus aparecem em segundo fechado.
RF-PUB-005, ADR-012. O prólogo e o shakedown já correram e têm resultado publicado, mas não entram no acumulado; nada na página dizia isso.
O que implementar: ao abrir uma etapa que não integra a classificação geral, a página avisa. O sinal vem do campo de status da própria cronometragem, cujo significado foi confirmado com eles antes de virar texto na tela; status diferente do conhecido não faz a página afirmar nada.
Como verificar (teste primeiro): abrir o prólogo ou o shakedown mostra o aviso; abrir um dia normal não mostra.
Aceite (H1): Dado uma etapa que não conta para a classificação geral, Quando o público a abre, Então a página informa que aquele tempo não entra no acumulado, E uma etapa que conta não recebe aviso algum.
Definição de Pronto da Onda PET: todos os cartões foram medidos no dado real do evento antes da implementação e conferidos no ar contra a tabela oficial da Chronosat; a suíte automatizada do motor passou inteira a cada entrega; e as duas dúvidas de contrato levantadas durante o plantão (significado do status da etapa e presença do horário de largada na geral) foram respondidas pela cronometragem e aplicadas.
Onda AUD, Audiência (medição do público)
Por que esta onda existe. O primeiro evento grande no ar (21 a 26 de agosto de 2026) foi acompanhado ao vivo pela organização e pela cronometragem, e ao fim ninguém soube dizer quantas pessoas acompanharam, porque o sistema não media nada e o registro do servidor web é descartado depois de poucos dias. A onda resolve isso por dois caminhos que não se substituem (DRS, ADR-013): a medição externa, que entrega os números às plataformas do cliente, e o registro interno, que é a verdade operacional e vira um painel de audiência dentro da própria ferramenta. Dependência: Ondas 2 e 3 do DRS (página pública e painel já existem). Ordem: os cartões estão na ordem de construção; AUD-01 vem antes de qualquer injeção porque nada pode ser ligado por código. Não altera arquitetura: tudo entra pelo motor único e vale para as quatro verticais.
RF-MEDIR-001. Registrar o estado de partida para que o ganho da onda seja medido contra um número, e não contra uma impressão. Nenhum código nasce neste cartão.
Contagem:
Universo: 3 tipos de página pública com documento HTML próprio, contados pelo catálogo de rotas públicas do DRS (home global RF-PUB-016, home da vertical RF-PUB-015, página do evento RF-PUB-001 a 014), e não por busca de texto no código.
Critério (comportamental): ao ser aberta, a página dispara alguma chamada de medição (etiqueta da plataforma de análise ou pixel da plataforma de anúncios) ou o servidor grava uma linha na série de acessos. Os dois lados do critério são medidos, porque o módulo tem duas metades e uma página pode medir por uma e não pela outra.
Por que o critério óbvio estaria errado: "carrega recurso de domínio de terceiro" foi descartado depois de medido. As três páginas carregam a tipografia oficial de um domínio externo desde a construção do site público, então esse critério devolveria 3 de 3 e o cartão nasceria afirmando o contrário do que é verdade. Carregar fonte é renderizar, não medir.
Placar: 0 páginas medidas / 3 páginas não medidas / 0 + 3 = 3.
Lado negativo, lido por inteiro, nos dois lados do critério: (a) navegador, as três páginas foram pedidas e lidas por inteiro no endereço público de produção e nenhuma contém etiqueta de análise ou pixel; os únicos recursos de domínio externo são os três da tipografia, e os dois roteiros de página são do próprio endereço do sistema; (b) servidor, o banco do sistema não tem a tabela da série de acessos nem a de configuração de rastreamento, ou seja, o segundo lado do critério não tem nem onde gravar. Zero pelos dois caminhos, medidos por meios diferentes.
Onde a injeção precisa entrar: 5 arquivos do motor emitem documento HTML completo; 3 servem rotas públicas e 2 servem o painel (a tela de entrada e a moldura do painel), 3 + 2 = 5. Os 2 do painel foram lidos por inteiro e servem apenas caminhos de painel, o que confirma que a injeção cabe nos 3 públicos e em nenhum outro lugar.
Universo é um só ambiente? Sim, o endereço público de produção. Por isso a afirmação vale para as páginas públicas e não se estende ao painel, que fica fora da audiência por decisão (RF-MEDIR-001).
Evidência de: 2026-09-18, contra o sistema no ar, em duas medições independentes (as três páginas pedidas pelo endereço público, e o esquema do banco consultado no próprio processo).
Reprova por: RF-MEDIR-001, cujo H1 exige "exatamente uma etiqueta da plataforma de análise e exatamente um pixel da plataforma de anúncios" em cada página pública. Com o placar em zero, o H1 reprova o estado atual. O requisito nasce nesta mesma evolução do DRS, ou seja, o cartão é a metade do par: o RF endurece o que se exige, este cartão registra o ponto de partida.
Como verificar (teste primeiro): o retrato está escrito no cartão com universo, critério, placar que fecha e o lado negativo lido.
Aceite (H1): Dado o retrato registrado, Quando a onda fecha, Então o mesmo critério aplicado às mesmas 3 páginas devolve 3 com medição e 0 sem, E o placar continua fechando.
RF-MEDIR-002, RF-PAINEL-012, RNF-SEG-006. Nenhum identificador e nenhuma credencial de medição vivem em código ou em configuração de ambiente: quem liga é o administrador, pela tela.
O que implementar: entidade de configuração de rastreamento (uma linha por destino, com interruptor, identificador público e credencial), estado carregado em memória na partida e recarregado a cada gravação (mesmo padrão do catálogo de textos, para render sem consulta ao banco); rota do painel atrás do teste de administrador, ao lado das demais telas exclusivas; formulário com interruptor e identificador por destino; campo de credencial de escrita apenas, exibido sempre mascarado, gravado só quando um valor novo é enviado e preservado quando o campo vai em branco, com o botão de ver o que foi digitado, como todo campo de senha do sistema; ação de enviar evento de teste a cada destino, marcado como teste; registro na auditoria em toda gravação e em todo envio de teste. Configuração de ambiente existe apenas como semente da primeira carga, lida uma única vez quando a tabela está vazia.
Como verificar (teste primeiro): o operador que abre a rota é barrado; gravar um identificador muda a página pública sem reinício; reabrir a tela mostra a credencial mascarada e nunca o valor; gravar com o campo de credencial em branco mantém a credencial anterior; a auditoria registra quem gravou e quando.
Aceite (H1): Dado o administrador na tela de integrações, Quando ele liga um destino, informa o identificador e grava, Então a página pública passa a injetar aquela marcação sem reinício do sistema, E a tela volta a exibir a credencial apenas mascarada, E a ação aparece na auditoria com quem gravou e quando, E o operador que tenta abrir a tela é barrado.
RF-MEDIR-001. A injeção entra nos 3 shells públicos medidos em AUD-00 e em nenhum outro lugar.
O que implementar: um trecho único de marcação, montado a partir do estado em memória da configuração, incluído pelos 3 renderizadores públicos; destino desligado ou identificador em branco produz trecho vazio; nada é incluído pelos renderizadores do painel nem pela tela de entrada.
Como verificar (teste primeiro): pedir as 3 páginas públicas e contar exatamente uma etiqueta e um pixel em cada; pedir as telas do painel e contar zero em ambas; desligar um destino e confirmar que aquela marcação some das 3 sem tocar a outra.
Aceite (H1): Dado os dois destinos ligados e com identificador preenchido, Quando o público abre a home global, a home de uma vertical ou a página de um evento, Então o HTML servido traz exatamente uma etiqueta da plataforma de análise e exatamente um pixel da plataforma de anúncios, E nenhuma tela do painel traz qualquer das duas, E com o destino desligado ou o identificador em branco aquela marcação não aparece em página alguma.
RF-MEDIR-003, DRS Ap.6. A lista é fechada, não ilustrativa: os sete nomes do Ap.6 e mais nenhum.
O que implementar: disparo de pagina_de_evento_vista no carregamento com os parâmetros do recorte; disparo de troca_de_modalidade, troca_de_trecho, troca_de_categoria, busca_de_competidor e documento_oficial_aberto no acionamento do controle, antes da navegação, por transporte de sinal; parciais_abertas na alternância do grupo de parciais da tabela, que não navega; todos carregando site, evento, vertical e o recorte, conforme a tabela do Ap.6.
Como verificar (teste primeiro): em janela anônima, percorrer as sete ações e conferir no relatório de tempo real do destino de análise que chegaram os sete nomes exatos, todos com o parâmetro de site; conferir que o evento de troca de filtro chega mesmo com a navegação acontecendo em seguida.
Aceite (H1): Dado a medição externa ligada, Quando o público abre a página de um evento, troca a modalidade, troca o trecho, troca a categoria, busca um competidor, abre as parciais e abre um documento oficial, Então cada uma das sete ações produz no destino de análise um evento com exatamente o nome correspondente, E todo evento carrega o parâmetro de site, E o evento de troca de filtro chega mesmo quando a navegação acontece logo em seguida.
RF-MEDIR-004, ADR-017. O ciclo de atualização pede a mesma rota, então sem tratamento ele viraria visita nova a cada meio minuto.
O que implementar: o roteiro de atualização automática passa a não disparar visualização de página em destino algum; dispara atualizacao_ao_vivo apenas no primeiro ciclo que trocar conteúdo, uma vez por carregamento de página; o registro interno continua gravando um registro do tipo atualização por ciclo.
Como verificar (teste primeiro): deixar a página de um evento ao vivo aberta por mais de dez ciclos e conferir que o contador de visualizações do destino não cresce, que chegou exatamente um evento de atualização, e que o registro interno tem um registro por ciclo.
Aceite (H1): Dado a página de um evento ao vivo aberta por mais de dez ciclos, Quando os ciclos acontecem, Então nenhuma visualização de página adicional é registrada nos destinos externos, E exatamente um evento de atualização ao vivo é enviado por carregamento de página, E o registro interno contém um registro do tipo atualização para cada ciclo.
RF-MEDIR-003, ADR-014. A propriedade é compartilhada de propósito (para a pessoa contar uma vez só), e por isso os caminhos colidem: é a configuração na plataforma que separa.
O que implementar, na plataforma, não no código: o nome do host declarado como dimensão de recorte nos relatórios que servem a este sistema; o parâmetro de site registrado como dimensão de evento, para que o relatório de tempo real, que não aceita recorte por host, consiga separar; e um público salvo próprio para os resultados.
Como verificar (teste primeiro): um acesso ao subdomínio de resultados e um acesso ao caminho de mesma vertical no site institucional aparecem separados tanto no relatório de tempo real quanto no relatório por host; o público salvo devolve apenas as sessões deste sistema.
Aceite (H1): Dado a propriedade compartilhada com o site institucional, Quando os dois sites recebem acesso no mesmo caminho de vertical, Então os relatórios separam os dois por host e por parâmetro de site, E o relatório de tempo real também separa, E o público salvo dos resultados não inclui sessões do site institucional.
RF-MEDIR-005, ADR-015. Só a visualização de página sai pelo servidor; interação fica no navegador para não pôr chamada externa no caminho quente.
O que implementar: geração de um identificador de evento por visualização, usado igual nos dois caminhos; envio pelo servidor ao destino de anúncios pela mesma fila assíncrona do registro interno (AUD-07), em lote; o dado de correspondência exigido pela plataforma (endereço de rede do visitante, assinatura do navegador e, quando existir, o identificador de navegador já gravado pelo pixel do cliente) segue junto da chamada e fora do banco, nunca sendo gravado em coluna alguma da série, conforme a exceção declarada em F.4; sem credencial configurada, nenhum envio é tentado e nada quebra.
Como verificar (teste primeiro): abrir uma página pública e conferir na ferramenta do destino que a visualização chegou pelos dois caminhos, foi contada uma vez e não foi descartada por falta de correspondência; inspecionar a linha gravada na série e confirmar que nenhuma das três informações de correspondência está lá; medir o tempo de resposta da página com e sem o envio ligado e confirmar que não muda; apagar a credencial e confirmar silêncio, não erro.
Aceite (H1): Dado a credencial de envio pelo servidor configurada, Quando o público abre uma página pública, Então a mesma visualização chega ao destino pelos dois caminhos com o mesmo identificador de evento, E a ferramenta a contabiliza uma única vez em vez de descartá-la por falta de correspondência, E nenhuma informação de correspondência aparece na série de acessos, E a resposta da página não espera o envio, E sem credencial nenhum envio pelo servidor é tentado.
RF-MEDIR-006, RF-MEDIR-007, RNF-PERF-003, ADR-018, DRS E.4. É a espinha da metade interna: sem ela nenhum bloco do painel existe.
O que implementar: entidade de acesso conforme o E.4 do DRS, só por acréscimo, com os índices compostos por evento e dia local e por evento e instante, e o índice único parcial de proveniência (arquivo e resumo da linha) que só vale para linha importada; captura do acesso em todas as rotas públicas, incluindo a rota de documento; gravação da rota pedida (caminho mais consulta normalizada, ou o caminho do arquivo no acesso a documento); desnormalização do dia e da hora locais na gravação; classificação do tipo de acesso (navegação, atualização, documento) e do momento (ao vivo ou repetição pelo estado do evento no instante, nulo nas homes, que não pertencem a evento algum); fila em memória descarregada em lote por transação com comando preparado, por intervalo ou por número de registros; teto de fila com descarte contado e o contador exposto.
Como verificar (teste primeiro): um acesso à página de evento gera exatamente uma linha com todos os campos preenchidos, inclusive a rota; um acesso a uma home gera uma linha com o momento nulo, sem erro; um acesso a documento grava o caminho do arquivo na rota; a resposta não espera a gravação; sob duzentas requisições por segundo durante trinta segundos o percentil noventa e cinco não piora mais de dez por cento contra a mesma medição com o registro desligado; forçar o teto e confirmar descarte contado sem erro ao público.
Aceite (H1): Dado o registro ligado, Quando a página do evento recebe duzentas requisições por segundo durante trinta segundos, Então o percentil noventa e cinco não piora mais de dez por cento contra a medição com o registro desligado, E nenhuma requisição falha, E cada acesso público gerou exatamente uma linha, E o descarte por fila cheia é contado.
RF-MEDIR-008, RNF-PRIV-001. É o que permite dizer pessoas e não só acessos, sem guardar quem é ninguém.
O que implementar: segredo gerado por dia, mantido só em memória e trocado na virada do dia; identificador calculado por resumo criptográfico sobre segredo do dia, endereço de rede e assinatura de navegador, guardado truncado; na importação de linhas antigas (AUD-16) o segredo é derivado do dia do próprio arquivo, gerado no momento da importação e descartado ao fim dela, porque o segredo do dia corrente não serve para linhas de outros dias; o endereço de rede nunca é gravado; nenhum cookie é criado; o painel rotula a contagem como única do dia.
Como verificar (teste primeiro): dois acessos do mesmo dispositivo no mesmo dia trazem o mesmo identificador; ao virar o dia o identificador muda; nenhuma coluna guarda endereço de rede; nenhum cookie do sistema aparece no navegador.
Aceite (H1): Dado dois acessos do mesmo dispositivo no mesmo dia, Quando os registros nascem, Então os dois trazem o mesmo identificador de visitante do dia, E no dia seguinte o mesmo dispositivo traz identificador diferente, E nenhuma coluna permite recuperar o endereço de rede, E nenhum cookie é criado para esse fim.
RF-MEDIR-009, DRS Ap.6. Lista fechada e nominal: própria máquina, verificação de saúde e rotas internas, agente automatizado, sessão de painel.
O que implementar: teste de exclusão aplicado antes de enfileirar, cobrindo as quatro classes exatamente como fichadas no Ap.6, sempre por origem da requisição e nunca por rota: retorno local ou ausência no cabeçalho de IP real repassado pelo servidor web, mais o cabeçalho próprio do monitor interno, mais a assinatura de agente automatizado, mais a sessão de painel. Excluir por rota está proibido porque a lista curada do monitor inclui a raiz e a home de uma vertical, que são páginas públicas de audiência real. A exclusão vale também para os destinos externos, que não são acionados nesses casos.
Como verificar (teste primeiro): disparar as quatro e confirmar zero linha para cada; disparar um acesso comum do público exatamente na raiz e na home de vertical que o monitor verifica e confirmar uma linha para cada um; conferir que nenhum número do painel e nenhuma exportação contém as quatro.
Aceite (H1): Dado uma verificação de saúde, uma requisição da própria máquina, um agente automatizado e uma requisição com sessão de painel ativa, Quando cada uma toca uma rota pública, Então nenhuma das quatro gera registro, E um acesso do público à mesma rota que o monitor verifica gera exatamente um registro, E nenhum número do painel nem nenhuma exportação inclui as quatro.
RF-MEDIR-010. Sem prazo por padrão (zero), ajustável sem deploy, dentro do próprio processo; vinte e quatro meses é exemplo de valor configurado, não o padrão.
O que implementar: rotina diária no próprio processo que remove os registros mais antigos que a janela quando a janela for maior que zero; janela lida da configuração, com valor de fábrica zero (sem prazo, nunca remove); a execução e a quantidade removida ficam registradas para a sustentação.
Como verificar (teste primeiro): com a janela no valor de fábrica (zero), rodar a limpeza e confirmar que nada é removido; ajustar a janela pela configuração para um valor maior que zero, semear registro fora e dentro dela, rodar a limpeza de novo e confirmar que só o de fora sumiu; confirmar que a próxima execução respeita o valor novo sem deploy.
Aceite (H1): Dado a janela no valor de fábrica (zero), Quando a limpeza diária roda, Então nenhum registro é removido por idade; Dado a janela ajustada pela configuração para um valor maior que zero, Quando a limpeza diária roda, Então todo registro mais antigo que essa janela deixa de existir, E nenhum registro dentro da janela é removido, E alterar a janela pela configuração muda o alcance da próxima limpeza sem novo deploy.
RF-MEDIR-012, RNF-SEG-006. É o que serve durante a prova, e por isso é o primeiro bloco da tela.
O que implementar: rota comum aos dois papéis no painel; bloco de tempo presente com pessoas dos últimos cinco minutos, páginas e recortes em uso e quantos acessos são atualização ao vivo; o bloco se atualiza sozinho com a tela aberta; janela vazia mostra zero.
Como verificar (teste primeiro): com acessos recentes, o bloco mostra o número sem recarregar a página; sem acessos, mostra zero e não quebra; operador e administrador alcançam a tela.
Aceite (H1): Dado acessos gravados nos últimos cinco minutos, Quando o operador abre a tela de audiência, Então o bloco do agora mostra as pessoas da janela, as páginas e recortes em uso e os acessos de atualização, E o bloco se atualiza sozinho, E com a janela vazia mostra zero em vez de erro.
RF-MEDIR-011, DRS Ap.6. O corpo do painel: resumo, séries, pico e as divisões.
O que implementar: seleção de evento; resumo com pessoas (únicos por dia somados, com a nota do dia) e acessos, mais o contador de descarte quando houver; série por dia e série por hora com o pico destacado; divisões por ao vivo e repetição, por dispositivo, por família de navegador, por tipo de página, por origem do registro, e por país e unidade federativa quando existirem; gráficos desenhados pelo próprio motor, sem biblioteca externa.
Como verificar (teste primeiro): com dado real de um evento, conferir bloco a bloco contra a consulta direta à série; conferir que a nota do dia aparece junto de pessoas; conferir que nenhuma biblioteca externa é carregada pela tela.
Aceite (H1): Dado um evento com acessos registrados, Quando o operador escolhe o evento, Então vê pessoas e acessos, série por dia, série por hora com pico, ao vivo e repetição, dispositivo, navegador, tipo de página e origem do registro, E a tela declara que único é do dia, E abre igualmente para o administrador, E nenhuma biblioteca externa de gráfico é carregada.
RF-MEDIR-013, DRS Ap.6. Os sete grupos de origem são nominais e fechados.
O que implementar: agrupamento do domínio de referência nos sete grupos do Ap.6, com ausência de referência caindo em direto; lista das buscas mais feitas, apenas o texto, sem ligação com visitante; lista dos documentos oficiais mais abertos; ranking de modalidades, trechos e categorias, cada item com a sua contagem.
Como verificar (teste primeiro): semear acessos com referências de origens distintas e confirmar que cada uma cai no grupo certo e que nenhum grupo fora dos sete aparece; confirmar que nenhuma busca é exibida ao lado de um identificador de visitante; confirmar contagem em todo item de ranking.
Aceite (H1): Dado acessos com referências distintas, buscas feitas e documentos abertos, Quando o operador abre a tela, Então vê a origem nos sete grupos nominais, as buscas mais feitas, os documentos mais abertos e o ranking de modalidades, trechos e categorias, E cada item traz a contagem, E nenhum texto de busca aparece ligado a um visitante.
RF-MEDIR-014. Permanência é sempre rotulada como aproximada, porque o sistema mede distância entre acessos, não tempo de aba em foco.
O que implementar: cálculo da distância entre primeiro e último acesso do mesmo visitante no mesmo dia e evento, e a distribuição dessa distância, rotulada como aproximada, tratando o visitante de acesso único sem quebrar; seleção de dois ou mais eventos e tabela lado a lado com as mesmas métricas e a mesma régua.
Como verificar (teste primeiro): com dois eventos semeados, a tabela sai lado a lado com colunas idênticas; um visitante de acesso único entra na distribuição; o rótulo de aproximada aparece.
Aceite (H1): Dado dois eventos com acessos, Quando o operador escolhe a comparação, Então os dois aparecem lado a lado com as mesmas métricas, E a comparação aceita ao menos dois eventos, E a permanência aparece rotulada como aproximada, E o visitante de acesso único entra na distribuição sem quebrar o cálculo.
RF-MEDIR-015. É o artefato que vai para o patrocinador, então os números têm que fechar com a tela.
O que implementar: exportação em arquivo de valores separados por vírgula, em dois níveis (agregado do evento e detalhe por dia e hora), respeitando o recorte escolhido na tela, com cabeçalho legível e codificação que abre em planilha sem ajuste.
Como verificar (teste primeiro): somar as colunas do arquivo e confrontar com os totais exibidos na tela; mudar o recorte na tela e confirmar que o arquivo muda junto; abrir o arquivo numa planilha e confirmar acentuação correta.
Aceite (H1): Dado um evento selecionado, Quando o operador pede a exportação, Então recebe o arquivo do agregado e o do detalhe por dia e hora, E os totais do arquivo conferem com os da tela, E o recorte escolhido vale no arquivo.
RF-MEDIR-016. Janela curta: o servidor descarta os arquivos depois de poucos dias, então o que não for importado agora some para sempre.
O que implementar: leitura dos arquivos de registro do servidor web; classificação por referência igual ao endereço pedido como atualização e o restante como navegação; exclusão dos agentes automatizados reconhecidos; preenchimento do que der para preencher (rota, instante, dispositivo, navegador, origem de referência, evento e recorte deduzidos do endereço); identificador de visitante do dia calculado com um segredo derivado do dia do arquivo, gerado na hora e descartado ao fim; marcação de proveniência em toda linha (origem de registro de servidor, mais o nome do arquivo e o resumo criptográfico da linha bruta); repetibilidade pelo índice único parcial sobre arquivo e resumo da linha, válido apenas para linha importada, e nunca pelo identificador de visitante, que é compartilhado de propósito entre acessos distintos do mesmo dispositivo no mesmo dia.
Como verificar (teste primeiro): importar um arquivo, conferir que os acessos aparecem no painel marcados como vindos do servidor; importar o mesmo arquivo de novo e confirmar que a contagem não muda em uma única linha; confirmar que duas linhas legítimas e distintas do mesmo visitante no mesmo dia continuam sendo duas linhas; confirmar que nenhum agente automatizado entrou; confirmar que o painel exibe a origem lado a lado.
Aceite (H1): Dado os arquivos de registro ainda disponíveis, Quando a importação roda, Então os acessos do período aparecem marcados como vindos do registro do servidor, E rodar duas vezes sobre o mesmo arquivo não aumenta a contagem em uma única linha, E dois acessos legítimos e distintos do mesmo visitante no mesmo dia continuam sendo duas linhas, E nenhum agente automatizado entra, E o painel exibe a origem de cada número.
RF-MEDIR-017, RF-CONFIG-006, ADR-019 (confirmado em 2026-09-19). Texto público, portanto do catálogo de textos, portanto editável e removível sem deploy.
O que implementar: duas chaves novas no catálogo de textos do site, no grupo de cabeçalho e rodapé, ambas removíveis: uma com o texto do aviso e outra com o endereço da política de privacidade do cliente, porque o catálogo não aceita marcação dentro do valor. O grupo passa de 12 para 14 chaves e o catálogo de 39 para 41 (contagem medida no catálogo em 2026-09-19, ART-CFG-07). Esvaziar a chave do texto remove o aviso inteiro; esvaziar só a do endereço mantém o aviso sem vínculo, com valor de fábrica trazendo o aviso curto e o vínculo para a política de privacidade do cliente; inclusão nos rodapés das páginas públicas, incluindo o rodapé da home global, que tem marcação própria; ausência nas telas do painel.
Como verificar (teste primeiro): com as duas chaves no valor de fábrica, o aviso aparece nas páginas públicas com vínculo para a política do ADR-019; esvaziada a do texto pela tela de textos, some sem deploy; esvaziada só a do endereço, o aviso continua visível sem vínculo; nenhuma tela do painel exibe o aviso.
Aceite (H1): Dado as duas chaves no valor de fábrica, Quando o público abre qualquer página pública, Então o rodapé exibe o aviso de medição com vínculo para a política de privacidade do cliente, E esvaziada a chave do texto o aviso some sem novo deploy, E esvaziada só a do endereço o aviso continua visível sem vínculo, E o aviso não aparece em nenhuma tela do painel.
RNF-PERF-003, RF-MEDIR-007. O sistema existe para aguentar o pico da prova; medir audiência não pode custar isso.
O que implementar: roteiro de medição repetível que pede a página do evento a duzentas requisições por segundo durante trinta segundos, uma vez com o registro ligado e uma vez com ele desligado, comparando o percentil noventa e cinco; execução contra o mesmo evento e o mesmo dado nas duas passadas.
Como verificar (teste primeiro): as duas passadas rodam contra o mesmo estado e a diferença do percentil noventa e cinco fica dentro de dez por cento; nenhuma requisição falha em qualquer das duas; o contador de descarte é lido ao fim.
Aceite (H1): Dado as duas passadas sobre o mesmo evento, Quando a carga termina, Então a piora do percentil noventa e cinco fica em no máximo dez por cento, E nenhuma requisição falhou, E o contador de descarte foi lido e registrado.
RF-MEDIR-001 a 017, AUD-00. Fecha o par aberto no retrato: o mesmo critério, o mesmo universo, o placar invertido.
O que implementar: nenhuma funcionalidade nova. Percorrer, em janela anônima e num evento ao vivo real, o caminho do público inteiro, e conferir no destino de análise, na ferramenta do destino de anúncios e no painel de audiência.
Como verificar (teste primeiro): aplicar às mesmas 3 páginas o mesmo critério de AUD-00 (dispara chamada de medição ou grava linha na série) e obter o placar invertido, 3 medidas / 0 não medidas / 3 + 0 = 3, com os dois lados do critério verdadeiros: cada página devolve exatamente uma etiqueta e um pixel, e cada acesso gera exatamente uma linha na série; as telas do painel devolvem zero pelos dois lados; os sete eventos chegam com os nomes exatos; a atualização ao vivo não gera visualização nova; o acesso aparece no painel de audiência em menos de um minuto; verificação de saúde, agente automatizado e sessão de painel não aparecem em número algum.
Aceite (H1): Dado a onda inteira no ar num evento real, Quando o público acessa e o operador abre o painel de audiência, Então o operador vê pessoas, acessos, pico e origem daquele evento, E o mesmo acesso aparece no destino externo separado do site institucional, E nada do que não é público entra em qualquer número.
Definição de Pronto da Onda AUD: o retrato de AUD-00 e a prova de AUD-19 usam o mesmo universo e o mesmo critério, e os dois placares fecham; as três páginas públicas medem e nenhuma tela do painel mede; os sete eventos chegam com os nomes exatos e com o parâmetro de site; a atualização ao vivo não produz visualização nova em destino algum; o painel de audiência responde por um evento real com todos os blocos do Ap.6 do DRS; a exportação fecha com a tela; a importação é repetível; a carga passa dentro do limite do RNF-PERF-003; e nenhum identificador ou credencial de medição existe em código.
Evoluções (fora da entrega inicial, sem mudança de arquitetura)
Não fazem parte das seis fases de construção; entram quando a dependência listada existir, não por calendário (DRS J.1, Evolução).
- Fotos e bandeiras no pódio: a bandeira (UF de cada integrante) já vem nos dados da Chronosat e pode entrar como ajuste de exibição em qualquer fase a partir de F2; a foto depende de uma fonte de fotos (pré-cadastro de competidor associado a numeral ou nome, com automação de imagens), que ainda não existe.
- Página de campeões históricos: uma página por vertical com os campeões de todas as edições, alimentada por conteúdo que a Sertões vai fornecer (planilha). Adiada por decisão do cliente; entra quando o conteúdo chegar, sem mudança de arquitetura.