Um plugin é uma página web sua que roda dentro de um iframe do Novus CRM. A página pode ficar no seu próprio servidor ou ser enviada ao Novus CRM como pacote. Os dois caminhos estão em Publicar um plugin. A página conversa com a plataforma por um protocolo baseado em postMessage. Ela se registra dizendo o que quer expor, e o Novus CRM chama de volta quando o usuário interage com aquilo. O plugin não recebe token de autenticação e não acessa o banco de dados da conta diretamente. Toda chamada de API passa por um proxy que roda no servidor do Novus CRM. Esse proxy decide o que é permitido e resolve qualquer segredo necessário, sem expor esse valor ao código do plugin.

Repositório de exemplo

Implementação completa de um plugin, com README explicando cada peça do protocolo. É o jeito mais rápido de ver isso funcionando.
Para criar ou adaptar seu plugin com um agente de IA, siga o guia Criar plugins com IA. Ele mostra como instalar a skill no Codex, Claude e Gemini, ou usar as instruções com outro modelo.

Onde um plugin pode aparecer

Um plugin se registra chamando initialize com um objeto descrevendo o que ele expõe. Cada chave do registro é opcional, e um plugin pode combinar quantas quiser.

Botões no atendimento (buttons)

Um botão aparece em um dos cinco grupos abaixo, dependendo de onde ele precisa ficar visível. O grupo escolhido também define o que chega no callback quando o atendente clica. Os botões do Chat recebem { id, usuario, contato, canal }. usuario e canal podem ser null. Quando existem, trazem apenas { id }. contato traz { id, numero }. Use id para identificar o atendimento no clique. Nos eventos de atendimento, o campo correspondente se chama atendimentoId e o payload inclui mais dados. Não use os dois formatos como se fossem iguais. Com o SDK, use label ou text para o nome do botão e passe uma função em callback. O SDK cria o callbackId usado pelo host. Se implementar postMessage diretamente, registre a função no seu JavaScript e envie apenas o callbackId. Para ícones em arquivo, use icon_url com uma URL absoluta. O payload de ticket-menu traz o ticket como a tela mostra:
  • Campos resolvidos — id, codigo, assunto, privacidade, status, urgencia, categoria, servico, justificativa, responsavel, solicitante, emailSolicitante, cliente, cc, abertoEm, abertoPor, tipoAbertura, dataDeVencimento, dataDeVencimentoPrimeiraResposta e etiquetas.
  • Vínculos — ticketsPais, ticketsFilhos e ticketsMesclados, só os códigos.
  • camposPersonalizados — cada item com id, nome e valor.
  • referencias — status, urgência, categoria, serviço, justificativa, responsável, solicitantes e etiquetas como pares { id, nome }, para quem vai chamar a API pública.
  • interacoes — ações carregadas no ticket, com número, modelo, autor, tipo de autor, data, corpo em HTML e nomes dos anexos.
Os itens só aparecem em ticket já salvo.

Mostrar o botão só em alguns casos (quando)

Declare quando no botão para que ele apareça só nos itens que atendem a uma condição. O Novus CRM compara esse objeto com o payload que o clique enviaria e mostra o botão quando todas as chaves batem. Isso vale para todos os grupos de buttons. No Plugin Studio, o preview usa o cenário escolhido para decidir.
  • Cada chave é um campo do payload. Para chegar a um campo dentro de objeto, use ponto, como em canal.id ou referencias.categoria.id.
  • Uma lista de valores aceita qualquer um deles, como em { status: ["Aberto", "Em andamento"] }.
  • Se o campo do payload já for uma lista, como etiquetas, basta um item bater.
  • O Novus CRM compara os valores como texto, sem diferenciar maiúsculas e ignorando espaços nas pontas.
  • Campo ausente ou null esconde o botão.
Sem quando, o botão aparece sempre, como antes.

Itens de menu (navbar)

Um item de navbar aparece no menu principal do Novus CRM. O tipo group só organiza outros itens e não dispara nada ao clicar. O tipo item abre a página do plugin em /extensao/{id}. Declare um id no item para que o callback rode no iframe da página, inclusive quando ela terminar de carregar depois do clique. Use label ou text no item. type: "item" é o padrão. Para organizar o menu, registre um item com type: "group" e um id. Nos itens desse grupo, use parentId com o mesmo valor. O grupo não executa callback.

Painel lateral (widgetbar)

Um item de widgetbar vira um ícone na barra lateral direita. Sem callback, clicar nele abre o próprio painel do plugin, o mesmo efeito do comando openWidget. Com callback, o clique roda lógica dentro do iframe em vez de abrir o painel.

Itens de configurações (options)

Um item de options aparece dentro de Configurações, na área de Plugins. Um item do tipo item abre o plugin dentro da tela de configurações ao ser clicado. O callback roda no iframe dessa página. Declare um id para que o item funcione também após atualizar a página ou abrir seu link direto. Os campos label, text, type e parentId seguem a mesma regra de navbar.

Eventos de atendimento (events)

Registre em events apenas os eventos que seu plugin usa. Ao selecionar um atendimento, o Novus CRM emite aoAbrirAtendimento e aoFocarAtendimento com o mesmo payload. Se você escutar os dois, evite repetir a mesma consulta. Os eventos de abertura e foco são reenviados ao plugin que se registra depois. A abertura de uma conversa anterior também é reenviada nessa situação.

Onde o código do plugin executa

O Novus CRM carrega um iframe em segundo plano para registrar botões e menus. Ao abrir o painel ou a página do plugin, carrega outro iframe visível. Cada iframe tem seu próprio estado em memória. Callbacks de buttons e de widgetbar com callback rodam no iframe em segundo plano. Callbacks de options rodam no iframe visível. Em navbar, um item com id também roda no iframe visível. Sem id, o callback roda em segundo plano. Os callbacks de widgetbar, navbar e options não recebem payload do clique. Para abrir um modal do plugin ou navegar dentro dele, use um callback no iframe visível. Eventos de atendimento chegam aos dois iframes quando ambos estão abertos. Uma chamada feita pelo handler pode ocorrer duas vezes. Evite ações que alteram dados nesse handler. Para consultas, trate a repetição e descarte respostas antigas quando o atendimento mudar.

Comandos disponíveis

Um plugin chama os comandos abaixo para interagir com o Novus CRM. getInfoUser, getInfoChannels, apiRequest, openAlert e openPage devolvem uma resposta. closeModal, load e openWidget não devolvem. initialize mantém o canal de eventos, enquanto openModal e openConfirmDialog usam canais para callbacks. Os exemplos desta página usam WlExtension. Baixe o SDK servido pelo Novus CRM como wlclient.js e inclua esse arquivo no seu projeto. Carregue-o antes do script do plugin:
Se você criar o plugin no Studio, mantenha o SDK dentro do pacote. A validação recusa scripts carregados de outro domínio. O repositório de exemplo implementa o mesmo protocolo diretamente com postMessage e MessageChannel, sem precisar desse arquivo. Com o SDK, openAlert é WlExtension.alert({ message, type }). O host mostra um aviso informativo e não usa type para mudar a aparência. openPage é WlExtension.openPage({ path }). Uma rota iniciada por / navega no Novus CRM. Uma URL absoluta só navega no iframe visível quando pertence à origem do plugin. Você pode passar { url } a openWidget para escolher a página mostrada no painel. Use uma URL HTTP(S) ou um caminho iniciado por /. Por padrão, o painel fecha quando a pessoa clica ou rola a tela fora dele. Com closeOnOutsideClick: false, ele só fecha pelo X ou por closeModal. openPage também aceita uma string no lugar de { path }. Para uma URL recusada, ele devolve { navigated: false }. WlExtension.identifier traz o identificador do plugin recebido no parâmetro ?id= do iframe. Ele não identifica o usuário logado. Para isso, use getInfoUser(). O SDK também exporta a constante button_action, mas o host não executa esse comando. Para reagir a um clique, registre o callback do botão em initialize.
WlExtension.confirmDialog() envia openConfirmDialog, mas o host devolve confirmação positiva sem mostrar um diálogo. Não use a resposta para autorizar uma ação irreversível. Mostre a confirmação na interface do próprio plugin.

Como obter os dados da tela

O atendimento em foco chega pelo callback de aoAbrirAtendimento ou aoFocarAtendimento. Registre esses eventos em initialize. O payload inclui atendimentoId, canalId, contato.id, contato.nome e contato.numero. O Novus CRM reenvia o atendimento em foco ao iframe que termina de se registrar. aoFecharAtendimento chega sem payload quando a seleção é limpa. Use-o para limpar o estado local.
Para identificar quem está logado, chame getInfoUser depois de initialize. A resposta tem id, name e email. getInfoChannels devolve canalId, descricao, identificador, number, type e status para cada canal. type é numérico. O host devolve CONNECTED ou OFFLINE em status. Os campos organizacao e organizacaoId vêm vazios, então não os use para descobrir a conta atual.
Se você usar o plugin.js do exemplo, faça as mesmas consultas com enviarComando("getInfoUser", null) e enviarComando("getInfoChannels", null). Essa função abre um MessageChannel por comando. O host responde com data ou error, e a função resolve ou rejeita a Promise. O usuarioId e o objeto usuario desse atendimento identificam o atendente atribuído. Eles não substituem getInfoUser, que identifica quem está logado. Para obter mais dados, use apiRequest com um endpoint confirmado da API pública. Os botões recebem o item clicado no callback. lista-contatos recebe o contato. Os três grupos do Chat recebem o resumo descrito acima. ticket-menu recebe o ticket com interacoes. Para openModal, use um canal de callback. closeModal, openWidget e load não enviam resposta. Não espere por eles com enviarComando.

Como a página do plugin abre

O campo modo do cadastro vale para abrir o plugin pelo menu do atendimento. modal sobrepõe a tela atual. rota abre /extensao/{id}. Um item de navbar sempre abre essa rota. Um item de options abre /opcoes/extensao/{id} dentro de Opções. widgetbar abre o painel lateral. Essas superfícies não mudam de lugar quando você altera modo. Em uma página visível do plugin, WlExtension.modal() envia openModal. No iframe em segundo plano, esse comando não abre o modal. Informe uma URL da mesma origem da página cadastrada. O host abre outro iframe e entrega o resultado ao callback. Fechar com Esc devolve null. Use titulo para o título mostrado pelo Novus CRM. As propriedades title e autoClose definidas no SDK não alteram esse modal.
Na página detalhes.html, carregue o SDK e chame initialize antes de enviar outros comandos. Depois de salvar, use WlExtension.closeModal({ salvo: true }). O host entrega esse objeto ao callback da página que abriu o modal.

Chamando uma API externa (apiRequest)

Para chamar um sistema externo, use o host externo, informe a URL completa em endpoint e declare o domínio em permissões do plugin. Guarde qualquer chave de API como variável da conta, nunca no código do plugin.
O plugin manda só o nome do segredo (meuErpApiKey, no exemplo). O Novus CRM resolve esse nome para o valor real do lado do servidor e injeta no cabeçalho, na query ou no corpo da requisição, conforme indicado em in. O código do plugin, rodando no navegador de quem atende, nunca recebe esse valor.
1

Cadastre o segredo

A chave de API do sistema externo é cadastrada como segredo no Novus CRM, com o nome que o seu plugin vai referenciar em secretRefs.
2

Declare o host e o segredo

Liste externo em permissoes.hosts, api.exemplo.com em permissoes.dominiosExternos e o nome do segredo em permissoes.segredos do novus-plugin.json. Veja Manifesto e permissões.
3

Publique e cadastre o plugin

Hospede o plugin no seu próprio domínio com HTTPS, ou envie o pacote para a hospedagem do Novus CRM, e cadastre-o na plataforma, como descrito em Plugins.
Se faltar uma declaração ou variável, apiRequest falha com um dos erros listados em Erros do proxy.
Um host pode dispensar secretRefs. A API pública do Novus CRM (host publica) já resolve a própria autenticação a partir da chave da sua conta, sem o plugin precisar referenciar segredo nenhum. Os exemplos abaixo mostram os dois casos lado a lado.

Exemplos de uso

Os exemplos abaixo mostram como combinar superfícies, eventos e comandos. As URLs em api.exemplo.com são ilustrativas. Troque-as pelo endereço do seu serviço.
Um widgetbar consulta um ERP externo sempre que o atendente abre um atendimento, e mostra o status do pedido daquele contato sem sair da tela. A implementação completa está no repositório de exemplo, no topo desta página.
Um botão no header do atendimento chama a API pública do Novus CRM para enviar um texto ao contato da conversa aberta. Esse host (publica) não pede secretRefs. A chave da API pública já é resolvida automaticamente pelo proxy.
O corpo segue o mesmo contrato de Enviar mensagem de texto na API pública. Se o atendimento tiver mais de um canal disponível, use getInfoChannels() para deixar quem atende escolher por qual reenviar, em vez de assumir atendimento.canal.id.
Um botão na lista de contatos recebe o contato clicado como payload e cria, ou atualiza, o mesmo cadastro num CRM externo, usando uma chave de API guardada como segredo.
Um item de navbar abre a página de indicadores do plugin na tela inteira. O Novus CRM abre /extensao/{id} como página própria.
Um item em Configurações abre uma tela de preferências. getInfoUser identifica quem está logado, útil para aplicar uma preferência por atendente ou por departamento.

Desenvolver e publicar

Publicar um plugin

Endereço próprio ou hospedagem no Novus CRM, desenvolvimento local, pacote, versões e isolamento.

CLI e API de publicação

Publicar versões do terminal ou da pipeline de CI.

Catálogo de plugins

Compartilhar um plugin hospedado com outras contas.

Criar com IA

O Plugin Studio escreve um plugin hospedado a partir de uma descrição em português. Um agente de IA escreve os arquivos, confere o código contra o protocolo e o manifesto e envia versões de rascunho. Você acompanha cada passo, testa o painel no host de atendimento e publica pelo mesmo fluxo de versões do envio manual.
1

Crie o plugin

Em Opções → Plugins, clique em Criar com IA. O plugin nasce hospedado no Novus CRM, visível só para quem criou, com um endereço provisório no formato studio-k3j9x0a2mq.
2

Descreva o que o plugin faz

O agente abre a conversa pedindo a descrição. Na coluna Conversa, escreva o pedido. Por exemplo, um painel na barra lateral que lista as vendas do contato no C-Plus 5. A conversa mostra cada arquivo escrito, a validação e o envio da versão, e termina com a resposta do agente. Você pode anexar até quatro imagens PNG, JPEG, WEBP ou GIF. Cada imagem pode ter até 5 MB, com limite de 10 MB por mensagem. Mesmo com imagens, escreva uma mensagem para explicar o pedido.
3

Confirme o endereço

O agente propõe um endereço livre para o plugin e pede a sua confirmação na conversa. Enquanto o endereço for provisório, Publicar fica desligado.
4

Teste no preview

A coluna Preview carrega o plugin no host de atendimento, com um atendimento ou um ticket da sua conta. Peça ajustes na conversa ou edite o código na coluna Código.
5

Publique

Clique em Publicar. O plugin continua visível só para você até alguém clicar em Liberar para a equipe.
Quem criou o plugin, o administrador e o responsável da conta podem abrir o Studio de um plugin. Em Opções → Plugins, cada pessoa vê os plugins que pode abrir. Quem não é administrador vê só os que criou. Pela tela de versões, o botão Abrir no Studio leva de volta a ele.

O que o agente faz

O agente trabalha com um conjunto fechado de ferramentas: O agente conhece só os nomes das variáveis globais. Nenhum valor chega ao modelo, aos arquivos do plugin ou às versões. Ele também não lê a resposta das APIs que o plugin chama no preview. Uma mensagem por vez. Enquanto o agente trabalha, o editor fica só para leitura e a conversa não aceita outra mensagem. Cada turno tem um limite de passos. Quando chega nele, o agente para e responde com o que já fez. Use Parar para interromper o turno. Os arquivos voltam ao estado anterior à mensagem, e o texto volta para o campo. Use Limpar para apagar o histórico da conversa sem alterar os arquivos do plugin.

Credencial na conversa

A conversa recusa, antes de sair do navegador, a mensagem que parece ter uma credencial. A mensagem não entra no histórico. Os padrões são os mesmos do aviso de credencial do envio de pacote:
  • X-Chave-Api seguido de um valor
  • Basic seguido de um valor em base64
  • chave com prefixo sk-
  • token do GitHub com prefixo ghp_
  • chave privada (-----BEGIN ... PRIVATE KEY-----)
  • chave de acesso da AWS com prefixo AKIA
Cadastre o valor numa variável global e cite só o nome dela na conversa.

Validação

Antes de enviar uma versão, o agente valida os arquivos e recebe todos os problemas de uma vez. A validação tem duas partes. Regras de texto. Rodam sempre, também a cada salvamento no editor. Captura do registro. O Novus CRM carrega index.html e o script de entrada num navegador simulado, sem rede e com tempo limite de 10 segundos. Ele confere que initialize é a primeira mensagem ao host, que nada lançou exceção antes dele e que o registro usa só chaves conhecidas. Uma exceção no escopo do módulo aparece com a linha. Se a captura não rodar, a validação segue só com as regras de texto e o resultado avisa isso. A ferramenta de linha de comando usa a mesma captura em novus-plugin validar. Veja CLI e API de publicação.

Rascunho ao vivo

Os arquivos em edição respondem num endereço próprio, sem cache:
Cada arquivo salvo, pelo agente ou pelo editor, recarrega o preview. O endereço exige o token t. Sem ele, ou com um token errado, a resposta é 404, a mesma de um endereço que não existe. As respostas levam os mesmos cabeçalhos de isolamento das versões numeradas. A raiz serve o arquivo de entrada do manifesto, ou index.html quando ele não existe. O menu Rascunho, no cabeçalho do preview, tem três ações:
  • Abrir em outra aba: abre o rascunho sozinho, fora do atendimento.
  • Abrir no atendimento: abre o chat numa aba nova com o rascunho no lugar da versão no ar. Só a sua sessão carrega o rascunho, e a faixa Só você vê essa versão fica no topo até você clicar em Encerrar.
  • Gerar novo link: troca o token. O link antigo passa a responder 404 na hora, e o preview do Studio e o rascunho aberto no atendimento passam a usar o novo.
Para mostrar o plugin a outra pessoa, use o endereço de uma versão numerada.

Preview

O preview roda o plugin no host de atendimento do Novus CRM, com o cabeçalho do atendimento, o menu de opções do ticket e a barra lateral direita. Você escolhe o cenário:
  • Atendimento: um atendimento da conta. O host reemite aoAcessarPaginaChat, aoAbrirAtendimento e aoFocarAtendimento a cada carregamento do plugin. Trocar de atendimento emite o fechamento do anterior e a abertura do novo.
  • Ticket: um ticket da conta, entregue ao clicar num botão de ticket-menu. O ticket do preview vem da listagem, sem interações, campos personalizados e etiquetas. Esse cenário aparece apenas quando a conta tem o módulo de tickets contratado.
apiRequest vai ao proxy de verdade. Enquanto o plugin não tem versão no ar, o proxy aceita no preview de quem criou o plugin as permissões do novus-plugin.json em edição. Depois da primeira publicação, valem as permissões aprovadas da versão ativa, como em qualquer plugin. Abaixo do preview, o painel de tráfego lista o initialize, os eventos, os cliques e cada apiRequest com host, endpoint, método, status e duração. Os erros do proxy aparecem já traduzidos, e as 20 entradas mais recentes vão ao agente junto com a sua próxima mensagem. O botão de tema mostra o plugin no tema claro ou no escuro.

Código

A coluna Código tem um editor com os arquivos do plugin. O arquivo é salvo com Ctrl+S ou meio segundo depois que você para de digitar. Cada salvamento roda as regras de texto e recarrega o preview. Use Buscar nos arquivos para procurar em todos os arquivos de texto. A busca pode diferenciar maiúsculas, considerar a palavra inteira ou usar uma expressão regular. Clique num resultado para abrir o arquivo naquela linha. Maximizar o código esconde as outras colunas do Studio. Use Restaurar as colunas para voltar à visualização anterior. Um erro de sintaxe em JavaScript ou JSON aparece no editor com a linha. O arquivo é salvo mesmo assim, e o preview continua no último estado que carregava. Depois de cada turno, as linhas que o agente mudou ficam destacadas. No turno seguinte, o agente recebe a lista dos arquivos que você editou e não desfaz a edição sem avisar.

Versões de rascunho

Cada iteração fechada do agente vira uma versão com origem Studio. O campo versao do manifesto recebe o sufixo -rascunho.{n}, em que n é o número da versão. Um manifesto 1.2.0 gera 1.2.0-rascunho.7. Sem versao válida, a base é 0.1.0. Uma iteração que não mudou nenhum arquivo não cria versão, e a conversa aponta a que já existe. Os rascunhos seguem regras próprias:
  • ficam fora da lista de versões, salvo com Mostrar rascunhos do Studio marcado
  • não contam nas 20 versões guardadas por plugin
  • o Novus CRM guarda até 30 rascunhos por plugin, por até 48 horas, e nunca apaga a versão ativa nem a última enviada
  • os bytes contam no espaço de 500 MB da conta
  • um rascunho não pode ser publicado pela lista de versões
Desfazer, na coluna Conversa, devolve os arquivos ao conteúdo da versão anterior. Se você mudou algo depois do último rascunho, a volta é para esse rascunho. Nenhuma versão nova é criada.

Publicar pelo Studio

Publicar empacota os arquivos atuais numa versão comum e a coloca no ar. O campo Versão é opcional. Vazio, o Studio soma 1 ao último número da maior versão já enviada que não é rascunho. Sem versão anterior, usa a base do manifesto. Uma versão com -rascunho. no nome é recusada. Quando a versão pede permissões que a versão no ar não tinha, o diálogo lista cada uma em linguagem de atendente. A lista sai do novus-plugin.json que vai virar a versão, inclusive com as edições feitas à mão no editor, e é conferida de novo logo antes de publicar. Se o arquivo mudou nesse meio tempo, a autorização é desmarcada e o diálogo pede uma nova revisão. Veja também Aprovação de permissões. O administrador ou o responsável marca Revisei e autorizo estas permissões. Para outro usuário, o botão vira Pedir aprovação. A versão fica criada, sem ir ao ar, e quem aprova publica na tela de versões. Publicar não muda quem vê o plugin. Liberar para a equipe é uma ação separada, com confirmação própria, e troca a visibilidade de só o autor para a conta inteira. O endereço fica fixo depois da primeira publicação.

Variáveis e hosts que faltam

Quando o plugin precisa de algo que a conta não tem, o agente encerra o turno com um pedido, e o Studio abre um painel no lugar do editor:
  • Criar variável: mostra os nomes das variáveis que a conta já tem e cria a variável pedida com o valor que você colar. O valor não passa pelo agente. O painel não sobrescreve variável que já existe.
  • Liberar host: monta o texto do pedido ao suporte, com conta, plugin e motivo. Você edita e copia com Copiar pedido.
Os dois casos têm Avisar o agente, que manda para a conversa uma mensagem pronta dizendo que a configuração foi feita.

Créditos de IA

O Plugin Studio consome os créditos de IA da conta. Cada turno aparece no extrato com a origem Plugin Studio, com os tokens lidos do cache separados dos demais. Sem saldo, a mensagem não chega ao modelo e a conversa mostra o aviso de créditos esgotados. Se o provedor de IA falhar ou passar do tempo limite, os arquivos voltam ao estado do começo do turno e nada é debitado.

Sincronizar com git

Um plugin hospedado pode ficar ligado a um repositório git de três jeitos:
  • CLI na pipeline: a sua CI roda novus-plugin publish. Não precisa de conexão. Veja CLI e API de publicação.
  • Espelho: o Novus CRM é a fonte. Cada versão publicada pelo Studio vira commit e tag no repositório.
  • Repositório: o git é a fonte. Cada push na branch configurada vira versão, e o Studio abre pull request em vez de gravar na branch.
Um plugin tem um modo só. A troca de modo é explícita e fica na auditoria da conta.

Conectar um repositório

1

Abra a tela de versões

Em Opções → Plugins, abra o menu da linha e clique em Versões. Na seção Repositório git, clique em Conectar repositório. Só o administrador ou o responsável da conta conecta e muda a conexão.
2

Informe o repositório

Escolha o Provedor, GitHub ou Azure DevOps, e preencha o Endereço do repositório em https, sem usuário ou senha na URL. Informe a Branch e, num monorepo, a Subpasta do plugin.
3

Escolha o modo

Escolha Espelho ou Repositório. No modo Repositório, Publicar sozinho a cada push publica as versões que não pedem permissão nova.
4

Dê acesso ao repositório

No GitHub, clique em Instalar o App no GitHub. Uma janela do GitHub abre para você escolher a organização, liberar o repositório e autorizar o Novus CRM com a sua conta do GitHub. No fim, a janela fecha e a conexão aparece na seção. Não existe número de instalação para digitar.No Azure DevOps, informe o nome da variável global que guarda o cabeçalho Authorization inteiro, com Basic na frente, e clique em Conectar. A conexão guarda só o nome, nunca o valor.
A sua conta do GitHub precisa enxergar a instalação do App. Instale numa organização em que você é administrador. Se a organização exige aprovação do dono, a conexão só termina depois dessa aprovação. Aí basta clicar no botão de novo. Se o navegador bloquear a janela, libere as janelas pop-up do Novus CRM.
A seção mostra provedor, branch, subpasta, modo, credencial, o último commit e o último erro da sincronização. Desconectar para a gravação no git e o recebimento de pushes. As versões já criadas continuam como estão.

Modo Espelho

Cada versão do Studio que não é rascunho vira um commit na branch novus/studio, com os arquivos da versão e o resumo da iteração como mensagem, e uma tag v{n}. A conversa mostra o link do commit. O Novus CRM nunca lê o repositório para mudar os arquivos do plugin. Se alguém commitar à mão em novus/studio, o próximo push do espelho é recusado. A seção Repositório git mostra o aviso com duas saídas:
  • Importar do git cria uma versão a partir de um commit. Sem commit informado, usa o último da branch. Nada vai ao ar até alguém publicar.
  • Sobrescrever a branch grava de novo os arquivos da versão publicada no Novus CRM. Os commits feitos à mão se perdem.

Modo Repositório

O push na branch configurada chega por webhook. A seção Repositório git mostra o endereço do webhook e o segredo. O segredo aparece uma vez só, logo depois de conectar ou de clicar em Gerar segredo novo. Gerar outro invalida o anterior na hora. O que acontece com cada push:
  • Branch configurada: o Novus CRM baixa o conteúdo do commit, filtra a subpasta e cria uma versão com origem Git, o SHA do commit e a ref. O pacote passa pela mesma validação e pelos mesmos limites do envio manual.
  • Outra branch: ignorado.
  • Assinatura que não confere: resposta 401, e nada é gravado.
Com Publicar sozinho a cada push ligado, a versão vai ao ar se não pedir permissão nova. Com permissão nova, ela fica criada e espera aprovação na tela de versões. Uma versão recusada deixa o motivo na seção Repositório git. Nesse modo, o Studio grava cada iteração numa branch studio/{endereço}-{n} e abre um pull request para a branch configurada. Ele nunca commita direto nela. O preview continua vindo dos arquivos em edição. O merge do pull request dispara o webhook e cria a versão, como qualquer push.

Versões com origem

A lista de versões mostra de onde cada uma veio. As versões do Studio e do git ganham o selo da origem, e as do git mostram o commit curto e a ref, com link para o provedor.

Manifesto e permissões

O plugin hospedado declara no arquivo novus-plugin.json o que pode pedir ao Novus CRM. Coloque esse arquivo na raiz do pacote. Para um plugin com endereço próprio, informe as permissões no cadastro.

O que cada permissão libera

O proxy aceita GET, POST, PUT, PATCH e DELETE. Envie parâmetros em query e um corpo JSON em body. Uma referência de segredo com in: "body" exige um objeto em body e só é enviada em métodos diferentes de GET. Cabeçalhos definidos pelo plugin em headers só são repassados no host externo. Para enviar um arquivo, como uma imagem ou um PDF, use bodyBase64 no lugar de body. O proxy decodifica o conteúdo e envia os bytes com Content-Type: application/octet-stream, a menos que o plugin informe outro tipo em headers. O host externo é o único que aceita esse corpo. Ele não vale em GET nem junto com segredo in: "body", e o arquivo decodificado pode ter até 10 MB. O host publica precisa estar em hosts, mas a chave da API pública não entra em segredos: o proxy resolve essa chave sozinho. Eventos e comandos como getInfoUser, openPage e openWidget não dependem de permissão. Para o plugin hospedado publicado, o proxy usa as permissões da versão ativa. Uma versão só enviada não amplia essas permissões. Depois de publicar ou reverter, a mudança vale em até um minuto.

Superfícies não declaradas somem

Para o plugin hospedado, o Novus CRM ignora no initialize as chaves do registro que não estão em superficies. Um plugin que declara só widgetbar e registra widgetbar e navbar mostra o botão do painel lateral, e o item de menu não aparece. O console do navegador registra um aviso com o id do plugin. events não precisa ser declarado.

Erros do proxy

Quando o proxy recusa uma chamada, a Promise de apiRequest é rejeitada com um Error cuja mensagem é o texto da coluna Mensagem. As mensagens são estáveis, e o seu plugin pode compará-las para mostrar um aviso claro a quem atende. Quando o sistema chamado responde com erro, o status dele é repassado, e a mensagem vira proxy {status} se o corpo não tiver um campo error.
Host not declared, Domain not declared e Secret not declared são problemas da declaração, não da conta: corrija o novus-plugin.json e publique uma versão nova, ou ajuste as permissões no cadastro do plugin com URL própria. Secret not found se resolve cadastrando a variável na conta, sem mexer no plugin.

Ver isso funcionando

Para ver o protocolo funcionando de ponta a ponta, incluindo o uso de segredo, use o repositório de exemplo. Ele implementa um plugin completo sem depender de nada além do protocolo público.