NexGate Messaging — Product Requirements & Feature Flows
NexGate / QBIT SPARK | Version 1.0 What the messaging platform does — rules, flows, permissions, scenarios
Table of Contents
- Document Purpose
- User Identity & Discovery
- Contact Sync
- Inbox Model
- Messaging Permissions
- Call Permissions
- 1:1 Messaging Flows
- Group Chat Flows
- Commerce DM Flows
- Offer Session Flows
- Shareable Content
- Message Interactions
- Voice & Video Call Flows
- Group Call Flows
- Offline & Notification Flows
- Privacy & Safety
- Shop Inbox & Staff Access
- Notification Settings
- Edge Cases & Scenarios
1. Document Purpose
This document defines WHAT NexGate messaging does — the rules, user flows, permissions, and scenarios for every messaging feature.
It is the product reference document. It does not describe HOW features are built technically. For technical architecture see:
- Doc 3: Phase 2 Production Architecture
- Doc 5: Private Chat & Calls Deep Dive
Audience: Product, mobile developers, QA, design.
2. User Identity & Discovery
Identity on NexGate
Every NexGate user has:
@username unique, chosen at registration
shown publicly on VP Feed
used for messaging: @kibuti
Display name full name shown in conversations
can differ from username
Phone number used for registration + auth
NOT shown publicly by default
discoverable only with user permission
NexGate ID internal UUID
never shown to users
How Users Find Each Other
Discovery mechanism Requires contact sync?
──────────────────────────────────────────────────────
VP Feed follow ❌ No
VP Shop (buyer/seller) ❌ No
Username search (@kibuti) ❌ No
QR code scan ❌ No
Shareable profile link ❌ No
Group chat membership ❌ No
Phone number search ❌ No (type manually)
Contact sync (phonebook) ✅ Yes (optional)
NexGate has multiple discovery paths. Contact sync is one option — not the only one.
Discoverability Settings
Two independent settings:
"Sync my contacts"
Find NexGate users in my phonebook
Default: OFF (user must opt in)
"Let others find me via phone number"
If someone has my number → can find me
Default: ON (can turn off)
These are INDEPENDENT:
I can sync contacts without being findable
I can be findable without syncing contacts
3. Contact Sync
Rules
✅ Optional — never mandatory
✅ Can be enabled/disabled anytime
✅ Can delete synced data anytime from settings
✅ Only finds users who have discoverability ON
❌ Not required to use messaging
❌ Not required for commerce DMs
❌ Contacts data never shared with third parties
❌ Non-NexGate contacts never stored on server
Privacy-Preserving Implementation
How it works when user accepts:
Step 1: Phone numbers hashed ON DEVICE
sha256(+255712345678) → hash
Actual numbers never leave the device
Step 2: Hashes uploaded to NexGate server
Not real phone numbers
Server cannot reverse hashes
Step 3: Server matches hashes
Against registered users who have
"Let others find me via phone number" = ON
Returns: which hashes are NexGate users
Step 4: App shows matched users
"3 of your contacts are on NexGate"
[Connect] buttons shown
Non-NexGate contacts:
Their hashes deleted from server immediately
Never stored
Never tracked
First Launch Prompt
Shown once at first launch after onboarding:
┌──────────────────────────────────────────────┐
│ 📱 Pata Marafiki Wako NexGate │
│ │
│ Ruhusu NexGate kutumia contacts zako │
│ kupata marafiki wanaotumia NexGate tayari │
│ │
│ ✓ Contacts zako hazitashirikiwa na mtu │
│ ✓ Unaweza kufuta ruhusa wakati wowote │
│ ✓ Nambari za simu zinabadilishwa kuwa │
│ msimbo kabla ya kupakiwa │
│ │
│ [Ruhusu Contacts] [Sasa Hivi Sio] │
└──────────────────────────────────────────────┘
If declined:
App works fully ✅
Remind once after 7 days
Never prompt again after second decline
Always accessible in Settings
Sync Scenarios
Scenario 1 — User accepts sync:
Hashes uploaded
Matched users shown
User can message/follow matched users
Sync runs again when contacts change
Scenario 2 — User declines sync:
App works fully
Can still find people via username/QR/VP Feed
No contacts uploaded
Scenario 3 — User accepts then disables:
Settings → Privacy → Contact Sync → OFF
All hash data deleted from server
Matched contacts remain as connections
(connections not removed — only future sync stops)
Scenario 4 — User wants to delete contact data:
Settings → Privacy → Delete Contacts Data
All hashes deleted from server immediately
Confirmation shown: "Contacts data imefutwa"
Scenario 5 — Contact not on NexGate:
Their hash deleted from server
User sees option: "Invite Juma to NexGate"
Tap → share NexGate invite link via SMS/WhatsApp
4. Inbox Model
Two Separate Inboxes
Every NexGate user has TWO completely separate inboxes:
Personal Inbox:
1:1 DMs with other users (personal)
Group chats (personal)
Friend conversations
Private — only the account owner sees this
NEVER accessible to shop staff
Shop Inbox (one per shop owned):
All customer conversations for that shop
Commerce DMs with buyers
Shared with authorized shop staff
Completely separate from personal inbox
Customer sees shop identity — not personal name
Inbox Tabs
User with 2 shops sees:
┌─────────────────────────────────────────────┐
│ 💬 Inbox │
│ │
│ [Personal ●3] [TechStore ●12] [ClothingHub]│
│ │
│ Personal tab: │
│ Regular DMs + group chats │
│ Private — owner only │
│ │
│ TechStore tab: │
│ Customer commerce conversations │
│ Shared with assigned staff │
│ │
│ ClothingHub tab: │
│ Separate shop conversations │
│ Different staff assigned │
└─────────────────────────────────────────────┘
Staff member (Amina assigned to TechStore):
┌─────────────────────────────────────────────┐
│ [Personal] [TechStore ●12] │
│ │
│ ClothingHub: NOT visible (no access) │
│ Owner personal: NEVER visible │
└─────────────────────────────────────────────┘
Conversation Types
Type Owner Participants
────────────────────────────────────────────────────
DM USER 2 users
GROUP USER 3-500 users
COMMERCE SHOP 1 shop + 1 buyer
BROADCAST USER or SHOP 1 sender + N followers
5. Messaging Permissions
Who Can Message Who
Relationship Can message? How
────────────────────────────────────────────────────────────
Saved contacts (phone) ✅ Always Direct
Mutual followers (VP Feed) ✅ Always Direct
Commerce relationship ✅ Always Direct (shop inbox)
Group chat members ✅ Always Via group only
Strangers (no relationship) ⚠️ Request Message request first
Blocked users ❌ Never Blocked
Message Request System
Stranger (no relationship) wants to message you:
They can send ONE message request:
┌─────────────────────────────────────────┐
│ 📩 Maombi ya Ujumbe │
│ │
│ Juma Mwangi anataka kukutumia ujumbe │
│ @juma_mwangi · 245 wafuasi │
│ │
│ "Habari, nilikuona kwenye VP Shop..." │
│ │
│ [Kubali] [Kataa] [Zuia] │
└─────────────────────────────────────────┘
If Kubali (Accept):
Full conversation opens
Juma can now message freely
Can call after conversation established
If Kataa (Decline):
Juma cannot send another request
One attempt only per account
Juma sees: "Ujumbe haukukubaliwa"
If Zuia (Block):
Juma blocked immediately
Cannot contact again in any way
Juma sees: nothing (as if you don't exist)
If Ignored (no response):
Request stays in request folder
Juma cannot send more messages
No call attempt allowed
Request expires after 30 days
Message Request Limits
Per account per day:
Max 10 message requests sent
Prevents spam
Per account to same person:
1 request only (ever)
If declined → cannot request again
Request folder:
Separate from main inbox
User checks it voluntarily
No notification for low-priority requesters
(unless they have mutual connections)
6. Call Permissions
Permission Tiers
Tier Voice call Video call
────────────────────────────────────────────────────────
Saved contacts ✅ ✅
Mutual followers ✅ ✅
Commerce relationship ✅ (shop) ✅ (shop)
Active conversation partner ✅ ✅
(message request accepted)
Group chat member ✅ (group) ✅ (group)
Strangers ❌ ❌
Blocked users ❌ ❌
Commerce Call Rules
Buyer can call:
The SHOP JID — not the owner personally
techstore@shops.nexgate.com
Any available staff answers as TechStore
Seller (shop) can call:
Buyers they have active commerce DM with
Call goes from shop JID to buyer
Buyer sees "TechStore" calling — not a personal name
Protecting personal contact:
Owner's personal phone/JID never revealed
Commerce calls always through shop identity
Staff cannot reveal personal number to customers
Anti-Harassment Call Rules
Call rate limiting:
Max 3 unanswered calls to same person in 24 hours
4th attempt → blocked for 24 hours automatically
Resets daily
Silence unknown callers:
Setting: "Pumzisha simu kutoka kwa wasio contacts"
Calls from non-contacts ring silently
Notification appears after — not during
First call warning:
First EVER call from this person:
┌───────────────────────────────────────┐
│ 📞 Simu ya kwanza kutoka │
│ Juma Mwangi (@juma_mwangi) │
│ │
│ [Jibu] [Kataa] [Zuia] │
└───────────────────────────────────────┘
Quick block during call:
Report button visible during call
One tap → ends call + reports + blocks
Privacy Settings for Calls
Who can call me:
○ Mutual followers + contacts (default)
○ My contacts only
○ Nobody
User can change anytime in Settings → Privacy → Calls
Call Permission Check Flow
Kibuti tries to call Juma:
│
Spring Boot permission check:
Is Juma blocked by Kibuti? ❌ → reject immediately
Is Kibuti blocked by Juma? ❌ → reject immediately
Are they saved contacts? ✅ → allow
Are they mutual followers? ✅ → allow
Active commerce relationship? ✅ → allow
Active accepted conversation? ✅ → allow
Does Juma's privacy setting allow? ✅ → allow
None of above → ❌ reject
│
If rejected:
App shows: "Huwezi kupiga simu mtu huyu"
No Jingle stanza sent
No TURN credentials issued
If allowed:
TURN credentials generated
Jingle session-initiate sent via Ejabberd
Juma's device rings
7. 1:1 Messaging Flows
Send Text Message
Happy path:
User types message
Taps send
Message shows: pending ⏳
Server receives → single tick ✓
Recipient receives → double tick ✓✓
Recipient reads → blue tick ✓✓
Offline path:
User taps send
Single tick ✓ (server received)
Recipient offline → queued
FCM push fires to recipient device
Recipient comes online → message delivered
Double tick ✓✓ appears
Send Voice Note
User holds mic button:
"Kibuti anarekodia..." shown to recipient (if online)
Recording in progress
Timer shown: 0:01, 0:02...
User releases:
Voice note sent
Waveform shown in thread
Duration shown: 0:15
User swipes up while holding:
Lock mode — records without holding
Release sends
User swipes left while holding:
Cancel recording — nothing sent
Limits:
Basic users: max 2 minutes
Pro users: max 15 minutes
File size: max 16MB
Send Media
Images:
Max 10 images per message
Formats: JPG, PNG, WebP, HEIC
Max 16MB per image
Auto-compressed for EA networks
Videos:
Max 1 video per message
Max 2 minutes (short video)
Max 64MB
Auto-transcoded to HLS by File Thunder
Files/Documents:
Max 100MB per file
Formats: PDF, DOCX, XLSX, ZIP, etc
ClamAV scanned before delivery
Available for 30 days then archived
8. Group Chat Flows
Create Group
User creates group:
Tap new group
Add members (min 2, max 500)
Set group name (required)
Set group photo (optional)
Tap create
Group created:
Members notified: "Kibuti amekuongeza kwenye kikundi"
All members see welcome message
Creator is automatically OWNER
Group Roles & Permissions
Role Add members Remove Send msg Delete msg Change info
──────────────────────────────────────────────────────────────────
OWNER ✅ ✅ ✅ Any msg ✅ ✅
ADMIN ✅ ✅ ✅ Any msg ✅ ✅
MEMBER ❌ ❌ ✅ Own only ✅ ❌
Group Size Limits
Free group: max 50 members
Pro group: max 500 members
At 500 members:
Consider using Broadcast Channel instead
Broadcast = one way (better for large audiences)
Group = two way (better for community)
Leave / Remove
Member leaves:
"Juma ameacha kikundi" shown in thread
No longer receives messages
Admin removes member:
"Amina ameondolewa na Kibuti" shown
Member notified: "Umeondolewa"
Deleted group (owner only):
All members removed
All messages deleted (for everyone)
Cannot be undone
9. Commerce DM Flows
Flow 1 — Buyer Initiates from Product Page
Step 1: Buyer on product page
Sees: [Chat na Muuzaji] button
Tap button
Step 2: Conversation opens
New DM opens OR existing conversation if already had one
Conversation type: COMMERCE
Conversation owner: SHOP (not personal)
Product card auto-appears:
┌──────────────────────────────────────┐
│ 📦 Samsung A15 │
│ TZS 450,000 │
│ Inapatikana: Vipande 12 │
│ TechStore │
│ [Jibu] [Angalia Bidhaa] │
└──────────────────────────────────────┘
NOTE: Price in card is frozen at this moment
Public price changes later → does NOT affect this card
Step 3: Negotiation
Buyer and seller exchange text messages
Normal conversation — no restrictions on text
Step 4: Agreement reached
Seller taps attach (+) → From My Shop
Selects product
Sets custom price for THIS buyer ONLY
Public product price: unchanged ✅
Sends price offer card
Step 5: Buyer receives offer
┌──────────────────────────────────────┐
│ 💰 Bei Maalum Kwako │
│ Samsung A15 │
│ ~~TZS 450,000~~ │
│ TZS 400,000 (-TZS 50,000) │
│ Inaisha: dakika 28 │
│ Idadi: [─ 1 +] │
│ [Kataa] [Endelea Kulipa →] │
└──────────────────────────────────────┘
Step 6: Buyer taps "Endelea Kulipa"
Redirected to checkout flow (OUTSIDE inbox)
Checkout at custom offer price
Quantity confirmed in checkout
Step 7: Order placed
Confirmation message appears in same thread:
┌──────────────────────────────────────┐
│ ✅ Agizo Limethibitishwa │
│ Ord #ORD-XYZ-789 │
│ Samsung A15 × 1 │
│ TZS 400,000 imelipwa │
│ [Fuatilia Agizo] │
└──────────────────────────────────────┘
Flow 2 — Seller Attaches from Inside Any Chat
Step 1: Seller inside any DM conversation
Taps attach (+) button
Menu appears:
📷 Picha
🎵 Sauti
📄 Faili
🏪 Kutoka Dukani ← this one
📅 Tukio
👥 Ununuzi wa Pamoja
Step 2: Seller taps "Kutoka Dukani"
Their shop product list opens
Seller browses and selects product
Sets custom price (optional)
Sets quantity limit (optional)
Adds note (optional): "Bei hii ni leo tu"
Taps Send
Step 3: Buyer receives offer card
Same offer card UI as Flow 1
Same checkout redirect
Same order confirmation in thread
Commerce DM Rules
✅ Buyer can initiate from any product page
✅ Seller can attach from inside any conversation
✅ Custom price is private to this buyer only
✅ Public product price never changes
✅ Checkout always happens outside inbox
✅ Order confirmation appears in thread
✅ Multiple offers allowed in one conversation
❌ Buyer cannot request specific price (only negotiate via text)
❌ Offer cannot be edited after sending (send new one instead)
❌ Offer cannot be forwarded to other conversations
❌ Order confirmation cannot be deleted or edited
10. Offer Session Flows
Offer Lifecycle
PENDING → offer sent, waiting for buyer response
│
├──▶ DECLINED buyer tapped "Kataa"
│ seller notified
│ seller can send new offer
│
├──▶ EXPIRED timer ran out
│ both parties notified in thread
│ seller can send new offer
│
▼
ACCEPTED → buyer tapped "Endelea Kulipa"
│ buyer enters checkout
▼
CHECKOUT → buyer in payment flow
│
├──▶ ABANDONED buyer left checkout without paying
│ offer returns to PENDING? NO
│ offer marked ABANDONED
│ seller must send new offer
│
▼
COMPLETED → order placed successfully
│ cannot be reversed here (order system handles)
▼
CANCELLED → order cancelled (handled by order system)
offer marked CANCELLED
Multiple Offers — Same Conversation
Seller can send multiple offers:
Each is independent session
Previous offers remain in thread with their status
Thread shows history:
┌──────────────────────────────────────┐
│ 💰 Bei Maalum: TZS 430,000 │
│ ❌ Ilikataliwa │
└──────────────────────────────────────┘
┌──────────────────────────────────────┐
│ 💰 Bei Maalum: TZS 410,000 │
│ ⏰ Imeisha muda │
└──────────────────────────────────────┘
┌──────────────────────────────────────┐
│ 💰 Bei Maalum: TZS 400,000 │
│ ✅ Imekubaliwa │
└──────────────────────────────────────┘
Offer Expiry Scenarios
Scenario 1 — Expires while buyer is reading:
Offer card shows live countdown timer
Timer hits 0:00
Card updates: "Imeisha muda"
Proceed button disabled automatically
Buyer sees: [Omba Bei Mpya] button
Scenario 2 — Expires while buyer in checkout:
Buyer was on checkout page when offer expired
Checkout validates offer at payment time
If expired: payment rejected
Buyer returned to conversation
"Bei yako imeisha muda. Omba bei mpya"
Scenario 3 — Seller sends same price again:
Allowed — new offer session created
New 30-minute timer
Both offers visible in thread (old + new)
Scenario 4 — Buyer tries to use expired offer link:
Deep link from notification opens expired offer
Shows: "Bei hii imeisha muda"
[Rudi kwa Mazungumzo] button
Price Security Rules
✅ Offer price stored server-side only
✅ Checkout validates price from server (not client)
✅ Client cannot manipulate price
✅ Offer is single-use (cannot complete twice)
✅ Offer belongs to specific buyer (others cannot use)
❌ Seller cannot change price after offer sent
(must send new offer)
❌ Buyer cannot change price
❌ Public product price never affected
11. Shareable Content
What Can Be Shared Into Any DM or Group
Content Who can share Restrictions
────────────────────────────────────────────────────────────
Text message Anyone None
Voice note Anyone Max 2 min (basic)
Image/Video Anyone Size limits
Product card Anyone Shows public price
Custom price offer Seller only Private — NOT forwardable
Event card Anyone None
Bei ya pamoja card Anyone None
VP Feed post Anyone None
VP Live stream Anyone None
Audio Space Anyone None
File/Document Anyone Max 100MB
Forwarding Rules
Forward chain tracking:
chain 1: "↪ Imetumwa kutoka Juma Mwangi"
chain 2-4: "↪ Imetumwa"
chain 5+: "↪ Imetumwa mara nyingi"
(misinformation warning — different icon)
Multi-forward limit:
Max 5 conversations per forward action
Prevents spam broadcasting
Cannot forward:
Custom price offers (private deal)
Order confirmations (private record)
Payment confirmations (private record)
System messages
12. Message Interactions
Editing Messages
Rules:
✅ Only original sender can edit
✅ Text messages only (not media captions yet)
✅ Within 15 minutes of sending
✅ Shows "Imehaririwa" label after edit
✅ Original send time stays the same
✅ Works in group chats (sender edits their own)
❌ Commerce cards cannot be edited (immutable)
❌ System messages cannot be edited
❌ Voice notes cannot be edited
❌ After 15 minutes: edit option disappears
UI:
Long press message → [Hariri] option (within 15 min)
After edit: message updates in place
"Imehaririwa" label appears below message
Position in thread unchanged (no jump to bottom)
Deleting Messages
Delete for Me:
✅ Any message, any time, no limit
✅ Only removed from your view
✅ Recipient still sees it
✅ Works on any message type
Delete for Everyone:
✅ Only original sender
✅ Within 15 minutes of sending
✅ Removed from all screens
✅ Shows: "Ujumbe huu umefutwa"
✅ Works in group chats
❌ Commerce cards: NOT allowed
❌ System messages: NOT allowed
❌ After 15 minutes: option disappears
Nothing is ever permanently deleted:
Soft delete only
For legal compliance + dispute resolution
Admin can view deleted messages for support cases
Users cannot recover deleted messages
Reactions
Rules:
✅ Any message can be reacted to
✅ One reaction per user per message
✅ Change reaction: send new emoji (replaces old)
✅ Remove reaction: tap same emoji again
✅ Works on commerce cards (reactions don't modify content)
❌ System messages: no reactions
Available emojis at launch:
❤️ 👍 😂 😮 😢 🙏
Expand to full emoji keyboard: Phase 3
Group reaction display:
1 type: "👍 3"
2 types: "👍 3 ❤️ 2"
3+ types: "👍 3 ❤️ 2 +2 zaidi"
Tap reaction to see who reacted:
Bottom sheet opens
List of names per emoji
Replying to Messages
Rules:
✅ Anyone in conversation can reply to any message
✅ Reply shows quoted original above new message
✅ Tap quote → scrolls to original
✅ Works in group chats
✅ Works on any message type
❌ Cannot reply to deleted messages
(shows: "Ujumbe umefutwa")
UI:
Swipe right on message → reply mode
OR long press → [Jibu] option
Quote appears in input field
Send normally
Forwarding
Rules:
✅ Anyone can forward allowed content
✅ Max 5 conversations per forward action
✅ Forward chain tracked and shown
✅ Original sender name shown (chain 1 only)
✅ Media: references original file (no re-upload)
❌ Custom price offers: not forwardable
❌ Order/payment records: not forwardable
❌ System messages: not forwardable
UI:
Long press message → [Tuma] option
Conversation picker opens
Select up to 5 conversations
Tap send
13. Voice & Video Call Flows
Initiating a Call
Kibuti taps call button on Juma's profile or conversation:
│
Permission check:
Relationship exists? ✅
Juma's privacy allows? ✅
Kibuti not blocked? ✅
│
TURN credentials generated (server)
│
Juma's phone rings:
┌──────────────────────────────────────┐
│ │
│ 📞 Simu Inayoingia │
│ │
│ [Kibuti Mwangi] │
│ @kibuti │
│ │
│ [❌ Kataa] [✅ Jibu] │
│ │
└──────────────────────────────────────┘
Works even if:
App is closed (FCM HIGH wakes it)
Screen is locked (full screen notification)
App is in background
During a Call — Controls
Voice call controls:
🔇 Mute/unmute microphone
🔊 Speaker on/off
📷 Enable camera (upgrade to video)
❌ End call
Video call controls:
🔇 Mute/unmute microphone
📷 Camera on/off
🔄 Switch camera (front/rear)
🖥️ Share screen
🔊 Speaker on/off
❌ End call
Switching Audio ↔ Video
Voice → Video:
Kibuti taps camera button during voice call
Juma sees: "Kibuti anataka kuongeza video"
Auto-accepted (based on Juma's settings)
OR Juma taps Accept
Video starts — same call session continues
Audio uninterrupted during upgrade
Video → Audio (manual):
Kibuti taps camera OFF
Video stops immediately for both
Audio continues
No renegotiation needed
Video → Audio (automatic):
Network degrades below video threshold
Video disabled automatically
Banner shown: "Video imezimwa — mtandao dhaifu"
Audio continues
Video resumes when network improves
Screen Sharing
Start screen share:
Tap screen share icon during video call
System permission dialog appears (Android/iOS)
"Ruhusu NexGate kunasa skrini yako?"
User accepts
Screen share starts
Other party sees your screen
During screen share:
Your camera: small PiP (picture in picture)
Their view: your screen (large) + your face (small)
Your view: normal call view + "Unaonyesha skrini" banner
Stop screen share:
Tap stop button
Returns to normal video call
Call Quality Indicators
Signal bars shown during call:
████ Excellent (WiFi / 4G strong)
███░ Good (4G)
██░░ Fair (3G) — may show quality banner
█░░░ Poor (2G) — video disabled, audio only
░░░░ Very poor — "Mtandao dhaifu sana" banner
Quality banner examples:
"Ubora wa sauti umepungua kwa sababu ya mtandao"
"Video imezimwa — data ndogo"
"Unaunganika tena..."
Call End Scenarios
Normal end:
One party taps end
Other party sees call ended
Duration shown in conversation: "Simu ya dakika 4:32"
Declined:
Juma taps Kataa
Kibuti sees: "Simu ilikataliwa"
Missed call notification NOT sent (was declined)
No answer (timeout 45 seconds):
Kibuti sees: "Hakujibu"
Juma sees: "Simu iliyokosekana kutoka Kibuti" notification
Network failure:
Both lose connection
App attempts reconnect (10 seconds)
If reconnect fails:
Call marked as FAILED
"Simu ilikatizwa" shown to both
Kibuti can redial
14. Group Call Flows
Starting a Group Call
From a group chat:
Tap call icon in group header
Choose: Voice only OR Video
All group members receive incoming call notification
Members who join → enter call
Members who don't → miss it (missed call shown)
From a 1:1 conversation:
Not supported directly
Must create group first
OR use "Add person" button during active 1:1 call
Add person to active 1:1 call:
During call → tap "Ongeza Mtu"
Pick from allowed contacts
They receive group call invitation
They join → 1:1 becomes group call
Group Call Limits
Voice only group call:
Max 8 participants (comfortable for 3G)
Up to 12 possible but discouraged on EA networks
Video group call:
Max 4 video feeds shown simultaneously
5th person onwards: audio only tile shown
Active speaker highlighted (larger tile)
Tap any tile to pin/feature them
Layout options:
Grid view: all tiles equal size
Speaker view: active speaker large, others small
Auto: switches based on who is talking
Group Call Permission Rules
Within a group chat:
Any member can start group call ✅
Any member can join ✅
No extra permission check needed
(group membership = call permission)
Adding someone outside the group:
Same call permission check as 1:1
Must have relationship (contact/follower/commerce)
If no relationship → cannot add
15. Offline & Notification Flows
Message Notification Levels
Level When FCM SMS after
──────────────────────────────────────────────────────────────
CRITICAL Order placed/paid/failed ✅ 0 min
Delivery update
Payment confirmation
IMPORTANT Commerce DM from buyer ✅ 10 min
Custom price offer received
Bei ya pamoja threshold reached
Call missed (commerce context)
NORMAL Regular DM ✅ Never
Group message
Reaction
Follow notification
Offline Message Delivery
User offline — message sent to them:
│
├── FCM HIGH priority push fired immediately
│ (all message levels)
│
├── CRITICAL: Textfy SMS sent simultaneously
│
├── IMPORTANT: Textfy SMS after 10 min
│ (if FCM not acknowledged)
│
└── Message queued in RabbitMQ
User comes back online:
│
├── WS connects → presence registered
├── Queued messages drained (priority order)
│ CRITICAL first → IMPORTANT → NORMAL
│
└── Catch-up banner shown:
"Umekosa: maagizo 2, ujumbe 8"
[Angalia Maagizo] [Ona Ujumbe]
Textfy SMS Templates
Order placed (to seller):
"NexGate: Agizo jipya kutoka [Buyer]!
TZS [amount]. Kagua: nexgate.app/orders/[id]"
Payment received:
"NexGate: Malipo ya TZS [amount]
yamepokelewa kutoka [Buyer].
nexgate.app/wallet"
Commerce DM (to seller):
"NexGate: [Buyer] anakuuliza kuhusu
[Product]. Jibu: nexgate.app/chat/[id]"
Bei ya pamoja:
"NexGate: Watu [n]/[target] wamejiunga!
nexgate.app/group-buy/[id]"
All SMS:
Swahili first ✅
Deep link included ✅
Shop name shown (not staff name) ✅
16. Privacy & Safety
Privacy Settings Matrix
Setting Options Default
────────────────────────────────────────────────────────────────
Who can message me Everyone / Followers Followers
+ Contacts / Contacts + Contacts
/ Nobody
Who can call me Followers+Contacts / Contacts
Contacts / Nobody only
Last seen Everyone / Contacts / Contacts
Nobody
Profile picture Everyone / Contacts / Everyone
Nobody
Be found by phone number On / Off On
Contact sync On / Off Off
Read receipts (blue ticks) On / Off On
(off = others see delivered but not read)
Block System
User A blocks User B:
User B cannot:
❌ See User A's profile
❌ Send messages to User A
❌ Call User A
❌ See User A in search
❌ See User A's VP Feed posts
❌ See User A's online status
User B sees:
Profile: "Mtumiaji huyu hayupo"
Messages: appear sent but never delivered
User A can:
✅ Unblock anytime from Settings
✅ See User B's profile still (A blocked B — not reverse)
Group chats:
If in same group: messages visible but
cannot DM or call each other directly
Admin can remove either from group
Report System
Report options:
Spam
Harassment / Vitisho
Inappropriate content
Fake account
Scam / Udanganyifu
Other
Report flow:
Long press message → [Ripoti]
OR profile → [...] → [Ripoti]
Choose reason
Optional: add description
Submit
After report:
User not notified they were reported
Report goes to NexGate moderation queue
Automatic temporary restrictions may apply
for high-volume reporters
Block on report:
"Ripoti na Zuia" option available
Blocks immediately + sends report
Safety for Women — Specific Features
This is important for EA platform trust:
Silence unknown callers:
ON by default for new accounts
Calls from non-contacts ring silently
User sees missed call — no disruption
Call rate limiting:
3 unanswered calls per day to same person
Automatic block after 4th attempt
Quick block during call:
One tap visible during any call
Ends + reports + blocks in single action
Message request system:
Strangers cannot freely DM
Must send request first
User controls who enters their inbox
Default privacy settings:
New accounts: strict defaults
Users open up if they choose
Better to protect by default
17. Shop Inbox & Staff Access
Shop Tiers
Basic shop (free):
Owner manages inbox alone
No staff assignment
One active stream at a time
Standard features
Pro shop (paid):
Staff roles unlocked
Multiple staff in inbox
Advanced analytics
Priority support
Audit logs
Staff Roles
Role Inbox Products Analytics Settings Staff mgmt
──────────────────────────────────────────────────────────────────
OWNER ✅ ✅ ✅ ✅ ✅
MANAGER ✅ ✅ ✅ ❌ ❌
SUPPORT_AGENT ✅ ❌ ❌ ❌ ❌
READ_ONLY 👁️ view ❌ ❌ ❌ ❌
Staff Identity Rules
Staff responds to customer:
Customer sees: "TechStore" (shop name)
Customer NEVER sees: "Amina" (staff name)
Staff identity is internal only
Audit log (internal):
Which staff member responded
Timestamp
Visible to OWNER and MANAGER only
Not visible to customers
Staff cannot:
❌ Reveal personal phone number to customers
❌ Switch conversation to personal DM
❌ Access owner's personal inbox
❌ Access other shops they're not assigned to
Multiple Shops — Inbox Separation
Owner with 3 shops:
Each shop = separate inbox tab
Each shop = separate conversation records
Each shop = separate staff assignments
Staff for Shop A cannot see Shop B
Owner sees all (as owner of all)
Commerce DM routing:
Buyer messages about Product A (TechStore product)
→ Goes to TechStore inbox
→ NOT to ClothingHub inbox
→ NOT to owner's personal inbox
Correctly routed by product ownership
18. Notification Settings
Per-Conversation Settings
Each conversation has:
Notifications:
○ All messages
○ Mentions only (groups)
○ Muted (until: 8 hours / 1 week / forever)
Media auto-download:
○ WiFi only
○ WiFi + Mobile data
○ Never
Global Notification Settings
Message notifications: On / Off
Call notifications: On / Off
Reaction notifications: On / Off
Group notifications: On / Off
Commerce notifications: On / Off (cannot turn off CRITICAL)
Sound: Default / Custom / Silent
Vibration: On / Off
In-app preview: Show / Hide content
CRITICAL Notifications — Always On
These cannot be turned off by user:
Order placed (seller receives)
Payment confirmed (buyer receives)
Payment failed (buyer receives)
Order cancelled (both receive)
Reason:
Financial events
User could miss critical money information
Platform liability without guaranteed delivery
Textfy SMS fallback ensures they always arrive
19. Edge Cases & Scenarios
Messaging Edge Cases
User deletes their account:
Their messages remain visible in conversations
Name shows: "Mtumiaji aliyefuta akaunti"
Profile picture: default avatar
Cannot be messaged or called
User changes username:
All conversations update automatically
Old username links still work (redirect)
No broken references
Very long message (>4000 chars):
Truncated in thread: first 200 chars + "...Soma zaidi"
Tap to expand full message
Not split into multiple messages
Same message sent twice (duplicate):
Detected by temp_id
Only one stored in DB
User sees single message (not duplicate)
Message sent to blocked user:
Appears sent (single tick)
Never delivered (stays at single tick)
User not informed of block
Commerce Edge Cases
Product goes out of stock while offer pending:
Offer still valid (was frozen at send time)
Checkout validates stock at payment time
If out of stock at payment:
Payment rejected
"Bidhaa hii imeisha"
Buyer returned to conversation
Seller notified to resend offer or cancel
Product price changes while offer pending:
Offer price locked at creation ✅
Public price change does NOT affect offer
Buyer pays the offer price always
Seller deletes product while offer pending:
Offer still valid (snapshot frozen)
Checkout validates product existence
If product deleted at payment:
Payment rejected
"Bidhaa hii haipatikani tena"
Two buyers get offers for last item:
Both offers exist simultaneously
First to complete checkout gets the item
Second buyer's payment rejected:
"Bidhaa hii imeisha"
Standard e-commerce race condition handling
Seller sends offer to wrong person:
Cannot retract offer
Offer expires naturally
Seller can contact NexGate support if urgent
Buyer in checkout when offer expires:
Payment attempt fails
"Bei yako imeisha muda"
Must request new offer from seller
Call Edge Cases
Call drops mid-conversation:
WebRTC detects loss
Auto-reconnect attempted (10 seconds)
If reconnect success: call continues
If reconnect fails: call ended
Both see: "Simu ilikatizwa"
Kibuti can redial immediately
Both call each other simultaneously:
Race condition — both see "Simu inayoingia"
System picks one (first to reach server)
Other cancelled automatically
One call established
Call during active call:
Second call: goes to missed calls
Busy signal not sent (no UX for this)
After first call: notification of missed call
Phone runs out of battery during call:
WebRTC detects disconnect
Same as network drop
Other party sees: "Simu ilikatizwa"
Someone calls during Do Not Disturb (DND):
DND on device: depends on device DND rules
NexGate mute: call goes to missed calls silently
CRITICAL commerce calls: bypass mute (configurable)
Group Chat Edge Cases
Owner leaves group:
Must transfer ownership first
OR system auto-assigns to oldest admin
OR if no admins: oldest member becomes owner
Last person leaves group:
Group archived automatically
Messages preserved for 30 days
Then permanently deleted
Adding member who blocked you:
Cannot add blocked users to groups
System rejects silently
No error shown (privacy)
Member blocked in group:
They stay in group (cannot remove via block)
Cannot DM each other
Can both still see group messages
Admin can remove either from group
Summary
NexGate messaging is built for East African social commerce — where every conversation can become a transaction, and every transaction has a conversation behind it.
The permission system is designed to be safe by default: contacts and mutual followers can communicate freely, strangers go through message requests, and calls require an established relationship. Commerce contexts create natural communication permissions — buyers and sellers can always reach each other through shop identities that protect personal privacy.
Contact sync is optional, privacy-preserving (hashed on device), and exists alongside multiple other discovery mechanisms. NexGate does not need contact sync to function — it is one convenience feature among many.
Commerce offer sessions are the unique heart of NexGate messaging — a formal negotiated deal between a specific buyer and seller, with a locked price, expiry timer, and full lifecycle tracking. The public product price is never affected. Checkout always happens outside the inbox. Everything is immutable for legal and dispute reasons.
The safety system protects users (especially women) through strict defaults, rate limiting, quick block options, and a message request system that gives users control over who enters their inbox.
NexGate Messaging — Product Requirements & Feature Flows v1.0 QBIT SPARK | Rules · Flows · Permissions · Scenarios · Edge Cases
No comments to display
No comments to display