Enviando um Plugin
Este e o passo a passo operacional para enviar um plugin ao marketplace Levy Fleets. Leia primeiro a visao geral do portal do desenvolvedor para contexto sobre a plataforma e modelo de receita.
Passo 1 - Registre-se como fornecedor
Va para /developers e clique em Registrar.
Voce fornecera:
- Nome do fornecedor - aparece em cartoes de plugin
- E-mail de contato - para notificacoes de revisao, nao exibido publicamente
- E-mail de suporte - exibido publicamente, onde operadores enviam problemas
- URL da homepage
- Logo - PNG 256x256, quadrado, fundo transparente
Enviaremos um e-mail de verificacao. Apos a verificacao, voce assina o Acordo de Parceiro de Plugin (termos padrao, leva ~5 minutos para ler).
Passo 2 - Configurar Stripe Connect (apenas plugins pagos)
Se seu plugin cobrara algo (unico, mensal ou uso), voce faz onboarding com o Stripe Connect Express. Do painel de fornecedor:
- Clique em Configurar repasses
- O Stripe abre seu fluxo de onboarding
- Forneca informacoes comerciais, conta bancaria e informacoes fiscais (~10 minutos)
- O Stripe verifica - normalmente no mesmo dia para EUA, 1-3 dias internacional
Plugins gratuitos podem pular este passo.
Passo 3 - Construa seu endpoint de webhook
Seu plugin precisa de um endpoint HTTPS que aceita POSTs assinados da Levy. Implementacao minima:
import crypto from 'crypto';
const PLUGIN_SECRET = process.env.LEVY_PLUGIN_SECRET!; // do seu painel de fornecedor
export async function POST(request: Request) {
const sig = request.headers.get('x-levy-signature');
const body = await request.text();
if (!verifyLevySignature(body, sig, PLUGIN_SECRET)) {
return new Response('Invalid signature', { status: 401 });
}
const event = JSON.parse(body);
// lidar com event.event_type, event.data
return new Response('ok');
}
function verifyLevySignature(body: string, header: string | null, secret: string) {
if (!header) return false;
const parts = Object.fromEntries(header.split(',').map((p) => p.split('=')));
const ts = parts.t;
const v1 = parts.v1;
if (!ts || !v1) return false;
// rejeitar se mais antigo que 5 minutos
if (Math.abs(Date.now() / 1000 - parseInt(ts, 10)) > 300) return false;
const expected = crypto
.createHmac('sha256', secret)
.update(`${ts}.${body}`)
.digest('hex');
return crypto.timingSafeEqual(Buffer.from(v1), Buffer.from(expected));
}
A Levy tenta novamente entregas falhadas 5 vezes com backoff exponencial (1m, 5m, 30m, 2h, 12h). Responda com HTTP 2xx em 30 segundos. Qualquer outra coisa e tratada como falha.
Passo 4 - Crie seu manifesto
Crie plugin.json na raiz do seu projeto. Exemplo minimo:
{
"slug": "my-fraud-scorer",
"version": "1.0.0",
"name": "My Fraud Scorer",
"vendor": {
"name": "Acme Fraud Inc",
"email": "support@acmefraud.com",
"url": "https://acmefraud.com"
},
"category": "other",
"description": "Pontua cada corrida quanto a risco de fraude e escreve um flag de volta para a Levy.",
"long_description_mdx": "# Acme Fraud Scorer\n\nPontua corridas...",
"screenshots": [
"https://cdn.acmefraud.com/screenshots/dashboard.png"
],
"homepage": "https://acmefraud.com",
"support_url": "https://acmefraud.com/support",
"permissions": ["read:rides", "read:rides.geo", "write:rides.flags"],
"webhook_subscriptions": ["ride.ended"],
"webhook_endpoint": "https://api.acmefraud.com/levy/webhook",
"config_schema": {
"type": "object",
"required": ["api_key"],
"properties": {
"api_key": {
"type": "string",
"title": "Chave de API Acme Fraud",
"description": "Encontre isto em sua conta Acme Fraud -> Configuracoes -> API"
},
"threshold": {
"type": "number",
"title": "Limiar de risco (0-100)",
"default": 70
}
}
},
"pricing": {
"model": "usage",
"unit": "corrida pontuada",
"unit_amount_cents": 5,
"currency": "USD"
}
}
Dicas de config_schema
- Use
titleedescriptionem cada campo - sao mostrados aos operadores no formulario de instalacao. - Marque campos obrigatorios com
required: ["field_name"]. - Use
format: "password"para chaves de API - a Levy as renderiza como entradas mascaradas. - Use enums para listas de selecao:
"enum": ["option_a", "option_b"]. - Use
format: "uri"para URLs para obter validacao inline.
Dicas de selecao de permissao
Operadores veem suas permissoes em linguagem clara. Cada escopo que voce solicita torna o dialogo de instalacao mais longo e intimidante. A melhor estrategia: peca o minimo e explique por que em seu long_description_mdx.
Passo 5 - Teste em sandbox
Do painel de fornecedor, solicite acesso Sandbox. Voce recebera uma subconta sandbox com dados sinteticos.
Teste estes cenarios:
- Instalar do marketplace sandbox - seu plugin aparece no marketplace sandbox uma vez enviado.
- Disparar um evento de teste - use Painel do fornecedor -> Sandbox -> Disparar evento de teste para enviar um
ride.endedsintetico ao seu endpoint. Verifique que sua verificacao de assinatura passa e seu handler faz a coisa certa. - Testar o formulario de configuracao - renderiza corretamente? Erros de validacao sao claros?
- Testar OAuth (se aplicavel) - a authorize_url redireciona corretamente? A token_url aceita o codigo de autenticacao?
- Testar tratamento de falha de webhook - retorne um 500 do seu endpoint uma vez. Verifique que a Levy tenta novamente e eventualmente marca a instalacao como falhando.
Passo 6 - Enviar para revisao
Do painel de fornecedor, clique em Enviar para revisao. Faca upload:
- Seu
plugin.json(analisado contra schema) - Todas as URLs de capturas de tela (verificadas acessiveis)
- Sua descricao longa (Markdown, max 20KB)
- Detalhes de precos para confirmacao
- Uma nota breve ao revisor (opcional, util para contexto - "esta e v2 com o novo fluxo de sandbox")
O envio passa para a fila de revisao de operacoes Levy. Voce recebera atualizacoes por e-mail conforme avanca.
Passo 7 - Enderecar feedback de revisao
O revisor aprova seu plugin ou solicita mudancas. Solicitacoes comuns:
- Reduzir escopo de permissao - "seu plugin pede
read:customers.piimas a descricao do manifesto nao justifica. Remova o escopo ou expanda a descricao." - Melhorar descricao - "a descricao nao explica o que este plugin faz em linguagem simples."
- Adicionar capturas de tela - "precisamos de pelo menos uma captura de tela mostrando o plugin em acao."
- Corrigir verificacao de assinatura - "enviamos um evento de teste com uma assinatura ruim e seu endpoint retornou 200. Por favor, verifique assinaturas corretamente."
- Ajustar precos - "US$ 999/mes e o maximo a menos que voce tenha um acordo personalizado. Abaixe o preco ou nos contate sobre uma excecao."
Reenvie atualizando seu plugin no painel e clicando em Reenviar. O relogio SLA de 5 dias reinicia; reenvios normalmente completam em 1-2 dias.
Passo 8 - Lancamento
Uma vez aprovado, seu plugin vai ao ar no marketplace em minutos. Operadores podem instalar imediatamente. Voce vera contagens de instalacao e instalacoes ativas em seu painel de fornecedor.
Recomendamos um lancamento suave:
- Verifique silenciosamente que as primeiras 5 instalacoes funcionam de ponta a ponta
- Observe a taxa de sucesso de webhook
- Corrija quaisquer problemas de producao antes de promover
- Entao promova atraves de seus canais (LinkedIn, seus clientes existentes, etc.)
A Levy pode co-comercializar seu plugin se for estrategicamente valioso - entre em contato com partnerships@levyelectric.com para coordenar.
Versionamento pos-lancamento
- Patch (1.0.0 -> 1.0.1) - correcoes de bugs, sem mudancas de API. Upgrades automaticos para todas as instalacoes.
- Minor (1.0.0 -> 1.1.0) - novos recursos opcionais, novos campos de configuracao opcionais. Upgrades automaticos.
- Major (1.0.0 -> 2.0.0) - mudancas breaking (novas permissoes obrigatorias, campos de configuracao removidos, formato de payload de webhook alterado). Operadores veem um banner pedindo que reconsensam. A versao antiga continua funcionando ate que atualizem.
Use semver responsavelmente. Bumps major sao friccao - agrupe varias mudancas breaking em um release.
O que vem a seguir
- Portal do desenvolvedor - visao geral, acordos, sandbox
- Cobranca de plugins - como repasses do Stripe Connect funcionam