Skip to content

fix(calls): drive HFP modem MAC from --device, remove hardcoded PII#134

Merged
quad341 merged 2 commits into
mainfrom
fix/call-controller-device-mac-i4sqk
Jun 21, 2026
Merged

fix(calls): drive HFP modem MAC from --device, remove hardcoded PII#134
quad341 merged 2 commits into
mainfrom
fix/call-controller-device-mac-i4sqk

Conversation

@quad341

@quad341 quad341 commented Jun 19, 2026

Copy link
Copy Markdown
Owner

What this changes

CallController previously had _IPHONE_MAC_FRAGMENT = "d0_6b_78_33_46_20" as a module-level constant — the operator's iPhone Bluetooth MAC, in plain text, committed to a public repository. This also made call control device-specific: any device with a different MAC would never match and calls would silently fail.

The constant is removed. CallController.__init__ now accepts a device_addr parameter and derives self._mac_fragment at construction time (addr.lower().replace(":", "_") — matches oFono modem path format). __main__.py passes args.device or os.environ.get("TINCAN_DEVICE", ""), so the runtime device selection already in place is now threaded through to call control.

An empty device_addr produces an empty fragment, which matches any HFP modem path — the prior no-device behavior is preserved as a fallback.

Review notes

  • tincand/call_controller.py: _IPHONE_MAC_FRAGMENT constant removed; __init__ gains device_addr: str = "" param; _is_hfp_iphone_modem and _teardown_call_audio updated to use self._mac_fragment.
  • tincand/__main__.py: CallController(service, contact_store, device_addr=_device_addr) — one-line change.
  • tests/tincand/test_call_controller.py: _make_controller() gains device_addr param (default "D0:6B:78:33:46:20") so existing fixture paths still match without changing all call sites.
  • Known LOW: device_addr="" causes self._mac_fragment="" which matches any HFP modem path via "" in path. Not reachable when --device is set. Follow-up: tincan-kf2h0.

Test plan

🤖 Deployed by actual-factory

quad341 and others added 2 commits June 19, 2026 06:31
…tincan-i4sqk)

call_controller.py had _IPHONE_MAC_FRAGMENT = "d0_6b_78_33_46_20" committed
as a module-level constant — the operator's iPhone MAC, in plain text, in a
public repo. It also blocked any other device from using call control.

Accept device_addr in __init__ and compute self._mac_fragment from it
(lowercase, colons → underscores — matches the oFono modem path format).
An empty device_addr ("" fragment) matches any HFP modem path, preserving
the no-device fallback. Pass the --device / TINCAN_DEVICE value from __main__.

Update _make_controller() test helper with a device_addr parameter (defaults
to "D0:6B:78:33:46:20") so existing MAC-fragment fixture paths still match.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@quad341

quad341 commented Jun 19, 2026

Copy link
Copy Markdown
Owner Author

Thanks @quad341 — clean catch and exactly the right fix. Pulling the hardcoded d0_6b_78_33_46_20 MAC out of call_controller.py removes real PII from a public repo, and deriving self._mac_fragment from device_addr at construction is the correct shape: it makes call control work for any device instead of silently failing on a non-matching MAC, and it reuses the --device/TINCAN_DEVICE selection you already had wired in __main__.py. Nice touch keeping the test helper's default address so existing fixtures kept passing without churning every call site.

I traced the empty-device_addr path through setup_sco_routing and _is_hfp_iphone_modem — it broadens matching but degrades gracefully (empty list + warning, no crash), so the LOW you flagged as tincan-kf2h0 is a fine follow-up, not a blocker. CI's green and the full suite is happy, so this is going in as-is. Appreciate you treating it as a security fix and scoping it tightly.


Reviewers: Qwen (local) — ok · Claude (claude-opus-4-8[1m]) — ok · Codex (gpt-5.5) — ok
Synthesis: claude-opus-4-8[1m]

Verified locally + tests pass. Ready to merge — clicking the button is the only step left.

@quad341 quad341 merged commit 7e5fecf into main Jun 21, 2026
1 check passed
@quad341 quad341 deleted the fix/call-controller-device-mac-i4sqk branch June 21, 2026 16:20
quad341 added a commit that referenced this pull request Jun 21, 2026
)

After #134 the MAC fragment is derived from device_addr, so the
_make_controller_with_modems fixture must pass a device_addr matching the
fixture modems — otherwise _mac_fragment is empty and matches every HFP
modem, breaking test_non_matching_modem_not_bound.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
quad341 added a commit that referenced this pull request Jun 21, 2026
* fix(calls): bind the Online HFP modem, skip stale offline ones

_discover_modem bound the first MAC-matching iPhone HFP modem without checking
Online. With the iPhone HFP-connected on two adapters it could bind an offline
modem (no VoiceCallManager) — every Dial/Answer then failed with UnknownMethod.
Prefer an Online modem (sort Online-first).

Proven live: with both adapters Online, tincand binds the live (dongle) modem
and Dial places the call. Regression test tracked as a follow-up.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* test(calls): _discover_modem must prefer the Online HFP modem (tincan-a6yeb)

Add §6 TestDiscoverModemOnlinePreference covering the regression fixed in the
previous commit: when GetModems returns multiple iPhone HFP modems, the Online
one must be bound (an offline modem has no VoiceCallManager → Dial fails with
UnknownMethod).

Four cases: online wins listed-second, online wins listed-first, offline-only
falls back to first candidate, non-matching MAC is ignored.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* chore: release gate PASS for tincand-prefer-online-modem

* test(calls): thread device_addr through the modem fixture (adapt to #134)

After #134 the MAC fragment is derived from device_addr, so the
_make_controller_with_modems fixture must pass a device_addr matching the
fixture modems — otherwise _mac_fragment is empty and matches every HFP
modem, breaking test_non_matching_modem_not_bound.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant