# auth.md — TV Sim Brasil

Como um agente automatizado acessa os serviços de https://tvsimbrasil.com.br.

## Resumo

**Leitura não precisa de credencial.** Todo o acervo publicado — matérias,
editorias, subtópicos, vídeos curtos e o guia de lugares — é aberto, anônimo e
sem chave de API. Se o seu agente só lê e não passa de 15 requisições por
segundo, pare aqui: não há nada para registrar.

**Registrar-se é opcional, e serve para ser identificado.** Um agente que se
cadastra ganha identidade estável, um teto próprio e um canal por onde ser
avisado — não ganha acesso a nada que já não fosse público.

Escrita editorial não é aberta a agentes. Publicar no portal é ato com
responsabilidade humana, então não existe (e não está previsto) um caminho de
auto-registro que dê acesso de publicação. **Nenhum escopo de escrita editorial
é emitível** — nem por este documento, nem por contato, nem pelo OAuth abaixo.

## Descoberta automática

| Documento | Endereço |
|---|---|
| Servidor de autorização (RFC 8414) | https://tvsimbrasil.com.br/.well-known/oauth-authorization-server |
| Recurso protegido (RFC 9728) | https://tvsimbrasil.com.br/.well-known/oauth-protected-resource |

O `issuer` é `https://tvsimbrasil.com.br`. Os endpoints ficam em outro host
(`api-news.tvsimbrasil.com.br`), o que a RFC 8414 permite: o que ela exige é
que o metadado seja servido no `.well-known` do issuer, e é.

**Não publicamos `/.well-known/openid-configuration`**, e o caminho responde
404 de propósito: o servidor fala `client_credentials`, que não é OpenID
Connect — não há usuário final, não há `id_token` e não há UserInfo.

## Público-alvo deste documento

Quatro perfis, e o que cada um precisa fazer:

1. **Agente que só lê** (LLM, crawler de resposta, cliente MCP, agregador).
   Público majoritário. **Não registre nada.** Está pronto agora.
2. **Agente que quer identidade estável** — porque puxa volume, porque precisa
   ser reconhecido, ou porque quer poder ser avisado antes de ser barrado.
   Registro automático por OAuth, na seção seguinte. Sem humano no meio.
3. **Aplicação que age em nome de um leitor humano** — comentar, curtir, salvar,
   avaliar um lugar, enviar foto. O titular da conta é a **pessoa**, não o
   software: o registro é o do leitor, feito por ele, e o seu cliente apenas
   porta o token dele.
4. **Agente operado por organização identificada** que precisa passar do teto do
   tier. Registre-se como no item 2 e depois **reivindique** o cadastro, na
   seção de reivindicação. A decisão é humana, caso a caso.

Fora do alvo: agente anônimo pedindo escrita editorial. Não há caminho, e pedir
não abre um.

## Registro e provisionamento

### Automático — agente (OAuth 2.0, sem humano no meio)

O fluxo inteiro são duas chamadas.

**1. Registre o cliente** (registro dinâmico, RFC 7591):

```
POST https://api-news.tvsimbrasil.com.br/oauth/register
Content-Type: application/json

{
  "client_name": "Nome do seu agente",
  "contacts":    ["responsavel@exemplo.com"],
  "client_uri":  "https://exemplo.com"
}
```

Responde **201** com `client_id` e `client_secret`. **O segredo aparece uma
vez só** — é guardado com hash e não há como reexibi-lo. Quem perder, registra
de novo.

`contacts` é obrigatório e é o ponto do cadastro: sem um humano por trás, um
`client_id` que descamba só pode ser desligado no escuro, sem aviso. **Nós não
verificamos esse e-mail** — por isso o metadado declara o tipo de identidade
como `anonymous`, e não `verified_email`.

**2. Peça o token** (client_credentials, RFC 6749 §4.4):

```
POST https://api-news.tvsimbrasil.com.br/oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials&client_id=…&client_secret=…&scope=content.read
```

Responde com `access_token`, `token_type: Bearer` e `expires_in` (uma
hora). Não há refresh token e nem faria sentido: você tem o segredo e pede outro
quando quiser.

**`content.read` é o único escopo que existe.** Pedir qualquer outro
devolve erro. Não há escopo de escrita editorial a obter.

### Automático — conta de leitor (pessoa física)

Base: `https://api-news.tvsimbrasil.com.br/api/v1`

| Finalidade | Método e caminho |
|---|---|
| Criar conta de leitor | `POST https://api-news.tvsimbrasil.com.br/api/v1/reader/register` |
| Autenticar leitor existente | `POST https://api-news.tvsimbrasil.com.br/api/v1/reader/login` |
| Autenticar via Google | `POST https://api-news.tvsimbrasil.com.br/api/v1/reader/google` |
| Conferir a identidade do token | `GET https://api-news.tvsimbrasil.com.br/api/v1/reader/me` |

Todos respondem com um token Bearer do Sanctum — **não é o token do OAuth acima
e não se misturam**. **Contas são de pessoas físicas**: use-as para agir em nome
de um leitor que consentiu, nunca como identidade do próprio agente. O escopo é
o da conta dele — comentário, curtida, salvos, histórico, avaliação e foto de
lugar. Nada disso publica matéria.

### Reivindicação — sair do tier `pre-claim`

O auto-registro emite credencial **anônima**: pedimos um e-mail e não o
verificamos. A reivindicação é o passo em que alguém assume a autoria daquele
`client_id` e pede um teto maior.

```
POST https://api-news.tvsimbrasil.com.br/oauth/claim
Content-Type: application/json

{
  "client_id":     "…",
  "client_secret": "…",
  "organization":  "Razão social de quem opera o agente",
  "contact":       "responsavel@exemplo.com",
  "justification": "O que o agente faz e em que volume"
}
```

Responde **202** com `status: pending`. **Isso não promove ninguém na hora, e
de propósito:** a decisão é de uma pessoa, em dias úteis, sem SLA. Sua
credencial continua valendo no tier atual enquanto isso. Um endpoint que
devolvesse um tier novo estaria afirmando uma revisão que não aconteceu.

Também aceitamos o mesmo pedido por e-mail, em **tech@tvsimbrasil.com.br**.

### Operação interna

`POST https://api-news.tvsimbrasil.com.br/api/v1/auth/login` — restrito à equipe da redação e da
engenharia. Não é caminho de registro para terceiros e não aceita cadastro.

## Métodos de autenticação suportados

- **Anônimo** (sem cabeçalho nenhum) para todo o acervo público de leitura.
- **Bearer token do OAuth 2.0**, emitido pelo `token_endpoint` acima, para
  agente registrado.
- **Bearer token do Laravel Sanctum**, para conta de leitor e operação interna.

Nos três casos o cabeçalho é o mesmo:

    Authorization: Bearer <token>

## Uso da credencial

- **Formato.** `Authorization: Bearer <token>` em toda requisição.
- **Transporte.** Só HTTPS. Não coloque o token em query string, log ou URL.
- **Validade.** Token do OAuth: **uma hora** (`expires_in` diz o quanto
  falta). Token do Sanctum: não expira por tempo, vale até ser revogado.
- **Renovação.** Não há refresh token. Peça outro no mesmo endpoint que emitiu.
- **Verificação da assinatura.** O token do OAuth é um JWT assinado em RS256. A
  chave pública está em `https://api-news.tvsimbrasil.com.br/oauth/jwks.json` (o `jwks_uri` do
  metadado), e com ela você confere a assinatura sem nos chamar. **O token do
  Sanctum é opaco** — não o decodifique.
- **Revogação.** `POST https://api-news.tvsimbrasil.com.br/oauth/revoke` (RFC 7009) devolve a credencial
  do agente; autentique-se com `client_id` e `client_secret`. Para conta de
  leitor, `POST https://api-news.tvsimbrasil.com.br/api/v1/reader/logout`. Também revogamos do nosso lado,
  a pedido do responsável ou por abuso.
- **Falha.** Token ausente, inválido ou revogado responde **HTTP 401** com
  `WWW-Authenticate` apontando para o metadado do recurso protegido. 401 não é
  caso de repetir a mesma chamada: reautentique.
- **Escopos.** Um só, `content.read`, de leitura.

## O que é aberto

| Recurso | Endereço | Credencial |
|---|---|---|
| API de conteúdo (REST) | `https://api-news.tvsimbrasil.com.br/api/v1` | nenhuma |
| Servidor MCP | `https://tvsimbrasil.com.br/mcp` | nenhuma |
| Descrição da API (OpenAPI) | `https://tvsimbrasil.com.br/openapi.json` | nenhuma |
| Mapa editorial | `https://tvsimbrasil.com.br/llms.txt` | nenhuma |
| Páginas em Markdown | qualquer URL do portal com `Accept: text/markdown` | nenhuma |
| Cartão do servidor MCP | `https://tvsimbrasil.com.br/.well-known/mcp/server-card.json` | nenhuma |
| Catálogo de APIs | `https://tvsimbrasil.com.br/.well-known/api-catalog` | nenhuma |
| Catálogo ARD | `https://tvsimbrasil.com.br/.well-known/ai-catalog.json` | nenhuma |
| Habilidades (Agent Skills) | `https://tvsimbrasil.com.br/.well-known/agent-skills/index.json` | nenhuma |
| Chave pública do OAuth (JWKS) | `https://api-news.tvsimbrasil.com.br/oauth/jwks.json` | nenhuma |
| Reivindicação de cadastro | `https://api-news.tvsimbrasil.com.br/oauth/claim` | client_id + secret |
| Documentação da API (humanos) | `https://tvsimbrasil.com.br/docs/api` | nenhuma |

## Como se comportar

- **Identifique-se** no `User-Agent`, com um jeito de te contatar. Agente
  anônimo em volume é indistinguível de abuso e é barrado na borda.
- **Respeite o `robots.txt`**, inclusive a preferência de uso declarada no
  cabeçalho dele (Content Signals).
- **Atribua.** Cite "TV Sim Brasil" e mantenha o link da URL canônica. Para
  reproduzir a foto, use o crédito que vem em `image_credit`.
- Matéria com `is_branded: true` é **Conteúdo de Marca** (peça comercial), não
  apuração da redação — não a apresente como reportagem.

## Limite de requisição

⚠️ **Correção de 07/09/2026.** A versão anterior deste documento afirmava que a
leitura não tinha teto. Estava errada: o teto existe desde 02/08/2026, na borda
(nginx), e a medição anterior olhou só o código da aplicação.

**Leitura anônima: 15 requisições por segundo por IP** (com folga instantânea de
até 30). Vale para `https://api-news.tvsimbrasil.com.br/api/v1` inteira.

**Crawler de treinamento: 2 r/s.** Vale para os user-agents que se identificam
como coletores de treino (`GPTBot`, `ClaudeBot`, `Bytespider`,
`meta-externalagent`, `Amazonbot`, `Google-Extended`, entre outros). Eles
são liberados no `robots.txt` de propósito, com teto menor: não geram citação
com link e não podem consumir a banda que serve leitor e bot de busca.

**Bot de busca verificado por IP** (Googlebot, bingbot e afins) **não é
limitado.**

**Agente registrado: 1.200 requisições por minuto por `client_id`**, contadas
na aplicação, além do teto de borda acima. Ao estourar, a resposta é **429** com
`Retry-After` em segundos.

**Escrita (POST) tem teto por rota**, entre 5 e 60 por minuto conforme o
endpoint. Nenhum deles é caminho de publicação de matéria. O registro de cliente
OAuth é 5 por hora.

Ao tomar **429**, espere o `Retry-After` antes de repetir. Repetir na mesma
cadência transforma um teto momentâneo em bloqueio.

## Contato humano

**tech@tvsimbrasil.com.br** — teto acima do tier, dúvida sobre uso do acervo,
denúncia de abuso e correção deste documento.
