Manual do Carino DICOM

O Carino DICOM é um gateway DICOM e um equipamento de continuidade: recebe estudos, roteia e encaminha, publica o acervo por Query/Retrieve e DICOMweb, e sustenta o setor de imagem quando o PACS ou o RIS param de responder. Este manual cobre a instalação, as tarefas do dia a dia e o que fazer quando elas falham, o modelo de segurança, cada serviço e os limites reais do software.

Todas as capturas deste manual são de uma instância real deste software com estudos inventados para a foto. Nenhum paciente aparece aqui.

Conteúdo

  1. O que é e qual papel ele cumpre
  2. Primeiros passos
  3. Como faço para…
  4. Quando algo dá errado
  5. O modelo de segurança e a regra do token
  6. Os serviços, um a um (referência)
  7. Isto não é um dispositivo médico
  8. Licença e onde pedir ajuda

1. O que é e qual papel ele cumpre

O Carino DICOM fica entre os equipamentos que geram imagem e os sistemas que guardam ou leem essas imagens. Ele não tenta substituir o seu arquivo: ele quer ser a peça que liga os dois e a que continua de pé quando alguma das outras cai.

São dois papéis, e vale distingui-los porque é isso que define quais serviços você liga:

Tudo é definido em um único config.json e tudo roda sem interface gráfica. O painel web é conveniente, não obrigatório.

Portas padrão

ServiçoPortaProtocolo
Receptor (Storage SCP)11112DICOM / DIMSE
Impressão virtual11113DICOM Print
Modality Worklist11114DICOM C-FIND
Query/Retrieve11115DICOM C-FIND/C-MOVE/C-GET
RIS de emergência2575HL7 sobre MLLP
Painel web + DICOMweb8042HTTP

Por que 11112 e não 104. A porta registrada do DICOM é a 104, que em Linux e macOS é privilegiada e exige rodar como root. O padrão aqui evita isso. Configure os equipamentos de acordo, ou publique 104 para 11112 no contêiner ou no firewall.

2. Primeiros passos

Escolha a forma de rodar

FormaPara qual casoVolta sozinho após queda de energia
App de desktop (bandeja)Uma estação com alguém sentado na frente: uma sala, um consultório, um teste.Só se você ligar «iniciar no login»
Docker / PodmanUm servidor, ou qualquer máquina onde você queira isolar e mover tudo junto.Sim (restart: unless-stopped)
Serviço systemdA caixinha permanente do setor de imagem, sem ninguém logado.Sim

App de desktop

Baixe o pacote do seu sistema na página de releases e abra. Ele fica na bandeja do sistema; ao clicar, abre o painel. Como ainda não é assinado digitalmente, Windows e macOS avisam na primeira execução: a página inicial traz o passo a passo para abrir mesmo assim.

Na primeira execução ele pergunta, uma vez só, se pode consultar no GitHub se existe uma versão mais nova. Responder que não — ou fechar a pergunta — deixa desligado, que é como ele vem. Se estiver ligado, uma versão nova aparece como uma linha no menu da bandeja e ao lado da versão no painel Resumo; clicar em qualquer uma das duas abre a página do release no seu navegador. Nada é baixado e nada se instala sozinho. A opção Procurar atualizações no menu da bandeja liga e desliga isso quando você quiser, e só a versão de desktop tem essa função: as instalações em contêiner e com systemd não têm.

Docker

git clone https://github.com/MiguelCarino/Carino-DICOM
cd Carino-DICOM
mkdir -p data
echo "PACS_UID=$(id -u)" >> .env
echo "PACS_GID=$(id -g)" >> .env
docker compose up -d --build
docker compose logs -f pacs

A primeira inicialização gera e imprime um token de acesso no log. Abra http://127.0.0.1:8042/ e cole o token quando o painel pedir. Tudo — configuração, estudos, logs, índice — fica em ./data, que é o que você precisa incluir no backup.

A falha mais comum na primeira execução é ./data pertencer ao root: o contêiner nunca roda como root e morre com EACCES. As duas linhas echo acima evitam isso, porque constroem a imagem para o seu próprio usuário; se você as pulou, acrescente-as e rode docker compose up -d --build de novo. Em hosts com SELinux (Fedora, RHEL, Rocky), o sufixo :z no volume não é enfeite: sem ele o bind mount fica sem permissão de escrita mesmo com as permissões aparentemente corretas.

Serviço systemd (Linux)

git clone https://github.com/MiguelCarino/Carino-DICOM.git
cd Carino-DICOM
sudo packaging/systemd/install.sh

O instalador cria o usuário de sistema carino-pacs, copia o código para /opt/carino-pacs, prepara /var/lib/carino-pacs e deixa a unit instalada… e não inicia o serviço. Não é esquecimento: iniciar um PACS abre portas que aceitam dados de pacientes, e essa decisão se toma depois de ler a configuração, não antes. Edite /var/lib/carino-pacs/config.json e então:

sudo systemctl enable --now carino-pacs
systemctl status carino-pacs
journalctl -u carino-pacs -f

Rodar o instalador de novo atualiza o código sem tocar no seu config.json.

Onde ficam os dados

FormaDiretório
Desktop / CLI~/CarinoDICOM/ (instalações existentes mantêm ~/CarinoPACS)
Docker/data dentro do contêiner → ./data no host
systemd/var/lib/carino-pacs/ (modo 0750)

O config.json fica junto dos dados, e não em /etc, porque os caminhos relativos do config ("./received", "./logs", "./index.db") são resolvidos em relação ao diretório do próprio arquivo de configuração. Um config em /etc espalharia estudos de pacientes pelo /etc.

Primeira execução, na ordem

  1. Escolha os serviços. Tudo vem desligado. O assistente do painel pergunta o que esta máquina deve rodar; ligue só isso.
  2. Cadastre os destinos (nome, host, porta, AE title) na aba Destinos de Configuração — é a aba com que ela abre.
  3. Teste a conectividade antes de mover uma única imagem: clique em Echo na linha do destino. Numa máquina sem painel, ./run.sh echo --name "PACS do hospital" faz o mesmo. Se o echo não passa, o problema não é o Carino: é rede, firewall ou AE title.
  4. Aponte um equipamento para cá usando a linha Aponte o equipamento para do cartão do receptor, e envie um estudo de teste (veja Como faço para…).
  5. Olhe a aba Registro de Atividade. Se algo falhar, aparece ali, e também no cartão do serviço como Último problema; este software prefere gritar a falhar em silêncio.
O assistente do primeiro arranque, com o título «Escolha os serviços que este PC deve executar» e seis cartões — Receptor, Auto-envio, Impressão, RIS de emergência, Worklist e Consulta/Recuperação —, cada um com uma caixa «Usar» e uma linha dizendo que sua porta está livre. Só o Receptor está marcado, então o rodapé diz «1 marcado», ao lado dos botões «Agora não» e «Ligar os marcados».
Passo 1. Os seis serviços são oferecidos de uma vez, e só o Receptor vem marcado — é ele que faz desta máquina um destino —, então o rodapé diz «1 marcado»; nada está rodando ainda, e nenhuma porta abre até você clicar em «Ligar os marcados». Cada cartão explica para que serve o serviço, então a escolha vem da descrição e não do nome do protocolo.

Sem interface gráfica

./run.sh init            # cria config.json e as pastas
./run.sh init --token    # e ainda gera o web.auth_token
./run.sh serve           # painel em http://127.0.0.1:8042
./run.sh receive         # só o receptor
./run.sh send            # só o monitoramento de pasta / encaminhamento
./run.sh qr              # só Query/Retrieve
./run.sh mwl             # só a worklist
./run.sh ris             # só o receptor de pedidos HL7
./run.sh print           # só a impressora virtual
./run.sh echo --host 10.0.0.5 --port 104 --aet PACSREMOTO

Todos os comandos aceitam -c / --config <caminho>. No Windows, run.ps1.

3. Como faço para…

Receitas curtas para as tarefas do dia a dia no setor. Cada uma termina dizendo como você sabe que deu certo; se não deu, o capítulo seguinte é a lista do que conferir.

…apontar uma modalidade para cá para guardar imagens

  1. Abra Serviços. Se o cartão Receptor disser que está parado, clique em Iniciar.
  2. Leia a linha Aponte o equipamento para do cartão: um AE title, um endereço IP e uma porta (por padrão CARINODICOM e 11112). O botão de copiar ao lado copia os três. Se a máquina tiver mais de um endereço, use o que está na rede da modalidade.
  3. Na modalidade, cadastre um destino de armazenamento — cada fabricante chama de um jeito: nó DICOM, arquivo, «Enviar para», destino de «Store» — com esses três valores. O AE title da própria modalidade é o AE chamador; você não precisa digitá-lo aqui.
  4. Se Configuração → Configurações → Este PACS tiver AE titles em Aceitar apenas estes AEs, inclua ali o AE title da modalidade, ou o receptor a recusa.
  5. Rode o teste de conexão da própria modalidade (costuma se chamar Verify ou Echo) e depois envie um estudo. Ele aparece em Estudos → Histórico.

O botão Testar do cartão verifica o receptor a partir desta própria máquina. Se o Testar passa e a modalidade continua falhando, o problema está entre os dois: endereço, porta, firewall ou a lista de AEs permitidos.

…apontar uma modalidade para cá para imprimir

Para equipamentos cuja única saída é o filme. O Carino finge ser a impressora de filme e captura cada folha para você identificar; nada é impresso em papel.

  1. Abra Serviços e clique em Iniciar no cartão Impressão.
  2. Leia a linha Aponte o equipamento para do cartão (por padrão CARINOPRINT, o IP desta máquina e a porta 11113).
  3. Na modalidade, cadastre uma impressora DICOM — às vezes chamada de impressora a laser ou impressora de filme — com esses três valores. Tons de cinza são sempre oferecidos; se a modalidade só imprime em cores, marque Aceitar também trabalhos de impressão em cores em Configuração → Configurações → Impressão.
  4. Clique em Enviar impressão de teste no cartão. Em poucos segundos aparece em Estudos → Pendentes uma folha marcada TEST PRINT — safe to discard (impressão de teste, pode descartar). Isso prova que o receptor funciona; descarte a folha.
  5. Imprima um filme a partir da modalidade. O cartão mostra Última impressão com o número de filmes, o AE title da modalidade e o endereço dela, o contador Capturados sobe, e o filme espera em Pendentes para você aprovar (veja abaixo).

Salvar cada filme capturado como (em Impressão) decide em que o filme se transforma quando você aprova. Muitos arquivos e visualizadores guardam um PDF mas não o mostram; escolha Imagem (Secondary Capture) se o filme precisar ser lido do outro lado.

O AE title da impressora digitado na modalidade não é conferido: mesmo com erro de digitação, a impressão sai. Só o AE title da própria modalidade é filtrado, e só se você preencher Aceitar apenas estes AEs. Se uma impressão falhar, o cartão mostra Último problema; a tabela de problemas de impressão lista cada mensagem e a solução.

…apontar uma modalidade para cá para puxar a worklist

  1. Garanta que haja pedidos. Ou o RIS envia pedidos HL7 ao serviço RIS de emergência (porta 2575), ou alguém os digita em Pedidos → Novo pedido.
  2. Em Configuração → Modalidades, registre a sala com o AE title exato da estação. O destino de um pedido passa a ser escolhido nessa lista em vez de digitado.
  3. Abra Serviços, clique em Iniciar no cartão Worklist e leia a linha Aponte o equipamento para (por padrão CARINOMWL e a porta 11114).
  4. Na modalidade, configure o provedor de worklist (MWL, «HIS/RIS» ou «servidor de worklist») com esses valores e faça a consulta.

Um pedido sem destino aparece em todas as estações; um pedido com destino aparece só na estação cujo AE title bate exatamente com ele. Quando o estudo volta, é conciliado com o pedido pelo accession number e o pedido se fecha sozinho.

…aprovar um filme pendente

Os filmes capturados, e os PDFs ou imagens encontrados junto de um estudo, esperam em Estudos → Pendentes. O contador 📎 ao lado de Estudos diz quantos são.

  1. Abra Pré-visualizar e olhe a folha.
  2. Se o paciente tiver um pedido aberto, clique em Associar a um pedido… e escolha-o. Nome, ID do paciente, accession e estudo vêm do pedido, e o pedido é fechado como capturado.
  3. Senão, digite a identidade você mesmo. ID do paciente e Nome do paciente são obrigatórios; accession, data e descrição são muito recomendados.
  4. Se o item chegou junto de um estudo e você trocou o paciente, escolha a que ele pertence: Anexar ao estudo original só se aquele estudo for mesmo deste paciente; senão, Novo estudo. A escolha errada arquiva a folha de um paciente dentro do estudo de outro.
  5. Clique em Aprovar e enviar. O item é convertido em DICOM e encaminhado como qualquer outro estudo.

Não há como desfazer: depois de aprovado, o arquivo original sai de Pendentes e a cópia DICOM já está a caminho. Um erro se corrige no arquivo de destino. Descartar remove um item sem enviá-lo.

…resolver um encaminhamento travado

Abra Estudos → Travados (o contador ⚠ ao lado de Estudos). As linhas são agrupadas por estudo, com paciente, accession e descrição, e separadas em três tipos:

…descobrir por que algo falhou

  1. Olhe o cartão do serviço. Todo listener mostra Último problema quando algo deu errado; clique nele para abrir o registro já filtrado por aquele serviço.
  2. Em Atividade → Registro, use os chips de serviço (store, send, print, worklist, Q/R, RIS…), Só erros e avisos e o filtro de texto — um AE title, um endereço IP ou um accession number estreitam a busca rápido.
  3. Para passar o problema adiante, copie as linhas visíveis ou baixe o registro de um dia inteiro.
  4. Clique em Testar no cartão. Se o teste passa a partir desta máquina e a modalidade continua falhando, olhe a rede entre as duas.
  5. Se uma configuração mudou e ninguém sabe quem mudou, Atividade → Auditoria nomeia a pessoa e as seções que ela alterou.

4. Quando algo dá errado

Primeiro o sintoma, depois onde olhar, depois a solução. Quase toda linha começa nos mesmos dois lugares: o cartão do serviço em Serviços (o Último problema dele) e Atividade → Registro. As linhas de registro aparecem em inglês, como o motor as escreve.

Envio, recepção e worklist

SintomaOnde olharSolução
A modalidade não consegue enviar nada para cáCartão do receptor; linhas de registro que começam com Receiver: refusedits AE title is not in the allowed list: inclua o AE da modalidade em Aceitar apenas estes AEs, ou esvazie a lista. Nada no registro: a conexão nunca chegou — confira IP e porta na modalidade, o firewall e se o cartão está rodando. O Testar do cartão separa «esta máquina» de «a rede».
A modalidade enviou, mas o estudo não está no HistóricoRegistro, chip store; Espaço livre no ResumoRefused C-STORE — low disk space: libere espaço em disco ou diminua scp.min_free_gb. A modalidade pode reenviar quando houver espaço.
Um cartão está âmbar: «Ligado mas não está rodando»Registro no momento em que ele iniciouA porta dele está ocupada por outro programa, ou por outro serviço daqui. Mude a porta ou pare o outro programa, e então Iniciar.
Os estudos não chegam ao PACS principalEstudos → TravadosO erro da linha diz o que o PACS fez: rejected permanently: calling AE title not recognised → cadastre no PACS o nosso AE de envio (por padrão CARINOSCU); connection refused → porta errada ou PACS parado; no reply → host desligado ou firewall; aborted → muitas vezes um desencontro de TLS.
Nada é enviado a um destino, e nada é tentado de novoTravados, seção «Retido»Uma retenção por anonimização — veja Anonimização no encaminhamento.
A modalidade não enxerga a worklistCartão da worklist; registro, chip worklistMWL: refused: inclua o AE dela na lista de permitidos da worklist. Nenhuma consulta no registro: IP/porta/AE errados na modalidade. A consulta chega mas a lista vem vazia: o AE de destino do pedido não bate exatamente com a estação — corrija em Modalidades.
O RIS do próprio hospital não entrega a lista à modalidadeConfiguração → Modalidades → Testar worklistVeja Sonda de worklist; as respostas ficam em Atividade → Sondas de worklist.
Os pedidos HL7 do RIS não aparecemCartão do RIS de emergência; registro, chip RISConfira se o RIS está enviando para este IP na porta 2575 e, se a lista ris.allowed_hosts estiver preenchida, se o endereço dele está nela.
Todo mundo foi deslogado—Normal depois de um reinício: as sessões vivem em memória de propósito. Entre de novo.
O painel para de responder ou os números param de mudarRecarregue a páginaSe não voltar, o motor não está respondendo: confira se o serviço ou o contêiner está rodando (systemctl status carino-pacs, docker compose ps) e leia o log dele.
O contêiner morre com EACCESdocker compose logs pacs./data não tem permissão de escrita para o usuário do contêiner: defina PACS_UID/PACS_GID no .env e reconstrua (veja Docker acima).
O e-mail de failover está ligado, mas ninguém recebeuConfiguração → PessoasO e-mail vai para perfis com endereço preenchido, não para uma lista. Veja Avisos.

Impressão

Cada recusa e cada falha do receptor de impressão vira uma linha no registro (o chip print), conta nos Erros do cartão e aparece como o seu Último problema. Um trabalho bem-sucedido aparece como Última impressão.

Linha de registro ou sintomaO que significaSolução
Print: refused X @ ip — its AE title is not in the allowed list (…)O AE title da modalidade não está na lista do receptor de impressão.Inclua-o em Impressão → Aceitar apenas estes AEs, ou esvazie a lista.
Print: refused X @ ip — too many connections at onceA modalidade, ou várias, abriu mais conexões do que o receptor aceita ao mesmo tempo.Deixe os trabalhos terminarem e imprima de novo; se repetir, imprima um trabalho por vez.
Print: X @ ip asked for Basic Color Print Management…, which this printer does not offerA modalidade quer cores e as cores estão desligadas.Marque Aceitar também trabalhos de impressão em cores. Não conta como erro: uma modalidade que oferece as duas coisas imprime em tons de cinza.
Print from X: nothing to print — no film was created first, … N film(s) were created but no image was sent into them, … the film it named (…) was never created hereA modalidade pulou um passo da sequência de impressão. Ela recebeu «página vazia» (um aviso, 0xB603).Configuração ou defeito do lado da modalidade: confira a configuração de impressora dela (formato de filme, número de imagens) e imprima de novo.
Print: X sent an image for a box this printer never handed out (…); refusedA modalidade se referiu a uma caixa de imagem de outra sessão.Reinicie a impressão a partir da modalidade; se repetir, reporte com a linha de registro.
Print: could not read image N from X (…); it is left blank on the filmUma imagem usou um formato de pixel que o receptor não lê; o resto da folha foi mantido.Mude as opções de impressão da modalidade (profundidade de bits, cor) se ela oferecer; senão, reporte a linha.
Failed to render or queue the print job from X: …O filme chegou mas não pôde ser gravado (status 0x0110).Confira o espaço livre em disco e se a pasta de pendentes (scu.pending_dir) tem permissão de escrita.
Outras linhas que começam com Print: …Repassadas das mensagens da própria biblioteca DICOM para aquela conexão de impressão.Leia junto com a linha anterior; reporte se não ficar claro.
Nada no registroA conexão nunca chegou.O cartão está rodando (não âmbar)? A modalidade está usando o IP desta máquina e a porta 11113? Há um firewall no caminho? Enviar impressão de teste no cartão prova este lado.

Duas coisas que não são a causa: o AE title da impressora digitado na modalidade (ele não é conferido) e a modalidade deixar para a impressora a numeração da sessão de filme e da caixa de filme (elas são criadas aqui quando faltam). Uma Presentation LUT é aceita e ignorada, e uma modalidade que primeiro pergunta a configuração da impressora recebe resposta.

A aba Registro de Atividade: acima do fluxo, um chip por serviço, uma caixa de só erros e avisos e um filtro de texto; abaixo, as linhas do dia com marcação de hora, as mais recentes embaixo, cada uma com o serviço que a escreveu; sob o fluxo, a contagem de linhas, «Copiar visíveis», um seletor de dia, «Baixar o registro do dia» e «Limpar exibição».
Onde começa cada linha das tabelas acima. O registro abre nas linhas mais recentes, embaixo; erros aparecem em vermelho e avisos em âmbar, e cada linha que importa diz o que fazer a respeito. Quando o fluxo estiver movimentado, restrinja com os chips de serviço (Receptor, Auto-envio, Impressão…), com Só erros e avisos e com o filtro de texto. Copiar visíveis copia o que os filtros deixam, Baixar o registro do dia salva o arquivo inteiro do dia escolhido ao lado, e Limpar exibição esvazia a tela, não o arquivo.

5. O modelo de segurança e a regra do token

A tela de acesso: um cartão com o título «Este PACS precisa do seu token de acesso», um campo de senha, um botão de entrar e uma nota dizendo que o token é web.auth_token no arquivo de configuração e que o painel nunca mostra um token guardado.
Isto é servido no lugar do painel, e de novo em qualquer 401 posterior: um reinício derruba todas as sessões de propósito, então entrar de novo é o normal, não uma falha.

Comecemos pelo que importa: o painel é a chave do acervo. Quem abre o painel pode ler todos os estudos armazenados, baixar os arquivos DICOM, mudar qualquer configuração, iniciar e parar serviços, apagar estudos e desligar o servidor. De fábrica há um único segredo compartilhado e quem o tem pode tudo: os perfis são opcionais e ficam desligados até você ativá-los. Ao ativar, cada pessoa entra como ela mesma, com as próprias permissões, a própria visão dos identificadores do paciente e o próprio nome na auditoria; o token compartilhado continua funcionando como administrador, então nada que já o utilize deixa de funcionar.

A aba Pessoas de Configuração, com a faixa de abas à vista e Pessoas selecionada, sob uma linha que diz «4 perfis.». O cartão do Administrador é curto: sua caixa «Administrador (tudo, incluindo permissões futuras)» está marcada, então não tem grade de permissões, só o campo de senha, Salvar e Excluir. Abaixo dele, o cartão de TI mostra a grade «Pode fazer» de caixas marcadas e desmarcadas, e a imagem corta no meio dessa grade, antes da linha «Pode ver». No canto inferior direito, um botão fixo «Adicionar alguém».
Os perfis, depois de ligados. As permissões são por pessoa e são verificadas em cada endpoint, não no navegador. O cartão do Administrador é curto de propósito: com «tudo, incluindo permissões futuras» marcado não sobra grade para mostrar, porque não há nada a negar. Nos demais, «pode ver» é separado de «pode fazer» — um perfil pode reencaminhar um estudo pelo número de accession sem nunca ler o nome de um paciente —, e o identificador que ficar desmarcado aparece como *** onde teria aparecido.

As mesmas permissões desenham a navegação. Uma linha da lateral aparece se o perfil tiver alguma das permissões que as abas dela pedem, e depois cada aba é conferida por conta própria: um Radiologista, que tem routing.read e não tem config.read, abre Configuração e enxerga Destinos e Rotas, mas nenhuma aba Configurações, que é onde ficam o token da API e o desligamento do servidor. A Recepção, que não tem nenhuma das três permissões, não vê a linha Configuração.

A mesma tela de acesso em um equipamento com perfis: quatro botões — Administrador, TI, Radiologista e Recepção —, cada um com um cadeado, e um link para entrar com o token de acesso.
A tela de acesso de um equipamento com perfis. O seletor só é desenhado enquanto users.list_profiles estiver ligado: publicar a lista de pessoal para quem alcançar a porta é uma divulgação de verdade, e a decisão é sua. O token continua funcionando, dobrado embaixo, porque é a volta para dentro quando alguém se tranca fora.

A regra

web.auth_token vazio só é aceito enquanto web.host for loopback. Se web.host for qualquer outra coisa — 0.0.0.0, um IP da rede, um nome — e o token estiver vazio, o servidor se recusa a iniciar. Essa recusa é um recurso do programa, não um erro para contornar.

O motivo é concreto. Sem autenticação, em 127.0.0.1, o sistema operacional é o controle de acesso: só um processo da própria máquina consegue falar com a API. Isso se defende. Mas web.host é configurável pelo operador, e no dia em que alguém troca para 0.0.0.0 para «acessar do outro PC» — com pressa, numa terça-feira, sem pensar em segurança — essa mesma API entrega a qualquer vizinho de rede a lista de estudos, os caminhos de armazenamento, os bytes DICOM e o /api/shutdown. A regra existe porque essa mudança leva dez segundos e as consequências duram anos.

Todo contêiner está sempre nesse caso: um contêiner publica em 0.0.0.0 por construção. Por isso a imagem gera um token de 256 bits na primeira inicialização se você não fornecer um — e o imprime. O que ela nunca faz é gerar em silêncio: um segredo que ninguém vê é um segredo que ninguém rotaciona.

Como gerar e como enviar o token

./run.sh init --token                                  # grava no config.json
python3 -c "import secrets; print(secrets.token_urlsafe(32))"
openssl rand -base64 32

O servidor aceita a credencial de três formas:

O cookie existe para o painel pedir o token uma vez em vez de guardá-lo em JavaScript, onde qualquer XSS e qualquer extensão do navegador conseguem ler. O cookie não carrega o token: carrega um HMAC calculado com um segredo gerado na inicialização e mantido só em memória. Por isso um restart desloga todo mundo — é a troca certa para um equipamento de operador único: nada guardado em disco para vazar, e no pior caso digita-se o token de novo uma vez por plantão.

O painel fala HTTP puro. Ele não tem TLS próprio. Se você publicar além do loopback, coloque atrás de um proxy reverso que termine HTTPS. Um token trafegando em HTTP sem criptografia numa rede compartilhada é um token que você já entregou.

O lado DICOM

O que o modelo não protege

Backup. O índice sqlite é cache e se reconstrói sozinho; as imagens não. Faça backup dos diretórios de armazenamento — e teste a restauração pelo menos uma vez.

Sem telemetria, com uma exceção que você mesmo liga. O motor não envia nada para lugar nenhum: sem analytics, sem relato de erros, sem contadores de uso, sem scripts de terceiros carregados em tempo de execução. Suas únicas conexões de saída são as associações DICOM e os ACKs HL7 que você configurou, para os pares que você nomeou — e uma instalação com Docker, Podman ou systemd é isso e nada mais, a menos que um administrador ligue a verificação de versão descrita abaixo, que é a frase que importa, porque é essa a forma que fica no setor de imagem com os dados dos pacientes em cima. O app de desktop pode, além disso, verificar se saiu uma versão mais nova, e só se você tiver dito sim à pergunta que ele faz uma vez, na primeira execução; vem desligado e a bandeja do sistema desliga de novo. Essa verificação é uma única requisição HTTPS por dia à lista de releases do GitHub, levando um User-Agent e nada mais — sem identificador, sem contador, sem configuração, sem dados de paciente —, de modo que o que o GitHub fica sabendo é o endereço IP desta máquina e mais ou menos quando o app foi aberto, e é só isso. Nada é baixado e nada se instala sozinho. O painel oferece a mesma verificação a partir do próprio servidor, para instalações sem o app de desktop: fica desligada até que um administrador a ligue, pelo botão ao lado da versão na Visão geral ou em Configurações → Integrações; envia exatamente essa requisição, do servidor e não do seu navegador; e a Visão geral passa a mostrar se esta versão está atualizada, com um botão Atualizar que abre este site. Uma mudança que enviasse mais do que isso, ou que enviasse algo que ninguém tivesse aceitado, seria tratada como vulnerabilidade.

A aba Auditoria de Atividade: uma linha com a contagem de arquivos, o tamanho e o topo da cadeia; uma fileira de filtros — todos, todas as ações e uma caixa de só falhas ou recusas — com os botões «Verificar integridade» e «Exportar» à direita; e linhas com marcação de hora, a mais recente no topo, todas «Pronto» e com os detalhes recolhidos: o motor entrando com o token de acesso, uma linha por entrada, e abaixo «Testou uma worklist» de US_ROOM_2, feito com o token de acesso.
A trilha de auditoria, com o topo da cadeia impresso acima: esse resumo é o valor que vale copiar para um lugar que esta máquina não alcança. A aba tem sua própria fileira de filtros — de quem (todos ou uma pessoa), qual ação e Só falhas ou recusas — com Verificar integridade e Exportar à direita; Limpar exibição é de Registro, não daqui. As recusas são registradas com a mesma fidelidade que os acertos: um pedido que não passa deixa a sua linha do mesmo jeito.

6. Os serviços, um a um

Tudo o que abre uma porta vem desligado. A pergunta certa não é «o que ele consegue fazer?», e sim «o que esta máquina precisa fazer?». Cada serviço ligado é mais uma porta aberta. O índice abaixo é a única exceção: ele sobe sozinho, porque é um cache sqlite local que não abre porta nenhuma.

Cada serviço tem um único interruptor. Iniciar no cartão liga o serviço e o mantém ligado depois de um reinício; Parar pergunta antes, depois para o serviço e o mantém desligado. Em Configuração → Configurações o mesmo interruptor é a caixa Executar este serviço (também ao iniciar), então o cartão e a configuração nunca discordam. Salvar as configurações reinicia só os serviços cujas próprias configurações mudaram, e o painel diz quais.

O painel de Serviços: um cartão por serviço — receptor, encaminhamento automático, receptor de impressão, RIS de emergência, worklist, Query/Retrieve —, cada um com um ponto de estado, um botão de parar, uma linha «Aponte o equipamento para» com AE title, endereço IP e porta e um botão de copiar, um botão Testar e seus contadores; o cartão do receptor de impressão mostra também a linha Última impressão e um botão Enviar impressão de teste.
Cada serviço liga e desliga sozinho, e cada cartão traz o que um técnico precisa: o endereço para digitar na modalidade, um Testar que verifica o serviço a partir desta máquina, e os dois números que valem atenção — o que ele atendeu e o que falhou. Quando algo falha, Último problema diz o quê e leva ao registro. O painel não é o motor: parar um aqui para aquele listener, não o equipamento.
O painel de Resumo: blocos contando serviços ligados, recebidos, enviados, travados, pendentes, pedidos abertos e espaço livre, sobre cartões com o endereço desta máquina, seu receptor, seus caminhos de configuração e de armazenamento, se cada destino responde e o último estudo recebido.
O resumo responde «esta máquina está funcionando?» em uma tela só. Os blocos que contam algo com casa são botões para o painel que governa o que eles contam — Travados e Pendentes abrem a sua própria aba de Estudos —, então um número inesperado continua a um clique do seu detalhe. Espaço livre é o único que não é botão: não conta nada que tenha uma tela, e um botão que não faz nada é pior que uma leitura simples.

Receptor — Storage SCP

Porta 11112 · C-STORE, C-ECHO

O que faz
Aceita estudos enviados pelas modalidades e grava em disco, opcionalmente organizados por Paciente / Estudo / Série. Aceita todas as sintaxes de transferência e guarda o que vem comprimido como está: não há transcodificação, então nenhum dado é alterado na entrada.
Quando ligar
Sempre que algo precisar enviar imagens para cá: modalidades, outro PACS, uma estação. É o serviço central.
Quando não
Se esta máquina só encaminha o que outra deixa numa pasta.
A aba Histórico de Estudos, mostrando os recebidos: uma caixa de filtro e chips de modalidade acima de uma linha por estudo com paciente, ID, data, número de accession, descrição, modalidade e número de imagens, suas séries logo abaixo, e em cada linha um botão de enviar e um botão ⋯ que abre as demais ações da linha.
O que chegou, do mais recente para o mais antigo, com as séries de cada estudo; a caixa de filtro e os chips de modalidade restringem a lista. Enviar é a única ação à vista na linha; o menu ⋯ guarda o resto: Adicionar PDF/imagem, Editar tags (quando há um endereço de editor configurado), Copiar caminho, Abrir pasta (só quando o painel roda na própria máquina) e Excluir. O caminho é real: o arquivamento é uma árvore de pastas, não um banco de dados de onde alguém precisa exportar. A barra acima da lista tem três posições, na ordem em que um estudo vive: Recebidos; Saída, a pasta de saída, com o estado de envio de cada destino para cada estudo; e Arquivados, que só se enche quando o Auto-envio está configurado para mover o estudo depois de enviá-lo. Com o padrão, manter, um estudo enviado fica em Saída.

Encaminhamento automático — Storage SCU e regras de roteamento

Cliente de saída · C-STORE

O que faz
Monitora uma pasta e encaminha cada arquivo novo para os destinos que couberem. Um arquivo só é enviado quando está estável (o tamanho não mudou entre duas varreduras), então nunca se encaminha arquivo pela metade. O progresso é registrado por destino: só conta como concluído quando todos os destinos habilitados aceitaram, e os que falharam são repetidos na varredura seguinte. Ao concluir, o original pode ser mantido, movido ou excluído.
Regras
Com roteamento ligado, uma regra decide os destinos por modalidade, AE title de origem, estação, ID do paciente ou descrição do estudo (curingas * e ?, sem diferenciar maiúsculas). Exemplo: TC vinda de ER_* para o arquivo de ensino, anonimizada.
A garantia
Um estudo nunca pode ficar sem destino. Se o roteamento estiver desligado, se nenhuma regra casar, se o cabeçalho não puder ser lido ou se uma regra citar um destino que não existe mais, o arquivo vai para todos os destinos habilitados. Enviar demais incomoda o operador; enviar de menos perde uma imagem.
A única exceção
Uma regra que pede anonimização para um destino, quando a limpeza não pode de fato ser feita, deixa aquele destino retido: nada é enviado a ele, em vez de mandar o estudo identificado. Duas coisas impedem a limpeza — o perfil estar em off, ou o perfil estar ligado e nenhum anonimizador poder ser construído com as configurações atuais — e elas se resolvem de maneiras diferentes. Nos dois casos nada se perde; veja Anonimização no encaminhamento abaixo.
Quando ligar
Quando esta máquina tiver que entregar imagens a outro sistema: encaminhar ao PACS central, alimentar uma estação de laudo, mandar cópias para um arquivo de ensino.
A aba Destinos de Configuração: três linhas — Main archive, Reading room e Teaching archive —, cada uma com host, porta, AE title, caixas para TLS, sem RIS e failover, e um botão de Echo.
Os destinos são nomeados aqui e referidos pelo nome em todo o resto, então renomear um nó não deixa órfãs as regras que apontam para ele. O «Echo» prova a associação antes que qualquer imagem dependa dela.
A aba Rotas de Configuração: uma caixa para rotear por regras e depois regras numeradas com campos de modalidade, AE chamador, estação, ID do paciente e descrição do estudo, e uma linha «enviar para» com caixas de destino mais anonimizar e parar nesta regra.
As regras são lidas de cima para baixo, e os campos em branco querem dizer «qualquer»: uma regra é um filtro, não um formulário para preencher. A ordem importa, e por isso cada regra traz setas para movê-la.
A aba Travados de Estudos, sob um aviso de que 8 arquivos precisam de atenção, e duas seções. «Tentando automaticamente»: o Teaching archive com duas instâncias do estudo de CR aguardando, uma linha vermelha com o último erro, um botão «Tentar agora» e a contagem para a próxima tentativa. «Retido — nada está sendo enviado»: o Teaching archive marcado «perfil desligado», com seis instâncias do estudo de TC aguardando sob o paciente e o accession number, a edição que as libera, os botões «Configurações de anonimização» e «A regra que pede isso», e «Enviar para…» e «Remover da fila».
As duas seções são problemas diferentes e a aba as mantém separadas. Em cima, um nó fora do ar que vai se resolver sozinho, com o relógio da próxima tentativa à vista; embaixo, uma retenção por anonimização, que nenhum temporizador libera: por isso cada linha soletra a edição que libera e traz os dois botões que abrem a aba onde cada uma se faz. As linhas são agrupadas por estudo, então você vê de quem são as imagens que esperam, não só nomes de arquivo.

A aba tem ainda uma terceira seção, Sem destino para tentar, que esta captura não mostra porque este equipamento não tem nenhum caso: são os arquivos encaminhados a um nome que deixou de ser um destino habilitado — apagado ou desligado na aba Destinos depois de a rota já ter sido decidida. Não sobrou nó para discar, então nada os tenta de novo e nenhum relógio corre a favor deles; o remédio também é outro: restaurar um destino com o mesmo nome, mandá-los a outro destino com Enviar para… ou aceitar a perda com Remover da fila. Cada linha diz o que será dos arquivos, e a distinção importa: uma cópia que a retenção e encaminhamento já prometeu àquele nó espera indefinidamente na pasta de saída, sem ser arquivada nem apagada, enquanto uma que ninguém prometeu é reencaminhada na varredura seguinte sem aquele nome e então arquivada ou apagada conforme o seu Ao enviar, sem nunca ter chegado lá — restaurar o nó só ajuda antes dessa varredura.

Anonimização no encaminhamento

Perfil PS3.15 Anexo E · aplicado só à cópia que sai

O que faz
Aplica o Basic Application Level Confidentiality Profile ao objeto enviado, declarando em (0012,0064) exatamente quais opções de retenção foram usadas, para que quem recebe possa conferir o que foi mantido. O original arquivado nunca é reescrito: essa assimetria é a ideia inteira.
Perfis
basic mantém datas (completas ou deslocadas), características do paciente, identidade do equipamento e da instituição. strict remove identidade de equipamento e instituição e apaga atributos privados mesmo que você peça para manter.
Quando ligar
Quando as imagens saírem do ambiente clínico: ensino, pesquisa, um fornecedor, uma segunda opinião externa.
Ao desligar
O perfil decide se alguma limpeza acontece; a marcação anonimizar de uma regra decide quais destinos recebem a cópia limpa. Se você puser o perfil em off enquanto uma regra continua pedindo, o Carino retém aquele destino em vez de mandar uma cópia identificada para um nó cujo responsável acredita não receber nenhuma.

Retido, não enviado — e é esta a resposta quando os estudos param de andar. Um destino que uma regra marca como anonimizar não recebe nada sempre que a limpeza não puder de fato ser feita. A entrega é adiada, a identidade não é revelada: um estudo esperando em disco se libera com uma edição, enquanto um nome que já chegou a um nó externo não se recupera com edição nenhuma.

Há dois motivos para a limpeza não acontecer, e eles não se resolvem do mesmo jeito. Cada retenção registra qual dos dois é, e a aba Travados imprime o remédio do motivo registrado em vez de adivinhá-lo:

  • O perfil está em off enquanto uma regra continua pedindo a limpeza. Ponha o perfil em basic ou strict e a próxima varredura do encaminhamento automático os libera.
  • O perfil está ligado, mas nenhum anonimizador pôde ser construído com as configurações atuais, então continua não havendo com o que limpar. A falha que impediu isso está na aba Registro de Atividade, no canal de envio — corrija ali. Desligar o perfil não libera esta retenção: não libera nada, só muda qual das duas metades está impedindo a limpeza.

Os dois lugares onde a retenção se solta ficam a um clique da própria linha: ela traz dois botões, Configurações de anonimização, que abre a aba Configurações, onde fica o perfil, e A regra que pede isso, que abre a aba Rotas. Os dois abrem a aba e param aí: nenhum rola até a regra nem a destaca, então a regra você ainda procura na lista. Antes de Configuração ser uma linha só, chegar aos dois era procurar painéis na lateral; agora o conserto é ler a retenção e clicar.

Desmarcar anonimizar na regra libera qualquer uma das duas retenções, e as libera identificadas — exatamente o desfecho que a retenção existe para impedir. Faça essa edição só se aquele destino realmente não deve mais receber dados anonimizados.

Nada se perde e nada disso é silencioso. Os estudos ficam na pasta de saída — nunca são arquivados nem apagados —, os demais destinos do mesmo estudo continuam recebendo, a aba Registro levanta um erro nomeando o estudo, o destino retido e o motivo, o bloco de anonimização da aba Configurações também o nomeia, e o contador ⚠ ao lado da linha Estudos inclui esses arquivos — e esse contador é um botão que abre a aba Travados direto. Nada libera uma retenção sozinho: nenhum temporizador a esgota e nada a tenta de novo.

Não limpa os pixels. Os dados do paciente gravados na imagem — a tarja que um ultrassom ou uma captura secundária imprime dentro do quadro — sobrevivem a todos os perfis, e são a forma mais comum de dados «anonimizados» saírem do hospital com nome e sobrenome. A opção Clean Pixel Data (113101) não é declarada de propósito, porque não é feita. Nada dentro do programa detecta esse vazamento por você: alguém precisa olhar as imagens. Texto livre dentro de laudos estruturados também não é analisado.

Índice

sqlite · index.db

O que faz
Mantém uma linha por arquivo armazenado e deriva dali as respostas de paciente, estudo e série, para que o resumo de um estudo nunca fique fora de sincronia com as instâncias que ele resume. É a camada de consulta por baixo do Query/Retrieve e do DICOMweb.
Quando ligar
Sempre que usar Query/Retrieve ou DICOMweb. É a única dependência dos dois.
O que ele garante
O índice é cache, nunca a fonte da verdade. Perdê-lo custa uma nova varredura, nunca uma imagem.

Query/Retrieve — C-FIND, C-MOVE, C-GET

Porta 11115 · Patient Root e Study Root

O que faz
Permite que outro sistema pergunte «quais estudos você tem deste paciente?» e depois «manda para mim / para aquela estação». É a metade do PACS com a qual o equipamento antigo consegue conversar: um ultrassom de 2009 ou um digitalizador de CR nunca vão falar DICOMweb, mas falam DIMSE.
Quando ligar
Quando estações ou modalidades precisarem puxar estudos daqui, ou quando você estiver servindo de arquivo temporário durante uma queda do PACS principal.
O que ele garante
Um C-MOVE nunca inventa a lista de instâncias: resolve pelo índice. O que o índice conhece mas não pode ser lido do disco é contado como sub-operação falha e nomeado na lista de UIDs que falharam. Nunca é descontado em silêncio: um C-MOVE que reporta sucesso enviando menos imagens do que encontrou é a pior falha possível deste software.

DICOMweb — QIDO-RS, WADO-RS, STOW-RS

HTTP, sob /dicom-web na porta do painel

O que faz
Deixa visualizadores modernos (OHIF, Weasis e afins) consultarem, baixarem e enviarem estudos por HTTP sem negociar uma associação DICOM. O que entra por STOW-RS passa pelo mesmo arquivamento de um C-STORE, então um estudo enviado por um visualizador é indistinguível de um enviado por uma modalidade.
Quando ligar
Quando quiser plugar um visualizador web no acervo. Lembre que o token também protege essas rotas.
CORS
cors_origins é comparado de forma exata (esquema + host + porta) e vem vazio, então nada é devolvido a uma origem que não esteja na lista. Não há sintaxe de curinga, mas um * literal é respeitado, e só porque você o digitou: dali em diante toda origem é refletida e qualquer página que o operador visite poderia ler o acervo desta máquina. Prefira nomear o visualizador.
O que ele não faz
/rendered, /thumbnail, URIs de bulkdata e conversão entre sintaxes de transferência não estão implementados e respondem 406. Um visualizador pela metade é pior que um recurso ausente: o que não pode ser produzido não é fingido.

Modality Worklist (MWL)

Porta 11114 · C-FIND de worklist

O que faz
Serve os pedidos às modalidades para o técnico não digitar os dados do paciente à mão. Cada pedido carrega um Study Instance UID pré-gerado que é gravado no exame, de modo que o estudo devolvido pela modalidade concilia exatamente com o pedido. O campo AE de destino direciona um pedido para uma estação específica; em branco, todas enxergam.
Quando ligar
Quando o RIS não chega até as modalidades: porque caiu, porque o destino simplesmente não tem RIS, ou para testar um fluxo RIS→PACS sem um RIS de verdade.

Modalidades registradas

Sem porta · Configuração → Modalidades

O que faz
A lista de salas que este equipamento atende: um nome que uma pessoa reconhece, o AE title da estação que a worklist compara exatamente, o código de modalidade e, se você quiser, o nome da estação. Não é uma lista de permissões: um aparelho não precisa estar aqui para enviar imagens, e estar aqui também não o autoriza. O que se ganha é que o destino de um pedido passa a ser escolhido numa lista em vez de digitado, e é dela que a sonda de worklist toma emprestado um AE title.
Preencha quando
Você serve a worklist ou digita pedidos à mão. Enquanto não houver nenhuma estação registrada, o destino de um pedido é digitado e um erro de digitação não tem como ser pego.
A aba Modalidades de Configuração: três salas registradas — ER CT, Ultrasound 2 e Portable CR —, cada uma com nome, AE title da estação, código de modalidade e nome da estação, uma caixa de ativo e um botão Testar worklist, sobre um botão de salvar as modalidades.
As salas que este equipamento atende. O destino de um pedido é escolhido nesta lista, e Testar worklist numa linha pergunta ao outro RIS do hospital o que ele daria àquela sala.

Sonda de worklist — perguntar ao outro RIS

Cliente de saída · C-FIND de worklist · Configuração → Modalidades

O que faz
Responde “por que este aparelho não está vendo a lista dele?” sem encostar no aparelho. Dê um endereço ao RIS real do hospital — ou ao broker dele — em Configurações e aperte Testar worklist na linha de uma modalidade: o Carino faz àquele RIS a pergunta que aquela modalidade faria, usando o AE title dela mesma, e arquiva cada resposta em Atividade → Sondas de worklist. Uma execução faz a mesma pergunta cinco vezes, alargando uma chave por vez — estação, data e modalidade; depois sem a modalidade; sem a data; sem a estação — porque o que localiza a falha é a diferença entre as respostas. Se nada volta em nenhuma delas, o outro RIS não tem nada agendado; se só a mais estreita volta vazia, o que está errado é o AE title da estação.
Antes de apertar
Tire a modalidade da rede primeiro. A sonda chama como aquela modalidade, e duas coisas atendendo pelo mesmo AE title num mesmo RIS é uma confusão que alguém depois tem que ir desfazer.
O que não é
Não é serviço, não é agenda e não é fila. O que fica em Sondas de worklist é o registro do que outro respondeu: esses pedidos nunca são servidos na worklist deste equipamento, que não reivindica nenhum deles. Limpar esvazia esse registro e nada mais.
A aba Sondas de worklist de Atividade: uma rodada de sonda feita como US_ROOM_2 ao outro RIS em pacs-peer, listando as cinco perguntas — estação, data e modalidade, depois cada chave retirada por vez — e o que cada uma devolveu, que aqui é sempre nada, porque o outro RIS da demonstração não tem pedidos; à direita, os botões Atualizar e Limpar.
Uma rodada de Testar worklist: o cabeçalho diz a quem se perguntou e com qual AE title, e cada linha é uma pergunta com as chaves que manteve, seguida do que voltou. Leia da mais estreita para a mais larga: se uma pergunta mais larga traz pedidos onde a mais estreita não trouxe nada, a chave que ela retirou é a que estava errada. Aqui todas respondem nada, o que quer dizer que o outro RIS não tem nada agendado para essa sala, não que haja uma chave errada: o RIS da demonstração não tem pedidos.

RIS de emergência — pedidos HL7

Porta 2575 · HL7 ORM^O01 sobre MLLP

O que faz
Recebe pedidos HL7 por MLLP e também permite digitá-los à mão no painel quando não sobrou nada vivo do lado de cima. Quando o estudo volta por C-STORE, ele é conciliado com o pedido pelo accession number (com o ID do paciente como reserva) e o pedido é fechado e arquivado para a trilha — nunca apagado.
Quando ligar
Durante uma queda do RIS, ou em testes de integração.
O que ele garante
A entrega das imagens nunca depende de existir um pedido. Um estudo sem pedido correspondente é armazenado e encaminhado do mesmo jeito; o pedido apenas fica em aberto para conciliação manual.
O painel de pedidos do RIS: um bloco para novo pedido manual, abas de abertos e fechados, uma caixa de busca, uma chave de bipe de chegada, e três pedidos abertos vindos do RIS com número de accession, paciente, modalidade, procedimento solicitado, o remetente HL7 e a hora em que entraram, cada um com um botão «Adicionar PDF/imagem».
Pedidos que chegaram por HL7, e o bloco de cima para digitar um quando não sobrou nada vivo acima. Cada um se fecha sozinho quando o estudo correspondente cai — e é arquivado em vez de apagado. Pedidos do RIS só podem ser cancelados pelo RIS, por isso não têm Cancelar. Um pedido novo faz piscar a linha Pedidos, e esta estação também pode bipar: a chave vale por máquina e é lembrada. Um pedido de fotos do olho (modalidade OP) também oferece Adicionar fotos do olho: o editor abre com esse pedido, e as fotos que ele cria voltam como o estudo do pedido, que assim é fechado.

Sem TLS e sem credencial. Veja a seção de segurança: quem conseguir abrir um socket nessa porta consegue injetar pedidos. Só em rede clínica confiável e com firewall.

Failover de emergência

Vigilância por C-ECHO do PACS marcado como principal

O que faz
Marque um destino como principal e arme o monitor: o Carino faz C-ECHO periodicamente e observa as falhas de encaminhamento. Se ele seguir inalcançável além do limite, você recebe o aviso e a oferta de ativar o RIS de emergência. Ao ativar, sobe a worklist local para os técnicos continuarem examinando, segura o que chega durante a queda e encaminha automaticamente quando o principal volta. Você decide quando voltar ao normal.
Quando ligar
Na máquina que faz de gateway para um PACS do qual você depende. É por isso que a palavra «continuidade» aparece na primeira linha deste manual.

Avisos — webhook e e-mail

Só de saída · webhook HTTP, SMTP

O que faz
Alcança quem não está com o painel aberto. O aviso na tela basta para quem está olhando um envio e não serve para o caso que justifica isto: o principal cai às 03:00 e o radiologista de plantão não está diante de tela nenhuma. Dois canais, independentes um do outro, os dois mortos enquanto a chave geral estiver desligada.
O que envia
Só eventos de failover: disparado, ativado, resolvido. Nenhuma outra parte do equipamento gera aviso. Isto não é um sistema de alertas geral e não vira um só por ser ligado.
Quem recebe o e-mail
Perfis, não endereços. A mensagem vai para cada perfil ativo que o failover esteja configurado para avisar e que tenha um endereço de e-mail preenchido. Com SMTP configurado e nenhum endereço em perfil nenhum não sai nada, e sem barulho: é a primeira coisa a conferir quando “o e-mail está ligado e ninguém foi avisado”. O texto muda conforme o papel de cada um, e o endereço do destino que falhou só aparece para quem já pode ver a tabela de destinos: um e-mail sai do prédio e não tem como ser recolhido.
O que nunca vai fazer
Atrasar ou quebrar aquilo que está reportando. Cada envio é entregue a uma thread separada, a fila tem teto — o mais antigo é descartado e o descarte é contado, porque um “o principal caiu” entregue depois da recuperação é pior que o silêncio — e uma falha vira um contador e uma linha de registro, não uma exceção. Enviados, falhados, descartados, na fila e o último erro são todos legíveis, então “ligado e nunca entregou nada” aparece antes da queda que depende disso. Teste numa tarde tranquila, não durante uma.
Onde configurar
Ainda não no painel: na seção notify do config.json (a URL do webhook, o servidor SMTP e a chave geral notify.enabled). O segredo do webhook e a senha do SMTP passam por POST /api/notify/secret, nunca escritos à mão no arquivo. Cada chave está descrita em CONFIGURATION.md.

Impressão virtual

Porta 11113 · DICOM Print, saída em PDF ou Secondary Capture

O que faz
Se apresenta como uma impressora DICOM (AE title CARINOPRINT por padrão) e captura cada folha de filme que mandarem. Para equipamentos cuja única saída é o filme, é a forma de guardar algo arquivável. Um filme não traz identidade de paciente confiável, então cada um espera em Pendentes até uma pessoa identificá-lo; nada impresso é encaminhado sozinho.
Quando ligar
Quando você tiver uma modalidade que só sabe imprimir e quiser resgatar o resultado dela. Os passos estão em Como faço para… imprimir.
Configurações
Em Configuração → Configurações → Impressão: o AE title e a porta, Aceitar apenas estes AEs (as modalidades que podem imprimir; vazio quer dizer qualquer uma), Aceitar também trabalhos de impressão em cores e Salvar cada filme capturado como PDF ou Imagem. Escolha Imagem quando o PACS ou o visualizador de destino não mostrar PDF — muitos não mostram.
Como saber que funciona
Enviar impressão de teste no cartão faz uma impressão completa passar pelo receptor e deixa em Pendentes uma folha marcada «TEST PRINT — safe to discard». Depois de um trabalho real, o cartão mostra Última impressão (quantos filmes, de qual AE e endereço) e o contador Capturados. Uma recusa ou falha aparece como Último problema; veja a tabela de problemas de impressão.
O que ele tolera
Modalidades que deixam para a impressora a numeração da sessão de filme e da caixa de filme, uma Presentation LUT (aceita e ignorada) e um AE title de impressora digitado diferente na modalidade — o AE chamado não é conferido.
A aba Pendentes de Estudos, com um 3 na aba: o JPEG e, abaixo dele, o PDF que chegaram ao lado do estudo de RM, com nome do paciente, ID, número de accession, data e descrição do estudo já preenchidos a partir desse estudo, um link de pré-visualização, um botão Associar a um pedido… e os botões Aprovar e enviar e Descartar. O terceiro item, o filme capturado pelo receptor de impressão, fica mais abaixo na lista, fora da captura.
Um JPEG e um PDF encontrados ao lado do estudo de RM, cada um com os dados desse estudo já preenchidos. O que não é DICOM espera aqui em vez de virar DICOM no chute; os filmes capturados pelo receptor de impressão também chegam a esta aba, nesta lista abaixo destes dois. Escolha o pedido aberto a que ele pertence com Associar a um pedido…, ou digite a identidade (ID e nome do paciente são obrigatórios), e então aprove. Se você trocar o paciente de um item que chegou junto de um estudo, o painel pergunta se ele continua pertencendo àquele estudo ou começa um novo.

Painel web

Porta 8042 · HTTP, 127.0.0.1 por padrão

O que faz
Estado de cada serviço, destinos, pedidos, registro de atividade ao vivo, configurações e um editor DICOM embutido. Tudo o que o painel faz também existe na CLI.
Como se navega
A lateral tem seis linhas: Resumo, Serviços, Estudos, Pedidos, Configuração e Atividade — e uma sétima, Nó de teste, só em um processo iniciado com --dev-peer. As três perguntas que se fazem sobre o mesmo monte de arquivos são as abas de Estudos — Histórico, Pendentes e Travados; o que se ajusta ao comissionar o equipamento são as abas de Configuração — Destinos, Rotas, Configurações, Modalidades e Pessoas, e ela abre em Destinos, não em Configurações; e os registros são as abas de Atividade — Registro, Conexões, Auditoria e Sondas de worklist. Conexões lista as conexões DICOM recentes nos dois sentidos e diz por que uma falhou e o que mudar, e em qual máquina; o botão O que aceita de cada destino pergunta a ele sobre cada tipo de imagem guardado aqui. Sondas de worklist é o que outro RIS respondeu quando este equipamento perguntou a ele como uma das suas modalidades. Pedidos mantém a própria faixa de abertos e fechados. A linha Estudos carrega dois contadores que são botões, 📎 pendentes e ⚠ travados, e cada um abre a sua aba direto, então chegar aos travados é um clique enquanto houver algo travado: um contador em zero fica escondido, porque um contador que marca 0 é um alarme sempre ligado, e sem ele o caminho é o de sempre — a linha, depois a aba, dois cliques. Pedidos tem o seu próprio contador. Cada painel e cada aba tem endereço na URL — #studies/stuck, #configuration/routing, #activity/logs —, então um lugar do painel pode ir para os favoritos e ser ditado por telefone durante uma queda, que é por que esses endereços são palavras e não ids de elemento; o botão «voltar» do navegador funciona e os endereços antigos no estilo #dlgStuck continuam resolvendo. Resumo é a exceção: ele atende por #overview se você digitar, mas nunca é escrito na barra de endereços nem deixa entrada no histórico, porque imprime o nome de um paciente e uma tela sem ninguém na frente não pode voltar sozinha para ele depois de um recarregamento.
Os chips do cabeçalho
Os chips de serviço no alto continuam iguais para quem pode iniciar e parar serviços. Um perfil que não pode continua enxergando-os como indicadores, mas desabilitados: o estado de um serviço não é informação privilegiada, e a recepção precisa ver um receptor morto sem receber um interruptor que o servidor recusaria.
Quando tirar do loopback
Só com um motivo concreto — e então com token obrigatório e HTTPS na frente. Veja a regra do token.
A aba Configurações de Configuração, aberta no primeiro grupo, Este PACS, marcado com o receptor em execução: a caixa Executar este serviço (também ao iniciar) do receptor, AE title, endereço de escuta, porta, pasta de armazenamento, a caixa de organizar por paciente, estudo e série, o mínimo de espaço livre, a lista de AEs permitidos e a caixa de servir DICOM por TLS. Os outros grupos ficam mais abaixo, e no canto inferior direito estão os botões Escolher serviços de novo e Salvar configuração.
Tudo o que está em config.json, em um formulário, agrupado por tarefa: abra o grupo de que precisa e deixe o resto dobrado. O arquivo continua sendo a fonte da verdade: editar aqui o escreve, e uma configuração que o painel se recusaria a salvar é recusada com o motivo e o campo a que se refere, não reescrita em silêncio. Os grupos são seções recolhíveis — aqui Este PACS aberto, e Envio, Worklist e pedidos, Impressão e os demais recolhidos abaixo —, e Desligar o serviço fica sozinho no último, Zona de perigo. Escolher serviços de novo e Salvar configuração são os botões do rodapé, sempre à vista.
O editor DICOM embutido com um estudo de amostra aberto: a imagem à esquerda com deslizadores de centro e largura de janela, um painel clínico à direita com paciente, modalidade e descrição do estudo — com o nome do paciente escondido atrás de um botão de mostrar — e abaixo um painel técnico com o SOP Instance UID, a sintaxe de transferência, a interpretação fotométrica e o SHA-256 do arquivo.
O editor embutido, aberto a partir de um estudo da aba Histórico ou sozinho. Ele roda inteiro no navegador — nada é enviado para lugar nenhum — e o nome do paciente começa escondido, porque o motivo mais comum para abrir um cabeçalho é ler um UID.
A aba de edição do editor: uma barra com anonimizar (PS3.15), opções, paciente fictício (dados de teste), desfazer e refazer, adicionar tag, JSON, CSV, imprimir, este arquivo e baixar tudo; uma tira com as cinco séries carregadas; filtros por paciente, estudo, série, imagem, equipamento, UIDs e tags privadas; a tabela de tags, uma linha por atributo com seu grupo e elemento, descrição, VR e um valor editável; e no terço direito um painel de edições de imagem —girar, espelhar, inverter e tarjar o texto gravado, escrito nos pixels armazenados— acima da pré-visualização, uma leitura de janela/nível recolhida e a área para soltar arquivos.
A tabela de tags, onde um cabeçalho é corrigido antes de o estudo ser reenviado: um número de accession errado ou um ID de paciente digitado torto, consertado no gateway e não na modalidade que já seguiu adiante.

O nó de teste — um segundo arquivo descartável

Só loopback · pacs serve --dev-peer · nunca em uma versão distribuída

O que faz
Cria um segundo arquivo completo dentro deste mesmo processo, apenas em 127.0.0.1, com AE title próprio, portas próprias de recepção e de Query/Retrieve e armazenamento próprio em uma pasta temporária — e deixa neste equipamento um destino já apontado para ele. É um lugar de verdade para um estudo ir enquanto você comprova que o encaminhamento, uma regra de roteamento, a anonimização no encaminhamento ou um C-MOVE fazem o que você acha que fazem. Ao lado dele é criado um destino “buraco negro” desativado: ative-o e os envios falham de propósito, que é como se enche a aba de travados na hora que você quiser e se vê a cara de um travamento antes que ele aconteça de verdade.
Como abrir um
Suba o motor com pacs serve --dev-peer — ele avisa na linha abaixo da URL do painel —, escolha 🧪 Nó de teste na lateral e aperte Criar nó. O painel passa a mostrar o AE title dele, as duas portas, a pasta e o que já recebeu. Sem esse parâmetro a linha não existe, a API responde 404 e nenhuma configuração do config.json a traz de volta. Isso é proposital: uma configuração pode ser mudada por qualquer um que tenha o token do painel, e um parâmetro de inicialização não é alcançável por HTTP.
Quem pode
Um perfil com permissão para criar e descartar o arquivo de teste descartável. Entre os perfis de fábrica, isso é TI e um administrador: provar onde um encaminhamento está morrendo é trabalho de bancada. A recepção e o radiologista não têm, porque um segundo arquivo é ferramenta de bancada, não clínica. Criar e descartar ficam os dois escritos na auditoria.
O que acontece com o que ele guardou
Vai tudo embora — a pasta e as duas linhas de destino deste equipamento — quando você aperta Descartar, quando o processo para e na próxima inicialização depois de uma queda ou de falta de luz. Nada sobrevive, que é exatamente o motivo de usar isto em vez de escrever à mão uma segunda configuração e esquecer a pasta. Uma coisa a esperar: se você descartar com envios ainda na fila contra ele, esses envios ficam sem para onde tentar de novo; limpe-os em Estudos → Travados.

É ferramenta de bancada, e o parâmetro é o que mantém isso assim. O nó é só loopback, e sem exceção: um arquivo de teste que uma modalidade da rede pudesse encontrar seria um segundo depósito, sem auditoria, das imagens de alguém, e ninguém perceberia que ele está lá. Não passe o parâmetro em um equipamento com estudos reais. As versões desktop e de contêiner nunca o passam por você.

7. Isto não é um dispositivo médico

O Carino DICOM não é um dispositivo médico. Não tem certificação, autorização nem registro em nenhuma autoridade regulatória, em país nenhum. Não tem registro na ANVISA, não tem marcação CE como dispositivo médico, não tem autorização da FDA nem de nenhum órgão equivalente. Ninguém executou sobre ele uma validação para uso clínico.

Não serve para diagnóstico primário. Aqui não há visualizador diagnóstico: sem janelamento, sem medições, sem cadeia de renderização calibrada, sem controle do monitor em que a imagem aparece. Faça o laudo na estação de trabalho validada que você já tem.

Dito sem rodeios, porque é mais útil que uma nota de rodapé:

Nada disso é pessimismo: o projeto leva a sério que uma imagem que nunca chega em silêncio é pior que uma falha barulhenta, e por isso prefere se recusar a iniciar, contar explicitamente as sub-operações que falharam e encaminhar demais em vez de encaminhar de menos. Ele segura uma entrega em um único caso, de forma barulhenta e reversível: um destino para o qual uma regra pede anonimização quando a limpeza prometida não pode ser feita, seja porque o perfil está desligado, seja porque o perfil está ligado e nenhum anonimizador pôde ser construído. Ele diz qual dos dois é, porque os dois se resolvem de maneiras diferentes. Mas o software só responde pelo que ele faz; pelo resto, quem responde é você.

8. Licença e onde pedir ajuda

O Carino DICOM é publicado sob AGPL-3.0-or-later. Como é um servidor de rede, vale o §13: se você roda uma versão modificada como serviço, precisa oferecer o código dela a quem a usa. Mantenha o arquivo LICENSE e um ponteiro para o código junto de qualquer implantação modificada.

Se você achar um erro neste manual — ou uma tradução que um radiologista nunca diria — abra uma issue. Os manuais em português, espanhol, japonês e russo são parte do projeto, não um extra.

Carino DICOM · página inicial · parte da oficina carino.systems · AGPL-3.0-or-later.