# Arquitetura

> A arquitetura do Nodaro, para operadores e colaboradores: editor, API Fastify, workers BullMQ, Redis, armazenamento, três modos de autenticação e edições.

Source: https://nodaro.ai/pt-BR/docs/self-hosting/architecture

O Nodaro é um **motor de workflows de IA que prioriza REST** (REST-first). Um editor no navegador permite que os usuários conectem nós de IA — geração de imagens e de vídeos, composição de vídeo, modelos de texto e áudio — em um grafo. O grafo é armazenado no Supabase Postgres e, quando é executado, uma API Fastify o ordena e entrega o trabalho de cada nó a workers de filas no Redis. Os provedores de modelos fazem a geração, e os resultados vão para um armazenamento compatível com S3.

O mesmo código atende três edições, Community, Business e Cloud, e aceita três tipos de tokens de acesso. Esta página é para os operadores que rodam o Nodaro e para os colaboradores que o modificam.

## O sistema em uma visão geral
Workflow: Os clientes chamam a API. A API guarda os dados no Supabase e coloca as execuções na fila do Redis. O orquestrador percorre o grafo de cada workflow e entrega os jobs de nós aos workers, que chamam os provedores de modelos e salvam os resultados no armazenamento.

- Editor e apps → API
- SDK, CLI, MCP → API
- API → Supabase
- API → Redis
- Redis → Orquestrador
- Orquestrador → Workers (jobs de nós)
- Workers → Armazenamento

## O repositório
O repositório público, [github.com/nodaroai/app.nodaro.ai](https://github.com/nodaroai/app.nodaro.ai), é um monorepo com npm workspaces:

| Pasta | O que fica ali |
| --- | --- |
| `backend/` | A API Fastify, os workers do BullMQ e o orquestrador. Node.js 22, TypeScript. |
| `frontend/` | O app do navegador: o editor, o executor de apps e o painel de administração. React 19, React Router 7, React Flow. |
| `packages/` | O código compartilhado e os pacotes npm publicados `@nodaro/shared`, `@nodaro/sdk` e `@nodaro/cli`, além das composições de vídeo do Remotion. |
| `supabase/` | O esquema do banco de dados, como migrações SQL que só avançam. |
| `docs/` | A documentação do produto, incluindo notas de design. |
| `tools/` | Scripts para operadores: o gerador de chaves, o teste de contrato, o backup e a restauração. |
| `examples/` | Exemplos, como um workflow do GitHub Actions que atualiza um servidor por SSH. |

## Frontend
O frontend é um app de página única em Vite. Na imagem Docker, o servidor web, o Caddy, o serve como arquivos estáticos. Ele reúne quatro produtos em um único bundle:

- **O editor** — o canvas React Flow, um painel de configurações por família de nós e um executor de grafos que executa os workflows no navegador durante a edição.
- **O executor de apps** — mostra um workflow publicado como um formulário simples de entradas e resultados.
- **A tela de consentimento OAuth** — onde os usuários aprovam apps de terceiros e clientes MCP, em `/oauth/authorize`.
- **O painel de administração** — só nas edições Business e Cloud.

O estado do servidor fica no React Query, o estado da interface no Zustand, e o estado do canvas no store do próprio React Flow.

## API
A API é um servidor Fastify em Node.js 22, escrito em TypeScript. As rotas são plugins do Fastify, e todo endpoint declara um schema para a requisição e a resposta. Os mesmos schemas validam cada requisição e geram o documento OpenAPI 3.1 em `/v1/openapi.json`. `GET /v1/nodes` lista os tipos de nó que a instalação consegue executar.

Um único hook de autenticação roda antes de todas as rotas: veja [Autenticação](#authentication).

## Processos e filas
O backend vem como cinco processos Node.js em uma única imagem:

| Processo | Papel |
| --- | --- |
| **Servidor da API** | A API HTTP. |
| **Worker de mídia** | Pega da fila os jobs por nó, chama os provedores de modelos e envia os resultados para o armazenamento. Mais de 40 tipos de job, como geração de imagens e de vídeos, processamento com ffmpeg e áudio. Concorrência padrão: `50`, porque ele passa a maior parte do tempo esperando a rede. |
| **Worker de renderização** | O renderizador Remotion, para composições, gráficos animados, sobreposições Lottie, títulos 3D e composições de camadas. Ele roda um Chrome headless e é limitado pela CPU. Concorrência padrão: `2`. |
| **Orquestrador** | Executa workflows inteiros: lê uma execução, ordena o grafo dela e o executa nível por nível. Concorrência padrão: `20`. |
| **Worker de pipeline** | O pipeline História → vídeo. Ele vem em todas as edições, mas só roda no Nodaro Cloud e encerra na hora nas outras. |

No Docker, um único script de inicialização inicia todos eles, e o Caddy fica na frente da API. Em uma instalação escalonada, cada um pode rodar no próprio contêiner. Eles só se coordenam pelas filas do BullMQ no Redis e pelos registros de execução no Postgres. Veja [Escalonamento](https://nodaro.ai/docs/self-hosting/scaling).

## Como um workflow é executado
Quando um usuário clica em **Executar** no editor, há dois caminhos:

1. **No navegador.** Durante a edição, o próprio editor executa o grafo e chama um endpoint da API por nó. Você vê cada resultado assim que o nó dele termina.
2. **No servidor.** As execuções disparadas, por um webhook, um agendamento ou a API, as execuções de apps e as execuções explícitas no servidor vão para o orquestrador. Ele salva o progresso no registro da execução, para que qualquer cliente possa acompanhá-lo.

O orquestrador:

1. Carrega os nós e as conexões do workflow.
2. Ordena o grafo em níveis. Um nível reúne os nós cujas entradas estão todas prontas.
3. Executa os nós de cada nível em paralelo, até o paralelismo do próprio usuário e o teto do servidor, `MAX_CONCURRENT_NODES_PER_EXECUTION`.
4. Executa cada nó de uma de três formas:

| Forma | Onde | Exemplos | Por quê |
| --- | --- | --- | --- |
| **Na fila** | Um job para o worker de mídia ou de renderização | **Gerar imagem** (Generate Image), **Gerar vídeo** (Generate Video), **Texto para fala** (Text to Speech), **Combinar vídeos** (Combine Videos), **Renderizar vídeo** (Render Video) | Trabalho longo ou chamadas externas, desacoplados do orquestrador para controlar a contrapressão (back-pressure) |
| **HTTP direto** | Uma chamada interna a uma rota da API | **Prompt**, **Gráficos animados** (Motion Graphics), o auxiliar de prompts, os nós de publicação em redes sociais | Chamadas rápidas a modelos de texto, sem o custo extra da fila |
| **Inline** | Dentro do orquestrador | **Combinar texto** (Combine Text), **Dividir texto** (Split Text), **Composição de camadas** (Composite) | Lógica pura, sem chamadas externas |

5. Depois de cada nó, passa a saída dele para os nós que dependem dele e salva o progresso da execução com uma gravação no banco de dados por nó.

Uma execução pode parar de duas formas. Com **Interrompido**, ela para na hora: os nós que já estão em execução são abandonados, e os créditos já cobrados não são reembolsados. Com **Interrompendo**, ela termina o nível atual e para antes do seguinte.

**Limites.** Cada nó pode levar até 90 minutos, e uma execução inteira, até 120 minutos. Um nó que declara o próprio orçamento de tempo, hoje o [**Aplicar EDL** (Apply EDL)](https://nodaro.ai/docs/nodes/video/apply-edl), dimensionado a partir da edição que ele renderiza, recebe esse orçamento, e o limite da execução cresce na mesma medida. Se o orquestrador reiniciar durante uma execução, um nó com orçamento cujo worker ainda está ativo é retomado, em vez de ser executado duas vezes. Os [Sub-workflows](https://nodaro.ai/docs/nodes/automate/sub-workflow) são executados de forma recursiva, até 5 níveis de profundidade, com detecção de ciclos.

## Armazenamento e banco de dados
- **Mídia** — toda imagem, todo vídeo e todo arquivo de áudio gerado vai para o armazenamento compatível com S3 e é referenciado pela chave dele. O Nodaro nunca apaga sozinho a mídia armazenada.
- **Banco de dados** — o Supabase Postgres guarda perfis, projetos, workflows, execuções e o progresso delas, jobs, registros de mídia, transações de créditos, apps OAuth e os tokens deles, tokens de API pessoais e conexões com redes sociais, criptografadas. Todas as tabelas aplicam segurança em nível de linha (row-level security), então o próprio banco de dados restringe cada usuário às próprias linhas.
- **Migrações** — o esquema fica em `supabase/migrations/`, aplicado na ordem dos nomes dos arquivos e só para a frente.
- **Redis** — guarda as filas e pequenos caches compartilhados. O estado dos jobs nele é de curta duração: veja [Backup e restauração](https://nodaro.ai/docs/self-hosting/backups).

## Autenticação
A API aceita três tipos de tokens bearer e os diferencia pelo formato:

| Token | Vem de | Age como |
| --- | --- | --- |
| `eyJ…`, um JWT | Uma sessão de login do Supabase no editor | O usuário logado |
| `ndr_app_<64 hex>` | Um app OAuth que um usuário autorizou | O usuário que autorizou o app, limitado aos escopos concedidos |
| `ndr_<64 hex>` | Um token de API pessoal | O dono do token |

Os processos de uma instalação também se autenticam entre si com o `INTERNAL_ORCHESTRATOR_SECRET`, comparado em tempo constante. O servidor web remove esse cabeçalho das requisições externas.

Para cada requisição, a API verifica nesta ordem:

1. **Rotas públicas**, como `/v1/openapi.json` e os webhooks de entrada, pulam a autenticação.
2. **O segredo interno**, para as chamadas entre os processos.
3. **Um token de app OAuth**, que não pode estar revogado nem expirado.
4. **Um token de sessão do Supabase**. A função do usuário é lida do perfil dele e fica em cache por 5 minutos.
5. **Qualquer outra coisa** responde `401`.

Os tokens de API pessoais são verificados pelas rotas que os aceitam, que também aplicam limites de taxa e restringem um token aos workflows dele. Veja [Autenticação](https://nodaro.ai/docs/developers/api/authentication) e [Apps OAuth](https://nodaro.ai/docs/developers/oauth).

## As edições no código
Uma única base de código atende as três edições:

- **Community** (`EDITION=community`, o padrão) — self-hosted, sem painel de administração, sem registro de créditos e sem cobrança. Qualquer pessoa que cria uma conta é um usuário comum.
- **Business** (`EDITION=business`) — acrescenta o painel de administração e o gerenciamento de usuários, e continua self-hosted e sem cobrança.
- **Cloud** (`EDITION=cloud`) — acrescenta créditos, cobrança e preços de crédito definidos por administradores. Ela é a base do app.nodaro.ai e não é feita para self-hosting.

As rotas verificam os recursos da edição, não o nome dela: uma rota de administração só roda em uma edição com painel de administração, e o código de créditos só roda em uma edição com créditos. A verificação vem primeiro na rota, antes de qualquer outra lógica. O app do navegador lê a edição dele na build, a partir de `VITE_EDITION`. Veja [Edições e perfis de superfície](https://nodaro.ai/docs/self-hosting/editions-and-profiles).

## Status e streaming
O **status** dos jobs e das execuções é consultado periodicamente, a cada 2 a 5 segundos: ele muda em uma escala de segundos, e a consulta periódica é simples de implantar. A **saída em streaming** — o texto dos modelos de texto, as execuções de workflows e os pipelines — usa Server-Sent Events. É por isso que um proxy reverso na frente do Nodaro não pode armazenar as respostas em buffer.

## Por que estas escolhas
- **Fastify** — tipos de TypeScript de primeira classe, validação guiada por schemas e plugins que mantêm cada rota no próprio escopo.
- **BullMQ** — uma fila madura sobre o Redis, com novas tentativas, backoff e controles de concorrência, na mesma stack Node.js.
- **REST** — escopos OAuth fáceis de definir por rota, um documento OpenAPI gerado e um modelo simples para clientes de terceiros.
- **Supabase** — Postgres, login, realtime e segurança em nível de linha em um único serviço. A segurança em nível de linha substitui boa parte do código de autorização personalizado.
- **React Flow** — um canvas comprovado para grafos de nós, que o Nodaro estende bastante.
- **Remotion** — composições declarativas em React que renderizam no servidor da mesma forma que na prévia do editor.
- **Uma única camada de provedores** — toda chamada a modelos passa por uma única abstração, então um modelo pode passar para outro provedor sem mudanças no código dos recursos.

## Frequently asked questions

### Com o que o Nodaro é construído?

Um app de página única em Vite e React 19, com um canvas React Flow, uma API Fastify em Node.js 22 e TypeScript, filas BullMQ no Redis, o Supabase para o Postgres e o login, um armazenamento compatível com S3 para a mídia e o Remotion para a composição de vídeo.

### Como um workflow é executado no servidor?

O orquestrador carrega o workflow, ordena o grafo em níveis e executa os nós de cada nível em paralelo, até os limites de concorrência. O trabalho longo ou externo vai para os workers de mídia e de renderização pelo Redis; as chamadas rápidas de texto e a lógica pura são executadas diretamente.

### Quais tokens a API do Nodaro aceita?

Um token de sessão do Supabase vindo do editor, um token de acesso OAuth de um app de desenvolvedor, que começa com ndr_app_, e um token de API pessoal, que começa com ndr_. Cada um corresponde a um usuário, e os tokens OAuth também trazem escopos.

### Quanto tempo uma execução pode levar?

Cada nó pode levar até 90 minutos, e uma execução inteira, até 120 minutos. Um nó que declara o próprio orçamento de tempo, como o Aplicar EDL, recebe esse orçamento, e o limite da execução cresce na mesma medida.

### Onde fica o documento OpenAPI de uma instalação?

Em /v1/openapi.json, na sua instalação. Todo endpoint valida a entrada com um schema, e os mesmos schemas geram o documento OpenAPI 3.1. GET /v1/nodes lista os tipos de nó que a instalação consegue executar.
