@m3r/sdk 0.5.0
Ciclo de vida da extensão
Validate, build, deploy assinado, activate, deactivate e gestão no tenant.
A extensão não é um plugin dentro do processo do ERP. É um processo Node isolado. O Core guarda o contrato (tabelas, telas, IPs). O runtime chama activate e deactivate.
1. Escrever
Pasta com m3r.json + src/index.ts. defineExtension exporta activate e, se quiser, deactivate. O index orquestra — cada domínio registra o próprio contrato. Padrões.
No activate o domínio declara o que o tenant passa a ter, nesta ordem: tables.ensure → screens.define → nav.define → reports.define → entryPoints.on → events.on.
deactivate não apaga tabela, tela nem dado. Só libera o processo (subscriptions, log). Soft delete e FAX#### ficam no banco.
2. Validate
m3r validate / M3R: Validate Project.
- Catálogo: permissions, events, entryPoints existem.
tables[]/screens[]/nav[]/reports[]dom3r.jsonbatem 1:1 com o código.- Imports proibidos (SQL, TypeORM, React no ERP).
Ainda não cria tabela no Postgres.
3. Build
m3r build gera:
.m3r/build/bundle/index.js— só o seu código (@m3r/sdkfica externo)- metadata +
integrity/sha256.json <id>-<version>.m3rx— zip determinístico
Credencial BUILD (extension.build / extension.package). Não chama ctx.m3r. Não tem executionId de negócio.
O hash local vai em integrity/sha256.json. A assinatura do Core só nasce no deploy (integrity/signature.json depois do POST).
4. Run (desenvolvimento) = ativar
VS Code / Cursor: M3R: Run Extension, ou m3r run.
- Build de desenvolvimento + checagem de integridade.
- Core emite credencial RUN (scopes do
m3r.json, TTL ~1h,executionId). - Runtime Host sobe em processo filho (
fork). A extensão não roda dentro do VS Code. - Host cria
ctxa partir da credencial — tenant/empresa vêm do token, não do seu código. - Chama
activate(ctx). - Se você registrou IPs, o host sobe HTTP em
127.0.0.1e grava o callback emFADEV04.
Estado: STARTING → RUNNING.
Aí o ensure acontece de verdade: JSONB em FADEV07 ou CREATE TABLE "FAX####". Telas aparecem em /apps/extensions/{code}. IPs passam a ser invocados no save/faturar.
5. Stop = desativar
M3R: Stop Extension ou Ctrl+C.
O que não acontece no stop:
- Não dropa
FAX####. - Não apaga linhas.
- Não remove tela/menu do ERP (o schema declarado continua no tenant até outro
ensureou ação de admin). - IPs deixam de responder: o callback local morreu. O Core trata timeout conforme
failPolicydo IP (opensegue,closedbloqueia).
6. Ambientes — o que isola de verdade
m3r run não é deploy. É “ligar o processo da extensão no laptop contra o tenant que você selecionou”. Qualquer um com Sign In + acesso à empresa consegue fazer isso. Não há fila, revisão nem versão instalada.
O seletor Development / Staging / Production no VS Code (FADEV02) não cria três bancos. Os três tipos nascem na mesma empresa. Tabela, tela, FAX#### e records são isolados por companyId + extensionId — não por environmentId. Rodar em “Production” da empresa X grava no mesmo lugar que “Development” da empresa X.
| O que você escolhe | O que realmente isola | O que não isola |
|---|---|---|
m3r.developerApiUrl | Stack (API/banco). Dev local ≠ HML ≠ prod. | — |
| Organization (empresa) | Tenant no banco daquela API | — |
| Environment type (FADEV02) | Política e rótulo (DEV / HML / PROD) | Dado. Mesmo companyId = mesmo FADEV06 / FAX#### |
m3r run | Processo no seu laptop + callback 127.0.0.1 | Instalação permanente, versão, sandbox |
Como distinguir os três mundos de verdade:
- Desenvolvimento — API local (ou stack de dev) + empresa de sandbox. Environment
development.m3r runo dia inteiro. - HML — outra API ou outra empresa, não o label Staging na empresa de prod. Environment
staging. Run só se a URL do developer apontar para o Core de HML. - Produção — Core de produção + empresa real. Obrigatório:
m3r build→m3r deploy/ M3R: Deploy Extension. O Core re-hash o.m3rx, assina (HMAC-SHA256) e grava emFADEV11/FADEV12. Sem esse install, a credencial RUN é recusada.
Regra prática: stack + empresa separam ambiente. O dropdown FADEV02 sozinho não separa.
7. Deploy — o Core toma conhecimento
Comando no editor: M3R: Deploy Extension. CLI: m3r deploy com M3R_API_URL, M3R_DEVELOPER_TOKEN, M3R_ORGANIZATION_ID, M3R_ENVIRONMENT_ID.
Versão é imutável: mesmo version com SHA diferente é recusado — incremente m3r.json.
| Ambiente | Run sem deploy | Deploy |
|---|---|---|
| development / staging | permitido | opcional (recomendado em HML) |
| production | bloqueado até existir install | obrigatório |
Ainda não é hosting permanente (container/microVM). Depois do deploy, o Core conhece o binário assinado. O processo no laptop só roda em prod se esse install existir.
No ERP, Configurações → Extensões lista todas (ativas e inativas), mostra logs de IP (FADEV05) e permite ativar/desativar (FADEV13). Desativar não apaga FAX#### nem records.
| Peça | Status |
|---|---|
| Registry FADEV11 / install FADEV12 | disponível |
| Assinatura HMAC-SHA256 pelo Core | disponível |
m3r deploy / M3R: Deploy Extension | disponível |
| Marketplace / billing | não |
| Host https 24/7 da extensão | não (próximo passo) |
8. Credenciais
| Purpose | Pode | Não pode |
|---|---|---|
| BUILD / TEST | validate, build, package | ctx.m3r, ctx.ext.records |
| RUN | scopes do manifest (sales.order.read, extension.storage.*) | scopes de build |
| JWT developer | m3r deploy / publish | substitui um purpose DEPLOY dedicado — ainda não há credencial só de publish |
O token RUN não entra no seu activate. O HttpTransport lê M3R_RUN_TOKEN no processo do host.
9. Tabela física nesse ciclo
ensurenoactivateé idempotente: mesma lógica, mesmophysicalName.- Sem
physicalName: Core geraFAX0001… e devolve{ storage, physicalName }. - Com
physicalName: "FAX0042": usa esse código se estiver livre. Não muda depois. ctx.ext.tables.list()relê o que o Core gravou (incluindo o nome atribuído).- Stop / deactivate não derruba a
FAX####.
