# bee-check report format (spec v1)

This document defines the JSON shape that `bee-check --output json`
emits and that `bee-check-web` will consume. Implementations in other
languages should match this exactly so reports are portable.

## Top-level

```jsonc
{
  "reference":   "c79394...bdc36a",  // 64- or 128-hex Swarm reference
  "status":      "retrievable",      // see Status below
  "vantages":    [ /* VantageResult, see below */ ],

  // Added in bee-check 0.3.0 — additive, no spec_version bump.
  // Both empty/absent when not used.
  "gateways":    [ /* GatewayResult, see below */ ],
  "resolution":  { /* Resolution,   see below */ },

  "chunks":      [ /* ChunkProbe,   see below */ ],  // omitted when --per-chunk not used

  // Added in bee-check 0.5.0 — additive, no spec_version bump.
  "cold_downloads": [ /* ColdDownloadResult, see below */ ],  // omitted when --cold not used

  "spec_version": 1
}
```

### Status

```jsonc
"retrievable"    // every vantage returned IsRetrievable=true
"unretrievable"  // every vantage either returned IsRetrievable=false or errored
"partial"        // mixed: some retrievable, some not
"error"          // every vantage produced an error (no retrievability answer at all)
```

Exit code is `0` when at least one vantage returned `retrievable=true`,
`2` otherwise.

## VantageResult

One per `--bee` URL, ordered by URL (lex).

```jsonc
{
  "bee_url":           "http://localhost:1633",
  "retrievable":       true,    // or false, or null when the call errored
  "elapsed_ms":        3004,
  "error":             null,    // omitted when null; non-null string when the call failed

  // Added in bee-check 0.2.0 — additive, no spec_version bump.
  // All three optional; absent if the corresponding GET /addresses
  // or GET /health call failed for the vantage.
  "overlay":           "7179856eb3c28642983d0e1b7f264693e407a2738593dec9fd59f2ee29046c9a",
  "bee_version":       "2.7.2-rc1-868c1d52",
  "proximity_to_root": 3
}
```

A vantage with `retrievable: null` AND `error: "..."` indicates the
`/stewardship/{ref}` call itself failed (network, 404, timeout, etc.).
A vantage with `retrievable: false` and no `error` means Bee said the
reference is not retrievable from that node's view.

`overlay` is the probed Bee's overlay address from `GET /addresses`.
The first 2 hex chars identify the node's neighborhood.
`bee_version` is the `version` field from `GET /health`.
`proximity_to_root` is the proximity order between the probe node's
overlay and the reference being checked — higher means the probe is
closer to where the chunk is stored; `0` means the probe is not in
the chunk's neighborhood at all.

## ChunkProbe

Emitted only when `--per-chunk` is used. One per chunk reachable from
the root manifest, up to `MAX_CHUNKS` (1000 in v1).

```jsonc
{
  "address":      "1a2b3c...ef",
  "neighborhood": "1a",    // first 2 hex chars (PO 0-7 → first byte)
  "per_vantage": {
    "http://localhost:1633": {
      "found":      true,
      "elapsed_ms": 412,
      "error":      null,
      // Added in bee-check 0.2.0 — optional.
      "proximity":  4
    },
    "https://b.example": {
      "found":      false,
      "elapsed_ms": 5012,
      "error":      "404: chunk not found",
      "proximity":  0
    }
  }
}
```

`proximity` (when present) is the proximity order between that
vantage's overlay and **this specific chunk's** address. Higher is
better; this is the per-chunk analog of `proximity_to_root` on the
vantage. Lets you see "this chunk's neighborhood is 0x1a; my probes
were at PO 0 and PO 3 from it" — i.e. neither probe is in the chunk's
neighborhood, which explains a miss without needing to inspect the
network.

The chunk list is **post-order BFS from the root**, deduplicated, and
capped. If the root chunk isn't a parseable manifest, the chunk list is
just `[<root>]`.

## GatewayResult

Added in bee-check 0.3.0. One per `--gateway` URL, ordered by URL.

```jsonc
{
  "url":         "https://api.gateway.ethswarm.org",
  "retrievable": true,    // 2xx HTTP status → true; 4xx/5xx → false; network err → null
  "elapsed_ms":  412,
  "status_code": 200,     // omitted when the call errored at network layer
  "error":       null     // non-null when status_code is omitted
}
```

Gateway probes call `HEAD {url}/bzz/{reference}/` and interpret the
HTTP status as a coarse retrievability signal: a public gateway only
returns 2xx if it could resolve and forward the content through the
network. Aggregates into the same top-level `status` as vantages —
"retrievable through any vantage or any gateway" is enough to call
the reference retrievable.

## Resolution

Added in bee-check 0.3.0. Present when the user supplied a mutable
input (a Swarm feed reference) and bee-check resolved it before
probing. Currently one variant:

```jsonc
{
  "kind":               "feed",
  "owner":              "1234...abcd",   // 40-hex Ethereum address
  "topic":              "5678...beef",   // 64-hex feed topic
  "resolved_reference": "c79394...bdc36a"
}
```

The CLI accepts `feed:OWNER:TOPIC` (or `feed:OWNER/TOPIC`) as a
positional input and resolves via `GET /feeds/{owner}/{topic}` on
the first `--bee` URL. The top-level `reference` field is then the
**resolved** chunk reference; the original input is recoverable
from `resolution`.

## ChunkStats (0.4.0+)

Populated alongside `chunks` (i.e. when `--per-chunk` was used).
Pure post-processing — no extra network calls.

```jsonc
"chunk_stats": {
  "per_vantage": {
    "http://localhost:1633": {
      "total":          42,
      "found":          40,
      "missing":         2,
      "elapsed_p50_ms": 120,
      "elapsed_p95_ms": 540,
      "elapsed_max_ms": 800
    }
  },
  "per_neighborhood": {
    "1a": {
      "total":          10, "found": 10, "missing": 0,
      "elapsed_p50_ms": 200, "elapsed_p95_ms": 1100,
      "elapsed_max_ms": 1400
    }
  }
}
```

Latencies are computed over `found == true` chunks only. `elapsed_*`
fields are absent when no chunk in that bucket was found.

The per-neighborhood roll-up keys on the first 2 hex chars of the
chunk address (PO 0-7 = first byte). Reveals patterns like "every
chunk in neighborhood 0x4a is slow regardless of which vantage" —
useful for distinguishing storer-node problems from probe-side ones.

## ColdDownloadResult (0.5.0+)

Emitted only when `--cold` is used. One entry per Bee URL (probed
via `GET /bytes/{ref}`) and one per gateway URL (probed via
`GET /bzz/{ref}/`). The body is streamed to EOF and discarded;
`bytes_downloaded` is the total received, `elapsed_ms` is wall-clock
for the entire transfer.

```jsonc
{
  "url":              "http://localhost:1633",
  "endpoint":         "/bytes/{ref}",   // or "/bzz/{ref}/" for gateways
  "success":          true,
  "bytes_downloaded": 4096,
  "elapsed_ms":       312,
  "status_code":      200,              // omitted on transport error
  "error":            null              // present on 4xx/5xx or stream error
}
```

Cold-download is informational and does NOT contribute to the
top-level `status` aggregate (which remains vantages + gateways).
It exists to expose end-to-end transport behavior — for instance,
a vantage that walks the chunk graph fine via stewardship but
serves bytes slowly, or a gateway that 200s a HEAD but errors mid-
stream on a full GET.

## VantageResult.target_proximity (0.4.0+)

When the CLI was invoked with `--target-overlay HEX`, each vantage
also reports its proximity order to that target overlay, and the
`vantages` array is sorted closest-first. Useful for "from a node
near neighborhood X, is this retrievable?" questions.

## Compatibility

- `spec_version` lets consumers refuse reports they don't understand.
- New fields may be added in a minor revision; consumers MUST ignore
  fields they don't recognize.
- Renames or removals bump `spec_version`.

## Implementation notes for other consumers

- **bee-check-web** consumes this shape. It also accepts user-uploaded
  JSON files in this format, so users can share a report by attaching
  the file rather than re-running the probe.
- **CLI piping**: `bee-check ... --output json | jq '.status'` is the
  canonical scripting pattern. Don't add CLI flags whose effect can't
  be inferred from the JSON.
