How Macro's Channel-Based Permission System Works with @mentions: A Complete Technical Guide

Macro's @mention system automatically grants channel-level access to documents, tasks, and projects when they are mentioned in channel messages, using atomic database operations across the comms_entity_mentions and channel_share_permission tables.

Macro implements a share-on-mention architecture that links communication and permissions. When you type @ followed by a document name, task, or project in a channel message, the backend executes a coordinated transaction that records the mention and propagates access rights to all channel members. This design eliminates manual sharing while keeping permissions synchronized with membership changes.

Core Architecture: Two-Stage Permission Flow

The permission system operates through two distinct but atomic stages. Understanding this flow is essential for debugging access issues or extending the platform.

Stage 1: Entity-Mention Recording

Every @mention in a channel message creates a permanent record in the comms_entity_mentions table. This table serves as the audit trail and trigger source for permission propagation.

The insertion logic resides in crates/comms_db_client/src/messages/create_message_mentions.rs. The function create_message_mentions handles bulk insertion when a message contains multiple mentions:

use comms_db_client::messages::create_message_mentions::{
    CreateMessageMentionOptions, SimpleMention,
};

let mentions = vec![
    SimpleMention { 
        entity_type: "document".into(), 
        entity_id: "doc123".into(), 
        user_id: None 
    },
    SimpleMention { 
        entity_type: "task".into(),    
        entity_id: "task456".into(), 
        user_id: None 
    },
];

let opts = CreateMessageMentionOptions {
    source_entity_type: "message".into(),
    source_entity_id:   message_id.clone(),
    mentions,
};

comms_db_client::messages::create_message_mentions::create_message_mentions(&pool, opts).await?;

The underlying SQL generated by this function:

INSERT INTO comms_entity_mentions
    (id, source_entity_type, source_entity_id, entity_type, entity_id, user_id)
VALUES
    (gen_random_uuid(), 'message', $1, 'document', 'doc123', NULL),
    (gen_random_uuid(), 'message', $1, 'task',    'task456', NULL);

The comms_entity_mentions schema captures five critical fields:

  • source_entity_type — always 'message' for channel mentions
  • source_entity_id — the UUID of the containing message
  • entity_type — the category of mentioned item (document, task, call, chat, project)
  • entity_id — the UUID of the target item
  • user_id — populated only for @user mentions

Stage 2: Channel Permission Granting

After mention records are created, the share-on-mention service automatically grants channel-wide access. This logic lives in crates/macro_db_client/src/share_on_mention/mod.rs.

The service filters mentions to only shareable item types — documents, tasks, calls, chats, and projects. User mentions trigger notifications but bypass permission changes since users are not shareable resources.

// Called after entity_mention insertion
for mention in mentions {
    if let Ok(item_type) = ShareableItemType::from_str(&mention.entity_type) {
        macro_db_client::share_on_mention::grant_share(
            &pool,
            channel_id,
            item_type,
            mention.entity_id,
        ).await?;
    }
}

The grant_share function creates channel_share_permission rows that bind the target entity to the channel. These rows enable inherited access: any current or future channel member automatically gains access to the mentioned item.

End-to-End Flow: From Message Submit to Permission Grant

The complete sequence executes in tooling/seed_cli/src/service/db/mod.rs and production message handlers:

Step Operation Code Location
1. Message submission UI sends payload with entity_mentions array Client → API gateway
2. Mention persistence INSERT INTO comms_entity_mentions create_message_mentions.rs
3. Permission trigger update_share_permissions_for_mention invoked tooling/seed_cli/src/service/db/mod.rs
4. Share grant channel_share_permission rows created macro_db_client/src/share_on_mention/mod.rs
5. Member notification Real-time updates pushed to channel members Notification service

Automatic Permission Revocation on Membership Changes

Channel-based permissions must contract as well as expand. When a user leaves a channel, Macro cleans up access through delete_entity_mentions_for_entities in crates/channels/src/domain/service.rs:

async fn delete_entity_mentions_for_entities(
    &self,
    fetched_entity_ids: Vec<String>,
    channel_id: Uuid,
) -> Result<()> {
    // Removes entity_mention rows and related channel_share_permission rows
    // ensuring former members lose access to items mentioned while they were present
}

This cleanup maintains principle of least privilege — access persists only while membership is active. The function operates on both table layers:

  • Deletes comms_entity_mentions rows where the user's messages contained mentions
  • Cascades to remove channel_share_permission entries, which severs the access inheritance

Boundary Conditions: Where @mentions Do NOT Share

Macro deliberately restricts the share-on-mention behavior to prevent notification spam and premature access grants.

Thread-Container Requirement

Only mentions within thread containers trigger sharing:

  • ✅ Channel messages
  • ✅ Comment threads

Mentions in document or task bodies do not automatically share the item or generate notifications. This prevents alerts during drafting when mentions are added for reference rather than distribution.

User Mention Special Case

When entity_type = 'user', the system:

  • Creates a notification for the mentioned user via the notification service
  • Skips permission changes — users cannot be "shared" like documents or tasks

This distinction preserves the semantic difference between notifying a person and granting access to a resource.

Key Files and Their Responsibilities

File Role
crates/comms_db_client/src/messages/create_message_mentions.rs Bulk insertion of mention records
crates/comms_db_client/src/entity_mentions/mod.rs Public API for mention deletion and cleanup
crates/macro_db_client/src/share_on_mention/mod.rs Core permission-granting service
crates/channels/src/domain/service.rs Membership change handling and permission revocation
tooling/seed_cli/src/service/db/mod.rs End-to-end orchestration for seeding and testing
apps/docs/concepts/mentions.mdx User-facing documentation

Summary

  • Atomic two-stage operation: Every @mention in a channel message creates both an audit record (comms_entity_mentions) and access rights (channel_share_permission)
  • Inherited permissions: Channel membership alone controls access to mentioned items — no per-user sharing required
  • Automatic cleanup: Membership changes trigger immediate permission revocation via delete_entity_mentions_for_entities
  • Scoped triggering: Only thread-container mentions share; body mentions and user mentions follow different paths
  • Shareable type filter: Only documents, tasks, calls, chats, and projects receive channel permissions

Frequently Asked Questions

How does Macro handle multiple @mentions in a single message?

Macro processes mentions as a batch through create_message_mentions, which accepts a vector of SimpleMention structs. Each mention generates its own comms_entity_mentions row, and the share-on-mention service iterates through all valid targets to grant channel access. This batch approach ensures atomicity — either all mentions and permissions succeed, or the transaction rolls back.

What happens to permissions when a mentioned item is deleted?

The entity_mentions table maintains foreign key relationships or soft-delete tracking (implementation-dependent in the Macro codebase). When an entity is deleted, the delete_entity_mentions_for_entities function in crates/channels/src/domain/service.rs cleans up associated rows. This prevents orphaned permission grants and ensures the channel_share_permission table stays consistent with actual existent resources.

Can administrators override or revoke share-on-mention permissions manually?

The channel-based permission system treats channel_share_permission rows as the source of truth. Administrators can directly manipulate these rows through the channel_permission CRUD APIs referenced in macro_db_client/src/share_on_mention/mod.rs. However, manual revocation may be reverted if the original mention record persists and a membership change triggers cleanup logic — the system prioritizes automated consistency over manual overrides.

Why don't document body mentions trigger sharing?

According to apps/docs/concepts/mentions.mdx, this limitation prevents premature notification and access during active drafting. Authors frequently reference documents, tasks, or colleagues while composing content, before the document is ready for distribution. Restricting share-on-mention to thread containers (messages and comments) ensures sharing is an intentional, public act rather than a byproduct of editing.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →