Files
shturman/docs/domains/g-connectivity-phone.md
T
kk0t9 fb4e585152 docs(domain G): v2 — связь/телефон (Connectivity+Phone), после adversarial-ревью (15 находок) + кросс-док
Новый домен G: Connectivity-core (WiFi/LTE/tethering + BT-адаптер/паринг) +
Phone-ап (HFP-звонки/контакты). Многоагентный adversarial-ревью: 24 находки,
15 подтверждено (default-refute; tech-измерение — 0, техника устояла), все применены.

Ключевое из ревью:
- BT-шов резолвнут двунаправленно: владелец BlueZ — Connectivity-core (G §3 ↔ H §6/§15 ).
- Граница голоса: только HFP спаренного телефона; встроенный модем — data-only (VoLTE/eCall вне скоупа).
- SIM PIN/PUK-флоу (sim_locked/no_sim) + captive-portal детект (portal/limited, не ложный online) — модем v1.
- Connectivity поднимается на Stage 2 (синхр. с architecture §6).
- Мультипаринг: ровно один active-телефон для HFP/PBAP (Dial/CallStateChanged однозначны).
- SCO-loss mid-call → CallState=audio_lost + снятие роли phone_call → H раскорчивает медиа (не залипает).
- Входящий-оверлей не перекрывает реверс-вид (z-order overlay-слота → C); tethering-петля AP+tether запрещена.
- PBAP-синк фоновый; отказ-пути паринга/no_service симметрично J/H.

Кросс-док: H §6/§15 (BlueZ ) + якоря D §147/§148→§10; architecture §3 (Connectivity+BT)
/§6 (Stage 2); ipc §3 (Type+tether, State enum, CallState=audio_lost); security-privacy §7
(контакты/журнал/SMS local-first); hardware §4 (Bluetooth); tech-stack (NM/MM/BlueZ);
C §11 (z-order overlay).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 19:08:52 +03:00

25 KiB
Raw Blame History

Домен G — Связь / телефон

Сетевой слой (WiFi/LTE-модем/tethering) и телефония (BT-паринг, HFP-звонки, контакты, проекция). Две сущности: Connectivity — привилегированный core-сервис (владеет сетевым/BT- железом); Phone — first-party ап на SDK (звонки/контакты). Транспорт для онлайн-ассистента (D), OTA/телеметрии (L) и стриминга (H).

Статус: v2 (на ревью). v2 — после adversarial-ревью (15 находок). Связано с: architecture.md (§3 Connectivity/Phone, §5 карта связей, §6 boot-Stage) · ipc.md (Connectivity, Phone) · security-privacy.md (§3 network, §5 runtime-грант, §7 приватность/152-ФЗ) · hardware.md (§4 модем/WiFi/BT/mic/amp, §3 load-shed) · tech-stack.md (NM/MM/BlueZ) · домены H (§3 phone_call, §6 BT-аудио-шов), D (§3 online-LLM, §5 креды, §6/§10 интенты/AEC), C (§4 слоты, §7 distraction, §9 ввод), K (§3 руль-кнопки), B (§4 load-shed, §7 sleep/wake), L (облако/компаньон), I (нав/TMC) · principles.md (#1,#2,#3,#6,#7,#8,#11,#12,#13)


1. Назначение и границы

  • Connectivity (core): IP-связность для companion-слоя — WiFi-клиент, LTE-модем, tethering от телефона; приоритет/failover путей, статус сети; владелец сетевого и BT-адаптера (§3).
  • Phone (first-party ап): BT-паринг UX, HFP-звонки (hands-free), контакты/журнал (PBAP), опц. сообщения (MAP); звук звонка — роль phone_call в арбитре H (§4).
  • Границы (красные линии):
    • Не safety-critical (#1): eCall / экстренный вызов — вне скоупа (регулируемая safety-система).
    • Голос — только HFP спаренного телефона; встроенный LTE-модем — data-only (CS-voice / VoLTE — вне скоупа: отдельный крупный стек; усиливает границу eCall — головблок физически не голосовой узел сети).
    • Модем — НЕ шлюз к машине (#2): Connectivity даёт IP только companion-слою; никакого моста модем↔CAN, никакого удалённого управления узлами. Удалённый доступ к данным машины (если будет, через L) — read-only + opt-in, не через G.
    • Проекция (CarPlay/Android Auto) — тяжёлые лицензионные ограничения, не first-party, later (§8).
  • Plane: control/состояние — D-Bus (Connectivity/Phone); звук звонка — PipeWire (роль phone_call, политика — H §3); сам IP-трафик — вне D-Bus.

2. Connectivity (core-сервис)

  • Пути данных (провайдер-агностично #8): (1) WiFi-клиент (домашняя/известная сеть на стоянке); (2) LTE-модем (USB, SIM/APN — ModemManager); (3) tethering от телефона (BT-PAN / WiFi-hotspot телефона).
  • Приоритет/failover: политика выбора активного пути (напр. WiFi > tethering > metered-LTE), бесшовное переключение; metered-aware (крупные загрузки — OTA L/A — не тянуть по дорогой LTE без согласия).
  • Состояние связности — НЕ бинарно на уровне источника правды: NM connectivity-check различает portal/limited (ассоциация + IP есть, реального интернета нет — публичный WiFi за captive-portal) от настоящего online. Портал не рапортуется как online — иначе D (online-LLM) / L (OTA) ломаются на ложном «online». Прохождение портала — UX вне MVP, но детект обязателен (инвариант «не маскировать»).
  • SIM/модем-стейты: PIN-locked SIM на boot/вставке → состояние sim_lockedno_sim/no_service), отличное от offline (как «сервис не поднят» ≠ offline); запрос PIN — через слот Shell (C §4, как входящий-оверлей §6), PUK-fallback после исчерпания попыток (ModemManager Sim.SendPin/SendPuk).
  • Обёртка NetworkManager/ModemManager (hardware §4); статус/состояния — ru.shturman.Connectivity (§11).
  • Boot-Stage: Connectivity поднимается на Stage 2 (фоном, как Vehicle-Data/Assistant; architecture §6), не в Stage 1 → статус-бар C §3 до первого ответа = «unknown»; online-LLM (D §3, v1) до прихода Connectivity деградирует по #3 (offline-first), не виснет.
  • Offline-first (#3): сеть в движении нестабильна → потребители (D, H, L) деградируют, не виснут; Connectivity лишь честно сообщает состояние, не маскирует. Безопасность: модем — отдельный процесс (net-ns).
  • Фаза: WiFi-клиент + LTE-данные (+ SIM-unlock) — v1 (нужно online-ассистенту D §3); hotspot/AP — later (§7).

3. Bluetooth (core: адаптер + паринг) (резолв BT-шва H §6; синхронизировано в H §6/§15)

  • Владелец BlueZ-адаптера и паринга — Connectivity-core (общий аппаратный радиоресурс → один привилегированный владелец, как сеть). 🟡 может выделиться в отдельный BT-сервис, если разрастётся (§15).
  • Паринг: BlueZ-Agent (PIN/just-works) — механизм в core; UX выбора устройства/подтверждения — в Phone-апе/Shell (слот C §4). Список спаренных, доверие, реконнект — здесь. Сбой паринга (неверный PIN / timeout / reject устройства) → видимая неблокирующая индикация + откат к списку устройств, без зависания.
  • Активное устройство (мультипаринг): одновременно активен ровно один телефон для телефонии (HFP/PBAP); при нескольких спаренных — выбор active-устройства (last-connected / явный выбор в Phone-апе, слот C). A2DP-медиа может жить на другом устройстве (координация H §6). Это делает Dial/CallStateChanged (§11) однозначными.
  • Диспетчеризация профилей к потребителям спаренного устройства:
    • HFP (звонок) → Phone-ап (G), §4;
    • A2DP/AVRCP (медиа) → Media-ап (H §6);
    • PBAP/MAP (контакты/сообщения) → Phone-ап (G), §5.
  • HFP-аудио идёт через PipeWire (bluez5-модуль, mSBC/CVSD) — H маршрутизирует по роли phone_call.
  • Фаза: v2 (вместе с Phone и A2DP H).

4. Телефония — HFP-звонки (Phone-ап)

  • Состояния вызова: idle/incoming/dialing/active/held(опц.)/audio_lost — публикуются на шине (§11), чтобы H проактивно корчил медиа (H §3 crash-safe: сигнал Phone → cork ДО появления аудио-ноды).
  • Аудио: downlink (голос собеседника) → усилитель; uplink — салонный mic-массив (hardware §4), тот же, что у ассистента → во время звонка mic отдан HFP-аплинку (политика арбитража H §3), ассистент подавлен. AEC/денойз на uplink — желателен (тот же тракт, что H §4 / D §10).
  • Звонок — это телефона, не наш: головблок — hands-free-периферия.
  • Потеря HFP-аудио-линка в середине звонка (SCO рвётся — телефон вышел из зоны, — но вызов жив на AG): отдельное событие от hangup. Phone эмитит CallStateChanged → audio_lost (§11), синхронно снимая заявку роли phone_call → H гарантированно опускает проактивный cork (медиа не залипает; H §3), mic освобождается, подавление ассистента снято. Инвариант: проактивный cork снят ⇔ оверлей не показывает hands-free-разговор (одно событие на обе оси). UI (§6) → «звонок продолжается на телефоне».
  • Фаза: v2.

5. Контакты / журнал / сообщения (PBAP/MAP) + приватность

  • PBAP: синхронизация контактов и журнала вызовов с телефона (имя вместо номера, набор по имени §6). Синхронизация — фоновая/ленивая (#11), не блокирует UI и не задерживает доступность HFP; на общем BT-линке голос (HFP) приоритетнее фоновой PBAP-синхронизации. MAP (SMS) — later (чтение вслух §6).
  • Приватность (#7, 152-ФЗ — высокочувствительно): контакты, журнал, тексты SMS — персональные данные. On-device, local-first; никогда в облако/онлайн-LLM без явного согласия (как память водителя D §7). Доступ — audit-log (security-privacy §7 / a-base §9); at-rest — fscrypt-поддерево (a-base §3). Чистка — factory-reset (a-base §12) + при отвязке устройства.
  • Фаза: контакты v2; SMS/MAP v3.

6. Управление вызовом и distraction (#6)

  • Ответ/сброс — аппаратно, не голосом: кнопки мультируля (answer/hangup) и тач (C §9, K §3, uinput→Wayland-input) — крупная single-tap-аффорданс, доступна и на скорости (distraction блокирует сложное, не одно-действие; C §7). Во время звонка mic занят HFP → голосового «положи трубку» нет (явное решение, не пробел).
  • Набор — голосом (до звонка): «позвони <контакт>» — assistant-интент (Phone — first-party, регистрирует assistant_intents; роутинг/коллизии D §6 + plugin-sdk §5), резолв имени по PBAP active-устройства (§3/§5).
  • Входящий вызов — оверлей в слоте Shell (C §4), упрощённый на скорости (distraction — владелец C §7); phone_call прерывает ассистента (лестница H §3). При активном реверс/парктроник-виде (J §6) входящий- оверлей НЕ перекрывает live-вид камеры — деградирует до компактной формы (полоса/PiP), сохраняя answer/decline; z-order overlay-слота — у C (§15 → C).
  • Имя не синхронизировано по PBAP (реконнект/большая книга §5) → оверлей показывает номер (#3 graceful), имя подтянется позже.
  • Фаза: v2.

7. WiFi-hotspot / tethering (later)

  • Головблок как AP (раздать текущий активный uplink §2 — не обязательно LTE) и/или приём tethering от телефона (§2). NM-управление.
  • Инвариант радио: AP-раздача и приём WiFi-tether делят одно WiFi-радио → взаимоисключающие, если железо не поддерживает concurrent STA+AP (зависимость от hardware §4); конфигурация «AP-uplink = тот же телефон, что и tether-источник» — запрещена (петля).
  • Энергобюджет/нагрев (hotspot тянет) — с B/hardware. Фаза: v3.

8. Проекция — CarPlay / Android Auto (later, лицензионно-ограничено)

  • 🟡 Серьёзные ограничения (#12, юр.): CarPlay требует Apple MFi-чип + лицензию (NDA, несовместимо с open-source); Android Auto-проекция — проприетарный протокол Google; открытые реализации (OpenAuto-класс) — реверс-инжиниринг, юридически серо, часто GPL. → не first-party; реалистично — community-плагин под ответственность интегратора или вне скоупа.
  • Если появится: аудио/видео проекции — роли projection/phone_call в арбитре H (§3); поверхность — слот C.
  • Фаза: v4/неопределённо; решение — отдельно (§15).

9. Lifecycle (шов с B)

  • Load-shedding: при power-loss модем/WiFi — среди сбрасываемых нагрузок (hardware §3, B §4) → Connectivity отрабатывает пропажу транспорта как обычный offline (#3), потребители деградируют (in-flight HTTP D — таймаут D §5; teardown через ShutdownImminentStopApp оркестрирует B §4).
  • Sleep/wake (B §7): модем/радио выключены в sleep/battery_cutoff (бюджет АКБ #5); опц. wake по сети — later.
  • Звонок при ACC-off: головблок — лишь hands-free; на shutdown HFP-аудио прекращается, звонок продолжается на телефоне (как при потере SCO §4) — активный звонок shutdown не блокирует.
  • Реконнект: на boot/accessory Connectivity переподнимает известные WiFi/спаренные BT (resume медиа H §9 зависит от этого).

10. Приватность и безопасность (#7, #1, #2, #12)

  • Local-first ПДн: контакты/журнал/SMS — §5; никаких автоматических выгрузок.
  • Модем ≠ шлюз к CAN (#2): изоляция companion-IP от шины машины — нет пути модем→Vehicle-Data→CAN-write (его не существует). Удалённое — только read-only/opt-in через L.
  • eCall/экстренный — вне скоупа (#1).
  • Лицензии (#12): BlueZ / ModemManager / NetworkManager (и obexd для PBAP/MAP) — GPL-2.0; используем как отдельные системные демоны через D-Bus (не линкуем в наши Rust-бинари) → copyleft изолирован процессом (#12-допустимо). Наш код (zbus-обёртки) — MIT.

11. IPC / интерфейсы

  • ru.shturman.Connectivity (ipc §3, ядро): GetStatus()/ListNetworks()/Connect(id)/Disconnect(); сигналы ConnectivityChanged(state)/NetworkChanged(...); properties Online(bool), State (offline/portal/limited/online + модем sim_locked/no_sim/no_service), Type (wifi/modem/tether), SignalStrength. Расширение enum Type (tether) + State + BT-устройства/ выбор active — расширить ipc §3 (хвост).
  • ru.shturman.Phone (ipc §4, домен G): Dial(number|contact)/Answer()/Hangup() (адресуют active- устройство §3); сигнал CallStateChanged(state, peer) (idle/incoming/dialing/active/held/ audio_lost — SCO потерян, вызов на телефоне §4) — на него H проактивно корчит/раскорчивает медиа (H §3); property CallState, Contacts(read). Закрывает ipc §4-делегацию H/I/G.
  • Гейтинг: network (security-privacy §3/§5, runtime-грант); HFP-аудио — PipeWire-нода роли phone_call (H §3); контакты стороннему — не отдаём без явного грана (приватность §5/§10).
  • UI: входящий-оверлей/набор/PIN-запрос — слот Shell (C §4); статус сети — статус-бар (C §3).

12. Dev-симулятор (#13)

  • Сеть/модем — управляемые состояния (уже в dev-environment: online/offline/слабый сигнал/portal/ sim_locked, для offline-first тестов D/H/L). Добавить: фейковый BT-стек (паринг + сбой паринга, профили HFP/A2DP/PBAP, мульти-устройство), сценарии вызова (incoming/active/hangup/SCO-loss → проверка cork/un-cork медиа H §3), мок-контакты (PBAP без реального телефона). → dev-environment.

13. Функции

функция MVP/later зависит от фаза
Connectivity-сервис (WiFi-клиент + LTE-данные + статус + SIM-unlock) MVP hardware §4, NM/MM v1
Состояние связности (portal/limited детект, не ложный online) MVP NM connectivity-check v1
Приоритет/failover путей + metered-aware MVP v1
BT-адаптер + паринг (core) + диспетчер профилей + active-устройство MVP hardware (BT), BlueZ v2
HFP-звонки (состояния + аудио phone_call + SCO-loss) MVP H §3, mic/amp v2
Отказ-пути (сбой паринга, no_sim/no_service) MVP v2
Контакты/журнал (PBAP, фоновый синк) + privacy MVP security-privacy, a-base §3 v2
Управление вызовом (руль/тач) + входящий-оверлей (vs реверс) MVP C §4/§7/§9, K §3 v2
Голосовой набор «позвони X» (assistant-интент) later D §6 v2
tethering от телефона (BT-PAN / hotspot) later v2/v3
WiFi-hotspot (AP, раздача uplink) later hardware/B v3
SMS/сообщения (MAP) + чтение вслух later D (TTS) v3
Проекция (CarPlay/Android Auto) later лицензии (§8) v4/неопр.

14. Зависимости

  • Вниз: hardware (§4 модем/WiFi/BT-адаптер/mic/amp, §3 load-shed), NM/MM/BlueZ/obexd (tech-stack), PipeWire (HFP-аудио через H), a-base (§3 fscrypt контактов, §9 audit, §12 reset).
  • Вбок: H (роль phone_call, BT-аудио A2DP/AVRCP — H цепляет к нашему адаптеру; arbiter ducking), D (online-LLM поверх Connectivity; интенты «позвони»/«прочитай SMS»; AEC-тракт §10), C (слоты входящего/ набора/PIN, distraction, мультируль-ввод, z-order overlay), K (руль-кнопки answer/hangup), B (load-shed, sleep/wake), L (Connectivity — транспорт OTA/телеметрии/компаньона), I (RDS-TMC — задел H §7).
  • Вверх: статус сети/звонка для Shell; network — потребляют апы/плагины (гейтинг security-privacy).

15. Открытые вопросы

  • 🟡 BT-адаптер в hardware §4: добавить Bluetooth в периферию (резолвится этим коммитом). → hardware.
  • 🟡 Владелец BlueZ: Connectivity-core (рек., §3) vs выделенный BT-сервис — подтвердить.
  • 🟡 Телефонный стек HFP: PipeWire-bluez5 (аудио) + BlueZ-D-Bus (управление) — достаточно, или нужен oFono (richer call control: held/swap, call-waiting, 3-way, DTMF — тоже GPL-демон)? → реализация/tech-stack.
  • 🟡 Проекция (CarPlay/Android Auto): не-first-party / плагин / вне скоупа — решить (лицензии §8). → отдельно.
  • ◻️ Z-order overlay-слота (входящий-вызов vs реверс-вид vs ассистент vs уведомления) — общее правило «вид манёвра > уведомление». → C (§4 слот-модель) + J §6.
  • ◻️ Политика приоритета путей (WiFi/tether/LTE, metered-пороги, failover-гистерезис, пороги SIM-ретраев) — числа. → реализация.
  • ◻️ Контакты/журнал/SMS в security-privacy §7 (потоки данных) — добавить строку local-first (резолвится этим коммитом). → security-privacy.
  • ◻️ 152-ФЗ для контактов/звонков (оператор ПДн, основание) — legal-трек (как BYO-LLM, security-privacy §7).
  • ◻️ Wake-on-network / входящий в sleep — нужен ли, бюджет АКБ. → B.
  • ◻️ tethering vs встроенный модем — оба или приоритет одного (стоимость SIM vs зависимость от телефона). → later.

Журнал решений (домен G)

Решение Выбор Дата
Структура Connectivity (core, сетевое+BT-железо, Stage 2) + Phone (first-party ап); оба в домене G 2026-06-22
Пути данных провайдер-агностично: WiFi/LTE/tethering, приоритет+failover, metered-aware; связность не бинарна (portal/limited) 2026-06-22
Голос только HFP спаренного телефона; встроенный модем — data-only (VoLTE/CS вне скоупа); eCall вне скоупа (#1) 2026-06-22
BlueZ владелец — Connectivity-core; active-устройство = ровно один телефон для HFP/PBAP; профили HFP→Phone, A2DP/AVRCP→H, PBAP/MAP→Phone (резолв H §6) 2026-06-22
Звонок HFP hands-free; звук — роль phone_call; SCO-loss → audio_lost + снятие роли (раскорчивает H); звонок «телефона» 2026-06-22
Управление ответ/сброс — руль/тач single-tap (mic занят HFP → нет голос-hangup); набор — голосом (assistant-интент) 2026-06-22
Приватность контакты/журнал/SMS — local-first, fscrypt, не в облако без согласия (152-ФЗ); PBAP-синк фоновый 2026-06-22
Красные линии модем ≠ шлюз к CAN (#2); GPL-демоны (BlueZ/NM/MM/obexd) изолированы процессом (#12) 2026-06-22
Проекция CarPlay/AA — лицензионно тяжело → не-first-party/плагин/вне скоупа, v4-неопр. 2026-06-22
Фазы Connectivity-данные+SIM v1; BT/HFP/контакты v2; hotspot/SMS v3; проекция v4 2026-06-22