# ONBOARDING-TELEGRAM.md — ligar o telemóvel ao DSH via bot Guia para conectar o Telegram ao DSH guardado por este plugin e parear o teu chat como dono. Todo o comando de controlo (ligar/desligar o túnel, estado) só é aceite de um chat pareado. > **Compat (arquitetura de provedores):** o worker é neutro ao provedor e o Telegram é o único > fornecedor hoje (`config.worker.provider`, default `telegram`). **Nada muda para si** no > onboarding: o token continua na variável `TELEGRAM_BOT_TOKEN`, o pareamento é o mesmo e os > comandos do bot não mudam. Detalhe em [`docs/PROVIDERS.md`](PROVIDERS.md). > **Não há senha a digitar em lugar nenhum.** O acesso pelo túnel entra por > **sessão** ou pela **chave no link** `?key=`. O bot é o canal de entrega: o > `/ligar` (e o `/acessar`) **envia automaticamente** o link com a chave > `https:///?key=`. A chave pode aparecer no chat — **é o > mecanismo** (é a chave do link, não uma "senha permanente"). Ela é > **reutilizável** até `/rotacionar` (gera chave nova e invalida sessões) ou > derrubar o túnel. > > Aviso honesto de canal: a conversa com bot é *cloud chat* — não é ponta-a-ponta, > o histórico fica nos servidores da Telegram. Como a chave viaja por aí, quem ler > o chat lê a chave; foi por isso que a revogação (`/rotacionar`) existe. Outros > segredos que **não** são a chave do link (token do bot, segredos internos) nunca > devem aparecer no chat. ## Ponto de partida A ferramenta de onboarding é a CLI `dsh-guard-setup`, que vem no próprio pacote (`bin` em `package.json` → `dist/bin/dsh-guard-setup.js`). Correr sem opções mostra **só o passo que falta** fazer, na ordem. É pensada para quem nunca viu o projeto: quem a corre do zero e segue cada passo sem perguntar nada ao autor cumpriu o critério de usabilidade (roteiro M1, `docs/plano/04-TESTES.md §9`). ## Passo 1 — criar o bot no BotFather 1. No Telegram, conversa com `@BotFather` e corre `/newbot`. 2. Dá um nome e um username **que termine em `bot`** (5–32 caracteres, `[A-Za-z0-9_]`, imutável). 3. O BotFather devolve um token no formato `:`. Guarda-o por agora; vai ser pedido no passo seguinte. O texto exato a digitar é mostrado pela própria CLI quando corres `dsh-guard-setup`, sem jargão. ## Passo 2 — colar o token Corre a CLI na máquina onde o DSH roda: ```sh dsh-guard-setup ``` Quando pedido, cola o token. A leitura é **sem eco** (não aparece no terminal) e o valor é gravado com modo `0600`. A CLI valida com `getMe` e mostra o `@username` do bot para conferência. Se colares um token errado, tens um erro claro, sem stack trace, com a instrução de `/token` no BotFather. > A CLI **recusa** qualquer forma de token no *argv* (`--token=...` ou valor solto) — > um argumento é visível em `/proc//cmdline` para qualquer processo local > (`src/telegram/onboarding.ts:423-434`). O token fica numa **allowlist de ambiente** do worker, nunca em `argv`. O worker de long-polling não herda `process.env` inteiro: o plugin monta um ambiente mínimo a partir de uma allowlist mais o token (`src/proc/env.ts`). ## Passo 3 — parear o teu chat (código de 6 dígitos) 1. A CLI mostra um **código de pareamento de 6 dígitos**, só no terminal, com TTL de 5 minutos e a instrução `/parear ` no bot. 2. Manda `/start` ao bot **antes** de parear, se quiseres: o bot responde uma boas-vindas inócua e **não pareia** ninguém. Por desenho, `/start` não pareia (`docs/plano/02-SEGURANCA.md` D8). 3. Manda `/parear ` com o código certo. A CLI confirma o `@username` e o `chat` pareado e **fecha** o pareamento. 4. Se o código estiver errado, o bot responde uma recusa genérica e conta a tentativa (teto de 5 errados). Se voltar a tentar `/parear` (ou de outra conta), é **recusado**; reabrir exige `--reset-pairing` na máquina. O pareamento é de um dono só (`worker/surface/auth.ts`). ## Passo 4 — conferir o que ficou em disco ``` ~/.dsh/guarded-bot/secrets.env # 0600, guarda TELEGRAM_BOT_TOKEN ~/.dsh/guarded-bot/state.json # 0600, guarda o pareamento ``` O caminho usa `$DSH_HOME` se estiver definido, senão `~/.dsh`, sempre sob `guarded-bot/` (`src/state/paths.ts`). Tudo `0600`, diretório `0700`, fora do workspace e fora do git. ## Passo 5 — ler os 5 avisos de exposição A CLI imprime (no terminal) os cinco avisos que tens de ter lido antes de expor: 1. `trustedRemotes` fica **inerte** como controlo de rede sob o túnel; 2. o túnel **fura a firewall** (qualquer porto de saída 443); 3. o **TLS termina na borda da Cloudflare** — o texto claro passa por um terceiro; 4. o endereço do túnel **não é segredo**; 5. `trycloudflare.com` tem reputação de malware em alguns filtros. ## Comandos do bot (depois de pareado) | Comando | O que faz | | --- | --- | | `/ligar` | Sobe o túnel e, quando fica READY, **envia automaticamente** o link com a chave `?key=` (pede confirmação) | | `/desligar` | Derruba o túnel (e revoga a chave) (pede confirmação) | | `/status` | Estado atual e a URL vigente | | `/acessar` | (Re)envia o link com a chave | | `/rotacionar` | Gera **chave nova** e invalida as sessões — encerra também as conexões ativas (WebSocket) além de revogar a chave e as sessões | | `/emergencia` | Derruba o túnel e revoga as sessões (kill switch) | Ações que **aumentam a exposição** (subir o túnel) exigem confirmação em duas etapas com um nonce do host. O botão de confirmar é identificado pelo **texto** (o estilo de botão é não confirmado pela referência — não dependemos dele). ## Se usas o painel / outra superfície Ligar/desligar também está no painel local e numa superfície de UI própria; ambas as superfícies mostram o mesmo estado e o mesmo `seq` (paridade por contrato, CTL-040). O worker de long-polling conflita com uma segunda instância do bot no mesmo token (`409 terminated by other getUpdates request`) — nunca corras duas instâncias no mesmo token.