# Segredos

Como o Beeuni armazena as credenciais do projeto e controla se o código do agente pode ler cada valor.

Canonical page: https://beeuni.ai/docs/pt/project/secrets

Um segredo é uma credencial por projeto — uma chave de API, um token ou uma string de conexão — de que uma sessão precisa, mas que não deve ficar no repositório. O Beeuni armazena os segredos no projeto, nunca na conta, e criptografa cada valor com AES-256-GCM usando uma chave derivada por projeto.

<a id="identifier-and-name"></a>

## Identificador e nome

Cada segredo tem dois nomes. O `identifier` é o identificador usado na CLI e na concessão `secrets` de um agente. O `name` é a chave de variável de ambiente em maiúsculas no sandbox, por exemplo `STRIPE_API_KEY`. Na maioria dos projetos, o identificador e o nome são iguais. Eles diferem apenas quando um projeto contém vários valores candidatos para um mesmo nome — por exemplo, uma chave principal e uma chave reserva do Google Maps podem ambas resultar em `GOOGLE_MAPS_API_KEY`.

Todas as regras de acesso usam o identificador. Nenhuma usa o nome.

<a id="exposure-and-usage"></a>

## Exposição e uso

Um segredo tem duas configurações independentes. Leia-as separadamente; elas respondem a perguntas diferentes.

| Configuração | Pergunta respondida | Valores |
|---|---|---|
| **Exposição** | O código do agente pode ler o valor real? | `environment`, `egress-enforced`, `none` |
| **Uso** | Quem o utiliza? | Código do agente, gateway de LLM, conector, Git |

A documentação antiga do Beeuni apresentava uma lista que misturava as duas coisas. Ela não existe mais. Não há escolha entre um “limite de rede” e um “proxy HTTPS”: um único mecanismo atende a todos os segredos com saída de rede controlada, em todos os provedores de sandbox.

<a id="the-three-exposures"></a>

### Os três tipos de exposição

| Exposição | O que o sandbox contém | Use para |
|---|---|---|
| **Ambiente** | O valor real, como variável de ambiente em texto simples | A opção padrão. Valores com os quais o agente precisa fazer cálculos e protocolos que não sejam HTTPS |
| **Saída de rede controlada** | Um **identificador** — um marcador autodescritivo, sem valor por si só | Experimental. Chamadas HTTPS, quando a flag `secrets_egress` estiver ativada |
| **Nenhuma** | Nada | Uma credencial usada apenas por um serviço do Beeuni ou um valor armazenado e desativado |

> **Regra prática**
>
> **Ambiente** é a exposição padrão. O valor real é carregado no sandbox, onde o agente pode lê-lo, imprimi-lo e encaminhá-lo. **Saída de rede controlada** mantém o valor fora do sandbox, mas é experimental: ative a flag de recurso `secrets_egress` (Settings → Feature flags) para usá-la. Até lá, o segredo é carregado no ambiente do sandbox.

<a id="usages"></a>

### Usos

A maioria dos usos é definida pelo Beeuni, não por você:

- **Código do agente** — implícito sempre que a exposição não for `none`.
- **Gateway de LLM** — definido quando o valor é uma chave reconhecida de um provedor de modelos. O gateway autentica as solicitações ao provedor no lado do servidor.
- **Connector:&lt;slug&gt;** — definido pelo fluxo de vinculação do conector.
- **Git** — definido pelo Beeuni para seu próprio acesso ao Git. Somente leitura; você não pode defini-lo nem removê-lo.

Um segredo com exposição `none` e sem uso aparece como **Desativado**: armazenado, criptografado e não utilizado por nada.

<a id="sent-secrets-and-computed-secrets"></a>

## Segredos enviados e segredos calculados

A exposição que um segredo pode usar depende do **sistema upstream**, não do Beeuni.

- **Segredos enviados** — o valor trafega pela rede. Chaves de API, tokens bearer e senhas. Essa é a grande maioria. Há um momento em que o valor está em bytes em uma solicitação de saída, então o próprio Beeuni pode inseri-lo, fora do sandbox. Um segredo enviado pode passar para **saída de rede controlada** quando a flag `secrets_egress` estiver ativada; por padrão, ele é carregado no ambiente do sandbox.
- **Segredos calculados** — o valor é um ingrediente de um cálculo e nunca trafega pela rede. Chaves de assinatura AWS SigV4, segredos de assinatura HMAC de webhook, asserções de cliente JWT e chaves privadas SSH. Quem faz o cálculo precisa ter o valor. Nenhum limite de rede ajuda, porque nada na comunicação contém a credencial. Segredos calculados precisam permanecer em **ambiente**.

Ambiente é a exposição padrão e a única que pode fornecer uma credencial com a qual o sandbox precisa fazer cálculos. Protocolos que não sejam HTTPS — uma string de conexão Postgres, credenciais SMTP — estão na mesma situação: precisam permanecer em ambiente.

Ao salvar um valor que parece ser material de assinatura, como um par de chaves de acesso `AKIA…` ou material PEM/SSH, o Beeuni define **ambiente** como padrão e explica o motivo: esta chave assina solicitações localmente, então não é possível aplicar o controle de saída de rede.

<a id="egress-enforced-exposure"></a>

## Exposição com saída de rede controlada

> **Experimental — requer a flag secrets_egress**
>
> O controle de rede é experimental. Ative a flag de recurso `secrets_egress` (Settings → Feature flags) para usá-lo. Até lá, o segredo é carregado no ambiente do sandbox. Com a flag desativada, criar um segredo com saída de rede controlada retorna `403` `feature_disabled`.

O sandbox recebe uma variável de ambiente cujo valor é um **identificador**, não a credencial. O agente usa essa variável exatamente como usaria a chave real — em um cabeçalho, uma string de consulta ou um corpo. `Authorization: Bearer $VAR`, `Cookie: …=$VAR`, um cabeçalho `X-Api-Key`, um parâmetro de consulta e um campo de corpo JSON ou de formulário funcionam: o Beeuni encontra o identificador onde quer que apareça (em formato bruto, codificado para URL, em base64 isolado ou escapado para JSON) e o substitui pelo valor real. Na saída, o Beeuni substitui o identificador pelo valor real, mas somente em solicitações para hosts aprovados por você.

> **Envie o identificador como está — não o codifique em base64 por conta própria**
>
> Uma coisa não funciona: ocultar o identificador em um bloco base64 criado por você, como faz a **autenticação HTTP Basic** (`curl -u $VAR:` → `Authorization: Basic <base64>`). O Beeuni não consegue encontrar um identificador incorporado e desalinhado dentro de uma codificação base64 feita por você, então a substituição não acontece e o sistema upstream responde `401`. Em vez disso, coloque o identificador em um cabeçalho Bearer/token, em um parâmetro de consulta ou em um campo do corpo. Se a API só aceitar autenticação Basic, use a exposição **ambiente** para esse segredo.

Fatos que decorrem desse funcionamento:

- O valor real **nunca** fica no sandbox: nem como variável de ambiente, nem em arquivo, nem como alias.
- Um identificador enviado a um host que você não aprovou chega como texto literal. O sistema upstream o rejeita. Ele não tem valor.
- Um identificador com assinatura inválida nunca é aceito, e o Beeuni o registra como identificador forjado. Um identificador válido de um segredo que esta sessão não pode usar é registrado como roubado.
- Cada solicitação retransmitida gera um registro de auditoria individual.
- O tráfego para hosts que não estão na lista é encaminhado por túnel sem ser lido. Clientes com TLS fixado e mTLS para esses hosts não são afetados.

<a id="hosts-match-exactly"></a>

### Correspondência exata de hosts

Liste todos os hosts que você chama, um nome de host exato por linha.

| Rejeitado | Motivo |
|---|---|
| Um host com curinga, `*.example.com` | O agente nunca deve escolher o destino |
| Um esquema de URL diferente de HTTPS | O Beeuni termina a conexão TLS para fazer a substituição |

`api.example.com` não abrange `uploads.api.example.com`. Adicione o segundo host ao mesmo segredo. O Beeuni rejeita uma política impossível de aplicar com `400` ao salvá-la — ele nunca armazena uma regra que não consegue aplicar.

Dois segredos com saída controlada podem compartilhar um host. Cada identificador é associado ao seu próprio valor, então ambos são substituídos corretamente na mesma solicitação.

<a id="verify-it-with-two-probes"></a>

### Verifique com duas sondagens

Execute as duas sondagens dentro do sandbox, para um host que esteja na lista.
O exemplo usa `postman-echo.com`, que disponibiliza um endpoint de cada tipo.
Adicione-o como host permitido durante o teste.

```bash
# 1. Reachability — an endpoint that does NOT echo request headers.
curl -s -o /dev/null -w '%{http_code}\n' https://postman-echo.com/status/200
# expected: 200

# 2. Substitution — an endpoint that DOES echo request headers.
curl -sS -H "authorization: Bearer $STRIPE_API_KEY" https://postman-echo.com/get
# expected: 200, with "Bearer [REDACTED]" in the echoed headers
```

Analise os resultados em conjunto, com a sondagem 1 primeiro: ela é a única que informa se o host está acessível, e a sondagem 2 não prova nada até que ela passe.

| Resultado da sondagem 2 | Significado |
| --- | --- |
| `200`, o cabeçalho retornado mostra `[REDACTED]` | Funcionando. O valor real foi enviado ao servidor de destino e a resposta de eco foi redigida no caminho de volta. |
| `200`, o cabeçalho retornado mostra o próprio identificador | A substituição não ocorreu. Verifique a lista de hosts e a concessão ao agente. |
| `401` de um host de API real | A substituição não ocorreu. Faça as mesmas duas verificações. |
| Resposta vazia ou erro de conexão | Falha real. Isso não é um sinal de sucesso. |

Confirme que o valor real não está em nenhum lugar no ambiente convidado:

```bash
env | grep '^STRIPE_API_KEY='
# expected: the handle, not the credential
```

O identificador também aparece em `BEEUNI_SECRET_CAPABILITIES`, o catálogo sem valores que informa ao agente quais segredos existem, qual variável contém cada identificador e quais hosts cada um abrange. Ele nunca contém um valor.

Um host da lista apresenta um certificado que a Beeuni emitiu para este sandbox e no qual o sandbox já confia, em vez do certificado próprio do servidor de origem:

```bash
curl -sv https://postman-echo.com/status/200 2>&1 | grep 'issuer:'
# issuer: CN=Beeuni Egress CA (<project prefix>); O=Beeuni
```

<a id="what-the-relay-changes"></a>

### O que o relay altera

Um host aprovado é acessado por meio da Beeuni, por isso funciona de maneira um pouco diferente de uma chamada direta:

- As respostas não são transmitidas em fluxo. Eventos enviados pelo servidor e websockets não funcionam por meio de um host aprovado.
- O corpo de uma solicitação tem limite de 1 MiB, o de uma resposta, 5 MiB, e a chamada inteira, 30 segundos. A Beeuni segue no máximo 3 redirecionamentos.
- Apenas um conjunto fixo de cabeçalhos de resposta é retornado: tipo e idioma do conteúdo, validadores de cache, a família de limite de taxa, `retry-after`, `x-request-id`.
- Apenas clientes que respeitam `https_proxy` são interceptados. A Beeuni define essa variável e a confiança na CA correspondente no ambiente do agente. Um processo iniciado com o ambiente limpo acessa o host diretamente, e sua solicitação sai levando o identificador.

Para solicitações que a Beeuni não consegue interceptar, o agente tem uma porta explícita para os mesmos hosts, sob a mesma política:

```bash
beeuni secrets call STRIPE_API_KEY https://api.stripe.com/v1/customers
```

<a id="environment-exposure"></a>

## Exposição no ambiente

O sandbox recebe o valor real como uma variável de ambiente em texto simples. O código do agente pode lê-lo, imprimi-lo e encaminhá-lo para qualquer lugar. A Beeuni não pode redigi-lo, auditar seu uso nem impedir que ele saia.

A exposição no ambiente é a opção padrão. Todo segredo novo usa essa opção, a menos que você o mude para saída controlada, que é experimental e exige a flag `secrets_egress`. Uma credencial calculada e qualquer protocolo que não seja HTTPS devem permanecer no ambiente.

<a id="who-can-use-a-secret"></a>

## Quem pode usar um segredo

Cada valor secreto tem um público, a mesma opção **Quem pode usar** de uma conta de conector:

| Opção | Quem pode usar o valor |
| --- | --- |
| **Todos no projeto** (padrão) | Todas as sessões do projeto, incluindo gatilhos, agendamentos e sessões compartilhadas. |
| **Somente você** | Você, diretamente, e suas próprias sessões privadas. |
| **Pessoas, grupos ou agentes específicos** | As pessoas e os grupos que você escolher (diretamente e nas próprias sessões privadas deles) e os agentes que você escolher (em todas as sessões deles). |

Uma sessão funciona como duas coisas ao mesmo tempo: seu **agente**, sempre, e sua **pessoa**, somente enquanto a sessão for privada.

- **Uma pessoa** acessa um valor em uma sessão **privada** iniciada por essa pessoa. Uma mensagem de qualquer outra pessoa remove a pessoa da sessão, e o valor deixa de ser disponibilizado. Sessões compartilhadas, gatilhos, agendamentos, webhooks e sessões de email e Telegram não têm uma pessoa.
- **Um agente** acessa um valor em todas as sessões desse agente, incluindo gatilhos, agendamentos e sessões compartilhadas. Compartilhe um valor com o agente quando uma execução não supervisionada precisar dele. Qualquer pessoa que possa executar esse agente poderá usar o valor por meio dele, então a execução do agente é o controle de acesso (quem pode executar um agente é definido no próprio agente).
- Os consumidores do lado do servidor seguem a mesma regra. Um conector associado ao segredo usa esse segredo somente para uma pessoa que esteja no público. Qualquer outra pessoa recebe `credential_not_shared`, e nenhuma solicitação sai da Beeuni.
- Os serviços da Beeuni que agem por conta própria — o proxy do Git, as verificações de assinatura de webhook, as instalações de canais e os Apps da Beeuni — usam somente valores compartilhados com todos.

Vários valores podem compartilhar o mesmo nome. Um valor compartilhado com a pessoa da sessão tem prioridade sobre um compartilhado com o agente, que tem prioridade sobre o valor compartilhado com todos. Exemplo: `DEEL_API_TOKEN` contém um valor da equipe, e um segundo valor com o identificador `DEEL_API_TOKEN-finance` é compartilhado somente com o grupo Finance. Os membros do Finance recebem o valor do Finance nas sessões privadas; todos os outros, assim como todos os gatilhos, recebem o valor da equipe.

Uma pessoa define o público. Uma sessão de agente não pode alterá-lo (`403`), então um agente não pode ampliar o acesso a um valor cujo público não o inclui nem adicionar a si mesmo. Quem gerencia os segredos do projeto ainda pode ver um valor que não foi compartilhado com essa pessoa, marcado como **Não compartilhado com você**, para que possa ampliar o acesso novamente.

<a id="sharing-a-session-that-holds-a-personal-value"></a>

### Compartilhar uma sessão que contém um valor pessoal

Um valor compartilhado somente com você que chegou à sua sessão privada como **variável de ambiente** está em texto simples dentro desse sandbox. Compartilhar a sessão permitiria que cada novo espectador o lesse, e não é possível remover uma variável de ambiente de um sandbox em execução. Por isso, a Beeuni se recusa a compartilhar essa sessão ou criar um link público para ela, se ela contiver `409 PERSONAL_SECRET_REQUIRES_PRIVATE_SESSION` e os nomes associados. Inicie uma nova sessão para compartilhá-la ou compartilhe primeiro o valor com todos. Valores acessados por meio do agente, bem como valores com saída controlada ou do lado do servidor (verificados em cada solicitação), não impedem o compartilhamento.

Ao restringir um público, a Beeuni envia novamente os valores a todos os sandboxes em execução. Um valor que já tenha sido entregue como variável de ambiente permanece no sandbox até que ele seja reiniciado. Se houver a possibilidade de alguém tê-lo lido, altere-o.

<a id="when-you-enter-a-value-through-a-link"></a>

### Quando você insere um valor por meio de um link

Um agente que precisa de um valor que você ainda não forneceu envia um link. A página do link oferece a opção **Quem pode usar**: todos no projeto (padrão) ou somente a pessoa que solicitou. Escolha a segunda opção para qualquer dado pessoal — um token de folha de pagamento ou um login pessoal. A página identifica quem solicitou pelo nome de exibição, nunca pelo email, pois qualquer pessoa com o link pode abri-lo.

<a id="personal-override"></a>

### Substituição pessoal

Uma substituição pessoal é um valor seu para um nome, usado no lugar do valor compartilhado nas sessões que você inicia. Atualmente, a Beeuni usa esse recurso somente para uma credencial de login OAuth. A Beeuni nunca permite que uma chave de provedor de LLM, por exemplo `ANTHROPIC_API_KEY`, seja uma substituição pessoal.

<a id="add-a-secret"></a>

## Adicionar um segredo

### Definir o valor pela CLI
```bash
beeuni secrets set STRIPE_API_KEY=sk_live_...
```

A Beeuni o salva para todos no projeto. Adicione `--only-me` para que somente você possa usá-lo. Para armazenar mais de um valor com o mesmo nome, adicione `--identifier <id>`. Os nomes não podem começar com `BEEUNI_` — a Beeuni reserva esse prefixo para valores da plataforma.

Altere quem pode usá-lo mais tarde:

```bash
beeuni secrets share DEEL_API_TOKEN --user me
beeuni secrets share DEEL_API_TOKEN --user finance@example.com --group <group-id>
beeuni secrets share NIGHTLY_REPORT_TOKEN --agent reporter
beeuni secrets share DEEL_API_TOKEN --everyone
```

### Ou use o dashboard
Abra a página Secrets do projeto, insira a chave e o valor, escolha **Who can use
it** e salve. O Beeuni criptografa o valor imediatamente e define como padrão para
cada novo segredo **Everyone in the project** e exposição **environment** — o valor
real é carregado no sandbox. A coluna **Who can use it** mostra o público de cada
valor.

Para mudar um segredo para exposição com aplicação de regras de egress, primeiro
ative o sinalizador de recurso `secrets_egress` (Settings → Feature flags); esse recurso é experimental. Com o sinalizador ativado, a página Secrets mostra o controle **"Can your code read this value?"**:
responder *não* muda o segredo para aplicação de regras de egress e exibe a lista
de hosts; responder *sim* mantém a exposição environment. Com o sinalizador
desativado, o segredo permanece em environment.

### Conceder acesso a um agente
Escolha um agente na página Secrets ou adicione você mesmo o identificador à
lista `secrets` desse agente em `beeuni.yaml`. Uma sessão recebe apenas os segredos
concedidos ao agente dela. Consulte [Conceder um segredo a um
agente](#grant-a-secret-to-an-agent).

<a id="grant-a-secret-to-an-agent"></a>

## Conceder um segredo a um agente

Uma sessão recebe um segredo somente quando o agente que a executa inclui o
identificador na lista `secrets`. A correspondência usa o identificador, não o
nome, e não diferencia maiúsculas de minúsculas.

> **Usos com aplicação de regras de egress e de serviços precisam de uma concessão explícita**
>
> `secrets: all` concede apenas exposição environment. Um segredo com aplicação de
> regras de egress, assim como qualquer segredo usado por um serviço Beeuni, precisa
> ter seu identificador incluído na lista de um agente. Um projeto sem um bloco
> `agents:` em `beeuni.yaml` nunca recebe nenhum. Segredos sem concessão são descartados
> de forma silenciosa: a sessão é iniciada normalmente, e a primeira chamada ao
> host falha como se a credencial estivesse incorreta.

<a id="from-the-dashboard"></a>

### Pelo dashboard

A página Secrets indica quando nenhum agente pode receber um segredo: **No agent can receive
this secret**. Escolha um agente nessa página e confirme. O Beeuni edita `beeuni.yaml` e
faz o commit como `chore(agents): grant <IDENTIFIER> to <agent>`.

A concessão funciona quer o manifesto já declare o agente ou não. Um agente não
declarado no manifesto recebe uma nova entrada com uma lista `secrets` que contém
apenas esse item. Um agente já declarado mantém todos os outros campos — modelo,
ferramentas, conectores — e o identificador é adicionado à lista existente. Se o
agente já tiver acesso ao identificador, não é necessário fazer commit, e o
Beeuni não faz nenhum.

Um agente em `secrets: all` é um caso especial. `all` não pode incluir um
segredo com aplicação de regras de egress, então o Beeuni grava uma lista
explícita: todos os identificadores que o projeto tem hoje, mais este. Nada muda
no que o agente recebe hoje. Um segredo adicionado depois precisará de sua
própria concessão.

Há dois casos em que a concessão é recusada:

- Um projeto em `beeuni_version: 1` (`beeuni.toml`) não tem um mapa de agentes para editar.
  A solicitação falha com `400` e `manifest_v1_unsupported`. Edite o manifesto manualmente
  ou mova o projeto para `beeuni_version: 2`.
- Um segredo **Disabled** não tem nada a oferecer. A solicitação falha com
  `409` e `secret_not_grantable`. Primeiro, defina uma exposição para ele.

Se o projeto ainda não tiver um bloco `agents:`, leia [O primeiro bloco
`agents:` muda o projeto
inteiro](#the-first-agents-block-changes-the-whole-project) antes de confirmar.
Essa única edição altera o acesso a segredos de todos os outros agentes.

<a id="by-hand"></a>

### Manualmente

A mesma concessão, escrita diretamente:

```yaml
beeuni_version: 2
agents:
  my-agent:
    secrets: [STRIPE_API_KEY]
```

<a id="when-a-session-asks-for-a-secret-its-agent-is-not-granted"></a>

### Quando uma sessão solicita um segredo não concedido ao agente dela

Um agente que precisa de uma credencial gera um link de segredo (`beeuni secrets request`).
O valor inserido é salvo mesmo quando não foi concedido ao agente da sessão.
Essa sessão nunca o recebe, então o Beeuni deixa isso claro em todas as
interfaces:

- O formulário do link mostra **Saved, but `<agent>` can't read it yet** e informa o
  nome do segredo.
- A resposta da geração do link e a mensagem de acompanhamento para a sessão
  listam os nomes de `withheld` e a solução.
- Dentro da sessão, `beeuni secrets ls` mostra uma chave declarada fora da concessão como
  `not granted`, não como `missing`.

O agente não pode ampliar a própria concessão. Abra **Customize → Agents → `<agent>` →
Secrets** e habilite o segredo. Ao salvar, o Beeuni envia a alteração às sessões
em execução do agente. O agente também pode buscá-lo imediatamente com
`beeuni secrets sync`, e cada prompt sincroniza novamente os segredos de uma sessão. Não é
necessário reiniciar.

<a id="the-first-agents-block-changes-the-whole-project"></a>

### O primeiro bloco `agents:` muda o projeto inteiro

> **Declarar um agente nega acesso aos demais**
>
> Um projeto sem um bloco `agents:` — ou sem nenhum `beeuni.yaml` — não tem controle:
> todos os agentes recebem todos os segredos com exposição environment, e nenhum
> agente recebe segredos com aplicação de regras de egress.
>
> No momento em que o projeto declara seu primeiro agente, todos os agentes que
> **não** estiverem na lista deixam de receber qualquer segredo do projeto —
> inclusive os segredos environment que funcionavam um minuto antes. Incluir um
> agente revoga o acesso dos demais.

Portanto, liste todos os agentes que precisam de segredos, não apenas aquele que
você está corrigindo. Por isso, o dashboard pede sua confirmação na primeira vez:
depois desse commit, `agents:` será a lista de permissões do projeto, e qualquer
agente que não estiver nela será executado sem segredos do projeto.

<a id="exposing-capabilities-to-third-party-users"></a>

## Expor recursos a usuários de terceiros

> **As políticas de segredos do Beeuni não são um sistema de autorização multi-tenant**
>
> Uma política de segredo protege o **agente do seu próprio projeto** para que ele
> não vaze sua própria credencial. Ela não determina quais usuários finais podem
> usá-la.

Se você estiver criando algo em que **usuários terceiros não confiáveis** tenham
acesso a um recurso — uma interface de chat pública, um app compartilhado, um
agente que qualquer pessoa na internet possa solicitar —, não confie apenas nas
políticas de segredos. Todos os usuários dessa interface compartilham um agente
do projeto, uma concessão e uma lista de hosts. O Beeuni não tem como distinguir
um cliente seu de outro, então um segredo com aplicação de regras de egress que
possa ser usado pelo prompt de qualquer usuário é uma credencial que todos os
usuários podem usar, até o limite total permitido pela chave do serviço upstream.

Implemente no seu lado o limite de segurança de que realmente precisa:

1. Configure seu próprio serviço de autorização e proxy. Ele armazena a
   credencial do serviço upstream.
2. Direcione o agente ao seu serviço, não ao serviço upstream. Forneça ao agente
   apenas uma credencial para seu serviço — essa credencial pode ter aplicação
   de regras de egress restrita ao seu próprio host.
3. Seu serviço identifica o usuário final, aplica suas próprias regras de
   autorização e cotas por usuário e só então faz a chamada ao serviço upstream
   com a credencial que armazena.

Esse serviço é o lugar certo para regras por usuário: quem pode chamar o quê,
com que frequência e para quais registros. A exposição de segredos do Beeuni é
uma camada abaixo disso e não a substitui.

<a id="list-your-secrets"></a>

## Listar seus segredos

Execute `beeuni secrets ls` para ver quais segredos o projeto declara e quais têm um valor
configurado.

A lista contém metadados de configuração. Ela nunca retorna valores de segredos.
Um token de agente com escopo limitado vê apenas os identificadores incluídos na
concessão do agente. Um `secrets_allowlist` específico da sessão controla a entrega para
essa sessão, mas não oculta os metadados de configuração permitidos pela
concessão do agente.

<a id="rotate-a-secret"></a>

## Rotacionar um segredo

### Definir um novo valor
Execute o mesmo comando com o novo valor ou defina-o novamente na página Secrets
do projeto:

```bash
beeuni secrets set STRIPE_API_KEY=sk_live_new...
```

### Beeuni envia para as sessões em execução
O Beeuni envia a alteração para cada sandbox com uma sessão ativa do
projeto, conforme possível. Para credenciais de modelo ou gateway, o Beeuni
reinicia o processo de compatibilidade do harness padrão.

A rotação de um segredo com saída restrita não exige o envio do valor: o
sandbox mantém um identificador, e o Beeuni lê o valor atual quando a próxima
solicitação chega.

<a id="remove-a-secret"></a>

## Remover um segredo

Execute `beeuni secrets unset STRIPE_API_KEY` (ou `unset <identifier>`), ou
exclua-o na página Secrets do projeto.

> **A remoção é imediata, a propagação não**
>
> O Beeuni exclui um segredo compartilhado imediatamente. O envio para
> sandboxes que já estão em execução é feito conforme possível, assim como na
> rotação.

<a id="share-a-value-without-seeing-it"></a>

## Compartilhar um valor sem vê-lo

Execute `beeuni secrets request STRIPE_API_KEY` para criar um link. Qualquer pessoa com o
link pode inserir o valor. Você nunca o vê. Por padrão, os links permanecem
válidos por 7 dias; ajuste com `--expires <minutes>` (máximo de 30 dias). Um link expirado
exibe uma página clara de "expired" — crie um novo com o mesmo comando.

<a id="give-an-agent-a-value-directly"></a>

## Fornecer um valor diretamente a um agente

Se você colar uma chave em uma sessão, o agente a armazenará imediatamente com
`beeuni secrets set`. Ele não enviará um link. O
agente precisa da permissão de gravação de segredos do projeto. Sem ela, o agente recebe
`403` e cria um link de segredo em vez disso. Um agente pode armazenar um segredo de ambiente
ou um segredo de conector (`--scope connector`). A entrega restrita e as listas de hosts
continuam disponíveis apenas para pessoas.

<a id="end-to-end-example"></a>

## Exemplo completo

`beeuni.yaml`:

```yaml
beeuni_version: 2
default_agent: my-agent
agents:
  my-agent:
    secrets: [STRIPE_API_KEY]
```

Configuração de segredo. O primeiro comando armazena o valor com a exposição
padrão ao ambiente. O segundo o move para a exposição restrita à saída, que é
experimental e requer a flag `secrets_egress` (Settings → Feature flags); ele
retorna `403` `feature_disabled` enquanto a flag estiver desativada.

```bash
beeuni secrets set STRIPE_API_KEY=sk_live_...
beeuni secrets delivery STRIPE_API_KEY egress --allow-host api.stripe.com
```

O agente então chama o Stripe com a variável que recebeu:

```bash
curl -s -o /dev/null -w '%{http_code}\n' \
  -H "authorization: Bearer $STRIPE_API_KEY" \
  https://api.stripe.com/v1/customers
# expected: 200
```

`$STRIPE_API_KEY` contém um identificador. O Stripe recebe a chave real, porque
`api.stripe.com` está na lista. A mesma solicitação para um host que não está na
lista envia o identificador, e o upstream o rejeita.

A mesma solicitação de um agente cuja lista `secrets` omite `STRIPE_API_KEY`
retorna `401`. Essa sessão é iniciada normalmente — um segredo não concedido não é um
erro; ele simplesmente nunca é entregue.

<a id="cli-commands"></a>

## Comandos da CLI

| Comando | O que ele faz |
|---|---|
| `beeuni secrets ls` | Lista os segredos declarados e definidos para o projeto |
| `beeuni secrets set KEY=VALUE [--identifier <id>] [--scope runtime\|connector]` | Cria ou atualiza um segredo. `KEY=-` lê o valor de stdin. `--scope connector` o mantém no servidor |
| `beeuni secrets unset IDENTIFIER` | Remove um segredo |
| `beeuni secrets delivery IDENTIFIER egress --allow-host <host>` | Exposição restrita à saída para os hosts listados. Experimental; requer a flag `secrets_egress` |
| `beeuni secrets delivery IDENTIFIER runtime` | Exposição ao ambiente (o padrão) |
| `beeuni secrets delivery IDENTIFIER denied` | Desativado |
| `beeuni secrets call IDENTIFIER URL` | Envia uma solicitação HTTPS vinculada à política por meio do Beeuni. Experimental; requer a flag `secrets_egress` |
| `beeuni secrets sync` | Em uma sessão de agente: obtém os segredos desta sessão e concede agora. Como pessoa: reenvia para todos os sandboxes ativos do projeto |
| `beeuni secrets request NAME [--scope runtime\|connector] [--expires <min>]` | Cria um link para que outra pessoa possa inserir um valor |
| `beeuni env push --from <path>` | Envia um arquivo `.env` como segredos |
| `beeuni env pull [--out <path>] [--force]` | Exporta nomes de segredos, não valores, para um arquivo `.env` |

A CLI mantém o vocabulário armazenado: `runtime` é exposição ao ambiente,
`egress` é restrita à saída, `denied` é desativada. Execute
`beeuni secrets --help` para ver todas as flags.

Os links de configuração usam `connector` por padrão. Use `--scope runtime` apenas quando o shell do agente
precisar receber o valor. Um segredo vinculado a um conector permanece no servidor.

<a id="names-and-permissions"></a>

## Nomes e permissões

Regras de formato para os dois nomes:

| Nome | Formato |
|---|---|
| `identifier` | `^[A-Za-z0-9][A-Za-z0-9_.-]{0,127}$` |
| `name` | `^[A-Z_][A-Z0-9_]{0,63}$` |

A leitura ou gravação de um segredo requer a permissão `project.secret.read` ou
`project.secret.write`. Um gerente de projeto possui ambas. Uma função personalizada
apenas adiciona permissões — o Beeuni não tem uma regra de negação — portanto nenhuma função pode retirar
qualquer uma delas de um gerente. Para restringir um gerente, remova a função de gerente.

A entrega a uma sessão é o resultado da função da pessoa que a iniciou,
intersectado com a concessão do manifesto do agente iniciado. Ambos precisam permitir o
segredo. Consulte
[Um vocabulário, duas vinculações](/docs/pt/accounts#one-vocabulary-two-bindings).

<a id="rest-routes"></a>

## Rotas REST

Todas as rotas ficam sob `/v1/projects/{projectId}`.

| Método | Caminho | Descrição |
|---|---|---|
| GET | `/secrets` | Lista os segredos. Limitado à concessão do autor da chamada quando ele é um token de agente com escopo. |
| POST | `/secrets` | Cria ou atualiza o valor compartilhado. Corpo: `{name, identifier?, value}`, além de uma política de entrega opcional. |
| PUT | `/secrets/{identifier}/strategy` | Altera a exposição e sua lista de hosts. |
| POST | `/secrets/{identifier}/grant` | Adiciona o identificador à lista `secrets` de um agente em `beeuni.yaml`. Corpo: `{agent}`. |
| DELETE | `/secrets/{name}` | Exclui o valor compartilhado. As substituições pessoais permanecem. |
| PUT | `/secrets/{name}/personal` | Define ou ativa a substituição pessoal do autor da chamada. |
| DELETE | `/secrets/{name}/personal` | Remove a substituição pessoal do autor da chamada. |

`POST /secrets` rejeita nomes que começam com `BEEUNI_`. Ele retorna `409`
se o `identifier` já existir com um `name` diferente. Ele rejeita o
nome exato `CODEX_AUTH_JSON` com `400` — o Beeuni gerencia esse segredo
por meio da integração de assinatura do ChatGPT.

Ambas as rotas de gravação retornam um objeto `delivery_sync` quando a alteração precisou chegar aos
sandboxes em execução. `ok: false` significa que o valor foi salvo, mas pelo menos uma sessão ativa ainda usa o anterior; as sessões listadas o receberão ao reiniciar.

Um segredo na lista contém `delivery_blocked_reason`. O valor
`no_agent_grant` significa que nenhum agente pode receber esse segredo. `null` significa que ele foi
concedido, que a exposição não requer concessão ou que o Beeuni não conseguiu ler o manifesto.

`POST /secrets/{identifier}/grant` limpa esse motivo. Ele retorna
`already_granted: true` quando a lista do agente já admite o identificador; nesse
caso, o Beeuni não confirma nada. Ele retorna `adopted_governance: true` quando
a edição adicionou o primeiro bloco `agents:` do projeto — a alteração [descrita
acima](#grant-a-secret-to-an-agent). Ele responde `400` `manifest_v1_unsupported`
para um projeto `beeuni.toml` e `409` `secret_not_grantable` para um
segredo desativado.

<a id="rotation-and-propagation"></a>

## Rotação e propagação

A gravação de um segredo não espera a reinicialização de uma sessão. O Beeuni envia a
alteração para todos os sandboxes ativos do projeto:

1. O Beeuni cria um novo snapshot do ambiente, usando a concessão `secrets` do
   agente em execução.
2. O sandbox grava o snapshot no ambiente ativo do agente. Novas chamadas de ferramentas
   recebem a alteração imediatamente.
3. Se o segredo alterado for uma credencial de provedor de LLM, o Beeuni reinicia
o harness padrão.

Esse envio é feito conforme possível. A chamada da API que altera o segredo retorna
antes que o envio seja concluído. Um envio com falha é apenas registrado, não repetido. Um
sandbox cujo envio falhou mantém o valor anterior até o próximo envio bem-sucedido ou até
a sessão ser reiniciada.

<a id="model-credentials"></a>

## Credenciais de modelo

Um projeto no acesso gerenciado a modelos do Beeuni não precisa de uma chave própria. Para usar
sua própria chave, defina as variáveis do provedor referenciadas pela configuração do provedor do harness padrão.
Uma chave de modelo reconhecida recebe o uso **LLM gateway**, que a consome no servidor;
ela não precisa estar presente no sandbox.

Não use um resultado genérico de verificação do provedor como prova em tempo de execução. Ele não pode
comprovar o modelo, a região, a autorização e o dialeto da API selecionados. Envie um prompt real
por meio do modelo exato.
