docs: NIP-CW and bridge-channel-window never show the POST /query request body, so the documented shape returns 400
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
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from block/buzz
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 86/100
-
workflow_sink's mention parser never masks code regions — @name inside a code span wakes the agent Open
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
-
Difficulty 2/5 Half a day Newbie friendliness 88/100
-
Difficulty 1/5 Under an hour Newbie friendliness 92/100
Similar issues
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
gitbutlerapp/gitbutler#15998 · 1 comment ·
-
bug triage:deciding
Difficulty 1/5 Under an hour Newbie friendliness 88/100
open-telemetry/otel-arrow#4132 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
bitcoindevkit/bdk-ffi#1125 ·