Documents what the code already does (no behavior change): GTI_FISCAL_VERSION (Hub) and the Agent's own version are separate numbers with separate release cycles; central.app.installation_identity.reference_agent_version() already compares an Agent's heartbeat version against the highest PUBLISHED Windows AgentRelease, never against the Hub's version - verified against test_version_reference.py. Also documents that there is no real minimum- version connection gate today (only SCHEMA_FINGERPRINT is enforced) and where one would go if ever needed. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
3.7 KiB
Versionamento — Hub e Agent (Missão 4 / Bloco B.3)
Hub e Agent têm números de versão independentes, cada um com seu próprio ciclo de release.
Um deploy do Hub (scripts/deploy_hub.ps1) nunca exige tocar no Agent, e vice-versa. Este
documento só descreve o comportamento já existente no código — nada foi alterado no Agent.
Fontes de verdade
- Hub:
release/VERSION==central/app/version.py::GTI_FISCAL_VERSION==central/pyproject.toml'sversion==RELEASE_MANIFEST.json'sGTI_FISCAL_VERSION/hub.version. Exposto emGET /version. - Agent:
agent/pyproject.toml'sversion== o default deAGENT_VERSIONemagent/scripts/run_agent_service.py==AGENT_VERSION_DEFAULTemagent/src/gti_fiscal_agent/preflight.py. Em produção, o valor real vem de.env(AGENT_VERSION=...), nunca do default do código — o default só importa para uma instalação legada sem essa variável. - Os dois só coincidem por coincidência numérica ocasional; não há relação obrigatória entre
eles.
tests/test_release_candidate.pytem dois testes separados que provam isso:test_versions_are_coherent_across_hub_and_packages(só Hub) etest_agent_version_is_internally_coherent(só Agent, consigo mesmo).
Como o painel decide "Atualização disponível" (já implementado, sem mudança nesta missão)
central/app/installation_identity.py::reference_agent_version(session) retorna a maior versão
entre os AgentRelease com status=PUBLISHED e platform=windows — nunca a versão do Hub.
Só cai de volta para settings.agent_server_version (env CURRENT_SERVER_VERSION, um valor de
compatibilidade legado, não a versão do Hub) quando não existe nenhum release Windows publicado.
compute_version_drift(agent_version, reference) compara a versão relatada pelo Agent com essa
referência: CURRENT se agent_version >= reference, OUTDATED caso contrário. Exemplo real
verificado nesta missão: Hub em 1.3.11, Agent 2 em 1.3.8, e o último AgentRelease Windows
publicado também é 1.3.8 → compute_version_drift("1.3.8", "1.3.8") == "CURRENT", sem alerta
falso, mesmo com o Hub numericamente "à frente". Testado em
central/tests/test_version_reference.py.
Versão mínima do Agent aceita pelo Hub
Não existe hoje um bloqueio "Agent versão X não pode nem se conectar" — qualquer Agent
autenticado (token válido) pode enviar heartbeat e reivindicar Jobs, independentemente da
versão. O único controle de compatibilidade real hoje é SCHEMA_FINGERPRINT (a impressão do
schema Firebird que o Agent relata), não a versão de software. api_compat em GET /version
(hoje "1.0") existe como um número de versão de contrato de API, mas nenhum código ainda
recusa uma chamada por causa dele — é informativo.
Matriz de compatibilidade (estado atual, não uma trava de código)
| Hub | Agent | Compatível? | Observação |
|---|---|---|---|
| 1.3.11 | 1.3.8 | Sim | Estado real de produção nesta missão. |
| 1.3.9+ | 1.1.0+ | Sim | Capabilities (RTC_CCLASSTRIB_WRITE_V1, enriquecimento) são negociadas por presença de campo no heartbeat, não por número de versão. |
| — | < 1.1.0 | Não testado | Antes da distribuição via installer/enrollment; fora do escopo de missões recentes. |
Se um dia for necessário recusar Agents antigos de verdade (ex.: um campo obrigatório novo no
heartbeat), o mecanismo natural é acrescentar uma verificação explícita em
central/app/api.py (heartbeat/claim) comparando agent_version a um mínimo configurável — isso
NÃO existe hoje e não foi adicionado nesta missão (mudaria o comportamento do Agent/Hub sem
necessidade concreta).