@oondemand/create-central-oon 0.4.29 → 0.5.0

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
@@ -36,8 +36,8 @@ Toda Central gerada possui um manifesto raiz com identidade e capabilities:
36
36
  "capabilities": ["core.collections"],
37
37
  "compatibility": {
38
38
  "core": {
39
- "minVersion": "0.3.45",
40
- "maxVersionExclusive": "0.4.0"
39
+ "minVersion": "0.5.0",
40
+ "maxVersionExclusive": "0.6.0"
41
41
  }
42
42
  }
43
43
  }
@@ -57,7 +57,7 @@ Responsabilidades do manifesto:
57
57
  - faixa compatível do OonCore;
58
58
  - metadados declarativos de ativação.
59
59
 
60
- `backend/central.config.js` fica reservado a extensões excepcionais de runtime. Em Centrais `member-central` e `portal-cockpit`, identidade, módulos e autenticação não podem ser reintroduzidos nesse arquivo. O token local de desenvolvimento é validado pelo próprio OonCore por `DEV_TOKEN`.
60
+ `backend/central.config.js` fica reservado a extensões excepcionais de runtime. Em Centrais `member-central` e `portal-cockpit`, identidade, módulos e autenticação não podem ser reintroduzidos nesse arquivo. O desenvolvimento local usa sessão aleatória HttpOnly; tokens fixos são reprovados pela conformidade.
61
61
 
62
62
  ## Verificação de conformidade
63
63
 
@@ -87,7 +87,7 @@ O comando falha quando encontra, entre outros desvios:
87
87
 
88
88
  A CI de uma Central deve executar o comando antes do build e da publicação.
89
89
 
90
- ## Documentação interna para Codex
90
+ ## Documentação distribuída para IA/Agents
91
91
 
92
92
  O pacote inclui documentação canônica em `docs/`. Ao criar uma Central, o CLI gera `.ooncore/` como cache local da documentação da versão instalada.
93
93
 
@@ -96,7 +96,7 @@ npm run ooncore:docs
96
96
  npm run ooncore:docs:check
97
97
  ```
98
98
 
99
- A pasta `.ooncore/` não é fonte de verdade; ela pode ser regenerada a partir do pacote npm.
99
+ `.ooncore/AGENTS.md` é a entrada neutra e `.ooncore/docs/` contém os contratos completos de backend, frontend e capacidades. A pasta pode ser regenerada a partir do pacote npm sem sobrescrever o `AGENTS.md` da raiz.
100
100
 
101
101
  ## Templates funcionais
102
102
 
@@ -133,9 +133,9 @@ O bootstrap gerado importa `central.app.json` e `central.ui.json` e chama `start
133
133
  ```bash
134
134
  cd <central>
135
135
  npm run check
136
-
137
- cd backend && cp .env.example .env && npm run dev
138
- cd ../frontend && cp .env.example .env && npm run dev
136
+ cp backend/.env.example backend/.env
137
+ cp frontend/.env.example frontend/.env
138
+ npm run dev
139
139
  ```
140
140
 
141
141
  Evoluir a Central significa declarar domínio, UI, mappings e regras específicas. O OonCore implementa como a aplicação funciona.
package/bin/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  "use strict";
3
3
 
4
- const { run, listTemplates, syncDocs, checkDocs } = require("../src/index");
4
+ const { run, listTemplates, syncDocs, checkDocs, runLocalDevelopment } = require("../src/index");
5
5
  const { checkConformance } = require("../src/conformance");
6
6
 
7
7
  function parseArgs(argv) {
@@ -35,8 +35,11 @@ function parseArgs(argv) {
35
35
  else if (!arg.startsWith("-")) positionals.push(arg);
36
36
  }
37
37
 
38
- if (["docs", "conformance"].includes(positionals[0])) opts.command = positionals[0];
39
- else opts.name = positionals[0];
38
+ if (["docs", "conformance", "dev"].includes(positionals[0])) {
39
+ opts.command = positionals[0];
40
+ if (opts.command === "docs" && positionals[1] === "check") opts.docsCheck = true;
41
+ if (opts.command === "docs" && positionals[1] === "sync") opts.docsSync = true;
42
+ } else opts.name = positionals[0];
40
43
  return opts;
41
44
  }
42
45
 
@@ -44,8 +47,9 @@ function printUsage() {
44
47
  console.error("Uso:");
45
48
  console.error(" npx create-central-oon <nome-da-central> [--template=basic]");
46
49
  console.error(" npx create-central-oon --list");
47
- console.error(" npx create-central-oon docs --sync|--check");
50
+ console.error(" npx create-central-oon docs sync|check");
48
51
  console.error(" npx create-central-oon conformance [--root .] [--json]");
52
+ console.error(" npx create-central-oon dev");
49
53
  }
50
54
 
51
55
  async function main() {
@@ -76,6 +80,10 @@ async function main() {
76
80
  }
77
81
  process.exit(result.ok ? 0 : 1);
78
82
  }
83
+ if (opts.command === "dev") {
84
+ runLocalDevelopment({ cwd: process.cwd() });
85
+ return;
86
+ }
79
87
  if (!opts.name) {
80
88
  printUsage();
81
89
  process.exit(1);
@@ -1,6 +1,6 @@
1
1
  # ADVANCED_UX_PATTERNS.md — UX Avançada Declarativa no OonCore
2
2
 
3
- Este documento orienta Codex e outras IAs a usarem o máximo de recursos do OonCore antes de criar telas customizadas. O foco é transformar padrões recorrentes de sistemas operacionais em **manifesto declarativo** e componentes reutilizáveis.
3
+ Este documento orienta Agents a usarem o máximo de recursos do OonCore antes de criar telas customizadas. O foco é transformar padrões recorrentes de sistemas operacionais em **manifesto declarativo** e componentes reutilizáveis.
4
4
 
5
5
  ## Objetivo
6
6
 
@@ -161,7 +161,7 @@ Use componente customizado apenas quando:
161
161
 
162
162
  Mesmo nesses casos, prefira plugar o componente em uma aba `customComponent` da modal, e não substituir a página inteira.
163
163
 
164
- ## Checklist para Codex
164
+ ## Checklist para Agents
165
165
 
166
166
  Antes de criar tela customizada:
167
167
 
package/docs/AGENTS.md ADDED
@@ -0,0 +1,47 @@
1
+ # OonCore — entrada canônica para IA/Agents
2
+
3
+ Este arquivo é o contrato inicial neutro para Codex, ChatGPT, Kimi, Manus e outros Agents que alterem uma Central Oon.
4
+
5
+ ## Ordem de leitura
6
+
7
+ 1. Leia primeiro o `AGENTS.md` da raiz do projeto consumidor, quando existir.
8
+ 2. Confirme `schemaVersion`, `version`, `docsHash` e `entrypointsHash` em `.ooncore/manifest.json`.
9
+ 3. Rode `npm run ooncore:docs:check`; se falhar, rode `npm run ooncore:docs` e verifique novamente.
10
+ 4. Consulte `docs/CAPABILITIES.md` antes de criar código.
11
+ 5. Leia os contratos de backend, frontend, runtime, RBAC ou integração indicados abaixo.
12
+ 6. Leia a documentação de domínio do projeto consumidor.
13
+
14
+ O `AGENTS.md` da raiz pertence ao projeto e nunca pode ser sobrescrito pelo scaffold ou pelo sync do Core.
15
+
16
+ ## Roteamento por tarefa
17
+
18
+ | Tarefa | Leitura obrigatória |
19
+ |---|---|
20
+ | Domínio, models, validações e fórmulas | `BACKEND_API.md`, `BACKEND_DOMAIN_MANIFEST.md`, `BACKEND_PATTERNS.md`, `REACTIVE_DOMAIN_FORMULAS.md` |
21
+ | CRUD, metadata e UI | `METADATA_CRUD_UI.md`, `FRONTEND_API.md`, `FRONTEND_MANIFEST_REFERENCE.md` |
22
+ | Auth, ativação, tenant ou permissões | `AUTH_ACTIVATION_RBAC.md`, `RBAC_SECURITY.md`, `DO_AND_DONT.md` |
23
+ | Execução local | `RUNTIME_MODES.md`, `LOCAL_DEVELOPMENT.md`, `LOCAL_SECURITY_BOUNDARY.md` |
24
+ | Rotas, hooks, jobs e filas | `ROUTES_HOOKS_WORKERS.md`, `BACKEND_PATTERNS.md` |
25
+ | Integrações | `CONNECTORS_AND_INTEGRATIONS.md`, `LOCAL_SECURITY_BOUNDARY.md` |
26
+ | Upgrade do Core | `CORE_UPGRADE.md`, `TESTING_CONFORMANCE.md`, `releases/0.5.0.md` |
27
+ | UX avançada | `ADVANCED_UX_PATTERNS.md`, `DETAIL_MODAL_AND_RELATED_GRIDS.md`, `PORTAL_COCKPIT_PATTERNS.md` |
28
+
29
+ ## Fronteira obrigatória
30
+
31
+ - A Central declara domínio e experiência; o Core fornece bootstrap, autenticação, ativação, RBAC, tenant, CRUD, metadata, shell, componentes genéricos, integração operacional e deployment.
32
+ - Use somente exports públicos documentados. Arquivos internos de `src/` não são contrato de extensão.
33
+ - Autorização, tenant e regras que alteram dados são sempre validados no backend.
34
+ - Não crie autenticação, ativação, RBAC, CRUD, shell, registry ou infraestrutura paralelos.
35
+ - Não coloque segredos em manifesto, frontend, log, URL permanente ou documentação.
36
+ - Recursos de plataforma devem falhar fechado no runtime local.
37
+
38
+ ## Gates antes de concluir
39
+
40
+ ```bash
41
+ npm run ooncore:docs:check
42
+ npm run ooncore:conformance
43
+ npm run check
44
+ npm test
45
+ ```
46
+
47
+ Se um contrato público exigir leitura do repositório privado do OonCore, registre a lacuna: a documentação distribuída está incompleta.
@@ -0,0 +1,13 @@
1
+ # Fluxo de trabalho para Agents
2
+
3
+ 1. **Descobrir:** leia `AGENTS.md`, manifesto documental e `CAPABILITIES.md`.
4
+ 2. **Classificar:** separe contrato do Core, domínio da Central e recurso exclusivo da plataforma.
5
+ 3. **Escolher extensão:** manifesto → validation/trigger/hook/mapping → renderer/rota pequena → código customizado somente se necessário.
6
+ 4. **Implementar:** use exports públicos; preserve segurança, tenant, auditoria e idempotência.
7
+ 5. **Executar local:** `npm run dev`, sem cadastro ou conexão com a plataforma.
8
+ 6. **Validar:** docs check, conformance, testes, typecheck e provas específicas do projeto.
9
+ 7. **Relatar:** arquivos, contratos usados, riscos, limitações e evidências.
10
+
11
+ Prompt operacional:
12
+
13
+ > Atualize os três pacotes OonCore para a linha 0.5.x, preserve o domínio e o AGENTS.md do projeto, sincronize `.ooncore`, consulte os contratos públicos de back e front, use apenas extensões suportadas, execute os gates e homologue em `127.0.0.1` sem conexão com a plataforma. Não crie autenticação, ativação, RBAC, CRUD, shell ou infraestrutura paralelos.
@@ -0,0 +1,22 @@
1
+ # Autenticação, ativação e RBAC
2
+
3
+ ## Plataforma
4
+
5
+ O backend verifica o token no escopo do App, resolve tenant e acesso, aplica a política local de RBAC e cria `req.accessContext`. O frontend usa permissões somente para experiência; o backend autoriza cada operação.
6
+
7
+ Ativação de plataforma cria a identidade operacional usada por integrações autorizadas. Rotas de login, launch exchange, ativação e primeiro acesso não estão disponíveis no runtime local.
8
+
9
+ ## Local
10
+
11
+ O principal técnico é `local:developer`, sem usuário/tenant/licença na plataforma. O papel inicial é `developer` quando declarado, seguido por admin ou primeiro papel. A troca de perfil aceita apenas o manifesto e atualiza a sessão local.
12
+
13
+ O estado é `ativa_local`; o `ActivationGuard` não cria nem consulta `InstanciaEcossistema`. Isso não equivale a `ativa` publicada.
14
+
15
+ ## Regras para extensões
16
+
17
+ - use `requirePermission` em rotas customizadas;
18
+ - derive filtros de `req.accessContext`;
19
+ - nunca autorize por header/body de perfil ou tenant;
20
+ - não implemente `verifyToken` em Central member/portal;
21
+ - não persista bearer no frontend;
22
+ - não trate simulação local como identidade operacional.
@@ -0,0 +1,43 @@
1
+ # API pública do `@oondemand/oon-core-back`
2
+
3
+ Importe exclusivamente de `@oondemand/oon-core-back`. Caminhos internos não têm estabilidade garantida.
4
+
5
+ ## Boot e definição
6
+
7
+ - `start(options)`: carrega a Central, conecta Mongo, inicializa capabilities e inicia HTTP. `options.listen=false` devolve somente o app.
8
+ - `createApp()`: cria o Express já protegido e com rotas do Core.
9
+ - `activate()`: fluxo legado de ativação; não é usado no runtime local.
10
+ - `defineCentral`, `defineModel`, `defineCollection`, `defineDocument`, `definePipeline`, `defineOmieMapping`, `defineRoutes`, `defineValidation`, `defineTrigger`: extensões imperativas suportadas.
11
+ - `fields`: factories de campos compatíveis com schema e metadata.
12
+ - `registry`: registry do processo; use APIs `define*`, não mutações internas.
13
+
14
+ ## Segurança, RBAC e tenant
15
+
16
+ - `requirePermission(permission)`: middleware obrigatório em rotas sensíveis.
17
+ - `CORE_PERMISSIONS`, `rbacPolicy`, `roleByCode`, `permissionGranted`: leitura e avaliação da política declarada.
18
+ - `TENANT_HEADER`, `TENANCY_MODELS`, `DATA_SCOPES`: constantes canônicas.
19
+ - `createAccessContext`, `readRequestedTenantId`: produzem contexto validado.
20
+ - `scopeFilter`, `mergeScopedFilter`, `scopeMutation`, `scopedIdFilter`: aplicam isolamento aos dados. Nunca aceite tenant do body como autoridade.
21
+
22
+ ## Manifestos
23
+
24
+ - App: `APP_MANIFEST_FILENAME`, `APP_MANIFEST_SCHEMA_VERSION`, `SUPPORTED_APP_KINDS`, `SUPPORTED_APP_MODULES`, `AppManifestError`, `validateAppManifest`, `resolveAppManifestPath`, `appManifestToConfig`, `registerAppManifest`, `loadAppManifest`.
25
+ - Domínio: `DOMAIN_MANIFEST_FILENAME`, `DOMAIN_MANIFEST_SCHEMA_VERSION`, `SUPPORTED_DOMAIN_FIELD_KINDS`, `DOMAIN_EXPRESSION_OPERATORS`, `DomainManifestError`, `DomainRuleError`, `validateDomainManifest`, `domainManifestToDefinitions`, `registerDomainManifest`, `loadDomainManifest`, `evaluateDomainExpression`, `applyDomainMutation`, `validateDomainRecord`, `detectChangedFields`.
26
+ - Processo: `PROCESS_MANIFEST_FILENAME`, `PROCESS_MANIFEST_SCHEMA_VERSION`, `ProcessManifestError`, `validateProcessManifest`, `registerProcessManifest`, `loadProcessManifest`, `prepareProcessMutation`, `resolveProcessBindings`, `assertReferencePolicies`, `assertAtomicInvariants`, `assertDeleteAllowed`, `recalculateDependents`, `drainProcessJobs`.
27
+
28
+ Erros de manifesto carregam `code`, `statusCode` e `issues[]` com `path` e `message`.
29
+
30
+ ## Integrações e capabilities
31
+
32
+ - `integrations`, `registerIntegrationProvider`, `enqueueIntegration`, `receiveIntegrationWebhook`.
33
+ - `omie`, `omieModule`, `createOmieClient`, `OmieApiError`, `enqueueOmieCall`, `ensureOmieProviderRegistered`, `collectOmieDefinitions`, `describeOmieDefinitions`, `saveOmieConfiguration`, `listOmieConfigurations`, `testOmieConnection`.
34
+ - `capabilities`, `PdfRenderingError`, `TransactionalEmailError`.
35
+ - `operationalRequestHeaders(options)`: headers de identidade do Deployment. Retorna `LOCAL_OPERATION_NOT_SUPPORTED` no runtime local; nunca improvise identidade local.
36
+
37
+ ## Runtime local
38
+
39
+ O namespace público `localDevelopment` expõe detecção, validação de loopback e utilitários de teste/integração do runtime. Apps consumidores normalmente apenas definem `OON_RUNTIME_MODE=local` e usam o scaffold.
40
+
41
+ ## Erros
42
+
43
+ `GenericError(message, { statusCode, code, details })` é o erro operacional base. Rotas devem lançá-lo e deixar o middleware do Core produzir o envelope sanitizado.
@@ -0,0 +1,24 @@
1
+ # Catálogo de capacidades do OonCore
2
+
3
+ Consulte este catálogo antes de criar infraestrutura ou componentes customizados.
4
+
5
+ | Capacidade | Backend | Frontend | Declaração/extensão | Local | Plataforma |
6
+ |---|---|---|---|---|---|
7
+ | Models e CRUD | `defineModel`, domain manifest, `/core/*` | `CoreCollection`, hooks de API | `central.domain.json`, `central.ui.json` | Sim | Sim |
8
+ | Metadata | registry e `/core/metadata` | `useCoreMetadata`, renderers | models/domain manifest | Sim | Sim |
9
+ | Validações e fórmulas | `defineValidation`, domain rules | prévia reativa | domain manifest/validation | Sim | Sim |
10
+ | Esteiras | process manifest/runtime | `CorePipeline` | `central.process.json`, UI manifest | Sim | Sim |
11
+ | Documentos | `defineDocument` | `CoreDocument` | UI/domain manifest | Sim | Sim |
12
+ | Dashboards | agregações e rotas | `CoreDashboard` | UI manifest | Sim | Sim |
13
+ | RBAC | policy, middleware e `requirePermission` | `PermissionGate`, `can` | `central.app.json` | Simulação declarada | Identidade real |
14
+ | Tenant e escopo | access context e scope helpers | `TenantProvider` | `central.app.json` | Contexto técnico | Contexto autorizado |
15
+ | Auditoria | CRUD e request context | headers do SDK | automática/extensão | Local | Operacional |
16
+ | Rotas customizadas | `defineRoutes` | página/ação declarada | `backend/src/routes` | Sim | Sim |
17
+ | Jobs e workers | process/integration workers | status operacional | manifestos/hooks | Sim | Sim |
18
+ | Integrações | runtime/provider registry | `CoreIntegration` | mapping/provider suportado | Dublê ou credencial local | Credencial operacional |
19
+ | E-mail transacional | capability nativa | `CoreTransactionalEmail` | capability settings | Dublê/local | Provider configurado |
20
+ | PDF | capability nativa | consumo por ação | capability contract | Dublê/local | Provider configurado |
21
+ | Publicação/promoção | contratos de delivery | indisponível no App | CLI/ponte pública | Não | Sim |
22
+ | Runtime local | sessão e guardas locais | bootstrap/cookie/banner | `OON_RUNTIME_MODE=local` | Sim | Não aplicável |
23
+
24
+ Para cada capacidade, use o manifesto quando houver contrato declarativo; use código da Central apenas em pontos de extensão documentados.
package/docs/CODEX.md CHANGED
@@ -1,83 +1,12 @@
1
- # CODEX.md — Regras de Codificação OonCore
1
+ # CODEX.md — ponte de compatibilidade
2
2
 
3
- Este arquivo é a porta de entrada para o Codex codificar uma Central Oon.
3
+ A fonte canônica, completa e neutra do OonCore é `AGENTS.md`.
4
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`.
5
+ Ao trabalhar em uma Central:
6
6
 
7
- ## Antes de codificar
7
+ 1. leia primeiro o `AGENTS.md` da raiz do projeto, quando existir;
8
+ 2. leia `.ooncore/AGENTS.md`;
9
+ 3. valide `.ooncore/manifest.json` com `npm run ooncore:docs:check`;
10
+ 4. siga as referências de `.ooncore/docs/` indicadas para a tarefa.
8
11
 
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
- ## Leitura obrigatória por tipo de tarefa
15
-
16
- ### Backend/domínio
17
-
18
- - `BACKEND_DOMAIN_MANIFEST.md`
19
- - `BACKEND_PATTERNS.md`
20
- - `COLLECTIONS_AND_PIPELINES.md`
21
- - `CONNECTORS_AND_INTEGRATIONS.md`
22
- - `RBAC_SECURITY.md`
23
-
24
- ### Frontend/manifesto
25
-
26
- - `FRONTEND_PATTERNS.md`
27
- - `FRONTEND_MANIFEST_REFERENCE.md`
28
- - `REACTIVE_DOMAIN_FORMULAS.md`
29
-
30
- ### UX avançada, modais, abas e itens relacionados
31
-
32
- Leia antes de criar páginas customizadas:
33
-
34
- - `ADVANCED_UX_PATTERNS.md`
35
- - `DETAIL_MODAL_AND_RELATED_GRIDS.md`
36
-
37
- Use estes documentos quando a necessidade envolver:
38
-
39
- - modal com abas;
40
- - dados principais agrupados;
41
- - grids relacionados;
42
- - edição inline;
43
- - ações por linha;
44
- - registros filhos como itens, parcelas, produtos, documentos ou pagamentos;
45
- - telas onde o usuário opera um registro principal e seus relacionamentos.
46
-
47
- ## Princípios obrigatórios
48
-
49
- - Escreva apenas o domínio da Central.
50
- - Use `central.domain.json` para models, campos, fórmulas e validações cobertos pelo contrato declarativo vigente.
51
- - Não repita fórmulas do domínio em componentes React: os formulários do Core geram a prévia reativa a partir da metadata e o backend recalcula antes de persistir.
52
- - Use `@oondemand/oon-core-back` para boot, autenticação, RBAC, CRUD, metadata, auditoria e padrões de API.
53
- - Use `@oondemand/oon-core-front` para shell, rotas, menu, datagrid, formulários, badges, ações e renderização por metadata.
54
- - Não recrie infraestrutura que já existe no Core.
55
- - Não crie autenticação paralela.
56
- - Não duplique RBAC no frontend.
57
- - Não hardcode tenant, app, usuário, perfil, permissões, URLs sensíveis ou segredos.
58
- - Não exponha chaves em código, templates ou documentação gerada.
59
- - Não altere arquivos gerados do Core se houver extensão declarativa disponível.
60
- - Prefira manifestos, validations, triggers, hooks, mappings, documents, pipelines, integrations e overrides declarativos.
61
- - Antes de criar uma página React customizada, tente resolver com `central.ui.json`, `detailModal`, `form.groups`, `relatedGrid`, `readonlyGrid` e `rowActions`.
62
-
63
- ## Ordem de decisão
64
-
65
- Ao implementar uma necessidade, siga esta ordem:
66
-
67
- 1. Configuração existente do Core.
68
- 2. Declaração em `central.config.js`, `central.domain.json` ou `central.ui.json`.
69
- 3. Validation, trigger, hook ou mapping no backend da Central.
70
- 4. Modal, abas, grid relacionado, ação e renderer declarativos do Core.
71
- 5. Override local pequeno e isolado.
72
- 6. Código customizado somente quando o Core não oferecer extensão adequada.
73
-
74
- ## Entrega segura
75
-
76
- Toda alteração deve manter:
77
-
78
- - rastreabilidade;
79
- - validação de entrada;
80
- - RBAC no backend;
81
- - ausência de segredo hardcoded;
82
- - separação entre domínio da Central e infraestrutura do Core;
83
- - compatibilidade com atualização futura dos pacotes `@oondemand/*`.
12
+ Não mantenha regras exclusivas neste arquivo. Codex, ChatGPT, Kimi, Manus e outros Agents devem consumir o mesmo contrato versionado.
@@ -0,0 +1,20 @@
1
+ # Atualização coordenada do OonCore
2
+
3
+ Os três pacotes devem permanecer na mesma linha:
4
+
5
+ - `@oondemand/oon-core-back`;
6
+ - `@oondemand/oon-core-front`;
7
+ - `@oondemand/create-central-oon`.
8
+
9
+ ## Procedimento para Agent
10
+
11
+ 1. Leia o `AGENTS.md` da raiz e preserve regras/domínio do projeto.
12
+ 2. Registre versões atuais, lockfiles e `central.app.json`.
13
+ 3. Atualize os três pacotes para a mesma versão `0.5.x`.
14
+ 4. Ajuste compatibilidade para `>=0.5.0 <0.6.0` somente quando a migração estiver pronta.
15
+ 5. Rode `npm run ooncore:docs` e revise o diff de `.ooncore/`.
16
+ 6. Remova `DEV_TOKEN`, `VITE_DEV_TOKEN`, tokens fixos e URLs da plataforma do caminho local.
17
+ 7. Preserve `AGENTS.md` raiz, models, regras, provas e documentação do domínio.
18
+ 8. Execute docs check, conformance, typecheck, testes e smoke offline.
19
+
20
+ Não atualize somente um pacote e não copie arquivos do Core manualmente para a Central.
package/docs/ERRORS.md ADDED
@@ -0,0 +1,18 @@
1
+ # Contrato de erros
2
+
3
+ Erros operacionais usam `{ error: { code, message, details?, requestId? } }` e status HTTP coerente.
4
+
5
+ | Código | Significado |
6
+ |---|---|
7
+ | `LOCAL_RUNTIME_ENV_INVALID` | modo local fora de development |
8
+ | `LOCAL_RUNTIME_PLATFORM_IDENTITY` | identidade de plataforma/Kubernetes presente |
9
+ | `LOCAL_RUNTIME_BIND_FORBIDDEN` | bind fora de loopback |
10
+ | `LOCAL_HOST_FORBIDDEN` / `LOCAL_ORIGIN_FORBIDDEN` | acesso de rede recusado |
11
+ | `LOCAL_PROXY_FORBIDDEN` | tentativa de proxy no modo local |
12
+ | `LOCAL_BOOTSTRAP_INVALID` | código ausente, reutilizado ou expirado |
13
+ | `LOCAL_SESSION_INVALID` | cookie ausente, inválido ou expirado |
14
+ | `LOCAL_CSRF_INVALID` | mutação sem prova CSRF |
15
+ | `LOCAL_ROLE_NOT_DECLARED` | perfil fora do manifesto |
16
+ | `LOCAL_OPERATION_NOT_SUPPORTED` | recurso exclusivo da plataforma |
17
+
18
+ Não faça branching por texto de mensagem; use `code`. Logs e respostas nunca devem conter token, cookie, credencial, senha ou conteúdo sensível.
@@ -0,0 +1,34 @@
1
+ # API pública do `@oondemand/oon-core-front`
2
+
3
+ Importe exclusivamente da raiz do pacote.
4
+
5
+ ## Bootstrap e manifestos
6
+
7
+ - `start`, `oonCoreFront.start`: inicialização com configuração completa.
8
+ - `startFromManifest`, `startCentralFromManifest`, `manifestToConfig`: caminho preferencial para uma Central declarativa.
9
+ - Tipos: `CentralUiManifest`, `CentralAppManifest`, `CentralManifestBundle`, `CentralUiOnlyManifest`, `ManifestRuntime`.
10
+ - `ManifestRuntime.runtimeMode`: `local` usa sessão HttpOnly; `platform` usa o contrato de autenticação publicado.
11
+
12
+ ## Views e componentes
13
+
14
+ - Definições: `defineCollectionView`, `defineDocumentView`, `definePipelineView`, `defineDashboard`, `defineOonModule`.
15
+ - Componentes: `CoreCollection`, `CoreDocument`, `CorePipeline`, `CoreIntegration`, `CoreCurrency`, `CoreAssistant`, `CoreDashboard`, `CoreUsersAccess`, `CoreTransactionalEmail`, `CorePage`.
16
+ - Primitivas UI v2: `CorePageHeader`, `CoreToolbar`, `CoreDataGrid`, `CoreCards`, `CoreForm`, `CoreField`, `CoreRelationField`, `CoreActions`, `CoreEmptyState`, `CoreLoadingState`.
17
+ - Registre componentes customizados por chave em `registry`; não serialize React no JSON.
18
+
19
+ ## Hooks, sessão e autorização
20
+
21
+ - `useOonAuth`, `can`, `PermissionGate`, `Can`: experiência baseada em permissões já resolvidas pelo backend.
22
+ - `useOonTenant`, `createTenantStorage`: seleção de tenant; o backend continua sendo a autoridade.
23
+ - `useOonApi`, `useOonResource`, `useCoreMetadata`, `useModelSchema`: acesso HTTP/metadata padronizado.
24
+ - O runtime local não grava bearer no `localStorage`, envia cookie com `withCredentials` e usa CSRF double-submit nas mutações.
25
+
26
+ ## Domínio reativo
27
+
28
+ - `DomainExpressionError`, `evaluateDomainExpression`, `applyReactiveFormulas`, `buildDomainMutationPayload`, `coerceDomainFormValue`.
29
+ - Tipos `OonDomainExpression`, `OonComputedFieldDefinition`, `OonReactiveFormField` e `ReactiveFormulaResult`.
30
+ - A prévia do frontend nunca substitui o recálculo e a validação do backend.
31
+
32
+ ## Tipos públicos
33
+
34
+ Os tipos exportados incluem config, app, auth, runtime, módulos, rotas, menus, UI v1/v2, layout, registry, páginas, blocos, ações, views, campos, metadata, paginação, erros e usuário. Consulte `dist/index.d.ts` da versão instalada quando precisar da assinatura exata; ele faz parte do pacote público.
@@ -1,6 +1,6 @@
1
1
  # Referência do Manifesto Frontend OonCore
2
2
 
3
- Este documento é a referência operacional para o Codex criar ou alterar manifestos do frontend OonCore.
3
+ Este documento é a referência operacional para qualquer Agent criar ou alterar manifestos do frontend OonCore.
4
4
 
5
5
  Use este arquivo junto com `FRONTEND_PATTERNS.md`. O arquivo de padrões explica como pensar a UI; este arquivo lista as opções do contrato atual e das extensões planejadas para UX avançada.
6
6
 
@@ -41,7 +41,7 @@ Existem três níveis importantes:
41
41
  2. `CentralUiManifest`: contrato lido por `startFromManifest`.
42
42
  3. `OonUiManifest` / `OonCoreFrontConfig`: contrato interno mais completo do Core Front.
43
43
 
44
- Para Codex, a ordem recomendada é:
44
+ Para Agents, a ordem recomendada é:
45
45
 
46
46
  1. Começar pelo `central.ui.json`.
47
47
  2. Usar `pages` e `blocks` quando precisar de UI v2.
@@ -0,0 +1,34 @@
1
+ # Desenvolvimento local desconectado
2
+
3
+ ## Início
4
+
5
+ ```bash
6
+ cp backend/.env.example backend/.env
7
+ cp frontend/.env.example frontend/.env
8
+ npm install
9
+ npm run dev
10
+ ```
11
+
12
+ O orquestrador inicia backend em `127.0.0.1:4000`, frontend em `127.0.0.1:5173`, gera códigos aleatórios e independentes para navegador e automação/seed, e abre o navegador. O Vite encaminha `/api` ao backend para manter cookies e CSRF na mesma origem.
13
+
14
+ O primeiro acesso troca o código de uso único por:
15
+
16
+ - cookie de sessão `HttpOnly`, `SameSite=Strict`;
17
+ - cookie CSRF de double-submit;
18
+ - sessão local cujo banco armazena somente hashes e expiração.
19
+
20
+ O prazo padrão é 30 dias. Reiniciar o processo rotaciona o segredo sem ampliar o prazo. Excluir o banco local cria um novo período; essa limitação é aceita na linha 0.5.
21
+
22
+ A decisão vem de `LocalExecutionPolicyProvider`. A fonte embarcada funciona offline e permite 30 dias. Uma fonte HTTP assinada poderá ser adicionada futuramente para novas emissões/renovações sem transformar a plataforma em dependência obrigatória.
23
+
24
+ ## Perfis
25
+
26
+ O banner permite selecionar apenas papéis declarados em `central.app.json`. A permissão é recalculada no backend. Convites e usuários reais não são criados. Apps com tenant usam o contexto virtual fixo `local:tenant`, sem criar um tenant persistente ou aceitar um tenant arbitrário do cliente.
27
+
28
+ ## Integrações
29
+
30
+ Use dublês ou credenciais explicitamente fornecidas no `.env` local do projeto. O Core não busca secrets da plataforma e não cria Deployment/binding/entitlement.
31
+
32
+ ## Encerramento
33
+
34
+ `Ctrl+C` encerra os dois processos. Nunca use `--host 0.0.0.0`; conformance e startup devem reprovar essa configuração.
@@ -0,0 +1,24 @@
1
+ # Fronteira de segurança local
2
+
3
+ ## Garantias
4
+
5
+ - bind real em loopback;
6
+ - Host e Origin limitados a `localhost`, `127.0.0.1` e `::1`;
7
+ - cabeçalhos de proxy recusados;
8
+ - códigos independentes de navegador e automação/seed, aleatórios, curtos e consumidos uma vez;
9
+ - segredo de sessão em cookie HttpOnly e somente hashes no banco;
10
+ - logout revoga a sessão no backend e invalida cookies anteriores;
11
+ - CSRF obrigatório nas mutações;
12
+ - nenhum bearer local no bundle ou `localStorage`;
13
+ - nenhuma identidade operacional ou chamada silenciosa à plataforma;
14
+ - `operationalRequestHeaders` falha com `LOCAL_OPERATION_NOT_SUPPORTED`;
15
+ - produção, Kubernetes e bind externo falham fechado.
16
+ - o contexto virtual `local:tenant` isola dados locais sem criar recurso na plataforma.
17
+
18
+ `Secure` é adicionado aos cookies quando `OON_LOCAL_HTTPS=true`; em HTTP loopback o cookie mantém `HttpOnly` e `SameSite=Strict`.
19
+
20
+ ## Limitações explícitas
21
+
22
+ Quem controla código, banco e relógio locais pode reiniciar ou alterar o prazo. Os 30 dias são uma regra de experiência, não licenciamento inviolável. Uma política remota futura pode afetar novas emissões/renovações, mas não revoga imediatamente sessão offline já emitida.
23
+
24
+ O objetivo de segurança é impedir exposição da máquina/rede e impedir que identidade local escape para o Ecossistema.
@@ -0,0 +1,11 @@
1
+ # Contrato ponta a ponta de metadata, CRUD e UI
2
+
3
+ 1. `central.domain.json` ou `defineModel` registra model, campos, CRUD, roles e metadata.
4
+ 2. O backend expõe `/core/metadata`, `/core/models` e o router CRUD do `basePath`.
5
+ 3. Escopo de tenant/usuário, validação, fórmulas, referência, auditoria e triggers são aplicados no servidor.
6
+ 4. `central.ui.json` declara coleções, formulários, filtros, relações, esteiras, documentos e dashboards.
7
+ 5. O frontend consulta metadata e monta componentes do Core.
8
+
9
+ O CRUD padrão inclui listagem paginada, leitura, criação, atualização parcial, exclusão e import/export quando habilitados. Use rota customizada somente quando a operação não puder ser representada por CRUD, ação declarativa ou processo.
10
+
11
+ Campos calculados são exibidos reativamente no frontend e recalculados no backend. Campos de escopo são internos e imutáveis. Referências devem usar os filtros declarados; não faça consultas sem escopo.
@@ -45,6 +45,6 @@ Cada Central começa como um mini-monolito de negócio: pequeno, coeso, isolado
45
45
  - Permissões são decididas no backend.
46
46
  - Integrações são tratadas como conectores, mappings, triggers e esteiras de integração.
47
47
 
48
- ## Objetivo do Codex
48
+ ## Objetivo dos Agents
49
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.
50
+ O Agent deve acelerar a construção da Central usando a arquitetura existente. O objetivo não é gerar um app genérico, mas completar a camada de domínio com segurança e aderência ao Core.
@@ -22,7 +22,7 @@ Use o RBAC do Core para:
22
22
  - proteger rotas;
23
23
  - permitir evolução de permissões sem reconstruir telas.
24
24
 
25
- ## Checklist de segurança para Codex
25
+ ## Checklist de segurança para Agents
26
26
 
27
27
  Antes de concluir uma alteração, confirme:
28
28
 
@@ -0,0 +1,11 @@
1
+ # Rotas, hooks, triggers e workers
2
+
3
+ - `defineRoutes(basePath, router)`: registra rota específica do domínio. Proteja com auth já montada, `requirePermission`, validação e `req.accessContext`.
4
+ - `defineValidation(model, fn)`: valida o estado consolidado antes de persistir.
5
+ - `defineTrigger(model, fn)`: efeito de domínio rastreável associado à mutação.
6
+ - Process manifest: transições, bindings, invariantes, recálculos e jobs transacionais.
7
+ - Integration runtime: outbox/inbox, retry, lock, idempotência, histórico e webhook.
8
+
9
+ Não crie processo web paralelo, registry local, timer genérico ou worker que replique o Core. Jobs devem ser idempotentes, limitar retry, sanitizar payload/erro e encerrar com o lifecycle do processo.
10
+
11
+ No runtime local, workers e filas podem operar contra Mongo local, mas operações que exigem identidade da plataforma devem retornar `LOCAL_OPERATION_NOT_SUPPORTED`.
@@ -0,0 +1,16 @@
1
+ # Modos de runtime
2
+
3
+ | Contrato | `local` | `platform` |
4
+ |---|---|---|
5
+ | Configuração | `NODE_ENV=development`, `OON_RUNTIME_MODE=local` | ambiente publicado |
6
+ | Bind | somente loopback | contrato da infraestrutura |
7
+ | Identidade | principal técnico local | usuário/tenant/Deployment reais |
8
+ | Ativação | `ativa_local` | estados da plataforma |
9
+ | Sessão | cookie HttpOnly, TTL de até 30 dias | auth/SSO configurado |
10
+ | RBAC | simula somente papéis do manifesto | acessos reais |
11
+ | Plataforma | nenhuma chamada obrigatória | conforme capability |
12
+ | Publicar/promover | bloqueado | por contratos autorizados |
13
+
14
+ `local` não é o ambiente publicado `desenvolvimento`. Ele não possui `deploymentId`, `instanceId`, `bindingId`, `entitlementId`, licença ou credencial operacional.
15
+
16
+ O Core falha no startup local quando encontra produção, Kubernetes, identidade operacional, bind não-loopback ou `PUBLIC_APP_URL` externa.
@@ -0,0 +1,30 @@
1
+ # Testes e conformidade
2
+
3
+ ## Gates do projeto consumidor
4
+
5
+ ```bash
6
+ npm run ooncore:docs:check
7
+ npm run ooncore:conformance
8
+ npm run check
9
+ npm test
10
+ ```
11
+
12
+ ## Runtime local
13
+
14
+ Comprove:
15
+
16
+ - `127.0.0.1` e `localhost` funcionam;
17
+ - `0.0.0.0`, IP de LAN, Host/Origin externos e proxy falham;
18
+ - nenhuma chamada alcança a plataforma;
19
+ - cookies existem e bearer não aparece no `localStorage`;
20
+ - bootstraps de navegador e automação não podem ser reutilizados nem invalidar um ao outro;
21
+ - expiração bloqueia a sessão e reiniciar o processo não amplia o prazo;
22
+ - Apps multi-tenant recebem somente o contexto virtual fixo `local:tenant`;
23
+ - perfis fora do manifesto falham;
24
+ - CRUD, metadata, dashboards, processos e integrações locais funcionam;
25
+ - `operationalRequestHeaders` falha fechado;
26
+ - apagar o Mongo local inicia novo prazo, como limitação documentada.
27
+
28
+ ## Documentação
29
+
30
+ `docs --check` valida fonte, versão, schema, entrada `AGENTS.md`, hashes dos documentos e entrypoints, além da presença de todos os arquivos. O tarball npm deve conter docs, templates e schemas. Exemplos devem compilar ou executar em CI.
@@ -0,0 +1,18 @@
1
+ # Troubleshooting
2
+
3
+ | Sintoma | Verificação | Correção |
4
+ |---|---|---|
5
+ | `LOCAL_RUNTIME_ENV_INVALID` | `NODE_ENV` | use `development` |
6
+ | bind proibido | `HOST`, Vite `server.host` | use `127.0.0.1` |
7
+ | bootstrap inválido | URL antiga/reutilizada | reinicie `npm run dev` e use a nova URL |
8
+ | 401 local | cookie apagado/expirado | abra a URL de bootstrap atual |
9
+ | `LOCAL_SESSION_EXPIRED` no startup | prazo local de 30 dias encerrado | exclua os dados locais para iniciar o período aceito na linha 0.5 |
10
+ | seed invalida o navegador | código incorreto usado no script | use exclusivamente o código **Automação/seed** |
11
+ | 403 CSRF | frontend não está na mesma origem/proxy | use `/api` pelo proxy Vite |
12
+ | docs desatualizados | versão/hash | `npm run ooncore:docs` |
13
+ | perfil ausente | `central.app.json.rbac.roles` | declare o papel e sincronize/reinicie |
14
+ | operação de plataforma bloqueada | código `LOCAL_OPERATION_NOT_SUPPORTED` | use dublê/credencial local ou homologue publicado |
15
+ | Mongo indisponível | `MONGO_URI`, replica set quando exigido | inicie Mongo local conforme o projeto |
16
+ | porta ocupada | 4000/5173 | encerre processo conflitante; não exponha outra interface |
17
+
18
+ Nunca resolva erro local adicionando token fixo, `0.0.0.0`, proxy externo ou credencial de Deployment.
@@ -0,0 +1,25 @@
1
+ # OonCore 0.5.0
2
+
3
+ ## Mudança principal
4
+
5
+ Runtime de desenvolvimento local desconectado, com sessão automática por até 30 dias, loopback obrigatório e documentação canônica distribuída para IA/Agents.
6
+
7
+ ## Migração obrigatória
8
+
9
+ - alinhar back, front e create-central em `0.5.x`;
10
+ - usar `OON_RUNTIME_MODE=local` apenas com `NODE_ENV=development`;
11
+ - remover `DEV_TOKEN`, `VITE_DEV_TOKEN` e o valor `dev-local`;
12
+ - usar Vite em `127.0.0.1` com proxy `/api`;
13
+ - sincronizar `.ooncore/` e preservar o `AGENTS.md` raiz;
14
+ - usar o código dedicado de automação para seed, preservando o bootstrap do navegador;
15
+ - atualizar compatibilidade do App para `>=0.5.0 <0.6.0` após homologação.
16
+
17
+ ## Segurança
18
+
19
+ Local não emite nem reutiliza identidade operacional. Rotas de plataforma são bloqueadas; cookies/CSRF substituem bearer local. Apps com tenant usam apenas `local:tenant`. Reiniciar processos não renova uma sessão expirada; reset do banco reinicia o prazo e permanece uma limitação conhecida.
20
+
21
+ O manifesto documental inclui hash dos documentos e dos entrypoints gerados (`AGENTS.md`, `CODEX.md` e `context.generated.md`).
22
+
23
+ ## Compatibilidade
24
+
25
+ `DEV_TOKEN` explícito permanece temporariamente apenas para testes/CI legados fora de `OON_RUNTIME_MODE=local`; novos scaffolds não o geram.
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@oondemand/create-central-oon",
3
- "version": "0.4.29",
3
+ "version": "0.5.0",
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 contratos declarativos, guardrails de conformidade e documentação interna para Codex.",
9
+ "description": "Gerador de Centrais Oon com contratos declarativos, runtime local e documentação versionada para IA/Agents.",
10
10
  "main": "src/index.js",
11
11
  "exports": {
12
12
  ".": "./src/index.js",
@@ -197,6 +197,7 @@ function checkBootstrap(root, files, issues) {
197
197
  (candidate) => candidate.startsWith("frontend/src/")
198
198
  && candidate !== file
199
199
  && candidate !== "frontend/src/vite-env.d.ts"
200
+ && path.basename(candidate) !== ".gitkeep"
200
201
  && !(portalCockpit && isPortalExtension(candidate)),
201
202
  );
202
203
  for (const extra of extraFrontendSources) {
@@ -270,6 +271,23 @@ function checkAllowedExtensions(files, issues) {
270
271
  }
271
272
  }
272
273
 
274
+ function checkLocalRuntimeSafety(root, files, issues) {
275
+ const checks = [
276
+ { pattern: /\b(?:VITE_)?DEV_TOKEN\b/, code: "LOCAL_FIXED_TOKEN", message: "token local fixo não é permitido; use a sessão automática do OonCore." },
277
+ { pattern: /["']dev-local["']/, code: "LOCAL_PREDICTABLE_TOKEN", message: "credencial previsível dev-local não é permitida." },
278
+ { pattern: /\bhost\s*:\s*["'](?:0\.0\.0\.0|::)["']/, code: "LOCAL_BIND_EXTERNAL", message: "servidor de desenvolvimento deve usar 127.0.0.1." },
279
+ ];
280
+ const candidates = files.filter((file) =>
281
+ /(?:^|\/)(?:env\.example|\.env\.example|vite\.config\.[cm]?[jt]s|main\.[jt]sx?|package\.json)$/.test(file),
282
+ );
283
+ for (const file of candidates) {
284
+ const source = readText(root, file);
285
+ for (const check of checks) {
286
+ if (check.pattern.test(source)) addIssue(issues, check.code, file, check.message);
287
+ }
288
+ }
289
+ }
290
+
273
291
  function checkConformance({ cwd = process.cwd() } = {}) {
274
292
  const root = path.resolve(cwd);
275
293
  const files = listFiles(root);
@@ -280,6 +298,7 @@ function checkConformance({ cwd = process.cwd() } = {}) {
280
298
  checkDomainManifest(root, issues);
281
299
  checkExecutableFiles(root, files, issues);
282
300
  checkAllowedExtensions(files, issues);
301
+ checkLocalRuntimeSafety(root, files, issues);
283
302
  return { ok: issues.length === 0, root, filesChecked: files.length, issues };
284
303
  }
285
304
 
package/src/dev.js ADDED
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+
3
+ const crypto = require("node:crypto");
4
+ const { spawn } = require("node:child_process");
5
+ const path = require("node:path");
6
+ const fs = require("node:fs");
7
+
8
+ function npmCommand() {
9
+ return process.platform === "win32" ? "npm.cmd" : "npm";
10
+ }
11
+
12
+ function openBrowser(url) {
13
+ const command = process.platform === "win32"
14
+ ? ["cmd", ["/c", "start", "", url]]
15
+ : process.platform === "darwin"
16
+ ? ["open", [url]]
17
+ : ["xdg-open", [url]];
18
+ const child = spawn(command[0], command[1], { detached: true, stdio: "ignore" });
19
+ child.on("error", () => {});
20
+ child.unref();
21
+ }
22
+
23
+ function runLocalDevelopment({ cwd = process.cwd(), open = true } = {}) {
24
+ const root = path.resolve(cwd);
25
+ for (const directory of ["backend", "frontend"]) {
26
+ if (!fs.existsSync(path.join(root, directory, "package.json"))) {
27
+ throw new Error(`Projeto inválido: ${directory}/package.json não encontrado.`);
28
+ }
29
+ }
30
+
31
+ const bootstrapCode = crypto.randomBytes(32).toString("base64url");
32
+ const automationBootstrapCode = crypto.randomBytes(32).toString("base64url");
33
+ const env = {
34
+ ...process.env,
35
+ NODE_ENV: "development",
36
+ OON_RUNTIME_MODE: "local",
37
+ OON_LOCAL_BOOTSTRAP_CODE: bootstrapCode,
38
+ OON_LOCAL_AUTOMATION_BOOTSTRAP_CODE: automationBootstrapCode,
39
+ };
40
+ const children = ["backend", "frontend"].map((directory) => spawn(
41
+ npmCommand(),
42
+ ["run", "dev", "--prefix", directory],
43
+ { cwd: root, env, stdio: "inherit" },
44
+ ));
45
+
46
+ const url = `http://127.0.0.1:5173/?oon_local_bootstrap=${bootstrapCode}`;
47
+ console.log("\nOonCore local desconectado");
48
+ console.log(`Frontend: ${url}`);
49
+ console.log("Backend: http://127.0.0.1:4000");
50
+ console.log(`Automação/seed: ${automationBootstrapCode}`);
51
+ if (open) setTimeout(() => openBrowser(url), 2500).unref();
52
+
53
+ let stopping = false;
54
+ function stop(signal = "SIGTERM") {
55
+ if (stopping) return;
56
+ stopping = true;
57
+ for (const child of children) if (!child.killed) child.kill(signal);
58
+ }
59
+ process.once("SIGINT", () => stop("SIGINT"));
60
+ process.once("SIGTERM", () => stop("SIGTERM"));
61
+ for (const child of children) {
62
+ child.once("exit", (code) => {
63
+ if (!stopping && code) {
64
+ stop();
65
+ process.exitCode = code;
66
+ }
67
+ });
68
+ child.once("error", (error) => {
69
+ console.error("Falha ao iniciar runtime local:", error.message);
70
+ stop();
71
+ process.exitCode = 1;
72
+ });
73
+ }
74
+ return { children, url, automationBootstrapCode, stop };
75
+ }
76
+
77
+ module.exports = { runLocalDevelopment, openBrowser };
package/src/index.js CHANGED
@@ -5,6 +5,7 @@ const path = require("node:path");
5
5
  const crypto = require("node:crypto");
6
6
  const { spawnSync } = require("node:child_process");
7
7
  const { copyTemplate } = require("./render");
8
+ const { runLocalDevelopment } = require("./dev");
8
9
 
9
10
  const PACKAGE_ROOT = path.join(__dirname, "..");
10
11
  const TEMPLATES_DIR = path.join(PACKAGE_ROOT, "templates");
@@ -90,6 +91,49 @@ function docsHash(files = listDocFiles()) {
90
91
  return hash.digest("hex");
91
92
  }
92
93
 
94
+ function copiedDocsHash(docsDir, files) {
95
+ const hash = crypto.createHash("sha256");
96
+ for (const file of files) {
97
+ const normalized = file.split(path.sep).join("/");
98
+ const absolute = path.join(docsDir, file);
99
+ if (!fs.existsSync(absolute)) return null;
100
+ hash.update(normalized);
101
+ hash.update("\n");
102
+ hash.update(fs.readFileSync(absolute));
103
+ hash.update("\n");
104
+ }
105
+ return hash.digest("hex");
106
+ }
107
+
108
+ function entrypointContents(files = listDocFiles()) {
109
+ return {
110
+ "AGENTS.md": fs.readFileSync(path.join(DOCS_DIR, "AGENTS.md"), "utf8"),
111
+ "CODEX.md": fs.readFileSync(path.join(DOCS_DIR, "CODEX.md"), "utf8"),
112
+ "context.generated.md": buildContext(files),
113
+ };
114
+ }
115
+
116
+ function contentMapHash(entries) {
117
+ const hash = crypto.createHash("sha256");
118
+ for (const [name, content] of Object.entries(entries).sort(([a], [b]) => a.localeCompare(b))) {
119
+ hash.update(name);
120
+ hash.update("\n");
121
+ hash.update(content);
122
+ hash.update("\n");
123
+ }
124
+ return hash.digest("hex");
125
+ }
126
+
127
+ function copiedEntrypointsHash(outDir, names) {
128
+ const entries = {};
129
+ for (const name of names) {
130
+ const absolute = path.join(outDir, name);
131
+ if (!fs.existsSync(absolute)) return null;
132
+ entries[name] = fs.readFileSync(absolute, "utf8");
133
+ }
134
+ return contentMapHash(entries);
135
+ }
136
+
93
137
  function resolveCentralRoot(cwd = process.cwd()) {
94
138
  const current = path.resolve(cwd);
95
139
  const parent = path.dirname(current);
@@ -134,12 +178,12 @@ function copyDocs(srcDir, destDir) {
134
178
 
135
179
  function buildContext(files = listDocFiles()) {
136
180
  const header = [
137
- "# OonCore Contexto Consolidado para Codex",
181
+ "# OonCore Contexto consolidado para IA/Agents",
138
182
  "",
139
- "> Arquivo gerado automaticamente por `create-central-oon docs --sync`.",
183
+ "> Arquivo gerado automaticamente por `create-central-oon docs sync`.",
140
184
  "> Não edite manualmente. A fonte de verdade está no pacote `@oondemand/create-central-oon` instalado.",
141
185
  "",
142
- "Este contexto consolida as regras mínimas para codificar Centrais Oon com segurança, usando o máximo dos recursos do OonCore.",
186
+ "Este contexto consolida os contratos públicos para Codex, ChatGPT, Kimi, Manus ou qualquer Agent compatível.",
143
187
  "",
144
188
  ].join("\n");
145
189
 
@@ -162,12 +206,15 @@ function buildContext(files = listDocFiles()) {
162
206
  }
163
207
 
164
208
  function buildManifest(files = listDocFiles()) {
209
+ const entrypoints = entrypointContents(files);
165
210
  return {
211
+ schemaVersion: 1,
166
212
  source: "@oondemand/create-central-oon",
167
213
  version: readPackageVersion(),
168
- generatedAt: new Date().toISOString(),
169
214
  docsMode: "generated-cache",
215
+ entrypoint: "AGENTS.md",
170
216
  docsHash: docsHash(files),
217
+ entrypointsHash: contentMapHash(entrypoints),
171
218
  files: files.map((file) => file.split(path.sep).join("/")),
172
219
  };
173
220
  }
@@ -186,9 +233,9 @@ function syncDocs(opts = {}) {
186
233
  removeDir(docsOutDir);
187
234
  copyDocs(DOCS_DIR, docsOutDir);
188
235
 
189
- const codexSource = path.join(DOCS_DIR, "CODEX.md");
190
- if (fs.existsSync(codexSource)) {
191
- fs.copyFileSync(codexSource, path.join(outDir, "CODEX.md"));
236
+ for (const entrypoint of ["AGENTS.md", "CODEX.md"]) {
237
+ const source = path.join(DOCS_DIR, entrypoint);
238
+ if (fs.existsSync(source)) fs.copyFileSync(source, path.join(outDir, entrypoint));
192
239
  }
193
240
 
194
241
  fs.writeFileSync(path.join(outDir, "context.generated.md"), buildContext(files));
@@ -205,6 +252,8 @@ function checkDocs(opts = {}) {
205
252
  const version = readPackageVersion();
206
253
  const files = listDocFiles();
207
254
  const currentHash = docsHash(files);
255
+ const expectedEntrypoints = entrypointContents(files);
256
+ const expectedEntrypointsHash = contentMapHash(expectedEntrypoints);
208
257
 
209
258
  if (!fs.existsSync(manifestPath)) {
210
259
  throw new Error("Documentação OonCore local não encontrada. Rode `npm run ooncore:docs`.");
@@ -217,6 +266,10 @@ function checkDocs(opts = {}) {
217
266
  problems.push(`fonte esperada @oondemand/create-central-oon, encontrada ${manifest.source || "(vazia)"}`);
218
267
  }
219
268
 
269
+ if (manifest.schemaVersion !== 1 || manifest.entrypoint !== "AGENTS.md") {
270
+ problems.push("manifesto documental não possui schemaVersion=1 e entrypoint=AGENTS.md");
271
+ }
272
+
220
273
  if (manifest.version !== version) {
221
274
  problems.push(`versão local ${manifest.version || "(vazia)"} diferente da instalada ${version}`);
222
275
  }
@@ -225,6 +278,27 @@ function checkDocs(opts = {}) {
225
278
  problems.push("hash da documentação local diferente da documentação instalada");
226
279
  }
227
280
 
281
+ if (manifest.entrypointsHash !== expectedEntrypointsHash) {
282
+ problems.push("hash dos entrypoints gerados diferente da documentação instalada");
283
+ }
284
+
285
+ const localHash = copiedDocsHash(path.join(root, ".ooncore", "docs"), files);
286
+ if (!localHash || localHash !== manifest.docsHash) {
287
+ problems.push("arquivos de .ooncore/docs estão ausentes ou foram alterados");
288
+ }
289
+
290
+ const entrypointNames = Object.keys(expectedEntrypoints);
291
+ for (const entrypoint of entrypointNames) {
292
+ if (!fs.existsSync(path.join(root, ".ooncore", entrypoint))) {
293
+ problems.push(`entrada obrigatória ausente: .ooncore/${entrypoint}`);
294
+ }
295
+ }
296
+
297
+ const localEntrypointsHash = copiedEntrypointsHash(path.join(root, ".ooncore"), entrypointNames);
298
+ if (!localEntrypointsHash || localEntrypointsHash !== manifest.entrypointsHash) {
299
+ problems.push("entrypoints de .ooncore estão ausentes ou foram alterados");
300
+ }
301
+
228
302
  if (problems.length) {
229
303
  throw new Error(`Documentação OonCore desatualizada:\n- ${problems.join("\n- ")}\nRode \`npm run ooncore:docs\`.`);
230
304
  }
@@ -261,7 +335,7 @@ async function run(opts) {
261
335
  // 2. Overlay do template escolhido (vence sobre o _base).
262
336
  copyTemplate(path.join(TEMPLATES_DIR, template.id), targetDir, tokens);
263
337
 
264
- // 3. Contexto local para Codex derivado da documentação da versão instalada.
338
+ // 3. Contexto local neutro para Agents derivado da versão instalada.
265
339
  syncDocs({ cwd: targetDir });
266
340
 
267
341
  console.log("✔ Arquivos gerados.");
@@ -289,15 +363,12 @@ function printNextSteps(tokens, opts) {
289
363
  ✅ Central "${tokens.name}" pronta.
290
364
 
291
365
  Próximos passos:
292
- ${cd} # Sincronizar/validar documentação local do Core para Codex
366
+ ${cd} # Sincronizar/validar documentação local do Core para Agents
293
367
  npm run ooncore:docs
294
368
  npm run ooncore:docs:check
295
369
 
296
- # Backend ( domínio — models/validations/triggers/...)
297
- cd backend && cp .env.example .env && npm run dev
298
-
299
- # Frontend (só declaração — central.ui.json)
300
- cd ../frontend && cp .env.example .env && npm run dev
370
+ # Runtime local desconectado (backend + frontend)
371
+ npm run dev
301
372
 
302
373
  O backend expõe /core/metadata; o frontend renderiza as telas a partir dele.
303
374
  Edite backend/src/models e frontend/central.ui.json para evoluir a Central.
@@ -313,4 +384,5 @@ module.exports = {
313
384
  syncDocs,
314
385
  checkDocs,
315
386
  resolveCentralRoot,
387
+ runLocalDevelopment,
316
388
  };
@@ -29,11 +29,12 @@ A pasta `.ooncore/` é um cache regenerável da documentação publicada no paco
29
29
  npm install
30
30
  npm run check
31
31
 
32
- cd backend && cp .env.example .env && npm install && npm run dev
33
- cd ../frontend && cp .env.example .env && npm install && npm run dev
32
+ cp backend/.env.example backend/.env
33
+ cp frontend/.env.example frontend/.env
34
+ npm run dev
34
35
  ```
35
36
 
36
- Em desenvolvimento, configure o mesmo valor em `DEV_TOKEN` no backend e `VITE_DEV_TOKEN` no frontend. A validação do token local é fornecida pelo Core; não implemente `auth.verifyToken` na Central.
37
+ O comando inicia backend e frontend exclusivamente em loopback, abre uma sessão local aleatória e não consulta nem cria recursos na plataforma. Não implemente autenticação ou ativação paralela na Central.
37
38
 
38
39
  ## Evoluindo a Central
39
40
 
@@ -3,19 +3,12 @@ SERVICE_NAME=__SLUG__
3
3
  SERVICE_VERSION=0.1.0
4
4
  PORT=4000
5
5
  NODE_ENV=development
6
+ OON_RUNTIME_MODE=local
6
7
 
7
8
  # Banco
8
9
  MONGO_URI=mongodb://localhost:27017/__SLUG__
9
10
 
10
- # Autenticacao e autorizacao pela Central de Ativacoes
11
- # URL publica/frontend da Central de Ativacoes.
12
- CENTRAL_ATIVACAO_URL=https://central-ativacao.central.oondemand.online
13
- # URL canonica do backend/API da Central de Ativacoes.
14
- CENTRAL_ATIVACAO_API_URL=https://central-ativacao.central.oondemand.online/api/
15
11
  APP_CODE=__SLUG__
16
- AUTH_PROVIDER_TIMEOUT_MS=10000
17
- # Compatibilidade temporaria: CENTRAL_ATIVACAO_BACKEND_URL, MEUS_APPS_BACKEND_URL e APP_KEY tambem sao aceitas.
18
12
 
19
- # Token de desenvolvimento local quando a Central sobrescrever verifyToken.
20
- # Deve ser igual ao VITE_DEV_TOKEN configurado no frontend.
21
- DEV_TOKEN=dev-local
13
+ # O runtime local cria uma sessão aleatória por 30 dias e escuta apenas em loopback.
14
+ # Não configure credenciais, URLs ou tokens da plataforma neste arquivo.
@@ -12,6 +12,6 @@
12
12
  "deploy": "oonCore-back deploy"
13
13
  },
14
14
  "dependencies": {
15
- "@oondemand/oon-core-back": "^0.4.29"
15
+ "@oondemand/oon-core-back": "^0.5.0"
16
16
  }
17
17
  }
@@ -24,8 +24,8 @@
24
24
  ],
25
25
  "compatibility": {
26
26
  "core": {
27
- "minVersion": "0.3.45",
28
- "maxVersionExclusive": "0.5.0"
27
+ "minVersion": "0.5.0",
28
+ "maxVersionExclusive": "0.6.0"
29
29
  }
30
30
  },
31
31
  "activation": {
@@ -1,9 +1,3 @@
1
- # URL do backend da Central (oonCore-back)
2
- VITE_API_URL=http://localhost:4000
3
-
4
- # Opcional: login externo/SSO. Sem essa variável, o Core usa /login.
5
- # VITE_MEUS_APPS_URL=https://login.example.com
6
-
7
- # Desenvolvimento local: deve ser igual ao DEV_TOKEN do backend.
8
- # O frontend envia este token para /auth/validar-token antes de qualquer redirect.
9
- VITE_DEV_TOKEN=dev-local
1
+ # O Vite encaminha /api ao backend em 127.0.0.1:4000.
2
+ # Não configure token ou URL da plataforma para desenvolvimento local.
3
+ VITE_API_URL=/api
@@ -11,7 +11,7 @@
11
11
  "sync:metadata": "oonCore-front sync:metadata"
12
12
  },
13
13
  "dependencies": {
14
- "@oondemand/oon-core-front": "^0.4.29",
14
+ "@oondemand/oon-core-front": "^0.5.0",
15
15
  "@chakra-ui/react": "^3.13.0",
16
16
  "@emotion/react": "^11.14.0",
17
17
  "@tanstack/react-query": "^5.65.0",
@@ -3,7 +3,7 @@ import app from "../../central.app.json";
3
3
  import ui from "../central.ui.json";
4
4
 
5
5
  startCentralFromManifest({ app, ui }, {
6
- apiBaseUrl: import.meta.env.VITE_API_URL ?? "http://localhost:4000",
7
- meusAppsUrl: import.meta.env.VITE_MEUS_APPS_URL,
8
- devToken: import.meta.env.DEV ? (import.meta.env.VITE_DEV_TOKEN ?? "dev-local") : undefined,
6
+ apiBaseUrl: import.meta.env.VITE_API_URL ?? "/api",
7
+ runtimeMode: import.meta.env.DEV ? "local" : "platform",
8
+ meusAppsUrl: import.meta.env.DEV ? undefined : import.meta.env.VITE_MEUS_APPS_URL,
9
9
  });
@@ -4,7 +4,16 @@ import react from "@vitejs/plugin-react";
4
4
  export default defineConfig({
5
5
  plugins: [react()],
6
6
  server: {
7
+ host: "127.0.0.1",
7
8
  port: 5173,
9
+ strictPort: true,
10
+ proxy: {
11
+ "/api": {
12
+ target: "http://127.0.0.1:4000",
13
+ changeOrigin: false,
14
+ rewrite: (path) => path.replace(/^\/api/, ""),
15
+ },
16
+ },
8
17
  fs: { allow: [".."] },
9
18
  },
10
19
  });
@@ -4,14 +4,15 @@
4
4
  "private": true,
5
5
  "description": "Central Oon __NAME__ gerada com create-central-oon.",
6
6
  "scripts": {
7
- "ooncore:docs": "create-central-oon docs --sync",
8
- "ooncore:docs:check": "create-central-oon docs --check",
7
+ "ooncore:docs": "create-central-oon docs sync",
8
+ "ooncore:docs:check": "create-central-oon docs check",
9
9
  "ooncore:conformance": "create-central-oon conformance",
10
10
  "check": "npm run ooncore:docs:check && npm run ooncore:conformance",
11
+ "dev": "create-central-oon dev",
11
12
  "dev:backend": "npm run dev --prefix backend",
12
13
  "dev:frontend": "npm run dev --prefix frontend"
13
14
  },
14
15
  "devDependencies": {
15
- "@oondemand/create-central-oon": "0.4.29"
16
+ "@oondemand/create-central-oon": "0.5.0"
16
17
  }
17
18
  }