Skip to main content

Módulo Anexos (Attachment) — visão geral

O módulo de anexos gerencia os arquivos vinculados a um exame — pedido médico, exame anterior, laudo externo, resultado, documento do paciente, termo de consentimento e outros — e a via de upload para quem não tem login no Portal 2.0. Ele vive em dois pacotes do backend (NestJS), dentro do domínio diagnosis:

  • diagnosis/clinical-media — upload, listagem, consulta, reclassificação e exclusão de anexos de um exame por um usuário autenticado do portal. O mesmo pacote também hospeda áudio, comentários e imagens-chave do exame, documentados em outras páginas; esta seção cobre só a faceta de anexo de arquivo.
  • diagnosis/external-attachment-invitation — emissão de um convite de upload de curta duração para que um terceiro sem conta no portal (ex.: paciente, outra clínica) anexe documentos a um exame específico, sem autenticação de usuário.

Escopo deste levantamento. Cobre só o backend do Portal 2.0 atual (branch integration/with-fixlaudo de mm-pacs-portal-main-api). As telas de frontend correspondentes não foram localizadas nem verificadas — ver A confirmar em cada página de rota.

Prefixo de rotas e versionamento​

Assim como o módulo Authentication, a API usa versionamento nativo do NestJS por URI (VersioningType.URI, versão padrão 1) na mesma aplicação "main" (app/main), então toda rota deste módulo é servida sob /v1/... (ex.: /v1/exams/:examId/attachments). Em desenvolvimento local, o serviço sobe na porta 3000 (MAIN_API_PORT, default 3000) e expõe o Swagger em http://localhost:3000/docs.

Arquitetura​

Anexo interno vs. anexo via convite externo​

As duas vias escrevem na mesma tabela de anexos (diagnosis_exam_attachments), mas com origin diferente: INTERNAL_OPERATOR para upload feito por um usuário autenticado do portal, e EXTERNAL_INVITATION para upload feito por um terceiro através de um convite. A resposta pública de leitura (DiagnosisExamAttachmentResponse) não expõe esse campo origin — só aparece internamente e na trilha de auditoria.

O convite externo nunca usa JwtAuthenticationGuard: a consulta e o consumo do convite são protegidos só por um ExternalAttachmentInvitationCapabilityGuard, que confere apenas o formato Bearer <token> do header Authorization — a validade real do token (existência, expiração, consumo) é responsabilidade do service de cada rota, não do guard.

Classificações de anexo​

O mesmo enum AttachmentClassification vale para as duas vias (upload interno e convite externo): OTHERS, PRIOR_EXAM, MEDICAL_REQUEST, EXTERNAL_REPORT, EXAM_RESULTS, PATIENT_DOCUMENT, CONSENT_FORM, OTHER_ATTACHMENTS. A ordem de exibição na listagem segue uma ordem fixa por classificação (não a data de upload) — ver a página de Anexos do exame.

Proteção de exame assinado​

Um anexo de um exame com status SIGNED ou RESIGNED só pode ser excluído se sua classificação for EXAM_RESULTS; qualquer outra classificação é recusada com ATTACHMENT_SIGNED_SHIELD (400). Essa proteção existe só na exclusão — reclassificar ou adicionar um novo anexo a um exame já assinado não é bloqueado pelo código lido neste levantamento.

Fora do escopo deste levantamento​

Um sistema legado equivalente (mm-pacs-portal-api / mm-pacs-public-api, fora deste levantamento) descrevia recursos adicionais — gestão de anexos duplicados por anexo_original_id, duplicação de anexos entre exames, conciliação de anexos via integração Clinux, e geração de PDF de imagens-chave/laudo. Nenhum desses recursos foi encontrado nos pacotes clinical-media e external-attachment-invitation lidos nesta branch — a coluna originalAttachmentId ainda existe na entidade, mas nenhum service ou rota deste levantamento a consome. Antes de assumir que essas capacidades existem no Portal 2.0 atual, confirme com o time de Diagnosis se elas foram migradas para outro pacote ainda não documentado ou se ficaram para trás como dívida do legado.

Páginas deste módulo​

PáginaCobre
Anexos do examePOST/GET/PATCH/DELETE /exams/:examId/attachments... — upload, listagem, busca, reclassificação e exclusão por um usuário autenticado
Convite de anexo externoPOST /exams/:examId/external-attachment-invitations, GET/POST /external-attachment-invitations/current... — upload por terceiro sem login, via token de curta duração

:::tip OpenAPI A documentação interativa (schemas + "Try it out") está disponível em /docs no ambiente onde a API está rodando (local: http://localhost:3000/docs). :::