fix(cli): require --channel on repos create for buzz-channel tag - #3594
Open
Chessing234 wants to merge 2 commits into
Open
fix(cli): require --channel on repos create for buzz-channel tag#3594Chessing234 wants to merge 2 commits into
Chessing234 wants to merge 2 commits into
Conversation
Without a buzz-channel binding the relay git read gate returns an opaque 404 for every clone/fetch/push. Make the channel UUID required and emit the tag from build_repo_announcement. Signed-off-by: Taksh <takshkothari09@gmail.com> Co-authored-by: Cursor <cursoragent@cursor.com>
Signed-off-by: Taksh <takshkothari09@gmail.com> Co-authored-by: Cursor <cursoragent@cursor.com>
tlongwell-block
approved these changes
Jul 29, 2026
tlongwell-block
left a comment
Collaborator
There was a problem hiding this comment.
Reviewed as part of the #3527 investigation (root cause is the same bug — see the linked discussion; #3539 and #3527 should be cross-linked and one closed as a duplicate).
Verified locally at head 6bbe384:
build_repo_announcementhas exactly one production caller (cmd_create_repo), so the signature change is contained — checked withrgacrosscrates/.cargo test -p buzz-sdk --lib: 241 passed.cargo test -p buzz-cli: green.- The SDK parameter staying
Option<&str>while the CLI flag is required matches the design consensus from the team thread.
Two non-blocking notes:
validate_uuidis parse-only — a well-formed UUID for a nonexistent channel (or one the announcer is not a member of) still produces an unreadable repo. Acceptable for this PR; a follow-up adds owner remediation messaging at the read gate and, later, ingest-time binding validation (tracked in the #3527 workstream).- The two unchecked live-test boxes in the test plan will be covered by our live regression matrix against a local Docker stack before this merges, alongside the follow-up PR.
The follow-up PR (buzz repos bind for existing unbound repos + read-gate remediation) composes with this change and does not touch these files. LGTM.
tlongwell-block
added a commit
that referenced
this pull request
Jul 30, 2026
…pos (#3626) Closes #3527. Repos announced via vanilla NIP-34 (kind:30617 without a `buzz-channel` tag) 404 forever: the SEC-005 read gate requires a channel-membership ACL, and nothing tells the author why or how to fix it. Per the ruling in the originating thread, this ships **bind/rebind tooling plus a narrow author-only remediation carve-out** — the shelved owner-circle approach is intentionally absent. ## Relay - **`api/git/binding.rs` (new):** shared tri-state binding resolver — `Bound(uuid)` / `NotBound` / `Broken`. First-tag, fail-closed: a malformed `buzz-channel` tag is `Broken`, never conflated with "no tag". Both gates use it. - **Read gate (`transport.rs`):** a **never-bound** repo read by **its own announcement author** still returns 404 (status byte-identical to the generic denial) but the body carries remediation: `run: buzz repos bind --id <repo> --channel <channel-uuid> — …`. This leaks nothing — the author announced the repo, and only the author can rebind (30617 is keyed by `(author, d)`). `Broken` bindings stay generic-denial for everyone, including the author (revocation shape). Bound-to-nonexistent-channel stays generic (phase 1; ingest validation is phase 2). - **Push gate (`policy.rs`):** unbound denial now returns `GIT_NO_CHANNEL_BINDING_BODY`. A deploy-skew test pins that the body carries both the new token (`no_channel_binding`) and the legacy phrase (`"no channel binding"`) so already-shipped desktops keep matching. **(Review r1, blocker 2)** `Broken` no longer collapses into "unbound": it denies 403 `invalid channel binding` for *everyone — including the announcement owner —* **before** the owner short-circuit, matching the read gate's fail-closed posture. The remediation token stays NotBound-only. - **`ingest.rs`:** side-effect failure `warn!` → `error!` — prod runs `RUST_LOG=error`, so these failures were invisible during triage. ## Contract - **`buzz-core/git_perms.rs`:** `GIT_NO_CHANNEL_BINDING_TOKEN` / `GIT_NO_CHANNEL_BINDING_BODY` consts as the declared cross-component contract; relay tests and desktop matcher both build on them. ## CLI - **`buzz repos bind --id <repo> --channel <uuid>`** — rebinds an existing announcement, preserving other tags. - **(Review r1, blocker 1)** **`--channel` on `buzz repos create`** — optional; injects exactly one shape-validated `buzz-channel` tag at creation via a pure `build_create_announcement` builder, so the primary create command stops producing repos the relay 404s. UUID existence/membership stays the relay's authority at git-access time (same TOCTOU posture as `repos bind`). Overlaps with #3594 (open, head 6bbe384) — happy to reconcile whichever lands first; this branch also carries the bind path and tag preservation. ## Desktop - **Rust:** new `commands/project_git_merge_error.rs` (extracted from `project_git_workflow.rs` to respect the 1000-line ratchet); maps the token to a structured `no_channel_binding` error carrying the bind command. - **TS:** new `features/projects/lib/projectBranchErrors.ts` + tests — dual matcher (new token AND legacy spaced phrase); `ProjectBranchDialogs.tsx` uses it. ## Tests / verification (at head f914c70, base 581baa6) - Workspace `cargo test` green; `clippy -D warnings` clean; desktop Rust 1859 pass; TS 3780 pass; tsc/biome/file-size checks pass. Pre-push hooks re-ran all suites at the pushed head. - Postgres-gated `sec005_read_gate_tests`: all 6 pass, including `read_gate_gives_author_of_unbound_repo_remediation_body` — asserts 404 status, `text/plain` content-type, and exact body bytes, distinguishing remediation from generic denial (a blind `is_err()` can't). - **New (review r1):** `buzz-cli` emitted-event tests — `create_with_channel_emits_exactly_one_binding_tag`, `create_without_channel_emits_no_binding_tag`, `create_rejects_malformed_channel_uuid` (266/266 pass). Postgres-gated `push_gate_denies_owner_through_broken_binding` — owner + malformed-first/valid-second binding → 403 generic body without the remediation token; never-bound control stays 200, pinning the denial to `Broken` specifically. - e2e git tests now bind announcements to a real channel via a `create_test_channel` helper. --------- Signed-off-by: Tyler Longwell <tlongwell@block.xyz> Co-authored-by: npub1qyvc0c5kl4gqv2fd97fsk46tu378sqgy35vc83rvgfwne90sel7s0ed67d <011987e296fd5006292d2f930b574be47c7801048d1983c46c425d3c95f0cffd@buzz.block.builderlab.xyz> Co-authored-by: Tyler Longwell <tlongwell@block.xyz>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
--channel <UUID>onbuzz repos createand emit abuzz-channeltag on the kind:30617 announcementbuzz repos createomits thebuzz-channeltag that the git read gate requires — every CLI-created repo 404s forever #3539)build_repo_announcementand update the nest skill exampleTest plan
cargo test -p buzz-sdk --lib builders::tests::repo_announcementbuzz repos create --id demo --channel <uuid> --clone https://<relay>/git/<pubkey>/demothengit ls-remotesucceeds--channelfails clap validationFixes #3539
Made with Cursor