# Conceitos

São seis conceitos que fazem todo app Fayz encaixar. Domine estes e você lê qualquer projeto Fayz sem se perder: o **plugin e seu manifesto**, a **biblioteca core multi-tenant**, os **providers**, os **dois caminhos** de construção, os **canais de versão** e os **plugins incubator**. Cada um vem com um parágrafo e, quando ajuda, um trecho de código.

## 1. Plugin e manifesto

Um plugin é uma capacidade empacotada — agenda, CRM, financeiro. Você o cria chamando a factory dele (`createAgendaPlugin`, `createCrmPlugin`, …), que retorna um **manifesto**: a descrição, em dados, de tudo que aquele plugin contribui para o app. Rotas, navegação, widgets de dashboard, migrações de banco, ferramentas de IA — tudo declarado num objeto, não espalhado pelo código.

```ts
import { createAgendaPlugin } from '@fayz-ai/plugin-agenda'

const agenda = createAgendaPlugin()
// → { id, name, icon, version, navigation, routes, widgets?,
//     dashboardWidgets?, migrations?, ... }  = PluginManifest
```

O app compõe uma lista desses manifestos e o runtime faz o resto: monta a navegação, resolve as rotas, registra os widgets e ordena as migrações. A regra que mantém isso são: um plugin **não emite nada específico do app por padrão** — o que ele contribui para uma superfície compartilhada é opt-in. O app decide o que aparece.

## 2. Biblioteca core multi-tenant

Todo app Fayz senta sobre a **biblioteca core** (antes chamada `saas_core`): as tabelas-base que todo negócio precisa — `tenants`, `people`, `tenant_members`, `role_permissions`, `appointments`, `transactions`. Essas tabelas não vivem num schema `core.` separado — moram todas em `public.*`. Por cima delas, o modelo tem só mais duas camadas:

```
public.*      tabelas-base compartilhadas (tenants, people, tenant_members, role_permissions, appointments…)
plg_*         tabelas que um plugin instala e possui (plg_shop_products, plg_courses_*…)
suas tabelas  o que o seu app/incubator cria por cima
```

Um plugin instala as próprias tabelas com prefixo `plg_` e **reutiliza** as tabelas do core que precisa em vez de copiá-las; se o financeiro precisa saber "quem recebeu", ele referencia `public.people`, não guarda uma cópia. Uma fonte de verdade por entidade.

O **tenant** é o cliente do seu SaaS (um salão, uma clínica). **Toda tabela** — do core, de plugin ou sua — carrega `tenant_id`, e o isolamento é garantido por **RLS** (Row-Level Security) do Postgres, chaveada nesse `tenant_id`. O RLS **é** a fronteira, não a separação de schemas: você não filtra por tenant na aplicação — o banco recusa linhas de outro tenant. Você traz o seu próprio Supabase (**BYOS**) e ele recebe exatamente essa forma; é a mesma que a plataforma hospeda em escala. O detalhe completo está em [Dados → Modelo](/pt-BR/docs/dados/modelo) e [RLS e multi-tenant](/pt-BR/docs/dados/rls).

## 3. Providers (mock-first)

Um **provider** é a abstração de backend de um plugin: a mesma interface, duas implementações. Todo app nasce com `backend.provider: "mock"` — dados de exemplo, auth simulada, **zero variável de ambiente** — então você desenvolve e demonstra sem tocar em infraestrutura. Quando estiver pronto, você faz o *flip*: troca o provider para `supabase` e o mesmo plugin passa a falar com o Postgres real.

```jsonc
// app.manifest.json — de mock para real é uma linha:
"backend": { "provider": "mock" }
"backend": { "provider": "supabase", "projectRef": "<seu-ref>" }
```

No nível do plugin isso aparece como um provider seguro que escolhe Supabase quando há credenciais e cai no mock quando não há — a mesma interface dos dois lados, então nada no resto do plugin muda no flip. Como conectar o Supabase de verdade está em [Dados → Supabase](/pt-BR/docs/dados/supabase).

## 4. Os dois caminhos

Existem dois jeitos de construir. No **App Fayz** você ganha um shell de admin completo pronto — navegação gerada, troca de tenant, permissões, CRUD — a partir da sua config. No **Fayz Headless** você consome o core e os bundles de plugin dentro do seu próprio site, sendo dono da casca. Os dois usam os mesmos plugins e o mesmo backend; muda quem monta a interface em volta.

Escolher o caminho certo no começo economiza retrabalho — a comparação completa, com quando usar cada um, está em [Os dois caminhos](/pt-BR/docs/dois-caminhos).

## 5. Canais de versão

Duas coisas diferentes usam nomes parecidos, então separe-as:

- **Canais de release** (`stable`, `latest`, `preview`) são *conjuntos de versões* — grupos coerentes de pacotes `@fayz-ai/*` que você instala juntos. `fayz create` fixa seu app no canal `stable` por padrão.
- **Tiers de maturidade** (`stable`, `beta`, `preview`, `internal`) são uma propriedade de *cada pacote* — o quanto você pode se apoiar nele hoje.

{% callout type="warn" %}
Seja honesto com você mesmo: **nada é tier `stable` ainda**. O Fayz é pré-1.0, e enquanto um pacote está em `0.x`, um bump *menor* (`0.4.0` → `0.5.0`) pode conter mudanças que quebram — e nós usamos essa margem. O core e os plugins que já rodam no dia a dia são tier **`beta`**. Fixe versões exatas em produção e leia o changelog antes de atualizar.
{% /callout %}

A tabela completa de tiers, com garantias de versionamento e resposta a bugs, está em [Referência → versões e canais](/pt-BR/docs/referencia/versoes).

## 6. Plugins incubator

Nem toda capacidade precisa virar um pacote publicado. Um **plugin incubator** é um plugin que mora dentro do seu próprio app (em `src/plugins/`), seguindo o **mesmo contrato** dos plugins oficiais — mesmo manifesto, mesmas rotas, migrações e providers. É onde você põe a lógica específica do seu produto, ou incuba um plugin novo antes de eventualmente graduá-lo para o catálogo.

```bash
fayz create plugin meu-plugin
```

Como o contrato é idêntico, um incubator injeta na UI da SDK do mesmo jeito que um plugin oficial — a diferença é só quem é dono do código. Os padrões para escrever um estão em [Plugins próprios → incubator](/pt-BR/docs/plugins-proprios/incubator).

## Próximo passo

{% cards %}
{% card title="Os dois caminhos" href="/pt-BR/docs/dois-caminhos" icon="🍴" %}
Decida entre o App Fayz e o modo Headless antes de escrever a primeira linha.
{% /card %}
{% card title="Tutorial completo" href="/pt-BR/docs/tutorial" icon="🧭" %}
Do primeiro comando ao deploy, em sete passos.
{% /card %}
{% /cards %}
