docs: NIP-CW and bridge-channel-window never show the POST /query request body, so the documented shape returns 400

Open Beginner friendly
#6,477 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
88/100
Issue type
Documentation
Clarity
Clearly specified
Activity status
Active
Tech stack
rust
Domain
documentation

Research direction

Start with the §Request sections in docs/nips/NIP-CW.md and docs/bridge-channel-window.md, then read the POST /query parsing in crates/buzz-relay/src/api/bridge.rs. Document that the request body is a JSON array and include a complete window-filter example in both files. Done means a reader can copy a valid body without receiving the reported 400 error.

Written by the indexing model from the issue text.

Description

Summary

Neither docs/nips/NIP-CW.md nor docs/bridge-channel-window.md shows a complete POST /query request body. Both present the window request as a bare filter object, which is what a reader implementing from the docs will send, and the relay rejects it with a 400. The body must be a JSON array of filters.

Reproduce

Send the request body exactly as the docs show it, with a valid NIP-98 header from a relay member:

POST /query
Content-Type: application/json
Authorization: Nostr <base64 kind:27235>

{"kinds":[9],"limit":1}

Response:

400 Bad Request
{"error":"invalid filters: invalid type: map, expected a sequence at line 1 column 0"}

A {"filters": [...]} wrapper is rejected identically. The array form works:

[{"kinds":[9],"limit":1}]
200 OK
[ ...signed events... ]

Why the docs read this way

docs/nips/NIP-CW.md §Request:

A window request is a standard filter plus extension fields, submitted wherever the relay accepts filters (for Buzz: the NIP-98-authenticated HTTP bridge POST /query):

followed by a fenced block containing a single object.

docs/bridge-channel-window.md §Request:

A standard bridge filter plus extension fields:

followed by the same single-object shape.

Both sentences are strictly true, because they describe the filter, not the request body. But neither document states that POST /query accepts an array, and no example anywhere in either file shows a complete body. /query is referenced three times across the two files and never once with a body a reader could copy.

The implementation is unambiguous

crates/buzz-relay/src/api/bridge.rs:

// Two-pass parse: preserve raw JSON for custom extension fields (before_id,
// depth_limit, feed_types) that nostr::Filter silently drops.
let raw_filters: Vec<Value> = serde_json::from_slice(body)
    .map_err(|e| api_error(StatusCode::BAD_REQUEST, &format!("invalid filters: {e}")))?;

The array is correct and consistent with NIP-01, where REQ carries one or more filters. The gap is only that the docs never say so.

Suggested fix

One line in each §Request, plus one complete example. For example in docs/nips/NIP-CW.md:

The request body is a JSON array of filters, as on any NIP-01 filter surface. A window request is one such filter:

[
  {
    "kinds": [9],
    "#h": ["<channel-id>"],
    "top_level": true,
    "limit": 50
  }
]

Minor, same area

The error text invalid filters: invalid type: map, expected a sequence at line 1 column 0 describes the serde failure rather than the contract. Something like expected a JSON array of filters would point a reader at the fix directly. Not important if the docs carry a full example.

Context

Found while implementing a browser client against the channel-window surface. The endpoint itself behaves exactly as specified once the body shape is right; top_level, the composite until + before_id cursor, and the 39006 bounds overlay are not in question here. This is a documentation issue only.

Dominant language
Rust
Stars
33.7k
Forks
4.4k
Avg merge
1d 21h
Merged PRs (30d)
239

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from block/buzz

All issues in block/buzz

Similar issues

More Rust issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.