Skip to content

Bug: buzz repos create omits the buzz-channel tag that the git read gate requires — every CLI-created repo 404s forever #3539

Description

@ashishd10x

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

buzz repos create --id my-repo --name "My Repo" \
  --clone "https://<relay>/git/<owner-hex>/my-repo"

# Announcement is accepted and renders as a Project in Desktop.
git clone https://<relay>/git/<owner-hex>/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:

    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 <UUID> 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions