Back to the catalog

Developer Portal — Open Knowledge Bundle

Bundle OKF 0.2 · 72 conceitos · andre-sato/lunar-limb

Open source Repository Open in the app JSON README (API)

About

# Developer Portal — Open Knowledge Bundle

Documentação para integrar produtos, plataformas e APIs com segurança.

# Referência da API

* [Autenticação](/api-reference/authentication.md) - Envie credenciais de forma segura em todas as requisições.
* [Branches do repositório](/api-reference/branches.md) - O endpoint que lista as branches locais para o editor, e por que ele nunca escreve no repositório.
* [Erros](/api-reference/errors.md) - Códigos HTTP e estrutura de erros retornados pela API.
* [Experimente a API](/api-reference/explorer.md) - Monte a chamada, envie e veja a resposta sem sair da página — os formulários vêm da própria especificação OpenAPI.
* [Feedback de página](/api-reference/feedback.md) - O endpoint que registra o voto de utilidade de uma página, o que ele guarda e o que ele recusa a guardar.
* [Sessão](/api-reference/sessao.md) - Como abrir e encerrar uma sessão no portal, o que o cookie carrega e por que não existe token de portador.
* [Streetlights Kafka API](/a

Details

Kind
OKF bundles
Topic
Developer tools
Publisher
andre-sato
Origin
okf_github
Category
dados
Version
0.2
Stars
2
Forks
2
Last push
2026-08-25T13:10:17Z
Repository state
ativo
Language
TypeScript
Added
2026-09-09 19:04:11
Updated
2026-09-09 19:04:11
Origin id
andre-sato/lunar-limb:okf/index.md

README

# Lunar

Template white-label de documentação para desenvolvedores, construído com Astro e Starlight. Luna é uma ferramenta completa de engenharia de documentação. Indicando onde sua documentação falha e a mantendo sempre atualizada.

O portal separa três tipos de conteúdo:

- **Guias:** instruções orientadas a tarefas e fluxos de integração.
- **Referência de API:** contratos técnicos, autenticação e erros.
- **Changelog:** alterações relevantes para integrações existentes.

Todas as páginas oferecem o menu **Compartilhar com IA**: ele copia o título, URL e conteúdo da página. A lista de clientes e seus destinos pode ser configurada em `src/config/portal.ts`.

A barra lateral traz **Fale com o chatbot**, aberto: você escreve a dúvida em linguagem natural e recebe uma resposta com as fontes. Sem chave de provedor no ambiente — que é o padrão — ele devolve os trechos das páginas e um resumo extrativo, sem redigir nada. Com `ANTHROPIC_API_KEY`, o mesmo pipeline redige a resposta a partir desses trechos, atravessando os guardrails descritos em *Assistente de documentação*. Um bloco de conteúdo reutilizável aparece com o link da página que o inclui, porque bloco não tem página própria.

## Idiomas

Português (Brasil) é o idioma nativo, sem prefixo de URL. As traduções completas ficam disponíveis em `/en/` e `/es/`, com o seletor de idioma nativo do Starlight. Para manter a associação entre idiomas, crie páginas com o mesmo caminho relativo em `src/content/docs/`, `src/content/docs/en/` e `src/content/docs/es/`.

## Personalização

Edite `src/config/portal.ts` para definir a empresa, o título do portal, a descrição, a URL base da API e o e-mail de suporte. As cores ficam em `src/styles/custom.css`.

## Estrutura de conteúdo

```text
src/content/docs/
├── api-reference/  # Contratos e convenções da API
├── changelog/      # Alterações por versão ou data
├── guides/         # Tutoriais e tarefas de integração
└── index.mdx       # Página inicial
```

Arquivos Markdown e MDX dentro de `src/content/docs/` são publicados automaticamente pelo Starlight. A navegação das três áreas é gerada a partir desses diretórios.

## Comandos

| Comando | Ação |
| --- | --- |
| `npm install` | Instala as dependências. |
| `npm run dev` | Inicia o ambiente de desenvolvimento. |
| `npm run build` | Gera a versão de produção em `dist/`. |
| `npm run preview` | Visualiza localmente a versão de produção. |
| `npm run check` | Typecheck de `.astro`, `.ts` e `.tsx` (`astro check`). |
| `npm test` | Roda os testes (Vitest). |
| `npm run docs:lint` | Analisa a documentação e calcula o Quality Score. |
| `npm run docs:test` | Testes de documentação: links, âncoras, referências e exemplos de API. |
| `npm run docs:health` | Observabilidade: dimensões, SLOs, orçamento, histórico e regressões. |
| `npm run twin` | Digital Twin: cobertura, não documentados, obsoletos, impacto. |
| `npm run contract` | Contract Testing: o exemplo representa o contrato de verdade? |
| `npm run gaps` | Gap Mining: o que as pessoas procuram e não encontram. |
| `npm run agent` | Agentes de documentação: pesquisa, rascunho, validação. |
| `npm run history` | Time Machine: timeline, snapshot, comparação e restore. |
| `npm run docs:code` | Vínculo com o código: impacto, cobertura, órfãos e entidades sem documentação. |
| `npm run governance` | Governança: donos, revisões pendentes, aprovações e auditoria. |
| `npm run analytics` | Observabilidade de leitura: busca, jornadas, abandono e lacunas comportamentais. |
| `npm run ai:eval` | Avaliação do assistente: conjuntos de perguntas, métricas verificáveis e regressão. |
| `npm run graph` | Knowledge Graph: consulta, impacto e frescor. |
| `npm run org` | Organização: repositórios, produtos, saúde agregada e busca global. |
| `npm run heal` | Self-healing: detectar, diagnosticar, propor e validar correções. |
| `npm run sdk` | SDK: gerar, verificar e comparar o cliente TypeScript da API. |
| `npm run overlay` | Overlays: validar, prever, aplicar, comparar e rastrear proveniência. |
| `npm run changelog` | Changelog mensal a partir dos commits, com filtro de ruído e links de endpoint. |
| `npm run api` | API Views: listar, construir as especificações efetivas e verificar. |
| `npm run docs:asyncapi` | Gera páginas de referência a partir de especificações AsyncAPI. |
| `npm run user:create` | Cria um usuário do portal (ver *Usuários e controle de acesso*). |
| `npm run db:*` | Supabase local: `db:start`, `db:stop`, `db:reset`, `db:migrate`, `db:types`, `db:test`, `db:prune` (ver [docs/banco-de-dados.md](docs/banco-de-dados.md)). |

> **Comece pelo [Manual completo](src/content/docs/guides/manual.mdx)** (publicado em `/guides/manual/`): recursos do portal e do editor, atalhos de teclado, fluxos de trabalho e casos de uso, com diagramas.

## Arquitetura e decisões

- **[docs/arquitetura.md](docs/arquitetura.md)** — o portal nos níveis do
  [modelo C4](https://c4model.com/): contexto, contêineres, componentes e dois
  diagramas dinâmicos (o portão de pull request e o ciclo de self-healing).
- **[docs/banco-de-dados.md](docs/banco-de-dados.md)** — a camada de
  persistência em nuvem: o que vive no Git e o que vive no Supabase, o modelo de
  dados, as políticas de RLS e o ambiente local.
- **[docs/adr/](docs/adr/)** — 22 Architectural Decision Records. Cada uma
  registra uma decisão, o que ela custou, o que foi descartado e — quando a
  decisão nasceu de um defeito observado — o defeito.

A distinção entre os dois vale saber: a arquitetura descreve como o sistema é
hoje e muda quando ele muda; uma ADR descreve por que ele ficou assim e não muda
nunca. Quando a decisão é revista, a ADR antiga é marcada como substituída e uma
nova é escrita.

## Recursos

Cada recurso tem um guia próprio no portal publicado. As seções abaixo dão o
resumo e o link.

Para ver todos operando ao mesmo tempo sobre um produto fictício, veja a
**[vitrine de recursos](src/content/docs/exemplos/index.mdx)** (publicada em `/exemplos/`).

```mermaid
flowchart LR
    A["<b>Escrever</b><br/>editor · reuso · glossário<br/>audiências · versões"]
    B["<b>Verificar</b><br/>linter · testes · contratos<br/>Digital Twin · proveniência"]
    C["<b>Revisar</b><br/>impacto · saúde · governança<br/>vínculo com o código"]
    D["<b>Publicar</b><br/>site · SDK · llms.txt<br/>MCP · API Explorer"]
    E["<b>Observar</b><br/>leitura · lacunas<br/>avaliação de IA"]

    A --> B --> C --> D --> E
    E -. "a lacuna medida vira tarefa de escrita" .-> A

    classDef s fill:#438dd5,stroke:#2e6295,color:#fff
    class A,B,C,D,E s
```

A seta de volta é a tese: o portal não termina em publicar. O que os leitores não
encontram vira item de backlog priorizado, e o ciclo recomeça.

### Autoria

_Escrever, revisar e reaproveitar conteúdo._

#### Editor de documentação

Um editor Markdown/MDX completo em `/editor`, com Monaco, preview em tempo real, reuso de conteúdo, grafo de dependências bidirecional, paleta de comandos e consciência de Git. Ele lê e grava os arquivos de `src/content/docs` diretamente — não há banco de dados no meio.
Detalhes em **[Editor de documentação](/guides/editor/)**.

#### Linter e Quality Score

Um revisor editorial automatizado que aponta problemas com id estável e calcula uma nota de 0 a 10 por dimensão. O style guide fica versionado em Git, e a nota não é `10 − nº de erros`: cada dimensão é pontuada isoladamente e o dano é normalizado por tamanho.
Detalhes em **[Linter e Quality Score](/guides/linter-e-quality-score/)**.

#### Navegação

Sidebar por diretório, breadcrumbs, paginação, índice da página e navegação por tags — tudo derivado da estrutura de arquivos, sem um índice paralelo para manter sincronizado.
Detalhes em **[Navegação](/guides/navegacao/)**.

#### Documentação adaptativa

A mesma página serve a quem programa, a quem atende cliente e a quem opera, sem duplicar arquivo. Nada é escondido: o conteúdo de outra audiência fica recolhido num `<details>` com rótulo, alcançável por teclado e pelo Ctrl+F. Quem lê escolhe o perfil; nada é inferido por comportamento.
Detalhes em **[Documentação adaptativa](/guides/documentacao-adaptativa/)**.

#### Busca

Busca local com Pagefind por padrão, Algolia DocSearch opcional, e a busca "warp drive" que cai direto no melhor resultado.
Detalhes em **[Busca](/guides/busca/)**.

#### Versionamento da documentação

Versões da documentação com seletor, aviso de versão antiga e congelamento. A versão é um diretório de conteúdo, não um branch — o que permite ler duas versões lado a lado.
Detalhes em **[Versionamento da documentação](/guides/versionamento/)**.

#### Glossário

Um arquivo Markdown por termo em `src/content/glossary/`, versionado pelo Git. Um termo cadastrado é destacado nas páginas, listado em `/glossary` e **usado pelo linter** para avaliar consistência de terminologia — o glossário é a fonte, e o linter é consumidor dela.
Detalhes em **[Mantenha o glossário](/guides/glossario/)**. Arquitetura em [docs/glossario.md](docs/glossario.md).

#### Testes de documentação

O linter pergunta "isto está bem escrito?". A suíte pergunta "isto **funciona**?" — um link para página inexistente passa em qualquer regra de estilo, e um exemplo que não bate mais com o schema está impecavelmente redigido.
Verifica links, âncoras, Content Graph e exemplos de API, em três perfis do mais barato ao mais caro. A execução de snippets fica desligada por padrão: rodar código vindo de arquivo de conteúdo é execução arbitrária.

```bash
npm run docs:test
```

Detalhes em **[Testes de documentação](/guides/testes-de-documentacao/)**.

#### Contratos de documentação

A suíte pergunta _"este exemplo funciona?"_. Esta camada pergunta _"ele representa o **contrato** de verdade?"_. O caso que as separa: a API exige `amount` e `currency`, a documentação mostra só `amount` — o exemplo roda, e está incompleto.

A comparação corre nos **dois sentidos**, e o segundo é o que quase nenhuma ferramenta faz: campo que o exemplo mostra e o contrato não tem. É assim que documentação envelhece sem quebrar nenhum teste.
Detalhes em **[Contratos de documentação](/guides/contratos-de-documentacao/)**.

#### Análise de impacto

O Content Graph responde "quem usa o quê" — informação. O Impact Engine responde "se eu mudar isso, o que preciso revisar?" — decisão. Aparece no editor e no corpo do pull request.
A razão de o motor existir é a dependência **indireta**: A inclui B, que inclui o bloco que você está editando, e não há aresta entre os dois. A contagem de um salto respondia "nenhuma página afetada" com convicção e errada.
Detalhes em **[Análise de impacto](/guides/analise-de-impacto/)**.

#### Confiança e proveniência

Uma página pode dizer "chaves expiram em 90 dias" sem que exista registro de onde isso veio, quem confirmou e quando. A proveniência é declarada no próprio conteúdo e versionada no Git.
**O limite do selo vem antes da funcionalidade.** "Verificado" quer dizer que a evidência citada existe e confere — o endpoint está na especificação, o arquivo e a linha estão no código. **Não** quer dizer que a frase é verdadeira.
Detalhes em **[Confiança e proveniência](/guides/confianca-e-proveniencia/)**.

#### Observabilidade e SLOs

Dez dimensões, SLOs, orçamento de erro e regressão entre medições — a pergunta de segunda-feira, que nenhuma das outras camadas responde: **a documentação está saudável, e o que fazemos primeiro?**
Ela não mede nada de novo; consulta as camadas que já medem. E a idade sozinha não determina obsolescência: o que empurra uma página para vermelho é evidência de divergência, não o calendário.
Detalhes em **[Observabilidade e SLOs](/guides/observabilidade/)**.

#### Avaliação de IA

Mede o assistente contra conjuntos de perguntas versionados em `evals/`. A camada separa **verificável** de **inferido** e só mede o primeiro: citação aponta para página que existe, página esperada foi citada, termo exigido apareceu. Por isso a métrica se chama "termos presentes", não "correção" — uma resposta pode conter todas as palavras e estar errada.
Em `npm run ai:eval` e em Settings → AI Evaluation.
Detalhes em **[Avaliação de IA](/guides/avaliacao-de-ia/)**.

### Qualidade e verificação

_Descobrir o que está errado antes de quem lê descobrir._

### O produto como fonte

_A especificação e o código dirigindo a documentação, os testes e o SDK._

```mermaid
flowchart TB
    spec["<b>OpenAPI</b><br/>src/schemas/"]
    parse["<b>parseOpenApi → ApiModel</b><br/><i>a única leitura da especificação</i>"]

    exp["API Explorer"]
    con["Contratos"]
    twin["Digital Twin"]
    imp["Análise de impacto"]
    sdk["SDK"]

    spec --> parse
    parse --> exp
    parse --> con
    parse --> twin
    parse --> imp
    parse --> sdk

    classDef f fill:#1168bd,stroke:#0b4884,color:#fff
    classDef n fill:#f0ad4e,stroke:#a8791f,color:#000
    classDef c fill:#85bbf0,stroke:#5d82a8,color:#000
    class spec f
    class parse n
    class exp,con,twin,imp,sdk c
```

Nenhum consumidor abre YAML. Quando um deles precisa de algo que o `ApiModel` não
carrega, o modelo ganha o campo — cinco leituras da mesma especificação divergem
na primeira vez que alguém corrige um caso de borda em uma delas.
O porquê está em [ADR-0004](docs/adr/0004-uma-leitura-do-openapi.md).

#### Digital Twin

O Content Graph responde sobre a documentação. O Twin sobe um nível e responde sobre o **produto**: o que está documentado, o que a documentação descreve e não existe mais, e o que quebra se um endpoint mudar.
O grafo de código é **exato**, não heurístico — a Astro mapeia arquivo para rota de forma determinística, então `src/pages/api/auth/me.ts` que exporta `GET` implementa `GET /api/auth/me`. Implementação sem documentação é dívida certa; documentação sem implementação é *potencialmente* obsoleta, porque a página pode descrever comportamento histórico.
Detalhes em **[Digital Twin](/guides/digital-twin/)**.

#### Vínculo com o código

Uma página declara, no frontmatter, quais entidades do produto ela documenta:

```yaml
documentation:
  bindings:
    - type: api
      id: POST /api/payments
```

A CI cobra a partir daí: entidade pública alterada sem página vinculada bloqueia o merge. Menção em texto não conta — só o vínculo declarado e resolvido contra o Digital Twin. E ele vive na documentação, nunca no código: o produto não deve depender de Markdown.

Em `npm run docs:code` e em Settings → Code Loop.
Detalhes em **[Vínculo com o código](/guides/vinculo-com-o-codigo/)**.

#### Knowledge Graph

Estende o Digital Twin com time, release, lacuna e contrato — **não** é um segundo grafo: duas estruturas com as mesmas entidades divergiriam na primeira semana.
Nem toda aresta propaga impacto. Se um endpoint muda, as páginas que o documentam são afetadas; a especificação que o define não é. Quando uma camada não carrega, o grafo é montado sem ela e declara a degradação, porque um grafo sem a governança responde "ninguém é dono disto" com a mesma confiança de um completo.
Em `npm run graph` e em Settings → Knowledge Graph.
Detalhes em **[Knowledge Graph](/guides/knowledge-graph/)**.

#### SDK

Gera um cliente TypeScript a partir da **mesma** especificação que já move a documentação, os contratos e o Digital Twin — sem segundo parser, segundo engine de contrato nem segundo engine de impacto.
Onde a especificação não diz o tipo, o código gerado diz `unknown`: um SDK que finge saber faz o compilador aprovar uma chamada errada. O diff deriva do contrato, não da comparação textual dos arquivos gerados.
Em `npm run sdk` e no portão de revisão de PR.
Detalhes em **[SDK](/guides/sdk/)**.

#### Changelog automático

Todo dia 1º uma automação lê os commits do mês anterior e abre um **pull request** com a página daquele mês. Ela não publica: o texto vem de mensagens escritas para desenvolvedores, e o changelog é o que um cliente lê para decidir se precisa mexer no código dele.

O filtro é a maior parte do valor — de 97 commits num mês, quase todos são manutenção. Mudança incompatível entra sempre, mesmo com tipo de manutenção. Endpoint citado só vira link se existir na especificação.

Em `npm run changelog`.

Detalhes em **[Changelog automático](/guides/changelog-automatico/)**.

#### Overlays e API Views

A mesma OpenAPI origina `base`, `public` e `partner` sem duplicar uma linha de contrato. Um **overlay** descreve a transformação — remova este endpoint, reescreva aquela descrição — em vez de ser uma segunda cópia da especificação, que diverge no primeiro erro corrigido só de um lado.

O motor entra **antes** do `parseOpenApi`, então a especificação efetiva alimenta documentação, contratos, SDK e Explorer como qualquer OpenAPI. E alvo que deixou de casar bloqueia a CI: é o defeito próprio desta camada — a ação que roda com sucesso e não faz efeito, deixando publicado um endpoint que deveria ter sumido.

Em `npm run overlay` e `npm run api`.

Detalhes em **[Overlays e API Views](/guides/overlays-e-api-views/)**.

#### API Explorer

Um console de requisições embutido, derivado da mesma especificação OpenAPI que move os contratos, o Digital Twin e o SDK. Nenhum endpoint é redigido de novo para ele.
Detalhes em **[API Explorer](/guides/api-explorer/)**.

#### Referência de API a partir de especificação

Páginas de referência geradas a partir de OpenAPI e AsyncAPI. O portal exige que a especificação se declare — um arquivo AsyncAPI aceito em silêncio por um gerador de OpenAPI produz uma página que parece certa e está errada.
Detalhes em **[Referência de API a partir de especificação](/guides/referencia-de-api/)**.

### Operação

_Quem é dono do quê, o que os leitores fazem e onde estão os buracos._

#### Governança

Cada página declara dono, revisor e intervalo de revisão no frontmatter; o `governance.yml` preenche o resto por regra de caminho, e a regra mais específica vence.
"Revisada" é o que alguém declarou, nunca a data do último commit — corrigir uma vírgula não reinicia o relógio de uma página que ninguém leu. E vencida (foi revisada, o intervalo passou) é contada à parte de nunca revisada (entrou no regime, nunca teve revisão): somar as duas acusaria a equipe de atraso no primeiro dia de qualquer regime.
Em `npm run governance` e em Settings → Governance.
Detalhes em **[Governança](/guides/governanca/)**.

#### Observabilidade de leitura

Mede se a documentação **resolve o problema de quem chegou**, não se ela está tecnicamente correta — e as duas notas ficam lado a lado, nunca somadas.
Nada identifica uma pessoa: sem IP, sem id de usuário, sem cookie, sem user-agent. O que existe é uma sessão efêmera do navegador que some quando a aba fecha. Do Not Track, Global Privacy Control e a escolha do leitor desligam a coleta; o texto das buscas é desligado por padrão; uma linha só aparece com 3+ sessões distintas.
Os nomes das métricas carregam os seus limites: "clique em resultado", não "taxa de sucesso" — clicar é o mais longe que a instrumentação enxerga.

Agentes de IA são contados à parte, no servidor: eles não executam JavaScript, então a medição acontece nas próprias rotas de `llms.txt` e do Markdown bruto — e não pelo referrer, que veria a pessoa clicando num link do ChatGPT e não o agente lendo o índice.
Em `npm run analytics` e em Settings → Observability.
Detalhes em **[Observabilidade de leitura](/guides/observabilidade-de-leitura/)**.

#### Lacunas de documentação

Saber que uma página teve dez mil acessos não diz o que falta. Esta camada pergunta **que informação as pessoas procuram e não encontram**, cruzando busca, assistente, MCP, feedback, contratos e o Digital Twin num backlog priorizado.
**Publicar não é resolver.** `start` registra o sinal de hoje como linha de base; depois de publicar, `resolve` compara — e recusa se o sinal não caiu. Não se exige queda a zero: a pergunta continua sendo feita mesmo quando a resposta existe.
Detalhes em **[Lacunas de documentação](/guides/lacunas-de-documentacao/)**.

#### Feedback de página

Um widget de utilidade no rodapé de cada página. Ele guarda o voto e o caminho, e nada sobre quem votou.
Detalhes em **[Feedback de página](/guides/feedback/)**.

#### Organização e múltiplos repositórios

Registra repositórios, produtos e times em `organization.yml` e agrega o que dá para agregar sem mentir.
O portal **não busca repositório da rede**: registrado por `url`, ele é listado e não lido — clonar e ler conteúdo arbitrário a cada coleta é decisão de quem opera. A profundidade da leitura é declarada por repositório, e o que não foi medido fica fora da média: contá-lo como zero faria registrar um repositório baixar a nota da organização.
Em `npm run org` e em Settings → Organization.
Detalhes em **[Organização e múltiplos repositórios](/guides/organizacao/)**.

### Automação

_O que o portal faz sozinho — e onde ele para para pedir aprovação._

#### Agentes de documentação

Cinco agentes especializados usam as ferramentas que o portal já tem — Twin, Content Graph, glossário, linter, testes, contratos — e produzem mudanças **verificáveis**. Quatro dos cinco funcionam sem provedor nenhum.
Os guardrails são **código, não instrução de prompt**: allowlist de ferramentas, escrita restrita a um workspace isolado, e nada publicado sem aprovação humana. O guardrail de descarte nasceu de um defeito real — a primeira execução substituiu uma página inteira por um esqueleto, e passou por revisão, testes e auditoria, porque esqueleto bem formado é Markdown válido.
Detalhes em **[Agentes de documentação](/guides/agentes-de-documentacao/)**.

#### Self-healing

Detectar → diagnosticar → propor → validar → revisar → PR. Nunca `detectar → corrigir`.
Nada é escrito fora do workspace isolado dos agentes, nada é publicado sem aprovação humana, e nenhum nível de autonomia faz merge. O diagnóstico recusa sem fonte autoritativa; quando fontes autoritativas discordam, o ciclo declara conflito e para, em vez de escolher uma — documentação errada com ar de certeza é pior que a lacuna.
Validação que não roda vale "não verificado", nunca "aprovado".
Em `npm run heal` e em Settings → Self-Healing.
Detalhes em **[Self-healing](/guides/self-healing/)**.

#### Time Machine

Como esta página evoluiu, como o portal estava em maio, o que mudou de **comportamento** entre dois pontos, e o que aquele commit afetou.
O Git continua sendo a fonte: cada consulta reconstrói do repositório, e nada aqui escreve, faz checkout ou muda de branch. O que não dá para reconstruir vem ausente, não estimado — o Health Score de uma data passada não é recalculado, porque ele dependia das ferramentas daquela época.
Detalhes em **[Time Machine](/guides/time-machine/)**.

#### Assistente de documentação

Um chatbot que responde a partir da documentação e cita as fontes. Sem chave de provedor ele devolve trechos e um resumo extrativo, sem redigir nada; com chave, o mesmo pipeline redige a resposta atravessando os guardrails.
Detalhes em **[Assistente de documentação](/guides/assistente/)**.

#### Documentação legível por máquina

`llms.txt`, Markdown bruto em cada página e metadados estruturados — para que um agente leia a documentação sem raspar HTML.
Detalhes em **[Documentação legível por máquina](/guides/documentacao-legivel-por-maquina/)**.

#### Consulta pelo terminal (MCP)

Um servidor MCP e uma CLI que expõem a documentação para agentes e para o terminal, com os mesmos filtros de público e versão do portal.
Detalhes em **[Consulta pelo terminal (MCP)](/guides/mcp/)**.

### Plataforma

_Acesso, fluxo de trabalho e publicação._

#### Usuários e controle de acesso

Três papéis — viewer, editor e admin. A leitura é pública; editar e administrar exigem entrar. A autorização é por capacidade, aplicada num único middleware, e os dados de usuário ficam fora do Git.
Detalhes em **[Usuários e controle de acesso](/guides/usuarios-e-acesso/)**.

#### Workflow de Git

Branch, diff, portão de qualidade e preparação de pull request a partir do editor — com o corpo do PR montado a partir do que os motores de análise já sabem.
Detalhes em **[Workflow de Git](/guides/workflow-de-git/)**.

#### Publicação no GitHub Pages

Publicação automatizada no GitHub Pages, com o caminho base tratado e a distinção entre o site estático e o modo servidor.
Detalhes em **[Publicação no GitHub Pages](/guides/publicacao-no-github-pages/)**.

#### Atualizações recentes

Uma lista do que mudou recentemente, derivada do Git — não uma lista mantida à mão que alguém esquece de atualizar.
Detalhes em **[Atualizações recentes](/guides/atualizacoes-recentes/)**.

#### Plugins da comunidade

Os plugins da comunidade Starlight em uso, com o que cada um resolve e por que foi escolhido
em vez das alternativas.
Guia: **[Plugins da comunidade](/guides/plugins/)**. Notas de avaliação: [docs/plugins.md](docs/plugins.md).

## Build e preview de produção

O projeto usa `@astrojs/node` com `output: 'server'`, porque as rotas do editor precisam de execução sob demanda para ler e gravar arquivos no filesystem.

```bash
npm run build
npm run preview
```

Também é possível iniciar diretamente o servidor standalone gerado:

```bash
node ./dist/server/entry.mjs
```

## Docker

Há um `Dockerfile` de dois estágios (build + runtime) que empacota o portal como imagem Node 22 Alpine. O container roda como usuário não-root (`node`) e espera um volume persistente em `/app/data`, onde ficam usuários, sessões e auditoria.

**Construir e rodar:**

```bash
docker build -t lunar-limb .
docker run -d --name lunar-limb \
  -p 4321:4321 \
  --env-file .env \
  -v lunar-limb-data:/app/data \
  --restart unless-stopped \
  lunar-limb
```

O portal fica em `http://localhost:4321`.

**Variáveis de ambiente:** o container lê as mesmas variáveis do `.env` (veja [`.env.sample`](.env.sample)) — `AUTH_SECRET`, `PORTAL_ADMIN_EMAIL`, `PORTAL_ADMIN_PASSWORD`, `SITE_URL`, `PORTAL_DATA_DIR` etc. Com `--env-file .env`, basta preencher o arquivo local.

**Volume de dados:** `data/` é o único estado persistente. Remover o volume (`docker volume rm lunar-limb-data`) apaga usuários e sessões e faz o portal semear um novo admin no primeiro request.

**Perda de senha do admin:** como `users.json` guarda só o hash, a senha não é recuperável. Apague o volume e reinicie com `PORTAL_ADMIN_EMAIL`/`PORTAL_ADMIN_PASSWORD` definidas, ou crie outro admin por `npm run user:create`.

> O seed do admin (`PORTAL_ADMIN_EMAIL`/`PORTAL_ADMIN_PASSWORD`) só roda quando não existe nenhum usuário. Depois que `users.json` é criado, mudar essas variáveis não tem efeito.

## Dependências

O projeto utiliza React, `@astrojs/react`, `@astrojs/node`, Monaco, `remark-mdx` e `js-yaml`. A Fase 5 adiciona `monaco-vim` como única dependência de runtime nova; as de desenvolvimento (`vitest`, `typescript`, `@astrojs/check`) vieram na Fase 4. Rode `npm install` sempre que o `package.json` mudar.

> `astro check` depende de uma API programática que o compilador nativo do TypeScript 7 ainda não expõe, por isso o projeto fixa `typescript@^6` em devDependencies.

## Limitações conhecidas

O que o portal não faz hoje, e por quê, em **[docs/limitacoes.md](docs/limitacoes.md)**.

## Clean install

Se o `node_modules`/lockfile ficarem inconsistentes com o `package.json` (por exemplo depois de puxar uma versão nova do editor):

```powershell
Remove-Item -Recurse -Force node_modules -ErrorAction SilentlyContinue
Remove-Item -Force package-lock.json -ErrorAction SilentlyContinue
npm install
npm run build
npm run dev
```

More