Matrix bridge integration plan
Original implementation plan for routing Claire messaging platforms through Matrix bridges.
Overview#
Add Matrix bridge support alongside existing direct adapters. A PLATFORM_MODE environment variable switches between:
- `direct` (current) - Native platform libraries (whatsapp-web.js, telegraf, etc.)
- `matrix` (new) - Matrix bridges via Synapse homeserver (mautrix-*)
Both modes use the same IPlatformAdapter interface - the client/API doesn't know the difference.
Architecture#
┌─────────────────────────────────────────────────────────────────────┐
│ Claire Backend │
│ PlatformManager (existing) │
│ │ │
│ ┌───────────────┴───────────────┐ │
│ ▼ ▼ │
│ PLATFORM_MODE=direct PLATFORM_MODE=matrix │
│ │ │ │
│ ┌─────────┴─────────┐ ┌───────┴───────┐ │
│ │ Direct Adapters │ │ MatrixAdapter │ │
│ │ (existing code) │ │ (new code) │ │
│ └─────────┬─────────┘ └───────┬───────┘ │
│ │ │ │
│ Platform APIs Matrix Homeserver │
│ (whatsapp-web.js, (Synapse + mautrix │
│ telegraf, etc.) bridges in Docker) │
└─────────────────────────────────────────────────────────────────────┘Why Matrix Bridges?#
| Aspect | Direct Adapters | Matrix Bridges |
|---|---|---|
| Reliability | Untested | Battle-tested by Beeper |
| Maintenance | We maintain | Community maintained |
| Edge cases | We handle | Already handled |
| Setup | npm install | Docker + config |
| Resource usage | Light | ~2-4GB RAM |
Files to Create#
server/src/adapters/matrix/
├── index.ts # MatrixBridgeAdapter class
├── types.ts # Matrix-specific types
├── client.ts # matrix-js-sdk wrapper
├── room-mapper.ts # Matrix rooms ↔ platform chats
├── user-mapper.ts # Ghost users ↔ platform contacts
├── event-converter.ts # Matrix events → UnifiedMessage
└── bridge-auth/
├── index.ts # Auth flow coordinator
├── whatsapp.ts # QR code flow via bridge bot
├── telegram.ts # Phone login flow
└── instagram.ts # Cookie auth flow
docker/matrix/
├── docker-compose.matrix.yml # Synapse + all bridges
├── synapse/
│ └── homeserver.yaml.template
└── bridges/
├── whatsapp/config.yaml.template
├── telegram/config.yaml.template
└── instagram/config.yaml.template
supabase/migrations/
└── 20260206_add_matrix_mappings.sqlFiles to Modify#
| File | Changes |
|---|---|
server/src/config/index.ts | Add PLATFORM_MODE, Matrix env vars |
server/src/adapters/index.ts | Add setMatrixMode() to PlatformManager |
server/src/index.ts | Conditional adapter initialization |
server/package.json | Add matrix-js-sdk dependency |
New Dependencies#
{
"matrix-js-sdk": "^34.0.0"
}Implementation Phases#
Phase 1: Configuration & Types (~1 hour)#
- Add to
server/src/config/index.ts: ``typescript PLATFORM_MODE: z.enum(['direct', 'matrix']).default('direct'), MATRIX_HOMESERVER_URL: z.string().url().optional(), MATRIX_SERVER_NAME: z.string().optional(), MATRIX_ADMIN_TOKEN: z.string().optional(),`` - Create
server/src/adapters/matrix/types.tswith Matrix-specific interfaces
Phase 2: MatrixBridgeAdapter Core (~3 hours)#
- Create
server/src/adapters/matrix/index.ts: - Extends
BasePlatformAdapter - Connects to Synapse via
matrix-js-sdk - Handles
RoomEvent.Timelinefor incoming messages - Manages control rooms for bridge bot commands
- Key methods:
initialize()- Connect to homeserver, start synccreateSession()- Create control room with bridge bot, send login commandsendMessage()- Find Matrix room, send via SDKgetChats()- List rooms with bridge ghost users
Phase 3: Room & User Mappers (~2 hours)#
- Create
room-mapper.ts: - Maps
platform:chatId↔matrixRoomId - Identifies rooms by ghost user presence (e.g.,
@_wa_12345:server.com) - Create
user-mapper.ts: - Converts ghost users to platform contacts
- Ghost patterns:
@_wa_*,@_telegram_*,@_instagram_* - Create
event-converter.ts: - Converts Matrix
m.room.messageevents toUnifiedMessage
Phase 4: Bridge Auth Flows (~2 hours)#
- Create
bridge-auth/whatsapp.ts: - Send
loginto bridge bot - Parse QR code from
m.imageresponse - Emit
qr_codeevent for client - Create
bridge-auth/telegram.ts: - Send
login +phoneto bridge bot - Handle verification code prompt
- Create
bridge-auth/instagram.ts: - Send
login-cookie <cookies>to bridge bot
Phase 5: Docker Infrastructure (~2 hours)#
- Create
docker/matrix/docker-compose.matrix.yml: ``yaml services: synapse: image: matrixdotorg/synapse:latest postgres-synapse: image: postgres:15-alpine mautrix-whatsapp: image: dock.mau.dev/mautrix/whatsapp:latest mautrix-telegram: image: dock.mau.dev/mautrix/telegram:latest mautrix-instagram: image: dock.mau.dev/mautrix/meta:latest`` - Create bridge config templates with environment variable substitution
- Create
scripts/init-bridges.shfor registration file generation
Phase 6: Mode Switching & Testing (~2 hours)#
- Update
server/src/index.ts: ``typescript if (matrixConfig.enabled) { const matrixAdapter = new MatrixBridgeAdapter(config); platformManager.setMatrixMode(matrixAdapter); } else { // existing direct adapter registration }`` - Update
PlatformManager.getAdapter()for matrix mode - Write integration tests with mock Matrix server
Database Migration#
-- Matrix room mappings for bridge mode
CREATE TABLE public.matrix_room_mappings (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
user_id UUID NOT NULL REFERENCES public.users(id),
session_id TEXT NOT NULL,
platform platform_type NOT NULL,
matrix_room_id TEXT NOT NULL,
platform_chat_id TEXT NOT NULL,
is_control_room BOOLEAN DEFAULT FALSE,
UNIQUE(matrix_room_id)
);Environment Variables#
# Platform Mode
PLATFORM_MODE=direct # or 'matrix'
# Matrix Configuration (required when PLATFORM_MODE=matrix)
MATRIX_HOMESERVER_URL=http://localhost:8008
MATRIX_SERVER_NAME=claire.local
MATRIX_ADMIN_TOKEN=replace_with_admin_token
# Telegram API (required for mautrix-telegram)
TELEGRAM_API_ID=12345
TELEGRAM_API_HASH=replace_with_telegram_api_hashPlatform Auth Flows (Matrix Mode)#
| Platform | Bridge Bot | Auth Command | User Action |
|---|---|---|---|
| @whatsappbot | login | Scan QR with phone | |
| Telegram | @telegrambot | login +phone | Enter SMS code |
| @instagrambot | login-cookie <c> | Extract browser cookies | |
| iMessage | N/A | N/A | Not recommended via Matrix |
iMessage Note#
iMessage via mautrix-imessage is NOT recommended for server deployment:
- Requires local macOS machine with SIP disabled
- Cannot run in Docker
- Keep using direct iMessage adapter instead
Verification#
- Start Matrix stack:
docker compose -f docker/matrix/docker-compose.matrix.yml up -d - Set env:
PLATFORM_MODE=matrix - Start server:
bun run dev - Test WhatsApp:
POST /platforms/whatsapp/connect→ Get QR code- Scan with phone
- Send message → Verify received in Claire
- Test Telegram:
POST /platforms/telegram/connectwith phone number- Enter verification code
- Message bot → Verify received
- Run tests:
bun test src/adapters/matrix
Critical Files#
server/src/adapters/types.ts- IPlatformAdapter interface to implementserver/src/adapters/base-adapter.ts- Base class to extendserver/src/adapters/index.ts- PlatformManager to modifyserver/src/config/index.ts- Config schema to extendserver/src/index.ts- Server startup to modify
Estimated Time#
| Phase | Time |
|---|---|
| Phase 1: Config & Types | 1 hour |
| Phase 2: MatrixBridgeAdapter | 3 hours |
| Phase 3: Mappers | 2 hours |
| Phase 4: Auth Flows | 2 hours |
| Phase 5: Docker | 2 hours |
| Phase 6: Testing | 2 hours |
| Total | ~12 hours |
Rollback Plan#
If Matrix mode has issues:
- Set
PLATFORM_MODE=direct - Restart server
- Direct adapters resume immediately
- No data loss - sessions stored separately by mode