Câmera (getUserMedia) trava indefinidamente ao debugar apps mobile no Service Studio/ODC Studio para macOS — causa raiz: falta de entitlement de câmera no app Produto / Componente Service Studio para macOS / ODC Studio para macOS — Debug de aplicações mobile (alvo "Chrome (emulated)") Ambiente macOS: 27.0 (build 26A5378j) Service Studio: 11.55.78.64991 ODC Studio: 1.7.14.10418 Chrome: 150.0.7871.115 (única instalação no sistema, sem Beta/Dev/Canary) Máquina: MacBook pessoal (não gerenciada por MDM), câmera integrada (MacBook Pro Camera) Resumo do problema Ao iniciar uma sessão de debug no Service Studio/ODC Studio com o alvo "Chrome (emulated)", qualquer chamada a navigator.mediaDevices.getUserMedia() na página fica pendente para sempre — a Promise nunca resolve nem rejeita. Não aparece nenhum prompt de permissão de câmera, nenhum erro no console, e chrome://media-internals → aba "Players" nunca registra sessão de captura alguma (fica "No media player logs" indefinidamente). O mesmo fluxo/URL funciona perfeitamente quando aberto manualmente em uma janela normal do Chrome (fora do Service Studio) — câmera abre e renderiza sem problemas. Impacto Não é possível debugar (breakpoints, inspeção de rede/console via Service Studio) nenhuma tela que dependa de câmera/getUserMedia — inclui fluxos de reconhecimento facial, liveness, upload de foto via captura direta, etc. — usando o Chrome (emulated) integrado ao Service Studio para macOS. Passos para reproduzir Abrir um módulo mobile/reactive com uma tela que chama getUserMedia (ex.: captura de câmera para liveness). Na aba Debug Setup, com "Entry Module: (this module)" e browser "Chrome (emulated)" (única opção disponível), clicar em Start debugging. Navegar até a tela que solicita a câmera. Observar: nenhum prompt de permissão aparece; a tela fica travada (spinner/preto); nenhum erro no console. Investigação já realizada (causa raiz identificada) Passamos por um processo de eliminação completo antes de chegar à causa raiz — resumo dos testes: Verificado que getUserMedia é de fato chamado (interceptado via console) — a Promise fica em estado pending para sempre, sem resolver nem rejeitar. chrome://media-internals → Players: sempre vazio ("No media player logs") durante o travamento — a chamada nunca chega a criar uma sessão de captura rastreável. Descartado: constraints de câmera — constraints usadas (640x480 ideal) são suportadas pelo hardware (confirmado em chrome://media-internals → Video Capture: câmera enumerada corretamente via AV Foundation, múltiplas resoluções). Descartado: iframe / Permissions Policy — elemento de câmera não está em iframe. Descartado: perfil efêmero / modo Convidado (--bwsi) isoladamente — reproduzimos a linha de comando exata usada pelo Service Studio (capturada via ps aux durante uma sessão de debug ativa): /Applications/Google Chrome.app/Contents/MacOS/Google Chrome \ --remote-allow-origins=* --ignore-certificate-errors --no-default-browser-check \ --no-first-run --profile-directory=Default --bwsi --test-type \ --remote-debugging-port=9222 --user-data-dir=/ChromiumAdapterTemp/ \ --disable-search-engine-choice-screen Ao lançar essa mesma linha de comando manualmente pelo Terminal (usuário, não Service Studio) — incluindo --bwsi, --remote-debugging-port (CDP) e perfil novo em $TMPDIR — a câmera funcionou normalmente em todos os testes isolados e combinados. Ou seja, nenhuma flag do Chrome usada pelo Service Studio é, por si só, a causa. Descartado: política/permissão de câmera — testamos inclusive forçar auto-concessão via política gerenciada do Chrome (VideoCaptureAllowedUrls, aplicada e confirmada em chrome://policy com status OK dentro da própria instância do Service Studio) — não teve efeito; media-internals continuou sem nenhuma sessão registrada. Causa raiz encontrada — falta de entitlement de câmera no processo pai: Inspecionamos a assinatura de código dos apps instalados: codesign -d --entitlements :- /Applications/ServiceStudio.appcodesign -d --entitlements :- "/Applications/ODC Studio.app" Resultado: nenhum dos dois declara NSCameraUsageDescription no Info.plist, e nenhum dos dois tem o entitlement com.apple.security.device.camera. Ambos rodam sob Hardened Runtime (com.apple.security.cs.allow-jit, allow-unsigned-executable-memory, allow-dyld-environment-variables), sem App Sandbox completo. Quando o Service Studio/ODC Studio lança o Chrome como processo filho para o debug ("Chrome (emulated)"), o macOS TCC (Transparency, Consent and Control) atribui a decisão de autorização de câmera ao processo responsável (o próprio Service Studio/ODC Studio, via o mecanismo de "responsible process"). Como esse app nunca declarou intenção de uso de câmera nem tem o entitlement correspondente, o TCC não tem como resolver o pedido do processo filho — não autoriza, não nega, não mostra prompt algum. A Promise do getUserMedia() fica pendente indefinidamente. Isso explica por que a mesma URL, com as mesmas flags de Chrome, funciona quando lançada pelo usuário (via Terminal ou Dock) — nesses casos o processo responsável não é o Service Studio, então não há a mesma lacuna de entitlement na cadeia. Bundle IDs afetados com.outsystems.servicestudio.launcher (ServiceStudio.app) com.outsystems.odcstudio.launcher (ODC Studio.app) Correção solicitada Adicionar ao build macOS do Service Studio / ODC Studio: NSCameraUsageDescription (e idealmente NSMicrophoneUsageDescription, caso fluxos de vídeo com áudio também sejam afetados) no Info.plist O entitlement com.apple.security.device.camera (e com.apple.security.device.microphone se aplicável) na assinatura de código para que o processo Chrome filho, lançado para debug ("Chrome (emulated)"), consiga negociar corretamente a autorização de câmera junto ao macOS TCC. Workaround atual (client-side, sem alteração do produto) Não há workaround dentro do Service Studio. Para continuar testando telas dependentes de câmera enquanto o fix não sai: usar "Chrome (emulated)" apenas para a lógica antes/depois da tela de câmera; para a tela em si, copiar a URL gerada pelo debug e abrir manualmente em uma janela de Chrome iniciada pelo próprio usuário (fora do Service Studio) — confirmado funcionando em todos os testes, mas perde a sincronia de breakpoints visuais do Service Studio nessa tela específica.