A Bruno collection is a working client's state, and some of it is not
documentation. duxt refuses to publish four things, and the refusal is not a
default a site can turn off.

## Environments

`environments/*.bru` is where a collection keeps its hosts, tokens and keys. The
files are **counted and never opened** — the overview says how many there are,
so a reader knows the collection expects one, and no code path exists down which
a value in one could reach a page. They are left out of the archive for the same
reason.

## Credentials in an auth block

`auth:bearer { token: … }` is a live secret as often as a placeholder. The
**mode** survives, because a reader has to know the endpoint wants a bearer
token; the value never does.

## Credentials written as a header, a parameter or in the URL

Values under `Authorization`, `Cookie`, `X-API-Key`, `api_key`, `access_token`,
`token`, `secret`, `signature`, `password` and their neighbours are withheld by
**name**, never by looking for something token-shaped — `sk-live-…`, a bare JWT
and a base64 pair have no form in common, so a heuristic that caught two of them
would publish the third.

The name is read **normalised**, so `api_key`, `api-key`, `API-Key` and `apikey`
are one name: adding a separator is the cheapest way past a list of names, and
it is not a way past this one.

The line still appears, marked as withheld: an endpoint that wants an
`Authorization` header is exactly what a reference has to say, and dropping the
line would describe a request the collection does not make.

### The URL is held to the same rule

Bruno writes a query parameter into **both** the `url` line and `params:query`,
so a value withheld in the parameter table would be published one line above it
if the URL were left alone. It is not:

- a **query parameter** whose name the rule withholds keeps its name and loses
  its value — `?api_key=sk-live-…` is published as `?api_key=`;
- **userinfo** — the `user:password@` in `https://svc:hunter2@api.example.com` —
  is removed outright. It has no parameter counterpart at all, so the URL is the
  only place it is ever written and the only place it can be taken out.

A URL something was taken out of carries the same **withheld** badge the table
gives a value, so a blank parameter does not read as one the collection forgot
to fill in.

### What counts as a placeholder

A value that is **nothing but `{{placeholders}}`** is kept. It names a secret
rather than carrying one, and hiding it would take away the variable name the
reader needs.

"Nothing but" is meant literally, and the only literal allowed beside a
placeholder is an **auth scheme word** — `Bearer`, `Basic`, `Digest`, `Token`,
`JWT`, `HMAC` — which is a scheme rather than a credential. So
`Authorization: Bearer {{token}}` is published and
`Authorization: Bearer sk-live-abc123 {{sig}}` is withheld: a literal next to a
placeholder is exactly where half a credential gets written.

> [!IMPORTANT]
> A withheld value is withheld everywhere, the try-it client included. A
> redacted entry carries no example at all, so its box opens empty and the
> reader supplies their own credential — prefilling it would put the collection
> author's live token into every reader's form.

## Scripts and tests

`script:pre-request`, `script:post-response`, `tests` and `assert` are code
written against Bruno's own runtime. A request page reports that they **exist**
and never shows them, and nothing on the site runs them. The download is where
they live.

> [!TIP]
> "It has a script" is worth saying out loud: a collection whose pre-request
> script signs a token behaves differently from what the page prints, and a
> reader who does not know that will wonder why their copy of the request fails.