Módulo Áudio — visão geral
O módulo de áudio cobre a gravação, a consulta e a exclusão de áudios de ditado anexados a um
exame — o recurso que permite a um médico laudista gravar a própria voz (pelo microfone do
navegador) durante o laudo ou a visualização de imagens, em vez de digitar. Ele vive em um único
controller do backend (NestJS), DiagnosisExamAudioController, dentro do pacote
diagnosis/clinical-media.
Escopo deste levantamento. O pacote
diagnosis/clinical-mediatambém implementa anexos genéricos (DiagnosisExamAttachmentController), comentários (DiagnosisExamCommentController) e marcação de imagens-chave (DiagnosisExamKeyImageController). Esta página e as páginas abaixo cobrem apenas a capacidade de áudio; as demais capacidades do pacote são documentadas em páginas próprias, fora deste módulo.
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), então toda rota deste módulo é servida sob /v1/...
(ex.: /v1/exams/{examId}/audios). 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, sob a tag
"Diagnosis — Exam audios".
Arquitetura
Autorização e RLS
Todas as rotas exigem um access token válido (JwtAuthenticationGuard) e uma permissão específica
por operação, avaliada pelo AuthorizationGuard com escopo resource (kind: 'resource',
resource: 'exam', enforcement: 'rls'), identificado pelo examId do path. Isso soma duas
camadas de controle, confirmadas no código:
- RBAC/ABAC no guard — decide se o ator tem a permissão exigida (
exam:add-audio,exam:list-audioouexam:delete-audio) no escopo (unidade/tenant) resolvido para aquele exame. Sem a permissão, a resposta é403 FORBIDDEN_ACTION. - RLS no banco —
DiagnosisAuthorizationTransactionInterceptorexecuta toda a requisição dentro de uma transação com o contexto de RLS aplicado (RlsContextApplier, a partir das unidades/tenants liberados pelo guard). Um exame fora do escopo do ator fica invisível para as consultas, mesmo que exista — a rota devolve404, não403, para não revelar a existência do recurso.
Os detalhes de como o RBAC/ABAC resolve papéis, políticas e escopos efetivos pertencem ao módulo Authorization; esta página assume esse comportamento e documenta apenas a permissão exigida por rota.
Formato de áudio aceito
O formato do arquivo enviado não é confiado pelo Content-Type declarado pelo cliente nem pela
extensão do nome do arquivo. O AudioContentTypeDetector lê os primeiros bytes do conteúdo
(assinatura binária) e só aceita seis formatos canônicos:
| Formato | Assinatura verificada |
|---|---|
audio/webm | EBML (0x1A 0x45 0xDF 0xA3) |
audio/ogg | OggS |
audio/wav | RIFF...WAVE |
audio/mp4 (m4a) | ftyp no offset 4 |
audio/mpeg (mp3) | ID3 ou frame sync MPEG (0xFF + 0xEx) |
audio/aac | frame sync ADTS (0xFF + 0xFx) |
Qualquer outro conteúdo (incluindo um arquivo vazio) é rejeitado com 415 Unsupported Media Type
antes de qualquer gravação.
Cobertura de testes automatizados
A confirmar — responsável: time de Diagnosis; data: 24/09/2026. A busca no diretório __test__
do pacote encontrou apenas testes unitários para o detector de formato
(audio-content-type-detector.spec.ts) e para a validação do input de domínio
(uploaded-audio.input.spec.ts). Não há teste automatizado (unitário ou e2e) cobrindo o
DiagnosisExamAudioController nem o MaintainDiagnosisExamAudiosService — upload completo,
listagem, busca por id e exclusão não têm cobertura própria confirmada neste levantamento.
Páginas deste módulo
| Página | Cobre |
|---|---|
| Gravar áudio | POST /exams/{examId}/audios — envio de um áudio de ditado para o exame |
| Ouvir e listar áudios | GET /exams/{examId}/audios e GET /exams/{examId}/audios/{audioId} |
| Excluir áudio | DELETE /exams/{examId}/audios/{audioId} — exclusão lógica |
:::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, tag "Diagnosis — Exam audios").
:::