matrix-bridge-teams 0.1.0

A bridge between Matrix and Microsoft Teams written in Rust
# matrix-bridge-teams

A Matrix <-> Microsoft Teams bridge written in Rust.

[中文文档](README_CN.md)

Maintainer: `Palpo Team`  
Contact: `chris@acroidea.com`

## Overview

- Rust-only implementation for Matrix <-> Microsoft Teams bridging
- Matrix appservice + Microsoft Graph API integration
- HTTP endpoints for health/status/metrics and provisioning
- Database backends: PostgreSQL, SQLite, and MySQL (feature-gated)
- Dockerfile for local build and container runtime

## Repository Layout

- `src/`: bridge implementation
- `config/config.sample.yaml`: sample configuration
- `migrations/`: database migrations
- `Dockerfile`: multi-stage container build

## Prerequisites

- Rust toolchain (compatible with the project; Docker build uses Rust 1.93)
- A Matrix homeserver configured for appservices
- Microsoft Teams tenant and app registration
- Database: PostgreSQL, SQLite, or MySQL

## Quick Start (Local)

1. Create your config file:

```bash
cp config/config.sample.yaml config.yaml
```

2. Set the required values in `config.yaml`:
   - `bridge.domain`
   - `auth.tenant_id`, `auth.client_id`, `auth.client_secret`
   - `database.url` (or `database.conn_string` / `database.filename`)
   - registration values via either:
     - `registration.id`, `registration.as_token`, `registration.hs_token`, or
     - `teams-registration.yaml` next to your config file, or
     - env vars (see Environment Overrides below)

3. Run:

```bash
cargo check -p matrix-bridge-teams
cargo test -p matrix-bridge-teams --no-run
cargo run -p matrix-bridge-teams
```

4. Verify:

```bash
curl http://127.0.0.1:9006/health
curl http://127.0.0.1:9006/status
```

## Configure Microsoft Teams (Step by Step)

1. Go to https://portal.azure.com/ and create a new App Registration:
   - Navigate to **Azure Active Directory** > **App registrations** > **New registration**
   - Name: "Matrix Bridge Teams"
   - Supported account types: Choose based on your needs
   - Redirect URI: `http://localhost:8080/callback` (for initial setup)

2. After registration, copy:
   - **Application (client) ID** (for `auth.client_id`)
   - **Directory (tenant) ID** (for `auth.tenant_id`)

3. Create a client secret:
   - Go to **Certificates & secrets** > **New client secret**
   - Copy the secret value (for `auth.client_secret`)

4. Configure API permissions:
   - Go to **API permissions** > **Add a permission**
   - Select **Microsoft Graph** > **Application permissions**
   - Add these permissions:
     - `Chat.Read.All` or `Chat.ReadWrite.All`
     - `ChannelMessage.Read.All` or `ChannelMessage.ReadWrite.All`
     - `Team.ReadBasic.All`
     - `User.Read.All`
   - Grant admin consent for your organization

5. Fill the auth section in `config.yaml`:

```yaml
auth:
  tenant_id: "YOUR_TENANT_ID"
  client_id: "YOUR_CLIENT_ID"
  client_secret: "YOUR_CLIENT_SECRET"
```

6. To bridge a specific Teams channel, collect IDs from:
   - Team ID and Channel ID from the Teams URL or API

## Configure Matrix / Palpo (Step by Step)

1. In Palpo config (`palpo.toml`), set your server name and appservice registration directory:

```toml
server_name = "example.com"
appservice_registration_dir = "appservices"
```

2. Place your bridge registration file under that directory, for example:
   - `appservices/teams-registration.yaml`
3. Ensure tokens are consistent between Palpo registration and bridge config:
   - `as_token` in registration == bridge appservice token
   - `hs_token` in registration == bridge homeserver token
4. Ensure bridge homeserver fields point to Palpo:

```yaml
bridge:
  domain: "example.com"
  homeserver_url: "http://127.0.0.1:6006" # Replace with your Palpo URL
```

5. Start Palpo, then start this bridge.
6. Confirm connectivity both ways:
   - Palpo must reach bridge registration `url` (for appservice transactions)
   - Bridge must reach `bridge.homeserver_url` (your Palpo endpoint)

Notes:

- If Palpo and bridge run in different containers/hosts, do not use loopback addresses unless they are in the same network namespace.
- For Docker Desktop, `host.docker.internal` is often useful when bridge container needs to reach host Palpo.

## Configure Matrix / Synapse (Step by Step)

1. Set your Matrix-facing values in `config.yaml`:

```yaml
bridge:
  domain: "example.com"
  homeserver_url: "https://matrix.example.com"
  bind_address: "0.0.0.0"
  port: 9006
```

2. Create `teams-registration.yaml` next to `config.yaml` (or set `REGISTRATION_PATH`):

```yaml
id: "teams"
url: "http://127.0.0.1:9006"
as_token: "CHANGE_ME_AS_TOKEN"
hs_token: "CHANGE_ME_HS_TOKEN"
sender_localpart: "_teams_"
rate_limited: false
protocols: ["msteams"]
namespaces:
  users:
    - exclusive: true
      regex: "@_teams_.*:example.com"
  aliases:
    - exclusive: true
      regex: "#_teams_.*:example.com"
  rooms: []
```

3. In Synapse `homeserver.yaml`, add:

```yaml
app_service_config_files:
  - /path/to/teams-registration.yaml
```

4. Ensure the registration `url` is reachable by Synapse.
   - Same host: `http://127.0.0.1:9006` is fine.
   - Different host/container: use a routable address.
5. Restart Synapse, then start this bridge.

Notes:

- `bridge.domain` should match your Matrix server domain (right side of MXIDs).
- `bridge.homeserver_url` should be the real homeserver URL (preferably public HTTPS if Teams needs to fetch media).
- If `registration` fields are missing in `config.yaml`, values are loaded from `teams-registration.yaml`.

## Docker

Build:

```bash
docker build -t ghcr.io/palpo-im/matrix-bridge-teams:main -f Dockerfile .
```

Run (expects `/data/config.yaml` in the mounted directory):

```bash
docker run --rm \
  -p 9006:9006 \
  -v "$(pwd)/config:/data" \
  -e CONFIG_PATH=/data/config.yaml \
  ghcr.io/palpo-im/matrix-bridge-teams:main
```

Notes:

- Container listens on `0.0.0.0:9006` by default.
- Health check endpoint: `GET /health`
- Default registration file path is `teams-registration.yaml` resolved relative to `CONFIG_PATH`.

## Database Configuration

The bridge auto-detects DB type from connection string prefix:

- `postgres://` or `postgresql://` -> PostgreSQL
- `sqlite://` -> SQLite
- `mysql://` or `mariadb://` -> MySQL / MariaDB
- anything else -> PostgreSQL fallback

MySQL backend note:

- Build with the `mysql` feature enabled, e.g. `cargo run -p matrix-bridge-teams --features mysql`
- Install `libmysqlclient` (or MariaDB Connector/C) so `mysqlclient-sys` can link

Examples:

```yaml
database:
  url: "postgresql://user:password@localhost:5432/matrix_bridge"
  max_connections: 10
  min_connections: 1
```

```yaml
database:
  url: "sqlite://./data/matrix-bridge.db"
```

```yaml
database:
  url: "mysql://user:password@localhost:3306/matrix_bridge"
  max_connections: 10
  min_connections: 1
```

## Environment Overrides

The following environment variables are supported:

- `CONFIG_PATH`
- `REGISTRATION_PATH`
- `APPSERVICE_TEAMS_AUTH_TENANT_ID`
- `APPSERVICE_TEAMS_AUTH_CLIENT_ID`
- `APPSERVICE_TEAMS_AUTH_CLIENT_SECRET`
- `APPSERVICE_TEAMS_REGISTRATION_ID`
- `APPSERVICE_TEAMS_REGISTRATION_AS_TOKEN`
- `APPSERVICE_TEAMS_REGISTRATION_HS_TOKEN`
- `APPSERVICE_TEAMS_REGISTRATION_SENDER_LOCALPART`

## Features

### Current Features

- [x] Basic Matrix AppService integration
- [ ] Microsoft Teams Graph API integration
- [ ] Message bridging (Matrix <-> Teams)
- [ ] User synchronization
- [ ] Room/Channel mapping
- [ ] File/Attachment handling
- [ ] Edit/Delete message support
- [ ] Typing notifications
- [ ] Read receipts
- [ ] Presence synchronization

### Planned Features

- [ ] Thread support
- [ ] Reaction bridging
- [ ] Rich text formatting
- [ ] Mentions (@user)
- [ ] End-to-end encryption support
- [ ] Multi-tenant support

## Development

### Building

```bash
cargo build
```

### Testing

```bash
cargo test
```

### Linting

```bash
cargo clippy
cargo fmt -- --check
```

## Contributing

Contributions are welcome! Please read our contributing guidelines before submitting PRs.

## License

Apache-2.0

## Acknowledgments

- Based on [matrix-bridge-discord]https://github.com/palpo-im/matrix-bridge-discord architecture
- Inspired by [mautrix-teams]https://github.com/mautrix/teams
- Uses [matrix-bot-sdk]https://github.com/matrix-org/matrix-rust-sdk
- Integrates with [Microsoft Graph API]https://docs.microsoft.com/en-us/graph/

## Support

- Issues: https://github.com/palpo-im/matrix-bridge-teams/issues
- Email: chris@acroidea.com