# Buzz Authentication Scopes: Complete Guide to Permissions and Access Control

> Explore Buzz's 16 granular authentication scopes controlling access to messages, channels, users, and more. Understand permissions and access control in this complete guide.

- Repository: [Block Open Source/buzz](https://github.com/block/buzz)
- Tags: api-reference
- Published: 2026-08-27

---

**Buzz defines 16 granular permission scopes in [`crates/buzz-auth/src/scope.rs`](https://github.com/block/buzz/blob/main/crates/buzz-auth/src/scope.rs) that control access to messages, channels, users, jobs, subscriptions, files, and repositories, utilizing database-backed TEXT[] storage and forward-compatible parsing for unknown scope variants.**

The `block/buzz` repository implements a robust permission system using **Buzz authentication scopes** to govern what authenticated clients can perform. These scopes function as capability strings granted to WebSocket connections, API tokens, and HTTP requests, with enforcement distributed across the `buzz-auth` crate.

## Available Authentication Scopes in Buzz

The system recognizes 16 distinct scope variants defined in [`crates/buzz-auth/src/scope.rs`](https://github.com/block/buzz/blob/main/crates/buzz-auth/src/scope.rs) (lines 10-45). Each variant maps to a wire-format string used during token serialization and API authorization.

### Core Messaging and Channel Scopes

- **MessagesRead** (`messages:read`): Grants permission to read messages from channels the authenticated user belongs to.
- **MessagesWrite** (`messages:write`): Allows sending messages to channels where the user holds membership.
- **ChannelsRead** (`channels:read`): Enables listing and reading channel metadata without requiring membership.
- **ChannelsWrite** (`channels:write`): Permits creating new channels and updating existing channel configurations.

### Administrative Scopes

- **AdminChannels** (`admin:channels`): Provides administrative channel actions including deletion and forced member removal.
- **AdminUsers** (`admin:users`): Enables administrative user management such as account suspension and impersonation capabilities.

### System and Resource Scopes

- **UsersRead** (`users:read`): Allows reading user profile information and public account data.
- **UsersWrite** (`users:write`): Permits updating user profile information and account settings.
- **JobsRead** (`jobs:read`): Grants access to inspect background job status and processing queues.
- **JobsWrite** (`jobs:write`): Allows submitting new background jobs or canceling existing operations.
- **SubscriptionsRead** (`subscriptions:read`): Enables reading subscription and billing plan details.
- **SubscriptionsWrite** (`subscriptions:write`): Permits modifying subscription information and plan configurations.
- **FilesRead** (`files:read`): Allows downloading files and message attachments.
- **FilesWrite** (`files:write`): Grants permission to upload files and create new attachments.
- **ReposRead** (`repos:read`): Reserved for cloning Git repositories via HTTP routes (future-use implementation).
- **ReposWrite** (`repos:write`): Enables pushing to Git repositories and creating new repositories, currently enforced for specific Nostr events.

### Forward Compatibility Handling

- **Unknown(String)**: Preserves any unrecognized scope strings to maintain compatibility with future scope additions without breaking existing token validation.

## How Buzz Stores and Parses Authentication Scopes

Buzz persists scopes as a `TEXT[]` column in the database, enabling the addition of new scopes without requiring schema migrations. When parsing tokens, the system invokes `parse_scopes()` (defined in [`crates/buzz-auth/src/scope.rs`](https://github.com/block/buzz/blob/main/crates/buzz-auth/src/scope.rs), lines 69-78) to convert raw string slices into typed `Scope` variants.

The parsing implementation handles unrecognized scope strings by wrapping them in the `Scope::Unknown` variant (lines 55-61). This design ensures that tokens containing future scope definitions remain valid and parseable by current system versions, with the unknown scopes preserved for forward compatibility.

## Scope-Based Access Patterns in Buzz

The authentication system applies **Buzz authentication scopes** differently depending on whether the client uses NIP-42 Nostr authentication or token-based API access.

**NIP-42 Authentication (Nostr Mode)**: During standard NIP-42 authentication, every authenticated WebSocket connection receives the complete set of scopes defined by `Scope::all_known()`. Fine-grained access control is subsequently enforced through NIP-29 membership checks rather than scope limitations.

**Token-Based Authentication**: For API tokens and HTTP-based endpoints, the `scopes` field within the token payload determines permissible operations. Request handlers inspect this vector through helper functions in [`crates/buzz-auth/src/access.rs`](https://github.com/block/buzz/blob/main/crates/buzz-auth/src/access.rs) to authorize specific actions such as message ingestion, file uploads, or channel administration.

### Utility Methods for Scope Management

The `Scope` enum provides helper methods for common access patterns in [`crates/buzz-auth/src/scope.rs`](https://github.com/block/buzz/blob/main/crates/buzz-auth/src/scope.rs):

- **`Scope::all_known()`** (lines 63-87): Returns a `Vec<Scope>` containing all 16 defined variants, useful for generating documentation or administrative interfaces.
- **`Scope::all_non_admin()`** (lines 89-111): Returns every scope except `AdminChannels` and `AdminUsers`, used in development mode when bare `X-Pubkey` headers grant broad access while still requiring properly scoped tokens for administrative functions.

## Implementing Scope Checks in Rust

Developers interact with scopes through the `buzz_auth::scope` module, utilizing typed enums rather than raw strings for type-safe permission management. The following example demonstrates token creation, scope serialization, and permission verification:

```rust
use buzz_auth::scope::{Scope, parse_scopes};

/// Create a token payload containing specific scope permissions.
fn make_token(scopes: &[Scope]) -> String {
    let scope_strings: Vec<&str> = scopes.iter().map(|s| s.as_str()).collect();
    scope_strings.join(" ")
}

/// Verify if the request contains message write permissions.
fn can_write_message(request_scopes: &[Scope]) -> bool {
    request_scopes.contains(&Scope::MessagesWrite)
}

fn main() {
    // Generate token with message and channel access
    let token_scopes = vec![
        Scope::MessagesRead, 
        Scope::MessagesWrite, 
        Scope::ChannelsRead
    ];
    let token = make_token(&token_scopes);
    println!("Token scopes: {}", token);

    // Parse and validate incoming request scopes
    let parsed = parse_scopes(&["messages:write", "channels:read"]);
    assert!(can_write_message(&parsed));
}

```

The `as_str()` method serializes each variant to its canonical wire-format representation, while `parse_scopes()` reconstructs typed variants from token data for runtime authorization decisions.

## Scope Enforcement Across the Codebase

Scope validation is distributed across several specialized modules within the `buzz-auth` crate:

- **[`crates/buzz-auth/src/scope.rs`](https://github.com/block/buzz/blob/main/crates/buzz-auth/src/scope.rs)**: Central definition of all scope variants, conversion logic, and parsing functions.
- **[`crates/buzz-auth/src/access.rs`](https://github.com/block/buzz/blob/main/crates/buzz-auth/src/access.rs)**: Contains access-check helpers that inspect request scope vectors to grant or deny specific operations.
- **[`crates/buzz-auth/src/nip98.rs`](https://github.com/block/buzz/blob/main/crates/buzz-auth/src/nip98.rs)**: Implements NIP-98 authentication for HTTP endpoints, consulting token scopes to enforce file and repository permissions.
- **[`crates/buzz-auth/src/lib.rs`](https://github.com/block/buzz/blob/main/crates/buzz-auth/src/lib.rs)**: Exposes the public API for token creation and validation, utilizing the `Scope` definitions for credential generation.

## Summary

- Buzz defines **16 granular authentication scopes** in [`crates/buzz-auth/src/scope.rs`](https://github.com/block/buzz/blob/main/crates/buzz-auth/src/scope.rs) covering messages, channels, users, jobs, subscriptions, files, and repositories.
- Scopes are stored as **TEXT[] arrays** in the database, allowing schema-free additions of new permissions.
- The **`Scope::Unknown`** variant preserves unrecognized scope strings for forward compatibility with future API versions.
- **NIP-42 authentication** grants full scopes with NIP-29 handling fine-grained access, while **token-based authentication** enforces strict scope boundaries.
- Utility methods **`all_known()`** and **`all_non_admin()`** facilitate development workflows and administrative access controls.
- The **`parse_scopes()`** function and **`as_str()`** method handle conversion between wire-format strings and typed Rust variants.

## Frequently Asked Questions

### How do I add a new authentication scope to Buzz?

Add the new scope variant to the `Scope` enum definition in [`crates/buzz-auth/src/scope.rs`](https://github.com/block/buzz/blob/main/crates/buzz-auth/src/scope.rs) (around lines 10-45) and implement the corresponding `as_str()` match arm to return the wire-format string. Because scopes are stored as `TEXT[]` in the database, no schema migration is required; however, you must add the parsing logic in `parse_scopes()` to recognize the new string and map it to your variant.

### What is the difference between NIP-42 and token-based scope handling?

In **NIP-42 authentication**, every authenticated WebSocket connection receives the full set of scopes defined by `Scope::all_known()`, with granular permissions enforced separately through NIP-29 group membership checks. In **token-based authentication**, the token's explicit `scopes` field restricts the client to only those specific permissions, which are validated by request handlers in [`crates/buzz-auth/src/access.rs`](https://github.com/block/buzz/blob/main/crates/buzz-auth/src/access.rs) before executing operations.

### How does Buzz handle unknown or future scope strings?

When `parse_scopes()` encounters a scope string that does not match any known variant in [`crates/buzz-auth/src/scope.rs`](https://github.com/block/buzz/blob/main/crates/buzz-auth/src/scope.rs) (lines 55-61), it wraps the string in the `Scope::Unknown(String)` variant rather than rejecting the token. This forward-compatibility mechanism ensures that older Buzz versions can still parse and validate tokens containing new scopes introduced in future updates.

### Which scopes are required for administrative operations?

Administrative functions require either **`AdminChannels`** (`admin:channels`) for channel management operations like deletion and forced member removal, or **`AdminUsers`** (`admin:users`) for user administration including suspension and impersonation. The `Scope::all_non_admin()` method (lines 89-111) specifically excludes these two variants, ensuring that development-mode access granted via `X-Pubkey` headers cannot perform administrative actions without a properly scoped token.