@oondemand/create-central-oon 0.3.8 → 0.3.9

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/README.md CHANGED
@@ -1,9 +1,9 @@
1
1
  # @oondemand/create-central-oon
2
2
 
3
- 📖 **[Documentação completa → ooncoredoc.vercel.app](https://ooncoredoc.vercel.app)**
4
-
5
3
  Gerador de **Centrais Oon**. Cria, a partir do nome da Central, um `backend/` de domínio e um `frontend/` declarativo prontos para consumir o Core (`@oondemand/oon-core-back` e `@oondemand/oon-core-front`).
6
4
 
5
+ > A documentação pública pode existir para consulta, mas a fonte de verdade para codificação assistida fica dentro deste pacote npm, versionada junto com o gerador.
6
+
7
7
  Toda Central gerada nasce com o padrão visual e operacional consolidado na **Central Minexco**:
8
8
 
9
9
  - identidade visual Oon/CST com Poppins, azul `#0474AF` e fundo `#F8F9FA`;
@@ -36,6 +36,51 @@ Aliases: o binário também responde por `scaffold-central-oon`.
36
36
  | `--no-install` | Não roda `npm install` nos projetos gerados. |
37
37
  | `--list` | Lista os templates e sai. |
38
38
 
39
+ ## Documentação interna para Codex
40
+
41
+ O pacote inclui documentação canônica em `docs/`. Ela é publicada no npm junto com o gerador.
42
+
43
+ Ao criar uma Central, o CLI gera uma pasta `.ooncore/` com um cache local da documentação da versão instalada:
44
+
45
+ ```txt
46
+ <central>/
47
+ └── .ooncore/
48
+ ├── CODEX.md
49
+ ├── context.generated.md
50
+ ├── manifest.json
51
+ └── docs/
52
+ ```
53
+
54
+ A pasta `.ooncore/` não é a fonte de verdade. Ela é apenas o contexto local para o Codex trabalhar sem depender de site externo.
55
+
56
+ ### Sincronizar documentação local
57
+
58
+ Na raiz da Central:
59
+
60
+ ```bash
61
+ npm run ooncore:docs
62
+ ```
63
+
64
+ ou diretamente:
65
+
66
+ ```bash
67
+ npx create-central-oon docs --sync
68
+ ```
69
+
70
+ ### Verificar se está atualizada
71
+
72
+ ```bash
73
+ npm run ooncore:docs:check
74
+ ```
75
+
76
+ ou diretamente:
77
+
78
+ ```bash
79
+ npx create-central-oon docs --check
80
+ ```
81
+
82
+ O check compara a versão e o hash da documentação local com a versão instalada do pacote.
83
+
39
84
  ## Templates funcionais
40
85
 
41
86
  Todos utilizam o mesmo frontend padrão Minexco.
@@ -55,6 +100,8 @@ Todos utilizam o mesmo frontend padrão Minexco.
55
100
  ```txt
56
101
  <central>/
57
102
  ├── README.md
103
+ ├── package.json # scripts de sync/check da documentação OonCore
104
+ ├── .ooncore/ # cache local gerado a partir do pacote instalado
58
105
  ├── backend/ # consome @oondemand/oon-core-back
59
106
  │ ├── central.config.js # identidade + módulos + paths de domínio
60
107
  │ ├── central.manifest.json # valores de deploy (render no Core)
@@ -70,8 +117,11 @@ Todos utilizam o mesmo frontend padrão Minexco.
70
117
  ## Próximos passos após gerar
71
118
 
72
119
  ```bash
73
- cd <central>/backend && cp .env.example .env && npm run dev
74
- cd ../frontend && cp .env.example .env && npm run dev
120
+ cd <central>
121
+ npm run ooncore:docs:check
122
+
123
+ cd backend && cp .env.example .env && npm run dev
124
+ cd ../frontend && cp .env.example .env && npm run dev
75
125
  ```
76
126
 
77
127
  Evoluir a Central significa criar models em `backend/src/models` e declarar as telas em `frontend/central.ui.json`. Menu, rotas, datagrids, formulários e esteiras são montados pelo Core mantendo o padrão Minexco.
package/bin/cli.js CHANGED
@@ -2,9 +2,11 @@
2
2
  "use strict";
3
3
 
4
4
  /**
5
- * CLI do create-central-oon (Fase 4 — Seção 5/25).
5
+ * CLI do create-central-oon.
6
6
  *
7
7
  * npx create-central-oon <nome-da-central> [opções]
8
+ * npx create-central-oon docs --sync
9
+ * npx create-central-oon docs --check
8
10
  *
9
11
  * Opções:
10
12
  * --template=<t> Template inicial (default: basic). Veja --list.
@@ -12,26 +14,62 @@
12
14
  * --force Sobrescreve pasta existente.
13
15
  * --no-install Não roda npm install nos projetos gerados.
14
16
  * --list Lista os templates disponíveis e sai.
17
+ *
18
+ * Documentação:
19
+ * docs --sync Gera/atualiza .ooncore/ com a documentação da versão instalada.
20
+ * docs --check Valida se .ooncore/ está sincronizado com a versão instalada.
15
21
  */
16
22
 
17
- const { run, listTemplates } = require("../src/index");
23
+ const { run, listTemplates, syncDocs, checkDocs } = require("../src/index");
18
24
 
19
25
  function parseArgs(argv) {
20
- const opts = { template: "basic", here: false, force: false, install: true, list: false };
26
+ const opts = {
27
+ command: null,
28
+ template: "basic",
29
+ here: false,
30
+ force: false,
31
+ install: true,
32
+ list: false,
33
+ docsSync: false,
34
+ docsCheck: false,
35
+ };
21
36
  const positionals = [];
22
- for (const arg of argv) {
37
+
38
+ for (let i = 0; i < argv.length; i += 1) {
39
+ const arg = argv[i];
40
+
23
41
  if (arg === "--here") opts.here = true;
24
42
  else if (arg === "--force") opts.force = true;
25
43
  else if (arg === "--no-install") opts.install = false;
26
44
  else if (arg === "--list") opts.list = true;
45
+ else if (arg === "--sync") opts.docsSync = true;
46
+ else if (arg === "--check") opts.docsCheck = true;
27
47
  else if (arg.startsWith("--template=")) opts.template = arg.slice("--template=".length);
28
- else if (arg === "--template") opts.template = argv[argv.indexOf(arg) + 1];
29
- else if (!arg.startsWith("-")) positionals.push(arg);
48
+ else if (arg === "--template") {
49
+ opts.template = argv[i + 1];
50
+ i += 1;
51
+ } else if (!arg.startsWith("-")) {
52
+ positionals.push(arg);
53
+ }
30
54
  }
31
- opts.name = positionals[0];
55
+
56
+ if (positionals[0] === "docs") {
57
+ opts.command = "docs";
58
+ } else {
59
+ opts.name = positionals[0];
60
+ }
61
+
32
62
  return opts;
33
63
  }
34
64
 
65
+ function printUsage() {
66
+ console.error("Uso:");
67
+ console.error(" npx create-central-oon <nome-da-central> [--template=basic]");
68
+ console.error(" npx create-central-oon --list");
69
+ console.error(" npx create-central-oon docs --sync");
70
+ console.error(" npx create-central-oon docs --check");
71
+ }
72
+
35
73
  async function main() {
36
74
  const opts = parseArgs(process.argv.slice(2));
37
75
 
@@ -41,13 +79,21 @@ async function main() {
41
79
  process.exit(0);
42
80
  }
43
81
 
44
- if (!opts.name) {
45
- console.error("Uso: npx create-central-oon <nome-da-central> [--template=basic]");
46
- console.error(" npx create-central-oon --list");
47
- process.exit(1);
48
- }
49
-
50
82
  try {
83
+ if (opts.command === "docs") {
84
+ if (opts.docsCheck) {
85
+ checkDocs();
86
+ } else {
87
+ syncDocs();
88
+ }
89
+ return;
90
+ }
91
+
92
+ if (!opts.name) {
93
+ printUsage();
94
+ process.exit(1);
95
+ }
96
+
51
97
  await run(opts);
52
98
  } catch (err) {
53
99
  console.error("\n✖", err.message);
@@ -0,0 +1,87 @@
1
+ # Padrões Backend
2
+
3
+ O backend da Central deve conter apenas domínio e extensões. Boot, infraestrutura, CRUD padrão, autenticação, RBAC e metadata pertencem ao `@oondemand/oon-core-back`.
4
+
5
+ ## Estrutura esperada
6
+
7
+ ```txt
8
+ backend/
9
+ ├── central.config.js
10
+ ├── central.manifest.json
11
+ └── src/
12
+ ├── models/
13
+ ├── validations/
14
+ ├── triggers/
15
+ ├── hooks/
16
+ ├── mappings/
17
+ ├── documents/
18
+ ├── pipelines/
19
+ ├── integrations/
20
+ ├── routes/
21
+ ├── controllers/
22
+ └── services/
23
+ ```
24
+
25
+ ## Models
26
+
27
+ Use models para declarar entidades de negócio. Cada model deve ser pequeno, com nomes claros e campos compatíveis com as telas e integrações.
28
+
29
+ Boas práticas:
30
+
31
+ - use campos explícitos;
32
+ - defina tipos, obrigatoriedade e enums quando aplicável;
33
+ - preserve campos de status para esteiras;
34
+ - evite regras complexas diretamente no schema;
35
+ - evite dependência direta de frontend.
36
+
37
+ ## Validations
38
+
39
+ Use validations para regras de negócio síncronas e mensagens claras para o usuário.
40
+
41
+ Exemplos:
42
+
43
+ - campo obrigatório condicional;
44
+ - status permitido para transição;
45
+ - valor mínimo/máximo;
46
+ - combinação inválida de campos;
47
+ - bloqueio por permissão ou perfil.
48
+
49
+ ## Triggers e hooks
50
+
51
+ Use triggers e hooks para efeitos controlados depois ou antes de alterações.
52
+
53
+ Exemplos:
54
+
55
+ - criar ticket de integração;
56
+ - recalcular campos derivados;
57
+ - gerar histórico operacional;
58
+ - disparar conector;
59
+ - atualizar etapa da esteira.
60
+
61
+ Regras:
62
+
63
+ - trigger não deve esconder regra crítica sem validação;
64
+ - evite efeitos irreversíveis sem log;
65
+ - integração externa deve passar por camada de integração/conector;
66
+ - falhas de integração devem gerar status rastreável, não quebrar silenciosamente o processo.
67
+
68
+ ## Rotas customizadas
69
+
70
+ Crie rotas customizadas somente quando o CRUD/metadata do Core não resolver.
71
+
72
+ Toda rota customizada deve ter:
73
+
74
+ - autenticação;
75
+ - verificação de permissão;
76
+ - validação de entrada;
77
+ - tratamento de erro;
78
+ - resposta padronizada;
79
+ - ausência de segredo hardcoded.
80
+
81
+ ## Serviços
82
+
83
+ Use `services/` para regras reutilizáveis. Evite controllers grandes.
84
+
85
+ ## Segurança
86
+
87
+ Nunca confie no frontend para permissão, tenant, app ou perfil. O backend deve validar tudo que altera dados, dispara integrações ou expõe informações sensíveis.
@@ -0,0 +1,41 @@
1
+ # Checklist de Implementação
2
+
3
+ Use este checklist antes de concluir qualquer tarefa de codificação em uma Central Oon.
4
+
5
+ ## Contexto
6
+
7
+ - [ ] Rodei `npm run ooncore:docs:check`.
8
+ - [ ] Rodei `npm run ooncore:docs` se havia documentação desatualizada.
9
+ - [ ] Li `.ooncore/context.generated.md`.
10
+ - [ ] Entendi qual recurso do Core já resolve parte da necessidade.
11
+
12
+ ## Backend
13
+
14
+ - [ ] Usei model, validation, trigger, hook, mapping ou integration quando aplicável.
15
+ - [ ] Evitei recriar CRUD.
16
+ - [ ] Validei entrada.
17
+ - [ ] Validei permissão no backend.
18
+ - [ ] Tratei erros.
19
+ - [ ] Não hardcodei segredos.
20
+ - [ ] Mantive rastreabilidade.
21
+
22
+ ## Frontend
23
+
24
+ - [ ] Usei `central.ui.json` antes de criar componente customizado.
25
+ - [ ] Evitei recriar shell, rotas, menu, datagrid ou form.
26
+ - [ ] Usei override apenas quando necessário.
27
+ - [ ] Não coloquei regra crítica apenas no frontend.
28
+
29
+ ## Integrações
30
+
31
+ - [ ] Usei camada de integração/conector.
32
+ - [ ] Modelei mapping.
33
+ - [ ] Registrei status de integração.
34
+ - [ ] Normalizei erros externos.
35
+ - [ ] Não expus credenciais.
36
+
37
+ ## Entrega
38
+
39
+ - [ ] A Central continua atualizável com novas versões do Core.
40
+ - [ ] A alteração é pequena, coesa e aderente à arquitetura.
41
+ - [ ] O comportamento esperado está documentado no README ou no próprio módulo quando necessário.
package/docs/CODEX.md ADDED
@@ -0,0 +1,46 @@
1
+ # CODEX.md — Regras de Codificação OonCore
2
+
3
+ Este arquivo é a porta de entrada para o Codex codificar uma Central Oon.
4
+
5
+ A fonte de verdade desta documentação é a versão instalada do pacote `@oondemand/create-central-oon`. A pasta `.ooncore/` gerada em cada Central é apenas um cache local, criado por `create-central-oon docs --sync`.
6
+
7
+ ## Antes de codificar
8
+
9
+ 1. Rode `npm run ooncore:docs:check` na raiz da Central.
10
+ 2. Se estiver desatualizado, rode `npm run ooncore:docs`.
11
+ 3. Leia `.ooncore/context.generated.md`.
12
+ 4. Identifique o recurso do Core que resolve a necessidade antes de criar código customizado.
13
+
14
+ ## Princípios obrigatórios
15
+
16
+ - Escreva apenas o domínio da Central.
17
+ - Use `@oondemand/oon-core-back` para boot, autenticação, RBAC, CRUD, metadata, auditoria e padrões de API.
18
+ - Use `@oondemand/oon-core-front` para shell, rotas, menu, datagrid, formulários, badges, ações e renderização por metadata.
19
+ - Não recrie infraestrutura que já existe no Core.
20
+ - Não crie autenticação paralela.
21
+ - Não duplique RBAC no frontend.
22
+ - Não hardcode tenant, app, usuário, perfil, permissões, URLs sensíveis ou segredos.
23
+ - Não exponha chaves em código, templates ou documentação gerada.
24
+ - Não altere arquivos gerados do Core se houver extensão declarativa disponível.
25
+ - Prefira models, validations, triggers, hooks, mappings, documents, pipelines, integrations e overrides declarativos.
26
+
27
+ ## Ordem de decisão
28
+
29
+ Ao implementar uma necessidade, siga esta ordem:
30
+
31
+ 1. Configuração existente do Core.
32
+ 2. Declaração em `central.config.js` ou `central.ui.json`.
33
+ 3. Model, validation, trigger, hook ou mapping no backend da Central.
34
+ 4. Override local pequeno e isolado.
35
+ 5. Código customizado somente quando o Core não oferecer extensão adequada.
36
+
37
+ ## Entrega segura
38
+
39
+ Toda alteração deve manter:
40
+
41
+ - rastreabilidade;
42
+ - validação de entrada;
43
+ - RBAC no backend;
44
+ - ausência de segredo hardcoded;
45
+ - separação entre domínio da Central e infraestrutura do Core;
46
+ - compatibilidade com atualização futura dos pacotes `@oondemand/*`.
@@ -0,0 +1,66 @@
1
+ # Coleções, Documentos e Esteiras
2
+
3
+ Coleções, documentos e esteiras são a base operacional da Central Oon.
4
+
5
+ ## Coleções
6
+
7
+ Use coleções para entidades de negócio:
8
+
9
+ - clientes;
10
+ - fornecedores;
11
+ - pedidos;
12
+ - pagamentos;
13
+ - documentos fiscais;
14
+ - serviços tomados;
15
+ - serviços prestados;
16
+ - integrações;
17
+ - tickets operacionais.
18
+
19
+ Cada coleção deve ter:
20
+
21
+ - model no backend;
22
+ - metadata para CRUD;
23
+ - campos de status quando participar de esteira;
24
+ - validações de negócio;
25
+ - configuração de tela no frontend.
26
+
27
+ ## Documentos
28
+
29
+ Use documentos para entidades que exigem governança documental, aprovação, anexos ou histórico específico.
30
+
31
+ Exemplos:
32
+
33
+ - NF;
34
+ - contrato;
35
+ - proposta;
36
+ - comprovante;
37
+ - ordem de serviço;
38
+ - pedido de compra.
39
+
40
+ ## Esteiras de processo
41
+
42
+ Use esteiras para fluxos operacionais com etapas claras.
43
+
44
+ Boas práticas:
45
+
46
+ - status/etapa deve estar no backend;
47
+ - transições devem ser validadas;
48
+ - ações devem registrar usuário e data;
49
+ - exceções devem ter status próprio;
50
+ - cada etapa deve representar uma decisão operacional real.
51
+
52
+ ## Esteiras de integração
53
+
54
+ Use esteiras de integração para acompanhar comunicação com sistemas externos.
55
+
56
+ Estados recomendados:
57
+
58
+ - pendente;
59
+ - em processamento;
60
+ - enviado;
61
+ - concluído;
62
+ - falha;
63
+ - aguardando retry;
64
+ - cancelado.
65
+
66
+ Integrações não devem ser caixas-pretas. O usuário operacional precisa enxergar o que aconteceu, qual erro ocorreu e qual ação pode ser tomada.
@@ -0,0 +1,66 @@
1
+ # Conectores e Integrações
2
+
3
+ Toda integração deve ser modelada como um processo rastreável, não como chamada solta dentro de controller.
4
+
5
+ ## Objetivo
6
+
7
+ Transformar cada integração em:
8
+
9
+ ```txt
10
+ configuração + mapping + execução + status + rastreabilidade
11
+ ```
12
+
13
+ ## Estrutura recomendada
14
+
15
+ ```txt
16
+ backend/src/integrations/
17
+ ├── <sistema>/
18
+ │ ├── client.js
19
+ │ ├── mappings/
20
+ │ ├── services/
21
+ │ └── README.md
22
+ ```
23
+
24
+ ## Client
25
+
26
+ O client deve concentrar:
27
+
28
+ - URL base;
29
+ - autenticação;
30
+ - headers;
31
+ - timeout;
32
+ - retry técnico;
33
+ - normalização de erro.
34
+
35
+ Não coloque regra de negócio no client.
36
+
37
+ ## Mapping
38
+
39
+ Mappings devem transformar dados entre a Central e o sistema externo.
40
+
41
+ Regras:
42
+
43
+ - mapping deve ser explícito;
44
+ - campos obrigatórios devem ser validados antes do envio;
45
+ - resposta externa deve ser normalizada;
46
+ - erros devem ser compreensíveis para operação.
47
+
48
+ ## Esteira de integração
49
+
50
+ Toda integração relevante deve gerar registro operacional com:
51
+
52
+ - origem;
53
+ - destino;
54
+ - payload resumido ou referência;
55
+ - status;
56
+ - tentativas;
57
+ - erro normalizado;
58
+ - data/hora;
59
+ - usuário ou processo responsável.
60
+
61
+ ## Segurança
62
+
63
+ - Nunca versionar app key, secret, token ou credencial.
64
+ - Não logar payloads sensíveis sem necessidade.
65
+ - Não expor credenciais no frontend.
66
+ - Usar `.env` e configuração de ambiente.
@@ -0,0 +1,27 @@
1
+ # Do and Don't
2
+
3
+ ## Faça
4
+
5
+ - Use o Core antes de criar código novo.
6
+ - Modele o domínio com clareza.
7
+ - Prefira configuração e metadata.
8
+ - Escreva validações explícitas.
9
+ - Mantenha regras críticas no backend.
10
+ - Use esteiras para processos com status.
11
+ - Use conectores para integrações.
12
+ - Registre erros de forma operacional.
13
+ - Mantenha compatibilidade com atualização dos pacotes.
14
+ - Atualize `.ooncore/` com `npm run ooncore:docs`.
15
+
16
+ ## Não faça
17
+
18
+ - Não recrie CRUD.
19
+ - Não recrie autenticação.
20
+ - Não duplique RBAC no frontend.
21
+ - Não criar um frontend inteiro se um override resolve.
22
+ - Não chamar APIs externas direto de qualquer lugar.
23
+ - Não hardcode tenant, app, usuário, URL sensível ou segredo.
24
+ - Não colocar regra crítica apenas no frontend.
25
+ - Não ignorar logs e rastreabilidade.
26
+ - Não editar `.ooncore/context.generated.md` manualmente.
27
+ - Não depender de documentação externa para codificar a arquitetura.
@@ -0,0 +1,66 @@
1
+ # Padrões Frontend
2
+
3
+ O frontend da Central deve ser declarativo. Shell, providers, rotas, menu, datagrid, formulários, documentos e esteiras pertencem ao `@oondemand/oon-core-front`.
4
+
5
+ ## Estrutura esperada
6
+
7
+ ```txt
8
+ frontend/
9
+ ├── central.ui.json
10
+ └── src/
11
+ ├── main.tsx
12
+ ├── collections/
13
+ ├── documents/
14
+ ├── pipelines/
15
+ ├── dashboards/
16
+ └── overrides/
17
+ ```
18
+
19
+ ## central.ui.json
20
+
21
+ Use `central.ui.json` como entrada principal para declarar:
22
+
23
+ - menu;
24
+ - coleções;
25
+ - campos exibidos;
26
+ - filtros;
27
+ - ações;
28
+ - formulários;
29
+ - documentos;
30
+ - esteiras;
31
+ - dashboards;
32
+ - agrupamentos.
33
+
34
+ ## Regras
35
+
36
+ - Não recrie layout completo se o Core já renderiza.
37
+ - Não duplique chamada REST manual se o SDK do Core já atende.
38
+ - Não coloque regra de permissão apenas no frontend.
39
+ - Não hardcode endpoints quando a metadata puder fornecer.
40
+ - Não crie variações visuais fora do padrão sem necessidade real.
41
+ - Use overrides pequenos, específicos e documentados.
42
+
43
+ ## Overrides
44
+
45
+ Overrides são permitidos para:
46
+
47
+ - campo especial;
48
+ - ação específica;
49
+ - card customizado;
50
+ - cabeçalho customizado;
51
+ - dashboard customizado;
52
+ - integração visual pontual.
53
+
54
+ Overrides não devem virar uma reimplementação do Core.
55
+
56
+ ## Experiência padrão
57
+
58
+ A Central deve manter o padrão OonCore:
59
+
60
+ - navegação consistente;
61
+ - datagrids densos;
62
+ - formulários claros;
63
+ - feedback visual;
64
+ - status por badges;
65
+ - ações rastreáveis;
66
+ - responsividade.
@@ -0,0 +1,50 @@
1
+ # Arquitetura OonCore
2
+
3
+ O OonCore é a base para criar Centrais operacionais sob demanda com arquitetura padronizada, segura e evolutiva.
4
+
5
+ A Central gerada não deve nascer como um sistema completo do zero. Ela deve nascer como uma camada de domínio que consome os recursos do Core.
6
+
7
+ ## Separação de responsabilidades
8
+
9
+ ```txt
10
+ Central
11
+ ├── backend/ domínio, regras, validações, integrações e esteiras
12
+ └── frontend/ declaração de telas, coleções, documentos e overrides
13
+
14
+ OonCore Back
15
+ ├── boot Express
16
+ ├── Mongo/Mongoose
17
+ ├── autenticação
18
+ ├── RBAC
19
+ ├── CRUD metadata-driven
20
+ ├── auditoria
21
+ ├── triggers/hooks
22
+ └── APIs padrão
23
+
24
+ OonCore Front
25
+ ├── shell React
26
+ ├── providers
27
+ ├── roteamento
28
+ ├── menu
29
+ ├── datagrid
30
+ ├── formulários
31
+ ├── documentos
32
+ ├── esteiras
33
+ └── SDK REST
34
+ ```
35
+
36
+ ## Modelo mini-monolítico
37
+
38
+ Cada Central começa como um mini-monolito de negócio: pequeno, coeso, isolado e capaz de entregar valor rapidamente. Quando uma parte do domínio se tornar reutilizável, crítica ou independente, ela pode evoluir para conector, serviço compartilhado ou micro-serviço.
39
+
40
+ ## Fonte de verdade
41
+
42
+ - Dados e regras ficam no backend.
43
+ - Metadata operacional é exposta pelo backend.
44
+ - Frontend renderiza a experiência a partir da metadata.
45
+ - Permissões são decididas no backend.
46
+ - Integrações são tratadas como conectores, mappings, triggers e esteiras de integração.
47
+
48
+ ## Objetivo do Codex
49
+
50
+ O Codex deve acelerar a construção da Central usando a arquitetura existente. O objetivo não é gerar um app genérico, mas sim completar a camada de domínio com segurança e aderência ao Core.
@@ -0,0 +1,35 @@
1
+ # RBAC e Segurança
2
+
3
+ A segurança da Central deve ser aplicada no backend. O frontend pode ocultar ou exibir ações, mas não é a fonte de decisão.
4
+
5
+ ## Regras obrigatórias
6
+
7
+ - Toda operação sensível deve validar usuário autenticado.
8
+ - Toda alteração de dados deve validar permissão.
9
+ - Toda ação de integração deve validar permissão e contexto.
10
+ - Nunca confiar em `tenantId`, `appId`, `perfil` ou `roles` enviados livremente pelo frontend.
11
+ - Segredos devem vir de variáveis de ambiente ou vault equivalente.
12
+ - Logs não devem expor tokens, senhas, app keys ou dados sensíveis desnecessários.
13
+
14
+ ## RBAC
15
+
16
+ Use o RBAC do Core para:
17
+
18
+ - controlar acesso por app;
19
+ - controlar perfis;
20
+ - controlar ações;
21
+ - filtrar funcionalidades;
22
+ - proteger rotas;
23
+ - permitir evolução de permissões sem reconstruir telas.
24
+
25
+ ## Checklist de segurança para Codex
26
+
27
+ Antes de concluir uma alteração, confirme:
28
+
29
+ - Existe validação de entrada?
30
+ - Existe validação de permissão no backend?
31
+ - Existe tratamento de erro?
32
+ - A operação gera rastreabilidade?
33
+ - Algum segredo foi colocado no código?
34
+ - Algum dado sensível foi exposto no frontend?
35
+ - O comportamento funciona para múltiplos usuários e múltiplos apps?
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@oondemand/create-central-oon",
3
- "version": "0.3.8",
3
+ "version": "0.3.9",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/oondemand/oon-platform.git",
7
7
  "directory": "packages/create-central-oon"
8
8
  },
9
- "description": "Gerador de Centrais Oon com backend declarativo e frontend padrão Central Minexco: menu, datagrids, formulários e esteiras.",
9
+ "description": "Gerador de Centrais Oon com backend declarativo, frontend padrão e documentação interna OonCore para Codex.",
10
10
  "main": "src/index.js",
11
11
  "exports": {
12
12
  ".": "./src/index.js"
@@ -19,6 +19,7 @@
19
19
  "bin",
20
20
  "src",
21
21
  "templates",
22
+ "docs",
22
23
  "README.md"
23
24
  ],
24
25
  "engines": {
@@ -30,7 +31,9 @@
30
31
  "central",
31
32
  "scaffold",
32
33
  "create",
33
- "generator"
34
+ "generator",
35
+ "codex",
36
+ "docs"
34
37
  ],
35
38
  "license": "SEE LICENSE IN LICENSE",
36
39
  "publishConfig": {
package/src/index.js CHANGED
@@ -2,10 +2,13 @@
2
2
 
3
3
  const fs = require("node:fs");
4
4
  const path = require("node:path");
5
+ const crypto = require("node:crypto");
5
6
  const { spawnSync } = require("node:child_process");
6
7
  const { copyTemplate } = require("./render");
7
8
 
8
- const TEMPLATES_DIR = path.join(__dirname, "..", "templates");
9
+ const PACKAGE_ROOT = path.join(__dirname, "..");
10
+ const TEMPLATES_DIR = path.join(PACKAGE_ROOT, "templates");
11
+ const DOCS_DIR = path.join(PACKAGE_ROOT, "docs");
9
12
 
10
13
  const TEMPLATES = [
11
14
  { id: "basic", description: "Central mínima com uma coleção dinâmica (Pessoa)." },
@@ -52,6 +55,183 @@ function npmInstall(dir) {
52
55
  return !r.status && !r.error;
53
56
  }
54
57
 
58
+ function readPackageVersion() {
59
+ const pkg = JSON.parse(fs.readFileSync(path.join(PACKAGE_ROOT, "package.json"), "utf8"));
60
+ return pkg.version;
61
+ }
62
+
63
+ function listDocFiles(dir = DOCS_DIR, prefix = "") {
64
+ if (!fs.existsSync(dir)) return [];
65
+ const files = [];
66
+
67
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
68
+ const relative = path.join(prefix, entry.name);
69
+ const absolute = path.join(dir, entry.name);
70
+
71
+ if (entry.isDirectory()) {
72
+ files.push(...listDocFiles(absolute, relative));
73
+ } else if (entry.isFile() && entry.name.endsWith(".md")) {
74
+ files.push(relative);
75
+ }
76
+ }
77
+
78
+ return files.sort((a, b) => a.localeCompare(b));
79
+ }
80
+
81
+ function docsHash(files = listDocFiles()) {
82
+ const hash = crypto.createHash("sha256");
83
+ for (const file of files) {
84
+ const normalized = file.split(path.sep).join("/");
85
+ hash.update(normalized);
86
+ hash.update("\n");
87
+ hash.update(fs.readFileSync(path.join(DOCS_DIR, file)));
88
+ hash.update("\n");
89
+ }
90
+ return hash.digest("hex");
91
+ }
92
+
93
+ function resolveCentralRoot(cwd = process.cwd()) {
94
+ const current = path.resolve(cwd);
95
+ const parent = path.dirname(current);
96
+
97
+ if (fs.existsSync(path.join(current, "backend")) && fs.existsSync(path.join(current, "frontend"))) {
98
+ return current;
99
+ }
100
+
101
+ if (
102
+ ["backend", "frontend"].includes(path.basename(current)) &&
103
+ fs.existsSync(path.join(parent, "backend")) &&
104
+ fs.existsSync(path.join(parent, "frontend"))
105
+ ) {
106
+ return parent;
107
+ }
108
+
109
+ return current;
110
+ }
111
+
112
+ function removeDir(dir) {
113
+ if (fs.existsSync(dir)) fs.rmSync(dir, { recursive: true, force: true });
114
+ }
115
+
116
+ function copyDocs(srcDir, destDir) {
117
+ if (!fs.existsSync(srcDir)) {
118
+ throw new Error(`Diretório de documentação não encontrado: ${srcDir}`);
119
+ }
120
+
121
+ fs.mkdirSync(destDir, { recursive: true });
122
+
123
+ for (const entry of fs.readdirSync(srcDir, { withFileTypes: true })) {
124
+ const from = path.join(srcDir, entry.name);
125
+ const to = path.join(destDir, entry.name);
126
+
127
+ if (entry.isDirectory()) {
128
+ copyDocs(from, to);
129
+ } else if (entry.isFile()) {
130
+ fs.copyFileSync(from, to);
131
+ }
132
+ }
133
+ }
134
+
135
+ function buildContext(files = listDocFiles()) {
136
+ const header = [
137
+ "# OonCore Contexto Consolidado para Codex",
138
+ "",
139
+ "> Arquivo gerado automaticamente por `create-central-oon docs --sync`.",
140
+ "> Não edite manualmente. A fonte de verdade está no pacote `@oondemand/create-central-oon` instalado.",
141
+ "",
142
+ "Este contexto consolida as regras mínimas para codificar Centrais Oon com segurança, usando o máximo dos recursos do OonCore.",
143
+ "",
144
+ ].join("\n");
145
+
146
+ const sections = files
147
+ .map((file) => {
148
+ const normalized = file.split(path.sep).join("/");
149
+ const content = fs.readFileSync(path.join(DOCS_DIR, file), "utf8").trim();
150
+ return [
151
+ "---",
152
+ "",
153
+ `<!-- source: ${normalized} -->`,
154
+ "",
155
+ content,
156
+ "",
157
+ ].join("\n");
158
+ })
159
+ .join("\n");
160
+
161
+ return `${header}\n${sections}`;
162
+ }
163
+
164
+ function buildManifest(files = listDocFiles()) {
165
+ return {
166
+ source: "@oondemand/create-central-oon",
167
+ version: readPackageVersion(),
168
+ generatedAt: new Date().toISOString(),
169
+ docsMode: "generated-cache",
170
+ docsHash: docsHash(files),
171
+ files: files.map((file) => file.split(path.sep).join("/")),
172
+ };
173
+ }
174
+
175
+ function syncDocs(opts = {}) {
176
+ const root = resolveCentralRoot(opts.cwd);
177
+ const outDir = path.join(root, ".ooncore");
178
+ const docsOutDir = path.join(outDir, "docs");
179
+ const files = listDocFiles();
180
+
181
+ if (!files.length) {
182
+ throw new Error("Nenhum arquivo .md encontrado em packages/create-central-oon/docs.");
183
+ }
184
+
185
+ fs.mkdirSync(outDir, { recursive: true });
186
+ removeDir(docsOutDir);
187
+ copyDocs(DOCS_DIR, docsOutDir);
188
+
189
+ const codexSource = path.join(DOCS_DIR, "CODEX.md");
190
+ if (fs.existsSync(codexSource)) {
191
+ fs.copyFileSync(codexSource, path.join(outDir, "CODEX.md"));
192
+ }
193
+
194
+ fs.writeFileSync(path.join(outDir, "context.generated.md"), buildContext(files));
195
+ fs.writeFileSync(path.join(outDir, "manifest.json"), `${JSON.stringify(buildManifest(files), null, 2)}\n`);
196
+
197
+ console.log(`✔ Documentação OonCore sincronizada em ${path.relative(process.cwd(), outDir) || ".ooncore"}`);
198
+ console.log(` Versão: ${readPackageVersion()}`);
199
+ console.log(` Arquivos: ${files.length}`);
200
+ }
201
+
202
+ function checkDocs(opts = {}) {
203
+ const root = resolveCentralRoot(opts.cwd);
204
+ const manifestPath = path.join(root, ".ooncore", "manifest.json");
205
+ const version = readPackageVersion();
206
+ const files = listDocFiles();
207
+ const currentHash = docsHash(files);
208
+
209
+ if (!fs.existsSync(manifestPath)) {
210
+ throw new Error("Documentação OonCore local não encontrada. Rode `npm run ooncore:docs`.");
211
+ }
212
+
213
+ const manifest = JSON.parse(fs.readFileSync(manifestPath, "utf8"));
214
+ const problems = [];
215
+
216
+ if (manifest.source !== "@oondemand/create-central-oon") {
217
+ problems.push(`fonte esperada @oondemand/create-central-oon, encontrada ${manifest.source || "(vazia)"}`);
218
+ }
219
+
220
+ if (manifest.version !== version) {
221
+ problems.push(`versão local ${manifest.version || "(vazia)"} diferente da instalada ${version}`);
222
+ }
223
+
224
+ if (manifest.docsHash !== currentHash) {
225
+ problems.push("hash da documentação local diferente da documentação instalada");
226
+ }
227
+
228
+ if (problems.length) {
229
+ throw new Error(`Documentação OonCore desatualizada:\n- ${problems.join("\n- ")}\nRode \`npm run ooncore:docs\`.`);
230
+ }
231
+
232
+ console.log(`✔ Documentação OonCore atualizada (versão ${version}).`);
233
+ }
234
+
55
235
  async function run(opts) {
56
236
  const template = TEMPLATES.find((t) => t.id === opts.template);
57
237
  if (!template) {
@@ -81,13 +261,19 @@ async function run(opts) {
81
261
  // 2. Overlay do template escolhido (vence sobre o _base).
82
262
  copyTemplate(path.join(TEMPLATES_DIR, template.id), targetDir, tokens);
83
263
 
264
+ // 3. Contexto local para Codex derivado da documentação da versão instalada.
265
+ syncDocs({ cwd: targetDir });
266
+
84
267
  console.log("✔ Arquivos gerados.");
85
268
 
86
269
  if (opts.install) {
87
270
  console.log("\n📦 Instalando dependências (best-effort)...");
271
+ const rootOk = fs.existsSync(path.join(targetDir, "package.json"))
272
+ ? npmInstall(targetDir)
273
+ : true;
88
274
  const backOk = npmInstall(path.join(targetDir, "backend"));
89
275
  const frontOk = npmInstall(path.join(targetDir, "frontend"));
90
- if (!backOk || !frontOk) {
276
+ if (!rootOk || !backOk || !frontOk) {
91
277
  console.warn(
92
278
  "\n⚠ npm install falhou em um dos projetos (esperado se os pacotes @oondemand/* ainda não foram publicados). Rode manualmente depois."
93
279
  );
@@ -103,7 +289,11 @@ function printNextSteps(tokens, opts) {
103
289
  ✅ Central "${tokens.name}" pronta.
104
290
 
105
291
  Próximos passos:
106
- ${cd} # Backend (só domínio models/validations/triggers/...)
292
+ ${cd} # Sincronizar/validar documentação local do Core para Codex
293
+ npm run ooncore:docs
294
+ npm run ooncore:docs:check
295
+
296
+ # Backend (só domínio — models/validations/triggers/...)
107
297
  cd backend && cp .env.example .env && npm run dev
108
298
 
109
299
  # Frontend (só declaração — central.ui.json)
@@ -114,4 +304,13 @@ Edite backend/src/models e frontend/central.ui.json para evoluir a Central.
114
304
  `);
115
305
  }
116
306
 
117
- module.exports = { run, listTemplates, toSlug, toPascal, toTitle };
307
+ module.exports = {
308
+ run,
309
+ listTemplates,
310
+ toSlug,
311
+ toPascal,
312
+ toTitle,
313
+ syncDocs,
314
+ checkDocs,
315
+ resolveCentralRoot,
316
+ };
@@ -1,7 +1,6 @@
1
1
  # __NAME__
2
2
 
3
- Central Oon gerada com `create-central-oon`. É composta por dois projetos
4
- mínimos que consomem o Core:
3
+ Central Oon gerada com `create-central-oon`. É composta por dois projetos mínimos que consomem o Core:
5
4
 
6
5
  - **backend/** — só domínio (`src/models`, `validations`, `triggers`, …).
7
6
  Sobe com `oonCore-back dev`. Toda a infra (boot, db, auth, RBAC, metadata,
@@ -10,9 +9,26 @@ mínimos que consomem o Core:
10
9
  dev`. Shell, providers, roteamento, auth e telas vêm do
11
10
  `@oondemand/oon-core-front`, renderizados a partir do `/core/metadata` do back.
12
11
 
12
+ ## Documentação local do OonCore
13
+
14
+ A pasta `.ooncore/` é gerada automaticamente a partir da versão instalada do pacote `@oondemand/create-central-oon`.
15
+
16
+ Ela serve como contexto local para o Codex codificar sem depender de site externo.
17
+
18
+ ```bash
19
+ npm run ooncore:docs # sincroniza .ooncore/
20
+ npm run ooncore:docs:check # valida versão/hash da documentação local
21
+ ```
22
+
23
+ Não edite `.ooncore/context.generated.md` manualmente. Atualize o pacote e rode o sync.
24
+
13
25
  ## Rodando
14
26
 
15
27
  ```bash
28
+ # raiz da Central
29
+ npm install
30
+ npm run ooncore:docs:check
31
+
16
32
  # backend
17
33
  cd backend && cp .env.example .env && npm install && npm run dev
18
34
 
@@ -24,4 +40,5 @@ cd frontend && cp .env.example .env && npm install && npm run dev
24
40
 
25
41
  1. Crie models em `backend/src/models` (só schema + CRUD).
26
42
  2. Declare as telas em `frontend/central.ui.json` (coleções/esteiras/documentos).
27
- 3. O resto — grid, form, rotas, menu é montado pelo Core automaticamente.
43
+ 3. Use validations, triggers, hooks, mappings e integrations para regras e processos.
44
+ 4. O resto — grid, form, rotas, menu — é montado pelo Core automaticamente.
@@ -12,6 +12,6 @@
12
12
  "deploy": "oonCore-back deploy"
13
13
  },
14
14
  "dependencies": {
15
- "@oondemand/oon-core-back": "^0.3.8"
15
+ "@oondemand/oon-core-back": "^0.3.9"
16
16
  }
17
17
  }
@@ -10,7 +10,7 @@
10
10
  "sync:metadata": "oonCore-front sync:metadata"
11
11
  },
12
12
  "dependencies": {
13
- "@oondemand/oon-core-front": "^0.3.8",
13
+ "@oondemand/oon-core-front": "^0.3.9",
14
14
  "@chakra-ui/react": "^3.13.0",
15
15
  "@emotion/react": "^11.14.0",
16
16
  "@tanstack/react-query": "^5.65.0",
@@ -0,0 +1,15 @@
1
+ {
2
+ "name": "__SLUG__",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "description": "Central Oon __NAME__ gerada com create-central-oon.",
6
+ "scripts": {
7
+ "ooncore:docs": "create-central-oon docs --sync",
8
+ "ooncore:docs:check": "create-central-oon docs --check",
9
+ "dev:backend": "npm run dev --prefix backend",
10
+ "dev:frontend": "npm run dev --prefix frontend"
11
+ },
12
+ "devDependencies": {
13
+ "@oondemand/create-central-oon": "^0.3.8"
14
+ }
15
+ }