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-07-06 |
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).
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 |
| 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) |
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-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.
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.
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.
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.