Embeds: travado ao carregar ou o tópico não é criado e sem logs, o que fazer!

Ao voltar ao trabalho hoje, algumas coisas se destacaram nas páginas de administração. Aqui estão algumas ideias sobre o que poderia ser melhorado.

Configurações de Incorporação — /admin/customize/embedding/settings

allowed_internal_hosts é uma configuração crucial para que a incorporação funcione de forma confiável em ambientes não públicos. Ela deve ser explicitamente listada como uma configuração relacionada nesta seção — não há dúvida sobre sua importância.

Hosts de Incorporação — /admin/customize/embedding

O trecho de configuração fornecido é mais do que útil, pois inclui muitas informações úteis. Acho que podemos usá-lo para fornecer orientação adicional.

Primeiro parágrafo

Atual:\n\n> Cole o seguinte código HTML em seu site para criar e incorporar tópicos do Discourse. Substitua EMBED_URL pela URL canônica da página em que você a está incorporando.\n\nAlternativa:\n\n> Cole o seguinte HTML onde você deseja que os comentários apareçam em sua página.\nA discourseEmbedUrl é a URL de sua página — aquela que será vinculada pelo Discourse. Quando sua página for carregada pela primeira vez, o Discourse tentará encontrar ou criar um tópico para essa URL e vincular de volta ao seu conteúdo.\n\n### Segundo parágrafo\n\nAtual:\n> Se você quiser personalizar o estilo, descomente e substitua CLASS_NAME por uma classe CSS definida no CSS Incorporado de seu tema.\n\nAlternativa:\n\n> Use a propriedade className para adicionar classes CSS à tag <html> dentro do iframe incorporado. Para estilizar, vá para /admin/customize/themes, clique no botão Editar de seu tema, depois no botão Editar Código e selecione Mostrar Avançado. Adicione seu CSS personalizado na seção CSS Incorporado.\n\n### Terceiro parágrafo\n\nAtual:\n> Substitua DISCOURSE_USERNAME pelo nome de usuário do Discourse do autor que deve criar o tópico. O Discourse procurará automaticamente o usuário pelo atributo content das tags <meta> com o atributo name definido como discourse-username ou author. O parâmetro discourseUserName foi descontinuado e será removido no Discourse 3.2.\n\nAlternativa:\n\n> Observação: O tópico é criado por um usuário real do Discourse — não um nome de exibição ou string de autor. Deve ser uma conta válida e existente. Existem três maneiras de determinar qual usuário é usado:\n> 1. Fallback padrão — definido em /admin/customize/embedding/posts_and_topics\n> 2. Substituição por host — definida em /admin/customize/embedding/\n> 3. Controle por URL — adicione uma tag <meta name=\"discourse-username\" content=\"USERNAME\"> à sua página com um USERNAME do Discourse existente\n>\n> Somente o nome de usuário de um usuário existente do Discourse funcionará. O Discourse recorrerá ao padrão de nível de host ou global se o usuário da meta tag não for encontrado. O método de tag <meta> ilustrado aqui permite controle programático por URL sobre qual usuário do Discourse é usado para criar o tópico. Por exemplo, você pode mapear autores de posts de blog em seu site para contas de usuário do Discourse correspondentes.\n\n\n### A seção Trecho de Configuração\n\nA seção recolhível "Trecho de Configuração" é fácil de perder. Visualmente, ela se assemelha a um cabeçalho, e a seta sutil não é intuitiva. Ao contrário do link "Saiba Mais", que é colorido e chamativo, este parece escondido à vista de todos.\n\nEu sei que isso pode ser discutível — alguns podem sentir que a interface do usuário é limpa e suficiente. Mas eu pessoalmente perdi esta seção muitas vezes antes de perceber que ela era clicável. Isso me diz que a usabilidade poderia ser melhorada, mesmo que ligeiramente. Um sinal visual mais claro ou um padrão não recolhido pode fazer uma grande diferença, especialmente para novatos que dependem de exemplos.\n\n### O Trecho\nAtual:\n\n<div id='discourse-comments'></div>\n <meta name='discourse-username' content='DISCOURSE_USERNAME'>\n\n <script type=\"text/javascript\">\n DiscourseEmbed = {\n discourseUrl: 'https://discourse.your-site.com/',\n discourseEmbedUrl: 'EMBED_URL',\n // className: 'CLASS_NAME',\n };\n\n (function() {\n var d = document.createElement('script'); d.type = 'text/javascript'; d.async = true;\n d.src = DiscourseEmbed.discourseUrl + 'javascripts/embed.js';\n (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(d);\n })();\n </script>\n\nAlternativa:\n\n<div id=\"discourse-comments\"></div>\n<!-- Opcional: especifique qual conta de usuário do Discourse cria o tópico -->\n<!-- Se omitido, o Discourse recorrerá ao usuário padrão por host ou global -->\n<meta name=\"discourse-username\" content=\"DISCOURSE_USERNAME\" />\n\n<script type=\"text/javascript\">\n DiscourseEmbed = {\n discourseUrl: 'https://discourse.mydomain.com/', // Barra final obrigatória\n discourseEmbedUrl: window.location.href, // Ou uma string de URL canônica codificada\n // className: 'my-iframe-theme another-class',\n // discourseReferrerPolicy: 'strict-origin-when-cross-origin',\n // topicId: '1234',\n };\n\n (function() {\n const d = document.createElement('script');\n d.type = 'text/javascript';\n d.async = true;\n d.src = `${DiscourseEmbed.discourseUrl}javascripts/embed.js`;\n document.head.appendChild(d);\n })();\n</script>\n\n\n### Opções DiscourseEmbed — descrições curtas\n\n> - discourseUrlObrigatório\n> A URL completa de sua instância do Discourse. Deve terminar com uma barra final, por exemplo, https://discourse.mydomain.com/\n> \n> - discourseEmbedUrlObrigatório\n> A URL completa da página atual onde os comentários estão sendo incorporados. É assim que o Discourse identifica e vincula tópicos ao seu conteúdo.\n> \n> - classNameOpcional\n> Adiciona classes CSS personalizadas ao elemento <html> dentro do iframe. Defina estilos na seção "CSS Incorporado" de seu tema do Discourse.\n> \n> - discourseReferrerPolicyOpcional \n> O padrão é no-referrer-when-downgrade. Veja: Referrer-Policy\n> \n> - topicIdOpcional \n> Se definido, o Discourse usará este tópico diretamente. Caso contrário, ele procurará um tópico correspondente a discourseEmbedUrl ou criará um se nenhum existir.\n\n### Documentação contextual DiscourseEmbed\n> A discourseEmbedUrl deve ser acessível ao seu servidor Discourse. Quando o iframe é carregado, o Discourse busca a página nesse URL para criar ou localizar o tópico. Isso funciona perfeitamente para sites hospedados em plataformas públicas.\n>\n> No entanto, se você estiver desenvolvendo localmente, a incorporação pode parecer presa em "Carregando Discussão…" ou não aparecer. Isso ocorre porque URLs de desenvolvimento local (como localhost) podem ser bloqueadas pela proteção SSRF do Discourse, ou pela opção force_https, ou por um host incorporável ausente.\n>\n> Se você estiver construindo novos recursos para um site existente, uma solução alternativa é apontar discourseEmbedUrl para a URL de produção. Quando embed_any_origin estiver habilitado, o Discourse permitirá que a incorporação funcione mesmo que o iframe seja servido de uma origem diferente. Os comentários serão carregados se existirem, ou um botão "Continuar Discussão" será exibido.\n>\n> Alternativamente, se seu domínio local (por exemplo, localhost) for adicionado em Hosts de Incorporação, você pode não precisar de embed_any_origin. Mas você ainda precisa adicionar localhost como um host incorporável.\n>\n> :warning: Uma ressalva: se a configuração force_https estiver habilitada e seu site de desenvolvimento não usar TLS, a incorporação falhará. Nesse caso, desabilite force_https durante o desenvolvimento ou considere iniciar uma instância separada do Discourse para testes.\n>\n> Observação: Se discourseEmbedUrl for publicamente acessível e a incorporação ainda mostrar "Carregando Discussão…" sem criar um tópico, seu domínio pode ser bloqueado pela proteção SSRF do Discourse.\n>\n> Isso geralmente acontece quando sua instância do Discourse está rodando em um ambiente com resolução DNS local — como Docker, Kubernetes ou uma LAN com um servidor DNS interno. Nesses casos, o Discourse pode resolver o domínio do seu site para um endereço IP local (por exemplo, 127.0.0.1 ou 192.168.x.x) e tratá-lo como inseguro.\n>\n> Para permitir o acesso, adicione seu domínio à configuração do site allowed_internal_hosts. Isso marca explicitamente seu domínio como seguro para buscar, contornando a filtragem SSRF.\n>\n> A lista completa de intervalos de IP bloqueados está disponível no código-fonte do Discourse.\n\n### Hosts Internos Permitidos — Descrição da Configuração do Site\nAtual:\n> Uma lista de hosts internos que o discourse pode rastrear com segurança para oneboxing e outros fins\n\nAlternativa:\n> Permite que o Discourse rastreie hosts que se resolvem para IPs internos. Necessário se o seu site rodar atrás de DNS local (por exemplo, Docker, LAN, Kubernetes). Requerido para incorporações de comentários, criação de tópicos e oneboxing quando a proteção SSRF de outra forma bloquearia o acesso.\n\n## Considerações\nAlgumas dessas sugestões podem ser mais adequadas como links para a documentação oficial. Na verdade, este post sozinho pode cumprir o objetivo, já que deve ser indexado como qualquer outro. Outras podem justificar um pull request adequado — o que eu posso eventualmente fazer, mas não hoje.\n\nDito isso, pode haver imprecisões técnicas no que escrevi. A maior parte vem da experiência prática, mas eu posso ter interpretado mal um comportamento, ter sido enganado pelo cache (ah, cache…), ou simplesmente ter esquecido algo. Nesse aspecto, eu me curvo aos veteranos experientes do Discourse.