Segredos (core.secrets)

Credenciais de integrações cifradas com AES-256-GCM, com chave por runtime e ambiente — put, status, use e remove a partir do contexto autorizado.

core.secrets V1 guarda credenciais (por exemplo appKey/appSecret de um ERP) cifradas no banco do App. É exclusivo para single_tenant dedicado, opt-in, e nenhum endpoint ou CRUD automático expõe a coleção técnica.

1. Declare

{
  "capabilities": ["core.secrets"],
  "capabilitySettings": { "core.secrets": { "enabled": true } }
}

Nunca coloque valores ou chave em manifesto, frontend, repositório ou imagem. O Publisher transmite somente a declaração; Core e executor precisam da release com V1.

2. Use no backend

const crypto = require("node:crypto");
const { capabilities, defineRoutes } = require("@oondemand/oon-core-back");

defineRoutes("/omie", (router) => {
  router.private.put("/credenciais", { permission: "segredos.manage", sensitiveBody: true }, async (req, res) => {
    const options = { name: "omie", context: req.accessContext, correlationId: crypto.randomUUID() };
    const { appKey, appSecret } = req.body ?? {};
    res.json(await capabilities.secrets.put({ ...options, value: { appKey, appSecret } }));
  });

  router.private.get("/credenciais", { permission: "segredos.manage" }, async (req, res) => {
    res.json(await capabilities.secrets.status({ name: "omie", context: req.accessContext }));
  });

  router.private.post("/sincronizar", { permission: "omie.sync", sensitiveBody: true }, async (req, res) => {
    await capabilities.secrets.use({ name: "omie", context: req.accessContext }, async (credential) => {
      // Serviço do App controla URL, timeout, redirects e sanitização do retorno.
      await omie.call(credential);
    });
    res.json({ ok: true });
  });

  router.private.delete("/credenciais", { permission: "segredos.manage", sensitiveBody: true }, async (req, res) => {
    res.json(await capabilities.secrets.remove({ name: "omie", context: req.accessContext }));
  });
});

context é o contexto autorizado do Core — nunca copie identidade do body/header. A V1 verifica App, tenant e usuário; a autorização da operação é da rota.

Contrato

Operação Comportamento
put Substitui atomicamente o objeto inteiro; retorna { state: "available" }. Valor incompatível exige replace: true.
status absent, available ou reentry_required (com reason/action). Erro de banco nunca vira "ausente".
use(options, callback) Aguarda o callback e descarta seu retorno. Erros viram SECRETS_USE_FAILED, sem mensagem externa.
remove Idempotente; não precisa decifrar.
  • Nome: [a-z][a-z0-9._-]{0,63}, definido pelo backend.
  • Valor: objeto JSON não vazio, até 16 KiB. Sem merge parcial, histórico ou compare-and-swap.
  • Correlação: 1–128 caracteres alfanuméricos, :, _ ou -, gerada no backend.
  • Auditoria técnica: registra operação, ator, escopo, nome, correlação e instante — nunca valor, envelope ou chave.

Criptografia

AES-256-GCM, chave aleatória de 32 bytes, IV novo de 12 bytes por gravação, envelope v1 autenticado com AAD que inclui App, identidade do runtime dedicado (appId + namespace), ambiente, tenant e nome. Uma chave por namespace/ambiente. As coleções oon_secrets e oon_secret_audit são técnicas, fora de CRUD/metadata/export.

Provisionamento e recadastro

  • Na publicação, o delivery cria o Secret imutável oon-core-secrets (e o marcador oon-core-secrets-initialized), montando só OON_SECRETS_KEY do ambiente alvo.
  • Republicação, reinício e réplicas reutilizam Secret e coleção. Promoção provisiona chave independente no destino, sem copiar dados ou chave da origem.
  • Valor incompatível com chave íntegra → usuário autorizado reenvia o objeto completo com replace: true.
  • Chave ausente → operador restaura o Secret correspondente.
  • Sem chave recuperável → procedimento operacional autorizado remove o Secret daquele ambiente, reprovisiona e solicita recadastro. Não há endpoint para trocar chave, nem rotação transparente nesta V1.

Desenvolvimento local

O exemplo (create-central-oon example) instala a página /segredos, menu, permissão segredos.manage e rotas. Configure no ambiente do backend:

OON_SECRETS_KEY=<32 bytes em base64>
OON_SECRETS_INSTANCE=local:sample
OON_SECRETS_TENANT=local:tenant
APP_ENVIRONMENT=desenvolvimento

Nunca use a chave local na Plataforma. Sem chave, as demais páginas continuam operacionais.