-
Notifications
You must be signed in to change notification settings - Fork 0
Phase 6 Quick Reference
github-actions[bot] edited this page Sep 2, 2026
·
46 revisions
cd .backend
psql -U postgres -d nchat -f migrations/040_advanced_channels_phase6.sqlimport { categoryService } from '@/services/channels/category.service'
import { communityService } from '@/services/channels/community.service'
import { broadcastService } from '@/services/channels/broadcast.service'
import { permissionService } from '@/services/channels/permission.service'import { GET_CATEGORIES_WITH_CHANNELS } from '@/graphql/channels/categories'
import { CREATE_COMMUNITY } from '@/graphql/channels/communities'
import { SEND_BROADCAST } from '@/graphql/channels/broadcasts'Create Category
const category = await categoryService.createCategory({
workspaceId: 'workspace-id',
name: 'Engineering',
icon: 'π»',
color: '#3b82f6',
})Reorder Categories
await categoryService.reorderCategories(['category-1-id', 'category-2-id', 'category-3-id'])Move Channel
await categoryService.moveChannel({
channelId: 'channel-id',
categoryId: 'new-category-id',
position: 0,
})Sync Permissions
await categoryService.togglePermissionSync('category-id', true)
await categoryService.syncPermissions('category-id')Create Community
const community = await communityService.createCommunity({
workspaceId: 'workspace-id',
name: 'Product Updates',
description: 'Latest product news',
announcementChannelId: 'announcement-channel-id',
addGroupsPermission: 'admin', // or 'member'
membersCanInvite: true,
maxGroups: 50,
maxMembers: 10000,
})Add Group to Community
await communityService.addGroup({
communityId: 'community-id',
channelId: 'channel-id',
position: 0,
addedBy: 'user-id',
})Remove Group
await communityService.removeGroup('community-id', 'channel-id')Create Broadcast List
const broadcastList = await broadcastService.createBroadcastList({
workspaceId: 'workspace-id',
name: 'Weekly Newsletter',
description: 'Weekly team updates',
ownerId: 'user-id',
subscriptionMode: 'open', // or 'invite', 'admin'
allowReplies: false,
trackDelivery: true,
trackReads: true,
maxSubscribers: 10000,
})Subscribe Users
// Single subscriber
await broadcastService.subscribe('broadcast-list-id', 'user-id')
// Bulk subscribe
await broadcastService.bulkSubscribe({
broadcastListId: 'broadcast-list-id',
userIds: ['user-1', 'user-2', 'user-3'],
})Send Broadcast
const message = await broadcastService.sendBroadcast({
broadcastListId: 'broadcast-list-id',
content: 'Important announcement!',
attachments: [
{ type: 'image', url: 'https://...' },
{ type: 'file', url: 'https://...' },
],
scheduledFor: new Date('2026-02-10T10:00:00Z'), // Optional
})Track Delivery
// Delivery stats are automatically tracked via triggers
const message = await fetch(`/api/channels/broadcasts/messages/${messageId}`)
// Returns: { delivered_count, read_count, failed_count }Permission Flags
import { CHANNEL_PERMISSIONS } from '@/types/advanced-channels'
// Available permissions:
CHANNEL_PERMISSIONS.VIEW_CHANNEL
CHANNEL_PERMISSIONS.SEND_MESSAGES
CHANNEL_PERMISSIONS.MANAGE_CHANNEL
// ... 28 total permissionsCreate Permission Override
// Create bitfield from permission names
const allowBits = permissionService.createBitfield([
'VIEW_CHANNEL',
'SEND_MESSAGES',
'ADD_REACTIONS',
])
const denyBits = permissionService.createBitfield(['MENTION_EVERYONE'])
// Apply override
await permissionService.createOverride({
channelId: 'channel-id',
targetType: 'role', // or 'user'
targetId: 'role-id',
allowPermissions: allowBits,
denyPermissions: denyBits,
createdBy: 'admin-user-id',
})Check Permissions
// Check single permission
const canSend = await permissionService.hasPermission('channel-id', 'user-id', 'SEND_MESSAGES')
// Get all permissions
const permissions = await permissionService.calculatePermissions('channel-id', 'user-id')
// Returns: { VIEW_CHANNEL: true, SEND_MESSAGES: false, ... }Work with Bitfields
// Parse bitfield to array
const permissions = permissionService.parseBitfield(12345n)
// Returns: ['VIEW_CHANNEL', 'SEND_MESSAGES', ...]
// Check specific permission in bitfield
const hasPermission = permissionService.hasPermissionInBitfield(12345n, 'MANAGE_CHANNEL')// Automatically when member count > 200
UPDATE nchat_channels
SET subtype = 'supergroup'
WHERE member_count > 200 AND type = 'group'await createChannel({
name: 'Announcements',
type: 'public',
subtype: 'gigagroup',
isReadonly: true, // Only admins can post
})const announcementChannel = await createChannel({
name: 'Community Updates',
type: 'public',
subtype: 'community_announcement',
isReadonly: true,
})
const community = await communityService.createCommunity({
name: 'My Community',
announcementChannelId: announcementChannel.id,
// ...
})SELECT * FROM nchat.channels_with_categories
WHERE workspace_id = 'workspace-id'
ORDER BY category_position, position;SELECT * FROM nchat.broadcast_lists_with_stats
WHERE workspace_id = 'workspace-id';SELECT * FROM nchat.communities_with_stats
WHERE workspace_id = 'workspace-id';SELECT * FROM nchat.nchat_channel_permission_overrides
WHERE channel_id = 'channel-id'
AND target_type = 'role'
AND target_id = 'role-id';query GetCategoriesWithChannels($workspaceId: uuid!) {
nchat_channel_categories(
where: { workspace_id: { _eq: $workspaceId } }
order_by: { position: asc }
) {
id
name
icon
color
position
channels(where: { is_archived: { _eq: false } }, order_by: { position: asc }) {
id
name
type
subtype
member_count
}
}
}mutation CreateCommunity($input: CreateCommunityInput!) {
insert_nchat_communities_one(object: $input) {
id
name
announcement_channel {
id
name
}
}
}subscription SubscribeToBroadcastMessages($broadcastListId: uuid!) {
nchat_broadcast_messages(
where: { broadcast_list_id: { _eq: $broadcastListId } }
order_by: { sent_at: desc }
limit: 50
) {
id
content
sent_at
delivered_count
read_count
}
}-
GET /api/channels/categories?workspaceId=xxx- List -
POST /api/channels/categories- Create -
PATCH /api/channels/categories/:id- Update -
DELETE /api/channels/categories/:id- Delete -
POST /api/channels/categories/reorder- Reorder -
POST /api/channels/move- Move channel
-
GET /api/channels/communities?workspaceId=xxx- List -
POST /api/channels/communities- Create -
GET /api/channels/communities/:id- Get -
POST /api/channels/communities/:id/groups- Add group -
DELETE /api/channels/communities/:id/groups/:channelId- Remove
-
GET /api/channels/broadcasts?workspaceId=xxx- List -
POST /api/channels/broadcasts- Create -
POST /api/channels/broadcasts/:id/send- Send message -
POST /api/channels/broadcasts/:id/subscribe- Subscribe -
POST /api/channels/broadcasts/:id/bulk-subscribe- Bulk
-
GET /api/channels/:id/permissions- List overrides -
POST /api/channels/permissions- Create override -
GET /api/channels/:id/permissions/calculate?userId=xxx- Calculate
import type {
ChannelCategory,
CategoryWithChannels,
CreateCategoryInput,
UpdateCategoryInput,
Community,
CommunityWithGroups,
CreateCommunityInput,
AddCommunityGroupInput,
BroadcastList,
BroadcastMessage,
BroadcastDelivery,
CreateBroadcastListInput,
SendBroadcastInput,
ChannelPermissionOverride,
CreatePermissionOverrideInput,
ChannelPermission,
ChannelSubtype,
SubscriptionMode,
} from '@/types/advanced-channels'import { permissionService } from '@/services/channels/permission.service'
describe('PermissionService', () => {
it('creates bitfield from permissions', () => {
const bitfield = permissionService.createBitfield(['VIEW_CHANNEL', 'SEND_MESSAGES'])
expect(bitfield).toBeGreaterThan(0n)
})
it('parses bitfield to permissions', () => {
const permissions = permissionService.parseBitfield(7n)
expect(permissions).toContain('VIEW_CHANNEL')
})
})describe('Category API', () => {
it('creates and retrieves category', async () => {
const created = await categoryService.createCategory({
workspaceId: 'test-workspace',
name: 'Test Category',
})
const categories = await categoryService.getCategories()
expect(categories).toContainEqual(created)
})
})- Check
workspace_idmatches default:ffffffff-ffff-ffff-ffff-ffffffffffff - Verify migration ran successfully
- Check user has permission to view workspace
- Verify permission override exists in database
- Check bitfield calculation (allow takes precedence over deny)
- Ensure category permission sync is enabled if using categories
- Verify
track_deliveryis enabled on broadcast list - Check triggers are installed (
update_delivery_counts) - Ensure delivery records are created when sending
- Verify channel is not archived
- Check
positionfield for ordering - Ensure user has access to both community and channel
- Cache category structures - They rarely change
- Batch permission calculations - Don't check per-message
- Lazy-load broadcast deliveries - Only load when viewing details
-
Use views -
channels_with_categories,broadcast_lists_with_stats -
Index properly - Composite indexes on
(workspace_id, position)
- Validate workspace ownership before modifying categories
- Check permissions before creating broadcast lists
- Rate limit broadcast sending (prevent spam)
- Sanitize content in broadcasts
- Validate bitfields before applying permissions
- All existing channels moved to default workspace
- Public/private channels assigned to "General" category
- No breaking changes to existing functionality
- Categories, communities, broadcasts are optional features
- Permission system augments (not replaces) RBAC
For issues or questions:
- Check implementation summary:
docs/Phase-6-Implementation-Summary.md - Review type definitions:
src/types/advanced-channels.ts - Examine database schema:
.backend/migrations/040_advanced_channels_phase6.sql - Test with GraphQL playground: http://localhost:8080/console
Last Updated: February 3, 2026 Version: 1.0.0 Status: Production Ready β
nself-chat v0.3.0 | GitHub | Issues | Discussions | Demo
Edit this page | MIT License | Β© 2026
(See π Security section below for 2FA, PIN Lock, and security audits.)
(Search lives in π Reference below.)
- π¬ Advanced Messaging
- π E2EE Setup
- π Search Setup
- π Call Management
- πΊ Live Streaming
- π₯οΈ Screen Sharing
- πΉ Video Calling
- ποΈ Voice Calling
- π± Mobile Optimization
- π§ͺ Testing
- π i18n
- π API Overview
- π Complete Reference
- π» API Examples
- π€ Bot API
- π Auth API
- π GraphQL Schema
- π Deployment Overview
- π³ Docker
- βΈοΈ Kubernetes
- β Helm Charts
- β Production Checklist
- π Production Validation
- π’ Multi-Tenant
- ποΈ Architecture
- π Diagrams
- ποΈ Database Schema
- π Project Structure
- π TypeScript Types
- π SPORT Reference
- π 2FA
- π¬ Messaging
- π Call Management
- π Call State Machine
- π E2EE
- πΊ Live Streaming
- π± Mobile Calls
- π PIN Lock
- π Polls
- π₯οΈ Screen Sharing
- π Search
- π Social Media
- ποΈ Voice Calling
- π Security Overview
- π‘οΈ Security Audit
- β‘ Performance
- π Best Practices
- π 2FA
- π PIN Lock
- π E2EE
- π‘οΈ E2EE Audit
v1.0.0 β’ 2026