getUserMedia is only exposed in a secure context (HTTPS, or the localhost
exemption). Reached over plain HTTP on a LAN IP — the dev server from a phone
at http://192.168.x.x:8000 — iOS/Android leave navigator.mediaDevices
undefined, so join() fetched TURN creds (a confusing 200) then silently
rejected deep in a .then() with no mic prompt. Desktop works because
127.0.0.1 IS a secure context. (Not a regression — voice never worked on the
HTTP dev server from mobile.)
- voice-mesh.js: _micSupported() seam + an early INSECURE_CONTEXT reject in
join() before any network, so the failure is fast + diagnosable.
- burger-btn.js: bindVoiceBtn catches the rejected join, rolls back the
optimistic .in-call/dataset.inCall (so the next click retries), and surfaces
a Brief — 'Voice needs HTTPS (or localhost) — your browser blocked the mic
here.' — instead of failing invisibly.
- VoiceMeshSpec: +2 specs (join rejects INSECURE_CONTEXT; btn rolls back +
Briefs on reject). Jasmine green.
Code architected by Disco DeDisco <discodedisco@outlook.com>
Git commit message Co-Authored-By:
Claude Opus 4.8 (1M context) <noreply@anthropic.com>