link-stack/packages/zammad-addon-bridge
Darren Clarke 3d8f794cab Add user ID support for Baileys 7 LIDs and Signal UUIDs
Baileys 7 uses LIDs (Linked IDs) instead of phone numbers in remoteJid for
some messages. This caused messages to be matched to wrong tickets because
the LID was used as the sender identifier. This commit adds proper support
for both phone numbers and user IDs across WhatsApp and Signal channels.

Changes:

Database:
- Add migration for whatsapp_user_id and signal_user_id fields on users table

Zammad controllers:
- Update user lookup with 3-step fallback: phone → dedicated user_id field →
  user_id in phone field (legacy)
- Store user IDs in dedicated fields when available
- Update phone field when we receive actual phone number for legacy records
- Fix redundant condition in Signal controller

Bridge services:
- Extract both phone (from senderPn/participantPn) and LID (from remoteJid)
- Send both identifiers to Zammad via webhooks
- Use camelCase (userId) in bridge-whatsapp, convert to snake_case (user_id)
  in bridge-worker for Zammad compatibility

Baileys 7 compliance:
- Remove broken loadAllUnreadMessages() call (removed in Baileys 7)
- Return descriptive error directing users to use webhooks instead

Misc:
- Add docs/ to .gitignore
2026-01-15 13:08:56 +01:00
..
src Add user ID support for Baileys 7 LIDs and Signal UUIDs 2026-01-15 13:08:56 +01:00
package.json Bump version to 3.4.0-beta.4 2026-01-14 11:33:11 +01:00
README.md WhatsApp/Signal/Formstack/admin updates 2025-11-21 14:55:28 +01:00

CDR Bridge Zammad Addon

Overview

The CDR Bridge addon integrates external communication channels (Signal, WhatsApp, Voice) into Zammad, supporting both the classic UI and the new Vue-based desktop/mobile interfaces.

Features

Signal Channel Integration

  • Reply button on customer Signal messages
  • "Add Signal message" button in ticket reply area
  • 10,000 character limit with warning at 5,000
  • Plain text format with attachment support
  • Full integration with both classic and new Vue-based UI

WhatsApp Channel Integration

  • Reply button on customer WhatsApp messages
  • "Add WhatsApp message" button in ticket reply area
  • 4,096 character limit with warning at 3,000
  • Plain text format with attachment support
  • Full integration with both classic and new Vue-based UI

Voice Channel Support

  • Classic UI implementation maintained
  • New UI support ready for future implementation

Channel Restriction Settings (NEW)

  • Control which reply channels appear in the UI
  • Configurable via cdr_link_allowed_channels setting
  • Acts as a whitelist while preserving contextual logic
  • Empty setting falls back to default Zammad behavior

Installation

Prerequisites

  • Zammad 6.0+ (for new UI support)
  • CDR Bridge backend services configured
  • Signal/WhatsApp/Voice services running

Installation Steps

  1. Build the addon package:
cd packages/zammad-addon-bridge
npm run build
  1. Install in Zammad:
# Copy the generated .zpm file to your Zammad installation
cp dist/bridge-vX.X.X.zpm /opt/zammad/

# Install using Zammad package manager
zammad run rails r "Package.install(file: '/opt/zammad/bridge-vX.X.X.zpm')"

# Restart Zammad
systemctl restart zammad

Configuration

Channel Restriction Settings

Control which reply channels are available in the ticket interface:

# Rails console
Setting.set('cdr_link_allowed_channels', 'note,signal message')  # Signal only
Setting.set('cdr_link_allowed_channels', 'note,whatsapp message') # WhatsApp only
Setting.set('cdr_link_allowed_channels', 'note,signal message,whatsapp message') # Both
Setting.set('cdr_link_allowed_channels', '') # Default behavior (all channels)

How it works:

  • The setting acts as a whitelist of allowed channels
  • Channels must be both in the whitelist AND contextually appropriate
  • For example, Signal replies only appear for tickets that originated from Signal
  • Empty or unset falls back to default Zammad behavior
  • Changes take effect immediately (browser refresh required)

Development

Adding New Channels

  1. Create TypeScript plugin in app/frontend/shared/entities/ticket-article/action/plugins/
  2. Add desktop UI plugin in app/frontend/apps/desktop/pages/ticket/components/TicketDetailView/article-type/plugins/
  3. Add corresponding backend implementation
  4. Create database migrations in src/db/addon/bridge/

Building the Package

# Update version and changelog in bridge-skeleton.szpm
# Build the package
make
# Output: dist/bridge-vX.X.X.szpm

Create a New Migration

Helper script to create new migrations (requires python inflection library):

# Install dependency
apt install python3-inflection  # Debian/Ubuntu
# Or: pip install --user inflection

# Create migration
make new-migration

Compatibility

  • Zammad 6.0+: Both Classic and New UI
  • Browser Support: All modern browsers

API Endpoints

Voice Channel

POST to submission endpoint with Authorization: SUBMISSION_TOKEN header:

{
  "startTime": "ISO date string",
  "endTime": "ISO date string",
  "to": "fully qualified phone number",
  "from": "fully qualified phone number",
  "duration": "recording duration string",
  "callSid": "unique call identifier",
  "recording": "base64 encoded binary",
  "mimeType": "binary mime-type string"
}

Signal/WhatsApp Channels

Handled via CDR Bridge backend services - see bridge documentation for API details.

License

License GNU AGPL v3.0

This is a free software project licensed under the GNU Affero General Public License v3.0 (GNU AGPLv3) by The Center for Digital Resilience and Guardian Project.