-
-
Notifications
You must be signed in to change notification settings - Fork 0
FAQ
Versão canônica no repo: docs/FAQ.md. Esta página da wiki é a porta de entrada; o documento no repo é a fonte única de verdade.
Esta página é para quem está começando. Explica os termos do projeto em linguagem simples, responde às dúvidas mais comuns e ajuda a resolver os erros mais frequentes.
Se você ainda não sabe o que a lib faz, comece por Conceitos. Para aprender na prática, veja o Tutorial. Para usar no dia a dia, veja Como usar. Para o detalhe técnico do algoritmo, veja o SPEC.
Três partes: glossário, perguntas frequentes e troubleshooting.
Agência Nacional de Saúde Suplementar. Órgão do governo brasileiro que regula os planos de saúde privados e define como operadoras (planos) e prestadores (clínicas, hospitais, laboratórios) trocam informações.
A menor unidade de informação que o computador guarda na prática: um número de 0 a 255. Texto, imagem e qualquer arquivo são, no fundo, uma sequência de bytes. Pense num byte como uma letra numa fita; o arquivo é a fita toda.
Um trecho especial dentro de um XML onde você escreve caracteres que normalmente teriam significado especial (como < ou &) sem confundir o leitor do arquivo. É como pôr um texto entre aspas dizendo "leia isto literalmente".
Command Line Interface, ou interface de linha de comando. O jeito de usar um programa digitando comandos numa janela de texto (o terminal), em vez de clicar em botões.
Seguir uma regra ou padrão à risca. Aqui, um port está em conformidade quando produz exatamente o mesmo resultado que a definição oficial manda, para todos os casos de teste. Ver também vetor de conformidade.
Um pedaço de código de terceiros que o seu programa precisa para funcionar. Quanto menos dependências, mais simples instalar e manter. O port Python tem apenas uma dependência de execução (defusedxml).
A regra que diz como transformar letras e símbolos em bytes e vice-versa. A mesma letra "é" pode virar bytes diferentes conforme o encoding. Escolher o errado é como ler com o dicionário errado. Os dois que importam aqui são UTF-8 e ISO-8859-1.
A parte final da mensagem TISS. No XML, é o elemento <ans:epilogo>, que fica no fim do documento e guarda o hash usado para verificar a integridade do conteúdo.
Um código-resumo calculado a partir de um conteúdo. Você joga um arquivo numa fórmula e recebe um código curto e de tamanho fixo. Muda um caractere, o código muda. Serve para conferir se dois conteúdos são idênticos. Aqui tem 32 caracteres hexadecimais, por exemplo o sintético 3aa0c578c95cdb861a125f480a8a4de5.
Um encoding antigo (também chamado Latin-1) que cobre as letras e acentos do português e de outras línguas da Europa ocidental. O manual do TISS diz que os arquivos devem usar este encoding. Atenção: isso vale para o arquivo, mas não para o cálculo do hash (ver a pergunta sobre UTF-8 abaixo).
Um conjunto de guias (pedidos de pagamento, autorizações, etc.) agrupado numa única mensagem TISS para enviar à operadora de uma só vez.
Uma fórmula específica para calcular hash. O resultado tem sempre 32 caracteres hexadecimais (0-9 e a-f). O Padrão TISS exige MD5. Aqui o MD5 serve só para conferir integridade, não para segurança.
Um rótulo que evita confusão de nomes dentro de um XML. Como o sobrenome de duas pessoas chamadas "João" numa sala. No TISS, o namespace é http://www.ans.gov.br/padroes/tiss/schemas, abreviado pelo prefixo ans: (como em <ans:hash>).
O componente que lê o texto do XML e o transforma numa estrutura que o programa entende (a árvore de elementos). "Parsear" significa analisar e interpretar.
Uma implementação da mesma biblioteca em outra linguagem. Este projeto tem 13 ports: Python, Rust, C, C++, Node.js, PHP, Java, Go, C#, Kotlin, Delphi/Object Pascal, Dart e WASM. Cada um fica em langs/<lang>/.
Troca de Informações na Saúde Suplementar. O padrão criado pela ANS que define o formato das mensagens trocadas entre planos e prestadores no Brasil. As mensagens TISS são arquivos XML.
O encoding mais usado hoje no mundo, capaz de representar qualquer caractere de qualquer língua. Neste projeto, UTF-8 é o encoding usado para calcular o hash, mesmo que o arquivo XML esteja declarado em ISO-8859-1. Essa é a "pegadinha" central do projeto.
Um caso de teste oficial: um arquivo de entrada mais o resultado esperado. Se o port produz o resultado esperado para todos os vetores, está em conformidade. O projeto tem 20 vetores (18 positivos, que devem gerar um hash certo, e 2 negativos, que devem ser recusados). Ficam em conformance/vectors.json.
eXtensible Markup Language. Um formato de arquivo de texto que organiza dados em tags aninhadas, parecido com as etiquetas do HTML. Por exemplo, <paciente><nome>Maria</nome></paciente>. As mensagens TISS são arquivos XML.
Não. Basta chamar uma função: você passa os bytes do XML e recebe o hash de 32 caracteres. O algoritmo é um detalhe interno. Veja os exemplos prontos em Como usar e o passo a passo no Tutorial. Se um dia quiser entender o porquê (curiosidade, portar para nova linguagem, depurar caso estranho), leia o SPEC e Conceitos.
Porque cada equipe usa a linguagem que já conhece, e ninguém deveria reimplementar este algoritmo do zero (e arriscar errar a pegadinha do encoding). Os ports cobrem os ambientes mais comuns na saúde suplementar: Python (scripts, integrações, back-ends), Rust e Go (serviços e microsserviços), C (FFI e embarcados), C++ (nativo e desempenho), Node.js (back-ends JavaScript), PHP (sistemas web de faturamento), Java (sistemas hospitalares e ERPs), C#/.NET (clínicas em Windows), Kotlin (apps Android e back-ends JVM), Delphi/Object Pascal (sistemas legados de clínica), Dart (apps Flutter) e WASM (hash no navegador, sem o XML sair da máquina). Ter vários ports também é rede de segurança: a CI compara todos contra os mesmos vetores.
Sim. Os 13 ports produzem exatamente o mesmo hash para o mesmo XML, byte a byte. Garantido por 20 vetores de conformidade (18 positivos, 2 negativos). Toda vez que o código muda, a automação confere que todos continuam batendo antes de liberar qualquer versão. A lista completa de vetores está no SPEC, seção 8.
Sim, desde a v0.2.0. O port WASM calcula o hash dentro do navegador do usuário (ou no Node.js), sem mandar nada para servidor nenhum. A motivação é de privacidade (LGPD): rodar o hash no cliente evita que o XML com dados de paciente trafegue até um servidor. O core é o mesmo Rust compilado para WebAssembly, então o resultado sai byte a byte idêntico aos outros 12 ports. Quickstart (browser e Node) em Como usar.
Sim, com prudência. Os 13 ports passam os 20 vetores e os parsers são endurecidos contra ataques conhecidos via XML. Antes de pôr no fluxo real, faça este teste: pegue alguns lotes seus que a operadora já aceitou, calcule o hash com a lib e confirme que bate. A licença é MIT: uso livre, inclusive comercial, sem garantias. Mais detalhes no DISCLAIMER.
Não. A lib apenas calcula o hash na memória e devolve o resultado. Não grava arquivo, não envia nada pela rede, não registra log do conteúdo. Quando a função termina, o XML some da memória do processo.
Atenção: o XML do TISS contém dados sensíveis de saúde. Quem manipula esses arquivos (você, o integrador) é responsável por protegê-los conforme a LGPD (Lei 13.709/2018). A lib cuida só do cálculo; cuidar do arquivo, dos logs e do acesso é com você. As recomendações mínimas estão na nota de LGPD.
Esta é a pergunta mais importante do projeto, e a razão de ele existir. O manual do TISS diz que o encoding é ISO-8859-1. Isso está correto para o arquivo XML, mas foi mal interpretado por muita gente como se valesse também para o cálculo do hash. Não vale. Quando você calcula o MD5 sobre bytes em ISO-8859-1, o hash sai diferente do que a ANS aceita. O hash correto só aparece quando os bytes são convertidos para UTF-8 antes do cálculo. Isso foi descoberto comparando com hashes reais que a ANS já tinha aceitado.
Resumindo:
- Encoding do arquivo XML: ISO-8859-1 (como o manual manda).
- Encoding usado para calcular o hash: UTF-8 (o que funciona na prática).
A lib já cuida dessa conversão internamente; você só passa os bytes brutos. A explicação técnica completa está no SPEC, seção 4.
Os nomes de erro variam por linguagem (Python InvalidTissXml, Java InvalidTissXmlException, Go um error não-nulo, etc.), mas as causas são as mesmas. O nome em cada linguagem está na seção daquela linguagem em Como usar.
Sintoma: a função lança um erro de XML inválido logo ao ler o conteúdo.
Causa provável: o XML está malformado (falta fechar uma tag, há caractere proibido, ou nem é XML, por exemplo um JSON passado por engano). Também cai aqui o XML com DOCTYPE ou entidade externa, recusado de propósito por segurança (proteção contra ataques tipo XXE).
Solução: confira que todo <tag> tem o seu </tag>; confirme que é mesmo XML TISS; valide com xmllint --noout arquivo.xml; não passe XML com DOCTYPE ou entidades externas.
Sintoma: o arquivo é processado sem erro, mas o hash difere do que a operadora ou o sistema antigo esperava.
Causa provável: quase sempre o encoding. Você decodificou e reencodou em ISO-8859-1 antes de chamar a função em vez de passar os bytes brutos; ou normalizou o XML antes (formatador, xmllint --format, --c14n, pretty-print), mudando espaços; ou o valor antigo dentro de <ans:hash> foi calculado com encoding errado por um sistema legado.
Solução: sempre passe os bytes brutos, lendo em modo binário; não rode formatadores nem normalizadores antes de calcular; não confie no hash já gravado, recalcule sempre. Para confirmar que a lib está certa, rode python3 conformance/reference.py conformance/inputs/syn_minimal.xml, que deve devolver 3aa0c578c95cdb861a125f480a8a4de5. Detalhes na seção 12 do USAGE.
Sintoma: a função recusa o arquivo com erro, mesmo o XML parecendo válido.
Causa provável: o documento tem mais de um elemento <ans:hash>. O padrão prevê exatamente um. A lib não adivinha qual zerar; por segurança, recusa.
Solução: corrija o XML para ter um único <ans:hash>, dentro do <ans:epilogo>. Se você monta o XML por concatenação, verifique se não duplicou o bloco do epílogo. Caso coberto pelo vetor negativo syn_multi_hash.xml.
Sintoma: a função recusa o arquivo com erro de encoding fora de escopo.
Causa provável: o arquivo está em UTF-16 (ou UTF-32), detectado pela marca no início (BOM). A lib trabalha apenas com ISO-8859-1 e UTF-8. UTF-16/UTF-32 são recusados de propósito, para não gerar um hash silenciosamente errado.
Solução: converta o arquivo para o encoding correto antes de calcular. Em geral o XML TISS deve estar declarado e salvo como ISO-8859-1. Cuidado com editores que salvam em UTF-16 sem avisar. Caso coberto pelo vetor negativo syn_utf16.xml.
Sintoma: ao usar a função que recebe um caminho (por exemplo hash_tiss_file), você recebe erro de arquivo não encontrado ou de permissão.
Causa provável: caminho errado, arquivo inexistente, ou sem permissão de leitura. Lembre que o caminho é relativo à pasta onde o programa roda, não à pasta do arquivo de código.
Solução: confira o caminho (prefira absoluto em dúvida); verifique existência e permissão; se o conteúdo já está na memória (banco, requisição HTTP), use a função que recebe bytes em vez da que recebe caminho.
- Conceitos: por que o projeto existe e como pensar nele.
- Tutorial: primeiro hash, passo a passo.
- Como usar: guia de uso e receitas, nas 13 linguagens.
- SPEC: especificação canônica do algoritmo.
- Nota de LGPD: obrigações de quem processa XML TISS.
Repositório · Release v0.2.1 · Licença MIT · Esta wiki é a porta de entrada; o detalhe técnico mora no repo.