# Licença comercial por aplicativo — contrato 1 (Core 0.6.7)

Disponível no namespace público `licensing` de `@oondemand/oon-core-back`.
Requer a Central de Ativações com `/licensing/decision` e `/licensing/identity`.
O SDK não substitui autenticação, RBAC, vínculo de Deployment ou licença organizacional.

```js
const { licensing } = require("@oondemand/oon-core-back");
await licensing.assertBusinessOperation({ tenantId: accessContext.tenantId, correlationId });
// Inicie agora o efeito autorizado: PDF, e-mail, emissão ou mutação externa.
```

Chame imediatamente antes de **cada novo efeito**, inclusive em jobs aceitos anteriormente.
Não guarde autorização no JWT, snapshot ou cache positivo. A decisão é uma leitura pontual;
uma suspensão posterior não cancela uma chamada já iniciada nem desfaz um efeito confirmado.
Preserve recibos, callbacks, reconciliação, downloads já gerados e histórico sem reiniciar efeitos.

O Core usa identidade operacional do próprio Deployment e a autoridade configurada pelo
runtime. O App não configura URL da Central, credencial interna ou transporte paralelo.
Timeout de 3 segundos, sem redirects, sem retry e sem cache positivo. Resposta ausente,
incompatível ou de outro escopo retorna `LICENSE_AUTHORITY_UNAVAILABLE` (503).
Runtime local não pode obter identidade operacional: `LOCAL_OPERATION_NOT_SUPPORTED`.
Em testes unitários, injete o guard na camada de domínio; isso nunca habilita operação local real.

Um contrato bloqueado retorna HTTP 423 com código `APP_LICENSE_REQUIRED`,
`APP_LICENSE_NOT_STARTED`, `APP_LICENSE_EXPIRED`, `APP_LICENSE_SUSPENDED`,
`APP_LICENSE_CANCELLED`, `APP_LICENSE_OVERDUE` ou `APP_LICENSE_INVALID`.
Bloqueios organizacionais e de entitlement também são preservados.
Exiba a razão comercial; deixe a operação pendente. Pagamento não renova nem reativa sozinho.

## Aplicabilidade: comercial, root/global e local

O guard abaixo se aplica a novos efeitos de negócio de um **App comercial licenciado**, com tenant obtido do contexto autenticado do backend. A licença de uso do App e a assinatura própria do cliente são independentes; o consumidor consulta a decisão da Central, sem recalcular essas regras.

Root e globais tenantless seguem sua autoridade operacional e RBAC próprios: não crie tenant, proprietário comercial ou licença fictícios para fazê-los passar pelo guard. A categoria vem do contrato governado do App, nunca de um booleano enviado pelo cliente, da ausência de tenant ou de um override de ambiente. Contexto de tenant ausente em App comercial deve falhar, sem executar o efeito.

No runtime local não existe autorização operacional. Use mocks da fronteira de licenciamento e da capability somente em testes isolados; não transforme indisponibilidade em sucesso nem injete credenciais operacionais.

## Gateway que recebe chamadas de outros Apps

```js
const identity = await licensing.verifyConsumerRequest({
  headers: req.headers,
  requireLicense: false,
});
// Vincule identity.{tenantId,appCode,environment} ao consumidor cadastrado no gateway.
// Autorize base e operação no domínio do gateway, depois:
await licensing.verifyConsumerRequest({ headers: req.headers, requireLicense: true });
```

`requireLicense` é `true` por padrão. `false` consulta apenas a identidade e vínculo
ativo Deployment–tenant, permitindo receber/consultar evidências durante suspensão.
**Não autoriza um efeito novo.** A autenticação específica do consumidor e sua política
continuam obrigatórias. O bearer do gateway nunca é encaminhado à Central.

Headers obrigatórios: `x-oon-deployment-id`, `x-oon-deployment-token`, `x-app-code`,
`x-oon-tenant-id`. Eles só são confiáveis depois da validação remota. Não aceite App,
ambiente ou tenant do body. Todas as respostas são comparadas com o escopo solicitado.
Nenhum segredo ou diagnóstico bruto do provedor é incluído nos erros normalizados.

## Resposta da autoridade

`POST /licensing/decision` (body vazio): `schemaVersion: 1`, `appCode`, `tenantId`,
`environment`, `allowed`, `code`, `version`, `checkedAt`, `maxAgeSeconds: 0`.
Permissão exige versão positiva e código nulo; negação tem código reconhecido.
`POST /licensing/identity`: `schemaVersion: 1`, `appCode`, `tenantId`, `environment`,
`maxAgeSeconds: 0`. Respostas autenticadas têm `Cache-Control: no-store`.

## Limite atual de jobs

Este contrato oferece o guard de efeitos, não um executor durável de integrações.
A documentação de process jobs existente não especifica registro público de handlers
externos, inbox/outbox e retomada autônoma necessários ao gateway da issue #170.
Essa extensão precisa de contrato e testes próprios antes de declarar I4 concluída.

