@oondemand/create-central-oon 0.6.9 → 0.6.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/docs/AGENTS.md +6 -3
- package/docs/APP_LICENSING.md +9 -0
- package/docs/PDF_RENDERING.md +11 -1
- package/docs/TRANSACTIONAL_EMAIL.md +16 -1
- package/package.json +1 -1
- package/templates/_base/backend/package.json +1 -1
- package/templates/_base/frontend/package.json +1 -1
- package/templates/_base/package.json +1 -1
package/docs/AGENTS.md
CHANGED
|
@@ -28,13 +28,15 @@ O `AGENTS.md` da raiz pertence ao projeto e nunca pode ser sobrescrito pelo scaf
|
|
|
28
28
|
| Domínio, models, validações e fórmulas | [BACKEND_API.md](BACKEND_API.md), [BACKEND_DOMAIN_MANIFEST.md](BACKEND_DOMAIN_MANIFEST.md), [BACKEND_PATTERNS.md](BACKEND_PATTERNS.md), [REACTIVE_DOMAIN_FORMULAS.md](REACTIVE_DOMAIN_FORMULAS.md) |
|
|
29
29
|
| CRUD, metadata e UI | [METADATA_CRUD_UI.md](METADATA_CRUD_UI.md), [FRONTEND_API.md](FRONTEND_API.md), [FRONTEND_CODE_FIRST.md](FRONTEND_CODE_FIRST.md) |
|
|
30
30
|
| Auth, ativação, tenant ou permissões | [AUTH_ACTIVATION_RBAC.md](AUTH_ACTIVATION_RBAC.md), [RBAC_SECURITY.md](RBAC_SECURITY.md), [DO_AND_DONT.md](DO_AND_DONT.md) |
|
|
31
|
-
| Renderizar, visualizar ou baixar PDF | [PDF_RENDERING.md](PDF_RENDERING.md), [BACKEND_API.md](BACKEND_API.md), [FRONTEND_API.md](FRONTEND_API.md) |
|
|
32
|
-
| Configurar templates ou enviar e-mail | [TRANSACTIONAL_EMAIL.md](TRANSACTIONAL_EMAIL.md), [RBAC_SECURITY.md](RBAC_SECURITY.md) |
|
|
31
|
+
| Renderizar, visualizar ou baixar PDF | [APP_LICENSING.md](APP_LICENSING.md), [PDF_RENDERING.md](PDF_RENDERING.md), [BACKEND_API.md](BACKEND_API.md), [FRONTEND_API.md](FRONTEND_API.md) |
|
|
32
|
+
| Configurar templates ou enviar e-mail | [APP_LICENSING.md](APP_LICENSING.md), [TRANSACTIONAL_EMAIL.md](TRANSACTIONAL_EMAIL.md), [RBAC_SECURITY.md](RBAC_SECURITY.md) |
|
|
33
33
|
| Execução local | [RUNTIME_MODES.md](RUNTIME_MODES.md), [LOCAL_DEVELOPMENT.md](LOCAL_DEVELOPMENT.md), [LOCAL_SECURITY_BOUNDARY.md](LOCAL_SECURITY_BOUNDARY.md) |
|
|
34
|
-
| Rotas, hooks, jobs e filas | [ROUTES_HOOKS_WORKERS.md](ROUTES_HOOKS_WORKERS.md), [BACKEND_PATTERNS.md](BACKEND_PATTERNS.md) |
|
|
34
|
+
| Rotas, hooks, jobs e filas | [APP_LICENSING.md](APP_LICENSING.md), [ROUTES_HOOKS_WORKERS.md](ROUTES_HOOKS_WORKERS.md), [BACKEND_PATTERNS.md](BACKEND_PATTERNS.md) |
|
|
35
35
|
| Upgrade do Core | [CORE_UPGRADE.md](CORE_UPGRADE.md), [TESTING_CONFORMANCE.md](TESTING_CONFORMANCE.md), [releases/0.6.0.md](releases/0.6.0.md) |
|
|
36
36
|
| UX avançada | [ADVANCED_UX_PATTERNS.md](ADVANCED_UX_PATTERNS.md), [DETAIL_MODAL_AND_RELATED_GRIDS.md](DETAIL_MODAL_AND_RELATED_GRIDS.md), [PORTAL_COCKPIT_PATTERNS.md](PORTAL_COCKPIT_PATTERNS.md) |
|
|
37
37
|
|
|
38
|
+
Antes de copiar exemplos de efeitos de negócio, determine a categoria do App pelo contrato governado. Em App comercial licenciado, aplique [APP_LICENSING.md](APP_LICENSING.md) antes de cada novo efeito. Root/globais tenantless não recebem tenant ou licença comercial artificiais; ausência de tenant em um App comercial não é isenção. Runtime local permanece sem efeitos operacionais.
|
|
39
|
+
|
|
38
40
|
## Fronteira obrigatória
|
|
39
41
|
|
|
40
42
|
- O App declara domínio e experiência em código; o Core fornece bootstrap, autenticação, ativação, RBAC, tenant, CRUD, metadata, shell, componentes genéricos e deployment.
|
|
@@ -54,3 +56,4 @@ npm test
|
|
|
54
56
|
```
|
|
55
57
|
|
|
56
58
|
Uma entrega que depende da leitura de fonte privada ou de outro App não está concluída: registre a lacuna na documentação distribuída.
|
|
59
|
+
|
package/docs/APP_LICENSING.md
CHANGED
|
@@ -28,6 +28,14 @@ Um contrato bloqueado retorna HTTP 423 com código `APP_LICENSE_REQUIRED`,
|
|
|
28
28
|
Bloqueios organizacionais e de entitlement também são preservados.
|
|
29
29
|
Exiba a razão comercial; deixe a operação pendente. Pagamento não renova nem reativa sozinho.
|
|
30
30
|
|
|
31
|
+
## Aplicabilidade: comercial, root/global e local
|
|
32
|
+
|
|
33
|
+
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.
|
|
34
|
+
|
|
35
|
+
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.
|
|
36
|
+
|
|
37
|
+
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.
|
|
38
|
+
|
|
31
39
|
## Gateway que recebe chamadas de outros Apps
|
|
32
40
|
|
|
33
41
|
```js
|
|
@@ -64,3 +72,4 @@ Este contrato oferece o guard de efeitos, não um executor durável de integraç
|
|
|
64
72
|
A documentação de process jobs existente não especifica registro público de handlers
|
|
65
73
|
externos, inbox/outbox e retomada autônoma necessários ao gateway da issue #170.
|
|
66
74
|
Essa extensão precisa de contrato e testes próprios antes de declarar I4 concluída.
|
|
75
|
+
|
package/docs/PDF_RENDERING.md
CHANGED
|
@@ -21,9 +21,12 @@ Não adicione URL, usuário, senha ou implementation reference. O runtime resolv
|
|
|
21
21
|
|
|
22
22
|
## API pública do backend
|
|
23
23
|
|
|
24
|
+
O exemplo é para **App comercial licenciado**; leia [APP_LICENSING.md](APP_LICENSING.md) antes de usá-lo. Root/globais tenantless não recebem tenant ou licença artificiais, e ausência de tenant em App comercial não dispensa o guard. A categoria não é escolhida pelo request. Runtime local não autoriza geração operacional.
|
|
25
|
+
|
|
24
26
|
```js
|
|
25
27
|
const {
|
|
26
28
|
capabilities,
|
|
29
|
+
licensing,
|
|
27
30
|
defineRoutes,
|
|
28
31
|
GenericError,
|
|
29
32
|
requirePermission,
|
|
@@ -47,6 +50,10 @@ defineRoutes("/pdf", (router) => {
|
|
|
47
50
|
res.once("close", abort);
|
|
48
51
|
|
|
49
52
|
try {
|
|
53
|
+
await licensing.assertBusinessOperation({
|
|
54
|
+
tenantId: req.accessContext?.tenantId,
|
|
55
|
+
correlationId: req.id,
|
|
56
|
+
});
|
|
50
57
|
const pdf = await capabilities.pdf.render(
|
|
51
58
|
{
|
|
52
59
|
html: req.body.html,
|
|
@@ -130,6 +137,8 @@ Nunca envie a geração diretamente a um endpoint de infraestrutura pelo navegad
|
|
|
130
137
|
|
|
131
138
|
## Erros
|
|
132
139
|
|
|
140
|
+
O guard propaga `423` com o código comercial (por exemplo, `APP_LICENSE_SUSPENDED`) ou `503`/`LICENSE_AUTHORITY_UNAVAILABLE`. Preserve o erro no tratamento padrão do Core, mostre o motivo e mantenha a operação pendente; não capture para continuar a geração nem devolva sucesso. O frontend deve tratar esses status também quando a resposta foi solicitada como blob. Contexto comercial ausente também impede a geração.
|
|
141
|
+
|
|
133
142
|
`PdfRenderingError` expõe `code`, `statusCode`, `retryable` e detalhes sanitizados.
|
|
134
143
|
|
|
135
144
|
| Código | Retry | Significado |
|
|
@@ -144,7 +153,7 @@ Nunca envie a geração diretamente a um endpoint de infraestrutura pelo navegad
|
|
|
144
153
|
| `PDF_RENDERING_TRANSPORT_ERROR` | sim | falha transitória de transporte |
|
|
145
154
|
| `PDF_RENDERING_INVALID_OUTPUT` | sim | saída inválida ou acima do limite |
|
|
146
155
|
|
|
147
|
-
Use retentativas apenas quando `error.retryable === true`, com backoff e idempotência na operação chamadora.
|
|
156
|
+
Use retentativas da capability apenas quando `error.retryable === true`, com backoff e idempotência na operação chamadora. Cada nova tentativa de geração deve passar novamente pelo guard; uma decisão anterior ou um job já aceito não autoriza a próxima chamada. A consulta é pontual, não atômica com o start: não cancela nem desfaz geração já iniciada. Downloads de documentos já produzidos não iniciam nova geração e seguem as regras de acesso existentes.
|
|
148
157
|
|
|
149
158
|
## Segurança e runtime local
|
|
150
159
|
|
|
@@ -155,3 +164,4 @@ Use retentativas apenas quando `error.retryable === true`, com backoff e idempot
|
|
|
155
164
|
- propague cancelamento do request por `AbortSignal`;
|
|
156
165
|
- no runtime local, a capability falha fechado com `PDF_RENDERING_UNAVAILABLE` quando não resolvida;
|
|
157
166
|
- em testes automatizados, um transport fake pode ser injetado por `capabilities.configurePdfRendering` e deve devolver bytes iniciados por `%PDF-`; não gere um “PDF” textual falso no código do App.
|
|
167
|
+
|
|
@@ -54,10 +54,16 @@ Templates usam somente interpolação Handlebars escapada. Blocos, helpers, sube
|
|
|
54
54
|
|
|
55
55
|
## Envio no backend
|
|
56
56
|
|
|
57
|
+
Leia [APP_LICENSING.md](APP_LICENSING.md). O exemplo de **App comercial licenciado** demonstra somente a revalidação antes de enfileirar, verificável com mocks isolados. **Não habilita envio comercial assíncrono operacional**: a pendência do executor abaixo precisa ser resolvida antes disso. Root/globais tenantless seguem autoridade/RBAC próprios, sem tenant ou licença artificiais. A categoria não vem do request; tenant ausente em App comercial não é isenção. Runtime local não autoriza envio operacional.
|
|
58
|
+
|
|
57
59
|
```js
|
|
58
|
-
const { capabilities } = require("@oondemand/oon-core-back");
|
|
60
|
+
const { capabilities, licensing } = require("@oondemand/oon-core-back");
|
|
59
61
|
|
|
60
62
|
async function enviarConfirmacao({ email, nome, idempotencyKey }, req) {
|
|
63
|
+
await licensing.assertBusinessOperation({
|
|
64
|
+
tenantId: req.accessContext?.tenantId,
|
|
65
|
+
correlationId: req.id,
|
|
66
|
+
});
|
|
61
67
|
return capabilities.transactionalEmail.send(
|
|
62
68
|
{
|
|
63
69
|
templateCode: "confirmacao",
|
|
@@ -77,6 +83,14 @@ async function enviarConfirmacao({ email, nome, idempotencyKey }, req) {
|
|
|
77
83
|
|
|
78
84
|
`idempotencyKey` é obrigatória. O retorno é `{ dispatchId, status, correlationId }`; `status` é `accepted` ou `duplicate`. Não trate `accepted` como entrega confirmada.
|
|
79
85
|
|
|
86
|
+
### Licenciamento, fila e retentativas
|
|
87
|
+
|
|
88
|
+
O guard propaga `423` com o código comercial (por exemplo, `APP_LICENSE_SUSPENDED`) ou `503`/`LICENSE_AUTHORITY_UNAVAILABLE`. Preserve status/código no tratamento padrão do Core, mostre o motivo e mantenha a operação pendente, sem enfileirar ou devolver sucesso. Contexto comercial ausente também impede o enqueue. Não use pagamento, cache positivo ou captura do erro como autorização.
|
|
89
|
+
|
|
90
|
+
A autorização no enqueue não autoriza um envio futuro. O executor precisa revalidar a autoridade e o contexto antes de **cada tentativa** no provedor, inclusive retry automático e retry de dead letter. Em OonCore 0.6.10, este exemplo não comprova essa integração no worker; não há neste contrato uma opção pública para adicioná-la. Não habilite esse caminho comercial até existir contrato/implementação e prova isolada de suspensão ou revogação entre enqueue e envio, indisponibilidade, contexto divergente e retentativa. Não contorne essa lacuna acessando internals do SDK ou criando executor paralelo no App.
|
|
91
|
+
|
|
92
|
+
Mesmo uma revalidação correta é pontual e não atômica com o envio: não cancela chamada já iniciada nem desfaz e-mail aceito pelo provedor. Recibos, callbacks, reconciliação e histórico de efeitos anteriores devem continuar acessíveis conforme suas regras; não confunda essas operações com um novo envio. `accepted` e `duplicate` não são comprovantes de autorização duradoura nem de entrega.
|
|
93
|
+
|
|
80
94
|
Outras operações públicas do namespace `capabilities.transactionalEmail` incluem preview e versionamento de templates, consulta de dispatches e retry de dead letter. Para administração interativa, prefira o componente do Core.
|
|
81
95
|
|
|
82
96
|
## Painel administrativo
|
|
@@ -109,3 +123,4 @@ O componente usa as rotas autenticadas em `/core/transactional-email/*`. Credenc
|
|
|
109
123
|
- erros usam `TransactionalEmailError` e códigos `EMAIL_*` sanitizados;
|
|
110
124
|
- no runtime local, falhe fechado até a capability e seu secret store/configuração estarem disponíveis;
|
|
111
125
|
- testes devem substituir a fronteira externa; não envie e-mail real e não grave credenciais de teste.
|
|
126
|
+
|
package/package.json
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"sync:metadata": "oonCore-front sync:metadata"
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
|
-
"@oondemand/oon-core-front": "^0.6.
|
|
14
|
+
"@oondemand/oon-core-front": "^0.6.11",
|
|
15
15
|
"@chakra-ui/react": "^3.13.0",
|
|
16
16
|
"@emotion/react": "^11.14.0",
|
|
17
17
|
"@tanstack/react-query": "^5.65.0",
|