Skip to main content

NNP

Quando usar: quando o serviço já está de pé localmente (./mvnw -q verify) e a imagem já existe. O NNP é o pacote do módulo: o que o Module Manager valida, instala e ativa. Ele não é um tar do repositório — é um ZIP canônico com conteúdo conferido.

Tudo é feito pela ferramenta do módulo, pelo wrapper commitado no repositório:

./nnconsolew nnp build

O que entra no pacote​

ConteúdoOrigem
Chart renderizávelnns/helm/chart/ (o MM renderiza e aplica byte a byte).
Imagem do serviçonns/build/image.ref — por digest.
Descritoresnnp/release.yaml, api.yaml, iam.yaml, audit.yaml, placement.yaml.
Descritor do serviçonns/service.yaml (rede, slots, config, banco, identidade).
Contrato HTTPnns/api/openapi.yaml.
Migrationsnns/internal/store/migrations/ + MANIFEST.
NNC (se o módulo tem UI)A superfície declarada em surfaces, com o bundle construído.
Status Probe (se declarado)status/status.yaml e a imagem do probe, por digest.
Docs e help (se declarados)docs/docs.yaml + docs/<locale>/, help/help.yaml.

O resultado sai em dist/: dist/<módulo>-<versão>.nnp e o .sha256 ao lado.

./nnconsolew nnp build # dist/sample-0.1.0.nnp
./nnconsolew nnp build --out dist --root . # explícito

O pacote é determinístico: o mesmo commit dá o mesmo sha256. Se o sha mudou sem você ter mexido em nada, algo no repositório mudou (imagem, migration, descritor).

Conferir antes de subir​

./nnconsolew nnp verify --signature-policy off dist/sample-0.1.0.nnp

O comando imprime uma linha por conferência e termina com o resumo. No --json, cada conferência tem id e status (pass, warn, fail):

./nnconsolew nnp verify --signature-policy off --json dist/sample-0.1.0.nnp \
| jq -r '.report.checks[] | "\(.id) \(.status)"'
ConferênciaO que olha
package_limitsTamanho e número de entradas do pacote.
entry_names, entry_types, entry_duplicates, entry_allowlistO que existe dentro do ZIP: nome, tipo, repetição, o que é permitido.
package_canonicalO ZIP na forma canônica (nomes, ordem, sem metadado de quem zipou).
forbidden_contentO que não pode estar no pacote (segredo, chave privada, arquivo de SO).
checksumsO conteúdo contra os checksums do próprio pacote.
release_metadatarelease.yaml × versão × módulo × imagens.
descriptorsOs descritores conferidos entre si (rota × permissão × trilha × rede).
chart_staticO chart: sem hook, sem lookup, sem host/namespace fixo.
sdk_compatibilitycompatibility.sdk × o SDK que construiu o serviço.
sbomO inventário de software do serviço (build.toolchain do runtime).
secret_scanVarredura de segredo no conteúdo do pacote.
docs_contentPágina de docs com texto de template (*_placeholder_content) sai como warn.
signatureA assinatura (com --signature-policy off, warn).

Depois de conferido, dá para ver o plano de instalação sem tocar em nada:

./nnconsolew nnp inspect dist/sample-0.1.0.nnp # o conteúdo do pacote, em texto
./nnconsolew nnp plan dist/sample-0.1.0.nnp # o que o Deploy vai criar (READY/BLOCKED)

Assinar​

A assinatura de produção é do operador, com a chave dele — a seed é lida no lugar e nunca é copiada:

./nnconsolew nnp sign \
--key-file <seed do operador, no cofre> \
--key-id nnumbers-console-prod-2026-09 \
--trusted-keys <deploy/prod/nnp-trusted-keys.json> \
--out dist/sample-0.1.0.signed.nnp dist/sample-0.1.0.nnp

E a verificação do pacote assinado:

./nnconsolew nnp verify --signature-policy required \
--trusted-keys <deploy/prod/nnp-trusted-keys.json> dist/sample-0.1.0.signed.nnp

A chave confiável declara o que ela pode assinar: nn_kinds (module/platform) e nn_modules (os ids reivindicados). Id de módulo na lista reivindicada sem a chave certa é recusado (permission_denied/module_id_claimed).

Erros comuns​

  • Imagem por tag no image.ref — o pacote é validado e recusado; o digest é o contrato.
  • Schema de audit com evento a mais, ou de menos — descriptors reprova: o audit.yaml é conferido contra as rotas que auditam e contra o código que emite.
  • Migration nova fora do MANIFEST — o arquivo não entra no pacote (a conferência de checksums não vê o que não foi listado) e o Job não a aplica.
  • Builder, hook ou lookup no chart — chart_static reprova: o chart é renderizado uma vez e o que foi conferido é o que é aplicado.
  • Assinar com a chave errada — assinatura de módulo com chave de plataforma (ou o contrário) é recusada pelo escopo da chave.
  • Confiar no warn de docs_content — texto de template publicado é entrega com defeito.
  • Versionar o pacote sem subir a versão — o mesmo release_id com outro digest é recusado.
  • Rodar nnp build com o repositório sujo — o pacote sai de um estado que ninguém consegue reproduzir; commite antes.