# 聊天室（訊息）功能部署說明

聊天功能由 `/var/www/html/vpn` 完整移植而來（私訊／群組、端對端加密、貼圖、語音/視訊通話、跨組織聊天、Web Push）。
架構細節見 vpn 專案的 `docs/messaging-architecture.md`；本檔只記錄 exam 站上線需要的動作與和 vpn 的差異。

## 需要 root 的三個步驟（尚未執行）

1. **Supervisor 啟動 Reverb**（本站用 8082；vpn=8080、portal=8081）：

   `/etc/supervisor/conf.d/exam-reverb.conf`
   ```ini
   [program:exam-reverb]
   process_name=%(program_name)s
   command=/usr/bin/php /var/www/html/exam/artisan reverb:start --host=127.0.0.1 --port=8082
   autostart=true
   autorestart=true
   stopasgroup=true
   killasgroup=true
   user=www-data
   numprocs=1
   redirect_stderr=true
   stdout_logfile=/var/www/html/exam/storage/logs/reverb.log
   stdout_logfile_maxbytes=20MB
   stdout_logfile_backups=5
   stopwaitsecs=10
   ```
   `sudo supervisorctl reread && sudo supervisorctl update`

2. **Apache**：在 `/etc/apache2/sites-available/pake.conf` 的 `*:443` VirtualHost 內加入（`mod_proxy_wstunnel` 已啟用）：
   ```apache
   ProxyPass        "/app/"  "ws://127.0.0.1:8082/app/"
   ProxyPassReverse "/app/"  "ws://127.0.0.1:8082/app/"
   ```
   `sudo apachectl configtest && sudo systemctl reload apache2`

3. 確認 `.env` 的 `BROADCAST_CONNECTION=reverb`（已設定）。**Reverb 沒啟動時，傳訊息的廣播會失敗**，所以步驟 1 要先做。

## 已完成
- `composer require laravel/reverb kreait/laravel-firebase`
- 45 個 migration 已在 `exam_pake` 執行（聊天相關資料表、`users.avatar_path`、`user_ui_preferences`、`system_settings`）
- `.env` 已加入 `REVERB_*`（本站專屬的 app id/key/secret）、`TURN_*`、`FIREBASE_CREDENTIALS`、`APNS_*`、`FEDERATION_*`

## 選用設定（留空不影響站內聊天）
| 變數 | 用途 |
|---|---|
| `TURN_SECRET`（及 `TURN_HOST`/`TURN_PORT`） | 語音/視訊通話的 TURN 中繼，需與 coturn 的 `static-auth-secret` 一致；未設定時通話取得 TURN 憑證會回 500 |
| `FIREBASE_CREDENTIALS` / `APNS_*` | 原生 App 推播（本站目前沒有員工版 App，見下） |
| `FEDERATION_*` | 跨組織聊天，設定後執行 `php artisan federation:register`；未填 `FEDERATION_ORG_ID` 時排程自動略過 |

## 與 vpn 的差異
- 聊天畫面是 Bootstrap 5，本站其他頁面是 Tailwind，所以聊天相關頁面用獨立版面 `layouts/messaging.blade.php`；Tailwind 頁面（`layouts/app`、`layouts/admin`）的「訊息」入口用輪詢更新未讀徽章，不載入 WebSocket。
- 行動 App API 見 [APP_API.md](APP_API.md)。用的是 `User` 的 Sanctum token，走專屬 guard `user_api`（`config/auth.php`）；考生（`Candidate`）的 token 通不過，反之亦然。停用／到期的帳號 token 會由 `user.active` middleware 立即失效。
- `/broadcasting/auth` 接受網頁 session 或 `user_api` token（`auth:web,user_api`），不接受考生 token。
- 大頭貼與「已連結裝置」管理放在新的 `/profile`（個人設定）；`/users/{user}/profile` 是聊天室點頭像看到的簡易資料頁。
- 跨組織通訊錄只推送非學生帳號，避免把學生名單公開給其他組織。
- 沒有右下角浮動聊天視窗（`showFloatingWidget=false`）。
- 站內聯絡人清單是「全部啟用中的使用者」（與 vpn 相同）。若不希望學生看到全部人，需要再依學校/班級限縮 `ConversationController::allUsers()`／`searchUsers()`。
