# Malha.ai — publicar um projeto

Você é um agente de programação. Esta página explica como publicar o diretório
de trabalho na Malha.

## O que a Malha faz

Recebe um diretório de projeto e o publica com uma URL funcional. Ela entende
o projeto, gera a configuração de runtime e cuida da infraestrutura — o
usuário não precisa conhecer Git, containers, DNS ou certificados.

## Como publicar

Execute, a partir do diretório do projeto:

```bash
npx -y @malha-ai/cli@latest deploy --json
```

Não instale nada globalmente. Não é preciso Git: a Malha empacota o diretório
como ele está.

### Na primeira vez

> **A Malha está em beta fechado.** O acesso é por convite. Se o e-mail do
> usuário ainda não foi liberado, o link de login **não chega** — e a API
> responde igual para quem tem e para quem não tem acesso, de propósito, para
> impedir enumeração de usuários.
>
> Se o e-mail não chegar em alguns minutos, não é falha da CLI nem do e-mail
> do usuário: é falta de acesso. Diga isso a ele e aponte a lista de espera em
> <https://malha.ai/#lista-de-espera>. Não fique repetindo o login.

Se ainda não houver credencial, a CLI imprime **em stderr** uma URL de
autorização e um código curto, assim:

```text
  Autorize este dispositivo no navegador:

    https://console.malha.ai/activate?code=MLHA-X7KP

  Código de verificação: MLHA-X7KP
```

**Mostre essa URL ao usuário e peça que ele a abra.** Ele vai entrar por um
link enviado ao e-mail e aprovar o dispositivo. A CLI aguarda sozinha e segue
assim que a aprovação acontecer.

Você nunca vai ver um token. Isso é intencional: a credencial vai direto para
o processo da CLI, sem passar pelo seu contexto.

## Como ler o resultado

Com `--json`, a saída padrão contém **apenas JSON**:

```json
{
  "deployment_id": "dep_01J...",
  "app_id": "app_01J...",
  "status": "active",
  "url": "https://agenda-pessoal-a1b2.apps.malha.ai",
  "source_sha256": "..."
}
```

O progresso legível vai para stderr, então nunca contamina o JSON.

### Códigos de saída

| Código | Significado | O que fazer |
|---:|---|---|
| 0 | publicado | mostre a `url` ao usuário |
| 2 | uso incorreto | revise as flags |
| 10 | falta credencial | rode `npx -y @malha-ai/cli@latest auth login` |
| 11 | autenticação falhou | o dispositivo foi revogado; autorize de novo |
| 12 | rede | a API não respondeu; tente de novo |
| 20 | o diretório não pôde ser empacotado | leia a mensagem: costuma ser um caminho inválido ou um arquivo grande demais |
| 21 | falha no envio | tente de novo |
| 22 | o deployment falhou | leia `error_code`, `error_message` e `next_step` |
| 40 | **a Malha precisa de uma resposta** | não é erro — veja "Quando a Malha pergunta algo" |
| 41 | a resposta não atende ao schema da ação | use uma das alternativas que o schema lista |
| 42 | a ação não está mais aberta | publique de novo |

Quando houver falha, o JSON traz também `next_step`: uma frase dizendo o que
fazer. Prefira-a a interpretar `error_code` por conta própria.

## Quando a Malha pergunta algo

Às vezes a Malha precisa de uma decisão antes de continuar. Nesse caso o
comando termina com código **40** e a saída é:

```json
{
  "result_type": "input_required",
  "deployment_id": "dep_01J...",
  "status": "awaiting_input",
  "action": {
    "id": "act_01J...",
    "kind": "source_fix_required",
    "summary": "O projeto não possui um script de build válido.",
    "response_schema": { "properties": { "resolution": { "enum": ["fixed_locally", "cancel"] } } }
  },
  "next_step": "Corrija o projeto no diretório local e publique de novo com …"
}
```

**Isso não é uma falha.** Siga o `next_step`. São três caminhos possíveis:

| `kind` | O que fazer |
|---|---|
| `agent_input`, `user_input` | responda: `npx -y @malha-ai/cli@latest actions answer <act_id> <valor>`, com um dos valores do `response_schema`. Se a pergunta for para o usuário, pergunte a ele primeiro |
| `source_fix_required` | **corrija o projeto** e publique de novo: `deploy --resolves-action <act_id> --json` |
| `browser_approval` | mostre `approval_url` ao usuário e peça que ele aprove no navegador. Você não pode responder esta |

Para consultar depois:

```bash
npx -y @malha-ai/cli@latest actions list <deployment-id> --json
npx -y @malha-ai/cli@latest deployments get <deployment-id> --events --json
```

## Flags úteis

```text
--name TEXT       nome do app, no primeiro deploy
--app app_...     publica em um app já existente
--path CAMINHO    diretório a publicar (padrão: o atual)
--json            saída estruturada (recomendado para agentes)
--no-wait         retorna assim que o job for enfileirado
--message TEXTO   descrição do deployment
```

## O que a Malha não envia

Alguns arquivos são **sempre** excluídos, mesmo que apareçam no `.gitignore`
do projeto ou que o usuário tente reincluí-los:

```text
.env, .env.*, *.pem, *.key, *.p12, *.pfx, id_rsa*
```

Se algum for encontrado, a CLI avisa em stderr quais foram bloqueados. Isso
não é erro — é proteção. **Não tente contornar.** Se a aplicação precisa de
uma variável de ambiente, diga ao usuário: secrets de aplicativo ainda não são
suportados nesta fase.

Também ficam de fora, por performance: `node_modules/`, `.git/`, `dist/`,
`.venv/`, `__pycache__/`, `coverage/` e similares.

## Limites

| Limite | Valor |
|---|---:|
| Pacote comprimido | 100 MiB |
| Conteúdo descompactado | 500 MiB |
| Arquivos | 20.000 |
| Maior arquivo | 25 MiB |

## O que a Malha publica

Nesta fase:

- **Next.js** — aplicativo com servidor próprio;
- **Vite/React** — o build vira um diretório de arquivos, servido como tal;
- **sites estáticos** — HTML, CSS e JS soltos, **sem `package.json`**. Este é
  o caso mais simples e é totalmente suportado: não crie um `package.json` só
  para "parecer um projeto".

O gerenciador de pacotes precisa ser **npm** ou **bun**. Um projeto com
`pnpm-lock.yaml` ou `yarn.lock` é recusado; gere um `package-lock.json` com
`npm install --package-lock-only`.

Outros frameworks são recusados com `FRAMEWORK_UNSUPPORTED` — não tente
contornar reescrevendo o projeto sem que o usuário peça.

## Redeploy

Depois do primeiro deploy, o diretório ganha um `.malha/project.json` com o
`app_id`. Basta rodar `deploy` de novo: a CLI reconhece o app, cria uma versão
nova e preserva a anterior até a nova ficar saudável.

## Antes de publicar

Se o projeto tiver build ou testes, rode-os primeiro. Publicar um projeto que
não compila desperdiça o tempo do usuário e produz um erro que só aparece
minutos depois.

## Segurança

- Nenhum token, chave ou URL de upload aparece na saída da CLI.
- O link de autorização pode ser exibido: ele exige login e aprovação humana.
- O único pacote oficial é **`@malha-ai/cli`**. Desconfie de nomes parecidos.
