# Changelog
## 0.2.9
### Changed
- `split_headers` now calls `binary:split(Headers, Rn, [global])`
instead of the hand-rolled recursive `binary_split_global/2`.
The native BIF skips the function-call-per-token overhead and
is generally faster on the hot path (header split fires once
per response). The hand-rolled helper is gone.
### Plan-time notes
- B6's "chunked decoding accumulates iolist instead of flattening
per chunk" recommendation was checked on inspection and not
acted on: `parse_chunks/3` already accumulates chunk bodies in
a list (`[Body | Acc]`) and calls `iolist_to_binary` exactly
once at the end. The plan's claim of "iolist_to_binary per
chunk" was incorrect.
## 0.2.8
### Added
- `error_reason/0` is now a documented sum type, exported alongside
`error/0`. It enumerates the eight atoms that buoy can put in the
second slot of `{error, _}`:
- `pool_not_started`, `buoy_not_started`, `pool_already_started`,
`invalid_url` (buoy-level)
- `invalid_headers`, `invalid_chunk_size` (HTTP parser errors)
- `no_server`, `shackle_not_started`, `timeout` (shackle errors
that propagate through buoy)
`error/0` itself stays loose (`{error, term()}`) — tightening it
to a closed sum produces dialyzer false positives in
`buoy_client:responses/5`, where the `{error, not_enough_data}`
buffering pattern is semantically required at runtime but
unreachable from dialyzer's flow analysis. The documented
`error_reason/0` covers the documentation half of the A2
standardization without the analyzer cost.
### Exported types
- `error/0`
- `error_reason/0`
## 0.2.7
### Added
- Two telemetry events at the request boundary:
| Event | Measurements | Metadata |
|---|---|---|
| `[buoy, request, sent]` | `count => 1` | `method, host, async` |
| `[buoy, request, error]` | `count => 1` | `method, host, reason` |
`sent` fires when the request hits shackle for dispatch (sync and
async paths both); `error` fires when the pool lookup fails (e.g.
`pool_not_started`). Attach handlers via `telemetry:attach/4`.
Per-request lifecycle (queue / send / receive) remains observable
via shackle's own telemetry — buoy's events surface the buoy-level
routing decision without duplicating that work.
- `telemetry` (1.4.2) is now a direct dependency (was already
transitively present via shackle).
- `vsn` in `buoy.app.src` is now an explicit string (`"0.2.7"`) — was
`git`, which only works when built from a checkout.
No source or API changes.
## 0.2.6
Infrastructure refresh: dep bumps + docs migration.
### Changed
- Bumped `shackle` from git ref `0.6.19` to hex `0.7.1` -- fixes the
OTP 27+ build break that buoy inherited transitively (old shackle
versions pulled `granderl 0.1.5` from hex, broken on modern OTP).
- Bumped `foil` from git ref `0.1.2` to hex `0.1.4`.
- CI matrix bumped from OTP 21-26 to OTP 25-28.
- `cowboy` test dep bumped from git ref `2.10.0` to hex `2.12.0`.
(Newer cowboy releases use a cowlib version constraint that the
rebar3 bundled in the OTP 25 container image can't parse;
pinning to 2.12.0 keeps the OTP 25 test row green.)
- `fprofx` test dep moved from `ransomr/fprofx` to `lpgauth/fprofx`
(`otp_19` branch), matching the rest of the ecosystem.
- Documentation migrated from `edown` to `rebar3_ex_doc`. Generated
`doc/` directory removed.
No source or API changes.