Bug: `buzz repos create` omits the `buzz-channel` tag that the git read gate requires — every CLI-created repo 404s forever
- Dominant language
- Rust
- Stars
- 32.7k
- Forks
- 4.3k
- Avg merge
- 1d 13h
- Merged PRs (30d)
- 253
Description
**Component:** `buzz` CLI (`repos create`) + relay git read gate
**Severity:** High — the CLI cannot produce a working repository; the failure is silent and misdiagnoses as "repo doesn't exist"
**Relay source referenced:** commit `3a4bf51`
## Summary
`buzz repos create` announces a NIP-34 repository (kind:30617) but provides **no way to set the `buzz-channel` tag**. The relay's git read gate (`authorize_git_read`) **requires** that tag to resolve the repo's bound channel, and denies any request whose announcement lacks it. The denial is `HTTP 404 "repository not found"` — byte-identical to a repository that was never announced. Result: **every repository created through the CLI is unreachable over git, permanently, with an error that points away from the cause.**
## Steps to reproduce
```bash
buzz repos create --id my-repo --name "My Repo" \
--clone "https:///git//my-repo"
# Announcement is accepted and renders as a Project in Desktop.
git clone https:///git//my-repo
# remote: repository not found
# fatal: repository '.../my-repo' not found
```
`ls-remote`, `clone`, `fetch`, and `push` all return `404 repository not found`, whether or not the caller is a member of any channel — because the announcement carries no channel binding for the gate to check against.
## Root cause
1. **CLI:** `repos create` exposes `--id --name --description --clone --web --nostr-relay` and **no `--channel`**. The signed kind:30617 therefore never contains a `buzz-channel` tag. (`buzz.exe` contains zero occurrences of the string `buzz-channel`.)
2. **Relay read gate** (`crates/buzz-relay/src/handlers/transport.rs`, ~line 381): resolving the bound channel is mandatory, and its absence is denied with the same response as a missing repo:
```rust
fn denied() -> Response {
(StatusCode::NOT_FOUND, "repository not found").into_response()
}
// ...
let Some(channel_id) = repo_bound_channel_id(&repo_event.event) else {
warn!(repo = %repo_name, "git read gate: missing/malformed buzz-channel binding (deny)");
return Err(denied());
};
```
Three distinct conditions collapse into one indistinguishable 404 — (a) no announcement, (b) announcement present but no `buzz-channel` binding, (c) caller has no role in the bound channel — which is good for not leaking repo existence, but means the CLI's omission is undiagnosable from the client side.
## Fix
Add a required (or strongly-encouraged) `--channel ` flag to `buzz repos create` that emits a `buzz-channel` tag on the kind:30617. Given that an unbound repo can never be served, consider making it **required** and rejecting creation without it, rather than announcing a dead repo.
Secondary, optional: have the read gate distinguish "announced but unbound" from "not found" in a way that doesn't leak existence to unauthorized callers — e.g. a distinct log/metric, or a 409 to the *owner* only. Not required for the fix; the flag is the fix.
## Workaround (in use on this nest)
Publish the announcement with a small signer that adds the `buzz-channel` tag and completes the NIP-42 AUTH challenge (`tools/announce-repo.mjs` in the `buzz-nest-activation` repo). Verified end-to-end: with the tag added and nothing else changed, `ls-remote` goes 404 → 200 and `push`/`clone` succeed.
## Note on a related dead end
Reports of this symptom are easy to misattribute to "the relay has no git storage for this community" — because probing three repos under three keys all return 404. That inference is wrong: the gate checks the **caller's** role in each repo's bound channel, so a non-member gets 404 for a perfectly healthy repo. Git hosting over HTTPS with NIP-98 auth works on this deployment (proven by push + fresh clone once the binding is present). No relay-admin provisioning is involved.
Contributor guide
Assessment
This issue has not been assessed yet.