Comentários — visão geral
O módulo de Comentários cobre duas capacidades independentes que aparecem juntas na worklist e no laudário, mas não têm relação técnica entre si: comentar um exame (texto livre, sem efeito clínico) e sinalizar um achado crítico (uma marcação booleana do exame, com justificativa obrigatória). Não existe uma tela própria de "comentários" — as duas capacidades vivem dentro de componentes embutidos, abertos a partir de ícones da linha da worklist e da grade de ícones do laudário.
Este levantamento cobre a interface (Angular) do repositório mm-pacs-portal-main-interface,
branch integration/with-fixlaudo, pastas src/app/features/exam-comments e
src/app/features/exam-critical-finding, testado no ambiente
https://task4.srv1812538.hstgr.cloud/. O contrato de API correspondente já está documentado em
Comment — visão geral (back); esta seção documenta a
experiência de tela.
:::caution Atualização (24/09/2026) — bug de bundle confirmado e corrigido; novo bloqueio distinto
Este levantamento inicial (mais cedo em 24/09/2026) foi feito contra um build do ambiente task4
desatualizado (branch integration/all-features, ~100 commits atrás de develop/with-fixlaudo),
que causava HTTP 400 "The GraphQL operation is invalid." ao salvar um comentário — o bundle
antigo ainda enviava os argumentos legados isCriticalFinding/isTechnicalSuspicion que o
código-fonte atual não declara mais.
Depois de atualizar o task4 para develop (front e API), repeti o teste: o erro de schema
desapareceu — a mutation AddExamComment é aceita normalmente (confirmado pelo payload real,
examId/description, sem as flags legadas). Ou seja, aquele 400 era mesmo um artefato do
ambiente de teste desatualizado, não um bug do código documentado nesta página.
Salvar um comentário agora falha por um motivo diferente e novo: a mutation retorna HTTP 200
com um erro GraphQL UPSTREAM_UNAVAILABLE ("A required service is temporarily unavailable.",
statusCode: 503) — reproduzido duas vezes seguidas. Não investiguei a causa raiz (é depuração de
infraestrutura de um serviço a jusante, fora do escopo desta documentação de tela) — audit-api e
RabbitMQ compartilhado estavam com status saudável quando verifiquei, então a causa provável é
outro serviço downstream específico da mutation de comentário. A confirmar — responsável: time de backend; data: 24/09/2026: identificar qual serviço a jusante da mutation addExamComment está
indisponível.
Por causa disso, as capturas abaixo ainda mostram o formulário preenchido e um estado de erro — não foi possível capturar um comentário efetivamente salvo e listado neste levantamento. :::
:::caution Pendência deste levantamento — sem exame concluído para achado crítico
O único exame de teste da unidade ("Paciente Teste Docs Portal2") está no status Recebido, não
Concluído. A política canFlagCriticalFinding (src/app/entities/exam/lib/exam-policy.ts:440)
exige isExamConcluded(exam.status), então o botão Sinalizar achado crítico simplesmente não
aparece na barra de ações da linha, para nenhum perfil — confirmado navegando com administrator.
O laudário, que também hospeda esse gatilho, continua inacessível de fato: o botão Abrir
Laudário está habilitado (comportamento atualizado — ver Laudário), mas
abri-lo falha com o bug real de schema GraphQL documentado lá (PreviousExamsFilter/
ReportVariables), então não dá para chegar à tela de achado crítico dentro do laudário. A confirmar — responsável: time de frontend; data: 24/09/2026: repetir este levantamento com um
exame concluído (laudo assinado) e o bug de laudário corrigido, para capturar o diálogo de achado
crítico e a matriz de permissões completa.
:::
As duas capacidades, na tela
Páginas deste módulo
| Página | Cobre |
|---|---|
| Comentários do exame | Popover app-exam-comments: listar, adicionar, apagar comentário; e os atalhos combinados Pendente/Reconvocar/Retornar para laudar que gravam um comentário e trocam o status numa única ação |
| Achado crítico | Diálogo app-exam-critical-finding-dialog: sinalizar ou remover a flag de achado crítico do exame, com justificativa obrigatória |
Onde cada capacidade vive
Nenhuma das duas é uma rota própria — não há entrada em app.routes.ts para nenhuma delas
(confirmado por busca em todo src/app). Os dois componentes são hospedados por dois pontos de
entrada cada:
| Capacidade | Componente | Hospedeiro 1 | Hospedeiro 2 |
|---|---|---|---|
| Comentar exame | ExamCommentsComponent (features/exam-comments) | Ícone de balão na linha da worklist — exam-worklist.component.html:639-644 e 664-697 | Ícone pi-comments da grade de ícones do laudário — exam-report-page.component.html:672-677, acionado por report-quick-icons.component.ts:162-166 |
| Achado crítico | ExamCriticalFindingDialogComponent (features/exam-critical-finding) | Botão Sinalizar achado crítico da barra de ações expandida da linha — exam-actions-bar.component.ts:229-231, exam-worklist.component.ts:1481-1482 | Ícone pi-exclamation-triangle da grade do laudário — report-quick-icons.component.ts:181-185, exam-report-page.component.ts:1393-1395 |
O código do próprio diálogo de achado crítico documenta que ele foi unificado: existiam dois
componentes com o mesmo nome de classe e o mesmo seletor em slices diferentes do projeto (um sabia
remover a sinalização, o outro não; o mínimo de caracteres do comentário divergia entre eles) —
hoje há um só, parametrizado por examId para servir tanto a worklist (que tem o Exam inteiro)
quanto o laudário (que só tem o id) (exam-critical-finding-dialog.component.ts:48-53).
Permissões usadas neste módulo
| Camada | O que decide | Onde |
|---|---|---|
| Front — mostrar/ocultar o ícone de comentário | canCommentExam(exam, user): !exam.isDeleted && (user.canAddComment || isPlatformAdmin), com canAddComment vindo de exam:add-comment em qualquer escopo do IAM | exam-policy.ts:171-173, exam-user-context.factory.ts:42 |
| Front — desabilitar (não ocultar) o ícone quando falta a permissão | commentDenied(exam), tooltip EXAM.ACAO.SEM_PERMISSAO_COMENTAR | exam-worklist.component.ts:940-941 |
| Front — apagar um comentário | Só ownership local: comment.userId === currentUserId() — não há checagem de exam:delete-comment no front; o backend segue sendo a fonte de verdade | exam-comments.component.ts:170-173 |
| Front — mostrar o botão de achado crítico na worklist | canFlagCriticalFinding(exam, user): !exam.isDeleted && isExamConcluded(exam.status) && isExamOperator(user), onde isExamOperator é isPlatformAdmin || canUpdate || canSign — não uma permissão dedicada | exam-policy.ts:440-443, exam-policy.ts:148-150 |
| Front — mostrar o ícone de achado crítico no laudário | Query GraphQL própria ExamCriticalFindingPermission → examPermissions.canFlagCriticalFinding, calculada pelo servidor para aquele exame específico — política diferente da usada na worklist | exam-actions.service.ts:880-887, exam.graphql.ts:480-485 |
| Back — todas as rotas | exam:add-comment, exam:list-comment, exam:delete-comment, exam:flag-critical-finding, exam:flag-technical-suspicion, escopo RLS por unidade | ver Comment — visão geral (back) |
:::info Achado de código: nenhuma permissão granular de flag é lida em produção no front
As strings exam:flag-critical-finding e exam:flag-technical-suspicion — que o backend exige nas
rotas PUT/DELETE /exams/:id/critical-finding e /technical-suspicion — só aparecem no catálogo
de personas de mock (personas.ts:19-20) usado pelos testes locais; nenhuma política de produção
lê essas strings. O front decide se mostra o botão com uma aproximação própria
(isExamOperator: platform admin, ou exam:update, ou exam:sign), não com a permissão granular
da flag. Isso significa que a visibilidade do botão no front e a autorização real da mutation no
backend podem divergir para um usuário no limite (ex.: alguém com exam:flag-critical-finding mas
sem exam:update/exam:sign veria o botão oculto, mesmo podendo executar a ação no servidor). A confirmar — responsável: time de frontend; data: 24/09/2026.
:::
Lendo o catálogo de papéis do backend
(mm-pacs-portal-main-api/package/identity/authorization/core/models/identity-system-role.ts), dos
9 perfis de teste deste levantamento (docs-usuarios.md):
| Permissão | Quem tem no catálogo | Observação |
|---|---|---|
exam:add-comment / exam:list-comment / exam:delete-comment | administrator, manager (ver nota abaixo) | doctor, technician, resident, read_only, typist, requestor, financial não têm essas três no catálogo (DOCTOR_PERMISSIONS, identity-system-role.ts:179-192, não lista nenhuma) |
exam:flag-critical-finding / exam:mark-clinical / exam:flag-technical-suspicion | administrator, manager | mesmos ausentes acima |
:::caution Discrepância confirmada entre catálogo e comportamento observado
O catálogo acima diz que doctor não tem exam:add-comment. Mas navegando com
docs.doctor@mobilemed.test neste ambiente, o ícone Inserir comentário aparece habilitado
(não desabilitado, sem tooltip de bloqueio) na linha do exame de teste — o mesmo padrão observado
com administrator. Isso sugere que o tenant "Clínica Docs Portal 2" foi provisionado com um
conjunto de permissões por papel diferente do catálogo hardcoded lido acima (possivelmente por um
caminho de reconciliação de papéis análogo ao já documentado para manager no módulo de
Exames (ver o quadro "Achado de código" na seção "Quem acessa o quê — visão
rápida").
Não foi possível confirmar a causa raiz dentro do escopo deste levantamento. A confirmar — responsável: time de backend/IAM; data: 24/09/2026.
:::
Contexto de negócio (legado) — Bitrix
Os cards abaixo (funil de features do sistema legado, entityTypeId 1320) descrevem a intenção de produto original deste módulo. Eles não são fonte de comportamento atual — várias regras do legado (prefixo de texto no comentário, exclusão mútua achado crítico/suspeita técnica, motivo obrigatório configurável por empresa) não foram portadas, como já detalhado nas ressalvas da doc de backend. Listamos aqui só id e título, como contexto histórico:
| Card | Título |
|---|---|
| 672 | F-001 — Comentar exame (criar e listar comentários) - Front |
| 680 | F-003 — Comentar achado crítico / suspeita técnica (com sinalização do exame) - Front |
Relacionado
- ⚙️ API: Comment — visão geral
- 💬 Comentários do exame
- 🩺 Achado crítico
- 📋 Exames — Ações da linha — onde os ícones desta doc se encaixam no restante da linha
- 🔐 Permissões