provisioning: Linphone setup QR, "Set up a phone app"
ci / check (push) Successful in 53s
ci / images (push) Successful in 24s

GET /api/extensions/:id/softphone-qr (admin) and /api/me/softphone-qr
return {url, qr, expiresAt}: the link Linphone fetches and its QR as a
PNG data URL (qrcode), valid 24 h. Both are audited like revealing the
SIP password. JSON rather than a bare PNG, so the page can show the
link for desktop Linphone too.

The token is stateless per 07 §5: base64url(extensionId.expiry.hmac),
HMAC-SHA256 with APP_SECRET, checked timing-safe. /prov/linphone/
<token>.xml matches it before the other file names are lower-cased
(the token is case-sensitive); a bad or expired token is a 404 and a
counted failure. auth_info keys checked against liblinphone's config
reader; proxy keys stay (verify).

Web: a "Set up a phone app" section on My settings and in the admin
Credentials tab: Linphone with the QR, MicroSIP/Baresip by hand, and
the plain warning about mobile apps without push. e2e m10-t3: as a
user, the QR's link gives the XML and a baresip phone registers with
only what it holds.

Task: M10-T3
This commit is contained in:
iamdoubz committed 2026-10-19 14:16:28 -05:00
1 parent 6195aca2fb
commit c1f8b04e7e
17 files changed
+631 -4

No files matched your search

+1
View File
@@ -354,6 +354,7 @@ Auth & self:
| POST | `/api/auth/change-password` | auth | `{currentPassword, newPassword}` |
| GET | `/api/me` | user | extension settings, runtime state |
| PATCH | `/api/me` | user | `{dnd?, cfu?, cfb?, cfna?, voicemailEmail?, voicemailAttachAudio?, voicemailDeleteAfterEmail?, voicemailPin?}` → DB, then AstDB |
| GET | `/api/me/softphone-qr` | user | `{url, qr, expiresAt}`: Linphone setup link and its QR (PNG data URL), 24 h (07 §5) |
| GET | `/api/me/webrtc` | user | `{ wsUrl: "wss://<host>/ws", sipUri: "sip:101-web@<host>", authUser: "101-web", password, displayName, iceServers: [...] }` |
| GET | `/api/me/calls` | user | own call history (via `call_extensions`) |
| GET | `/api/me/voicemail` | user | list |
+12
View File
@@ -205,6 +205,18 @@ Linphone provisioning:
```
**(verify against Linphone's remote provisioning docs)**
As built (M10-T3), `provisioning/linphone.ts`:
- The `auth_info_0` keys (`username`, `passwd`, `domain`) match liblinphone's `AuthInfo` config
reader; the `proxy_0` keys are its classic names and stay **(verify)** until a phone scans it.
- Both QR endpoints return JSON `{url, qr, expiresAt}` (`qr` = PNG data URL from `qrcode`), not a
bare PNG: the page shows the link too, for desktop Linphone. Each is in the audit log like
revealing the SIP password (the config carries it).
- The token is case-sensitive, so `/prov/linphone/…` is matched before the other files are
lower-cased; a bad or expired token is a 404 and counts as a failure (07 §2 limits).
`provisioning.lanOnly` applies to it too: a mobile off the LAN can't fetch it then.
- The display name's `"` becomes `'` in `reg_identity` (it sits inside a SIP quoted string).
- "Set up a phone app" is a section of `/me/settings` and of the admin Credentials tab.
Mobile limitation (state it plainly in the UI and admin guide): without push
notifications, iOS and battery-optimized Android apps miss calls while in the
background. A push gateway is a v2 item. For v1, recommend the desk phone + browser softphone,