mirror of
https://github.com/block/buzz.git
synced 2026-10-27 04:30:52 +00:00
feat(relay): add the system channel type (#8180)
🤖 ## Summary Buzz uses channel membership to decide who can read what, and every channel a person belongs to shows up in their client as a chat. So there is no way to make a group that exists only for access control, for example "only this agent and its owner can read the agent's config". Such a channel would appear in both people's sidebars, search results and unread counts. This stack adds a **system channel**: an ordinary channel that queries leave out unless they ask for it. This first PR adds the type itself. - `kind:9007` (create channel) with `["channel_type", "system"]` creates a system channel. - It is private unless the creator sends `["visibility", "open"]`. - While it is private, its channel metadata event (kind:39000) carries the NIP-29 `hidden` marker, which means "hide this group's metadata from non-members". Until now the relay set `hidden` only for DMs. On its own this PR does not yet hide system channels from queries. Part 2 does that. Part 1 of 3, stacked on #8176 (the channel labels and creator lookup stack, which this feature uses). ### Related issue None found. ### Details - Migration 0062 adds `system` to the `channel_type` Postgres enum. No new columns. - `buzz_core::channel::ChannelType::System`, and `system` is now a reserved label name (labels cannot equal a channel type name). - `buzz-admin` reconcile writes `hidden` with the same rule as the relay. Usage metrics count system channels. - **Rollback.** A relay older than this change cannot read `channel_type = 'system'`. Do not roll back past it while system channels exist. - **Spec.** NIP-CL gets a "System channels" section. `ARCHITECTURE.md` lists the `System` type. ### Testing - Relay test: a system channel is private and `hidden` by default; opening it removes `hidden`; its first `t` tag is `system`. - Migration embed and usage-metrics tests. ### Stack These are two stacks. Merge them in this order. Client support (creating, labeling and finding these channels) will be in block/buzz-app, not the buzz SDK and CLI. **Stack 1: channel labels and creator lookup (#8174–#8176)** 1. #8174 channel type and creator tags, and the channel creation time 2. #8175 channel labels 3. #8176 database-side label and creator match, and the rule for choosing one channel **Stack 2: system channels (#8180–#8182)**, stacked on stack 1 because it uses labels and the creator tag 4. #8180 the system channel type ← this PR 5. #8181 leave system channels out of reads that do not name them 6. #8182 channel-state filters opt in to system channels --------- Signed-off-by: Logan Johnson <loganj@squareup.com> Co-authored-by: Larry <627498bd4bd1f281a16431e3c6cce3b5c25b6692798c78672298aefbf2f8f8b5@buzz.block.builderlab.xyz>
This commit is contained in:
@@ -705,7 +705,7 @@ mod postgres_tests {
|
||||
let mut migrations: Vec<_> = MIGRATOR.iter().collect();
|
||||
migrations.sort_by_key(|migration| migration.version);
|
||||
|
||||
assert_eq!(migrations.len(), 61);
|
||||
assert_eq!(migrations.len(), 62);
|
||||
assert_eq!(migrations[58].version, 59);
|
||||
assert!(migrations[58].sql.as_str().contains("buzz.push_enabled"));
|
||||
assert_eq!(migrations[59].version, 60);
|
||||
@@ -715,6 +715,11 @@ mod postgres_tests {
|
||||
.contains("ALTER TABLE push_leases DROP COLUMN app_profile"));
|
||||
assert_eq!(migrations[60].version, 61);
|
||||
assert!(migrations[60].sql.as_str().contains("ADD COLUMN labels"));
|
||||
assert_eq!(migrations[61].version, 62);
|
||||
assert!(migrations[61]
|
||||
.sql
|
||||
.as_str()
|
||||
.contains("ALTER TYPE channel_type ADD VALUE IF NOT EXISTS 'system'"));
|
||||
assert_eq!(migrations[55].version, 56);
|
||||
assert!(migrations[55]
|
||||
.sql
|
||||
|
||||
@@ -38,6 +38,8 @@ pub struct FleetStockSnapshot {
|
||||
pub channels_dm: i64,
|
||||
/// Non-deleted workflow channels.
|
||||
pub channels_workflow: i64,
|
||||
/// Non-deleted system channels.
|
||||
pub channels_system: i64,
|
||||
/// Relay owners.
|
||||
pub members_owner: i64,
|
||||
/// Relay administrators.
|
||||
@@ -96,7 +98,8 @@ where
|
||||
COUNT(*) FILTER (WHERE channel_type = 'stream') AS stream,
|
||||
COUNT(*) FILTER (WHERE channel_type = 'forum') AS forum,
|
||||
COUNT(*) FILTER (WHERE channel_type = 'dm') AS dm,
|
||||
COUNT(*) FILTER (WHERE channel_type = 'workflow') AS workflow
|
||||
COUNT(*) FILTER (WHERE channel_type = 'workflow') AS workflow,
|
||||
COUNT(*) FILTER (WHERE channel_type = 'system') AS system
|
||||
FROM channels
|
||||
WHERE deleted_at IS NULL
|
||||
),
|
||||
@@ -122,6 +125,7 @@ where
|
||||
channels.forum AS channels_forum,
|
||||
channels.dm AS channels_dm,
|
||||
channels.workflow AS channels_workflow,
|
||||
channels.system AS channels_system,
|
||||
members.owner AS members_owner,
|
||||
members.admin AS members_admin,
|
||||
members.member AS members_member,
|
||||
@@ -1455,7 +1459,7 @@ mod postgres_tests {
|
||||
.await
|
||||
.expect("deactivate user");
|
||||
|
||||
for channel_type in ["stream", "forum", "dm", "workflow"] {
|
||||
for channel_type in ["stream", "forum", "dm", "workflow", "system"] {
|
||||
sqlx::query(
|
||||
"INSERT INTO channels (id, community_id, name, channel_type, visibility, created_by) \
|
||||
VALUES ($1, $2, $3, $4::channel_type, 'open', $5)",
|
||||
@@ -1589,8 +1593,9 @@ mod postgres_tests {
|
||||
stock.channels_forum,
|
||||
stock.channels_dm,
|
||||
stock.channels_workflow,
|
||||
stock.channels_system,
|
||||
),
|
||||
(1, 1, 1, 1)
|
||||
(1, 1, 1, 1, 1)
|
||||
);
|
||||
assert_eq!(
|
||||
(
|
||||
|
||||
Reference in New Issue
Block a user