feat(relay): gate kind 30178 team-catalog reads behind the shared tag - #3358
Merged
Conversation
wpfleger96
force-pushed
the
duncan/relay-team-catalog-shared-gate
branch
from
July 28, 2026 19:24
88ea0ca to
5307fed
Compare
wpfleger96
marked this pull request as draft
July 28, 2026 19:27
wpfleger96
force-pushed
the
duncan/relay-team-catalog-shared-gate
branch
from
July 28, 2026 19:52
5307fed to
d724013
Compare
Team catalog projections carry every member's system prompt, so they need
the same read gate personas already have: only the author sees an unshared
event. The gate was hardcoded to kind 30175 in six read surfaces plus the
SQL pushdown, so instead of adding a second special case it becomes
kind-generic over SHARED_GATED_KINDS = {30175, 30178}.
Team ids embed a colon (builtin-team:welcome), which the persona slug
grammar rejects, so 30178 gets its own d-tag rule: exactly one non-empty
tag, <=64 chars, no control chars or whitespace. Without the exactly-one
and non-empty checks every team collapses onto (pubkey, 30178, "") and
silently overwrites its predecessor.
Kind 30176 is deliberately left out of the gate: its reads need an
authenticated principal set rather than a boolean tag, tracked separately.
Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
wpfleger96
force-pushed
the
duncan/relay-team-catalog-shared-gate
branch
from
July 28, 2026 20:32
d724013 to
da06aa4
Compare
wpfleger96
marked this pull request as ready for review
July 28, 2026 21:17
tlongwell-block
approved these changes
Jul 30, 2026
tellaho
pushed a commit
that referenced
this pull request
Jul 30, 2026
* origin/main: fix(desktop): allow linux-only media items as dead code off-linux (#3811) fix(desktop): report authenticated relay recovery (#3812) fix(desktop): don't gate hover affordances on the hover media query (#3657) feat(relay): gate kind 30178 team-catalog reads behind the shared tag (#3358) test(desktop): click visible thread collapse guide (#3800) feat(desktop): raise the install ceiling and make installs observable (#3368) fix(db): isolate usage metrics advisory-lock test on scratch DB (#3670) Add Devin as a preset ACP harness (#3225) feat(desktop): improve agent activity header ui (#3321) perf(presence): reduce heartbeat frequency (#3783) Tighten continuation message rows (#3724) Fix video reviews in thread replies (#3719) feat(release): make desktop releases immutable (#3568) Make relay reconnect backoff authoritative (#3774) feat(desktop): add password-protected backups in settings (#3701) fix(desktop): reuse profiles when joining communities (#2155) Signed-off-by: npub1223z34hd7vtwc6qj4s7flsxkj644nlre2nthu7lrrmkumhu3xddsrx9r6w <52a228d6edf316ec6812ac3c9fc0d696ab59fc7954d77e7be31eedcddf91335b@buzz.block.builderlab.xyz>
brow
pushed a commit
that referenced
this pull request
Jul 31, 2026
* origin/main: (70 commits) fix(catalog): update Amp tagline (#3806) fix(desktop): channel topic and membership metadata cleanup (#3642) fix(desktop): align data deletion labels (#2230) fix(relay): align NIP-11 max_limit with REQ ceiling (#3635) fix(desktop): allow linux-only media items as dead code off-linux (#3811) fix(desktop): report authenticated relay recovery (#3812) fix(desktop): don't gate hover affordances on the hover media query (#3657) feat(relay): gate kind 30178 team-catalog reads behind the shared tag (#3358) test(desktop): click visible thread collapse guide (#3800) feat(desktop): raise the install ceiling and make installs observable (#3368) fix(db): isolate usage metrics advisory-lock test on scratch DB (#3670) Add Devin as a preset ACP harness (#3225) feat(desktop): improve agent activity header ui (#3321) perf(presence): reduce heartbeat frequency (#3783) Tighten continuation message rows (#3724) Fix video reviews in thread replies (#3719) feat(release): make desktop releases immutable (#3568) Make relay reconnect backoff authoritative (#3774) feat(desktop): add password-protected backups in settings (#3701) fix(desktop): reuse profiles when joining communities (#2155) ... Signed-off-by: npub15w828kxsxu2684ynste0uah2jwkgatd99flt7ds4523hzm8ju6cshdr8hh <a38ea3d8d03715a3d49382f2fe76ea93ac8eada52a7ebf3615a2a3716cf2e6b1@buzz.block.builderlab.xyz>
adrienlacombe
added a commit
to adrienlacombe/buzz
that referenced
this pull request
Jul 31, 2026
Three findings from the first live sync, which merged nothing and reported success on both stages while the fork sat 17 commits behind. **The handoff had no receiver.** `Sync this fork with upstream` was `disabled_manually`. The 01:30 stage hit conflicts, aborted, and handed off exactly as designed — to a disabled workflow. No PR, no issue, no red badge, because a conflicted handoff *is* success for the first stage. Re-enabled, and recorded in the repo-settings table with the one command that reveals it, since `gh workflow list --all` is the only place that state shows. **The two stages ran out of order.** GitHub delays scheduled runs under load: the 01:30 job started at 02:17, after the 02:00 slot the agentic stage held, so the deterministic stage was no longer first. Moved the agentic stage to 05:00 — a 30-minute gap is not a guarantee, 3.5 hours is a margin. **Kind 30178 collided.** Upstream shipped `KIND_TEAM_CATALOG = 30178` (block#3358) against this fork's `KIND_STARKNET_WALLET_BINDING = 30178`: two unrelated schemas on one integer, so `ingest_event_inner` would run both the on-chain attestation verifier and `validate_team_catalog_envelope` on every such event and one would always reject the other's traffic. No text resolution fixes that. Settled rather than left to per-merge judgement: kinds 30900-30999 are reserved for this fork, upstream keeps the integer whenever it claims one first, and the fork's constant moves. Upstream's parameterized-replaceable kinds cluster at 30174-30178 and grow upward, so anything the fork puts near them gets claimed eventually — reserving a block away from that path is what stops this recurring. The rule is in AGENTS.md with the full move checklist, and the sync prompt now points at it and says not to escalate it as ambiguous. No merge in this commit. The 17-commit merge and the 30178 move are the sync workflow's job, dispatched next. Signed-off-by: adrienlacombe <6303520+adrienlacombe@users.noreply.github.com>
wpfleger96
pushed a commit
that referenced
this pull request
Jul 31, 2026
…chive * origin/main: (25 commits) feat(desktop): import local Pocket voices (#3259) fix(desktop): open profiles from avatars (#3751) refactor(voice): extract reusable Pocket primitives + Pocket voice settings (relands #2467 + #3208) (#3910) docs: add VISION_REMOTE_AGENTS.md (#3924) feat(desktop): auto-enable huddle transcription for agents (#3180) feat(agent): optional reply guard reminds a silent turn to publish (#3763) feat(desktop): upgrade Pocket TTS model (#3266) feat(desktop): delete a message by clearing its edit to empty (#3813) feat(relay): raise hosted community limit to five (#3829) feat(desktop): locally stored NIP-49 encrypted key backup (#2937) fix(catalog): update Amp tagline (#3806) fix(desktop): channel topic and membership metadata cleanup (#3642) fix(desktop): align data deletion labels (#2230) fix(relay): align NIP-11 max_limit with REQ ceiling (#3635) fix(desktop): allow linux-only media items as dead code off-linux (#3811) fix(desktop): report authenticated relay recovery (#3812) fix(desktop): don't gate hover affordances on the hover media query (#3657) feat(relay): gate kind 30178 team-catalog reads behind the shared tag (#3358) test(desktop): click visible thread collapse guide (#3800) feat(desktop): raise the install ceiling and make installs observable (#3368) ... Co-authored-by: Will Pfleger <pfleger.will@gmail.com> Signed-off-by: Will Pfleger <pfleger.will@gmail.com> # Conflicts: # desktop/src/testing/e2eBridge.ts # desktop/tests/helpers/bridge.ts
wpfleger96
pushed a commit
that referenced
this pull request
Jul 31, 2026
…chive * origin/main: (25 commits) feat(desktop): import local Pocket voices (#3259) fix(desktop): open profiles from avatars (#3751) refactor(voice): extract reusable Pocket primitives + Pocket voice settings (relands #2467 + #3208) (#3910) docs: add VISION_REMOTE_AGENTS.md (#3924) feat(desktop): auto-enable huddle transcription for agents (#3180) feat(agent): optional reply guard reminds a silent turn to publish (#3763) feat(desktop): upgrade Pocket TTS model (#3266) feat(desktop): delete a message by clearing its edit to empty (#3813) feat(relay): raise hosted community limit to five (#3829) feat(desktop): locally stored NIP-49 encrypted key backup (#2937) fix(catalog): update Amp tagline (#3806) fix(desktop): channel topic and membership metadata cleanup (#3642) fix(desktop): align data deletion labels (#2230) fix(relay): align NIP-11 max_limit with REQ ceiling (#3635) fix(desktop): allow linux-only media items as dead code off-linux (#3811) fix(desktop): report authenticated relay recovery (#3812) fix(desktop): don't gate hover affordances on the hover media query (#3657) feat(relay): gate kind 30178 team-catalog reads behind the shared tag (#3358) test(desktop): click visible thread collapse guide (#3800) feat(desktop): raise the install ceiling and make installs observable (#3368) ... Co-authored-by: Will Pfleger <pfleger.will@gmail.com> Signed-off-by: Will Pfleger <pfleger.will@gmail.com> # Conflicts: # desktop/src/testing/e2eBridge.ts # desktop/tests/helpers/bridge.ts
joahg
added a commit
to joahg/buzz-dev-mode
that referenced
this pull request
Jul 31, 2026
…-style * origin/main: (22 commits) feat(desktop): import local Pocket voices (block#3259) fix(desktop): open profiles from avatars (block#3751) refactor(voice): extract reusable Pocket primitives + Pocket voice settings (relands block#2467 + block#3208) (block#3910) docs: add VISION_REMOTE_AGENTS.md (block#3924) feat(desktop): auto-enable huddle transcription for agents (block#3180) feat(agent): optional reply guard reminds a silent turn to publish (block#3763) feat(desktop): upgrade Pocket TTS model (block#3266) feat(desktop): delete a message by clearing its edit to empty (block#3813) feat(relay): raise hosted community limit to five (block#3829) feat(desktop): locally stored NIP-49 encrypted key backup (block#2937) fix(catalog): update Amp tagline (block#3806) fix(desktop): channel topic and membership metadata cleanup (block#3642) fix(desktop): align data deletion labels (block#2230) fix(relay): align NIP-11 max_limit with REQ ceiling (block#3635) fix(desktop): allow linux-only media items as dead code off-linux (block#3811) fix(desktop): report authenticated relay recovery (block#3812) fix(desktop): don't gate hover affordances on the hover media query (block#3657) feat(relay): gate kind 30178 team-catalog reads behind the shared tag (block#3358) test(desktop): click visible thread collapse guide (block#3800) feat(desktop): raise the install ceiling and make installs observable (block#3368) ... Amp-Thread-ID: https://ampcode.com/threads/T-019fb8e1-6ece-72a7-8808-9b12e0f7e833 Co-authored-by: Amp <amp@ampcode.com> Signed-off-by: Joah Gerstenberg <joah@squareup.com> # Conflicts: # desktop/src-tauri/src/linux_media.rs # desktop/src/app/AppShell.tsx
This was referenced Jul 31, 2026
kbst9
added a commit
to kbst9/buzz
that referenced
this pull request
Jul 31, 2026
Upstream assigned kind 30178 to its new KIND_TEAM_CATALOG (block#3358), colliding with the fork's swarm definitions. Move swarms to 30978 -- outside upstream's sequential 3017x allocation block so the race cannot recur. Stored prod events need a matching kind UPDATE at deploy time. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: kbst9 <kevinbsteiner@gmail.com>
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.
Team catalog projections (
kind:30178) embed every member's system prompt, so they need the same read gate personas already have: only the author sees an unshared event. The gate was hardcoded tokind:30175at six read surfaces plus the SQL pushdown, so rather than adding a second special case it becomes kind-generic overSHARED_GATED_KINDS = {30175, 30178}.Kind 30178
New parameterized-replaceable kind, addressed by
(pubkey_o, 30178, team_id). It embeds sanitized member projections instead of referencingkind:30175heads — a foreign reader of a shared team could not otherwise hydrate members whose own persona events are unshared or, for built-ins, absent entirely.kind:30176's wire body is untouched, so device sync keeps its contract.Kind-generic shared gate
buzz_core::kindreplacesis_persona_shared_kind/is_unshared_persona_event/persona_event_is_sharedwithSHARED_GATED_KINDSand the kind-agnosticis_shared_gated_kind/is_unshared_gated_event/event_is_shared. Every read surface consults the set:idslookupcrates/buzz-relay/src/handlers/req.rscrates/buzz-relay/src/handlers/event.rscrates/buzz-relay/src/handlers/count.rs/query,/count,/searchcrates/buzz-relay/src/api/bridge.rsLIMITSQL pushdowncrates/buzz-db/src/event.rsThe SQL clause generalizes from
kind != 30175tokind NOT IN (...)bound fromSHARED_GATED_KINDS, still applied beforeORDER BY … LIMITso a page of newer private events cannot starve an older shared one off the candidate set.EventQuery::persona_readeris renamedshared_gated_readerandneeds_persona_filteringtoneeds_shared_gate_filteringto match.Because the
buzz-corerename has consumers outside the relay, the four desktop call sites ofpersona_event_is_sharedtravel with it:desktop/src-tauri/src/commands/personas/pending.rs,desktop/src-tauri/src/event_sync.rs, and two indesktop/src-tauri/src/managed_agents/persona_events.rs. Each call is unchanged apart from the name — the personasharedprojection behaves exactly as before.Ingest validation
validate_persona_envelopesplits into two reusable pieces —validate_shared_tag(exactly-two-element["shared","true"], at most one occurrence) andsingle_bounded_d_tag(exactly onedtag, non-empty,<=64chars, no ASCII control characters or whitespace).validate_team_catalog_envelopecomposes both; personas additionally keep the slug grammar^[a-z0-9][a-z0-9_-]{0,63}$.kind:30178deliberately does not get the slug grammar. Team ids are UUIDs or built-in identifiers such asbuiltin-team:welcome, and the colon is not slug-legal; rewriting ids to fit would break NIP-33 addressing against the team's ownkind:30176head. The non-empty and exactly-one checks are load-bearing regardless — without them generic NIP-33 storage maps a missingdonto(pubkey_o, 30178, "")and every team overwrites its predecessor.The exact two-element
sharedshape is enforced because the SQL visibility clause is JSONB containment (tags @> '[["shared","true"]]'), which would match a three-element superset such as["shared","true","extra"].kind:30178is also added to theScope::UsersWriteallowlist and tois_global_only_kind, so a strayhtag cannot channel-scope an owner-authored definition.Deferred
kind:30176is deliberately not a gate member. Its writers never emitshared, so catalog opt-in semantics do not describe it — it needs owner-private reads driven by an authenticated principal set, tracked as a separate follow-up.Tests
ingest.rsunit tests covering the 30178 envelope (UUID and colondtags, 64-char boundary, non-ASCII bound, empty/valueless/duplicate/missingd, embedded newline,sharedfalse/three-element/duplicate, scope and global-only membership).["d"]shapes, since thed-tag helper is shared by both validators.kind.rsgate tests generalized and extended to assert the gate applies to 30178 as it does to 30175.crates/buzz-test-client/tests/e2e_team_catalog.rs: 9 WS-level tests over a live relay covering author reads of unshared heads, foreign omission from REQ,ids-lookup denial, COUNT existence-leak, share and unshare transitions, and the mixed-kind filter case..github/workflows/ci.ymladds--test e2e_team_catalogto the Relay E2E job so the new suite runs.Docs
docs/nips/NIP-AP.mdgains a "Team catalog projection: kind:30178" section and an "Ingest validation: kind:30178" subsection, records the gate as kind-generic, documents 30178 deletion vs. unshare semantics, and adds a security note that sharing a team exposes every member's instructions even when that member's ownkind:30175head is unshared.