Новый домен 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>
25 KiB
Домен 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_locked(иno_sim/no_service), отличное отoffline(как «сервис не поднят» ≠ offline); запрос PIN — через слот Shell (C §4, как входящий-оверлей §6), PUK-fallback после исчерпания попыток (ModemManagerSim.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 через
ShutdownImminent→StopAppоркестрирует B §4). - Sleep/wake (B §7): модем/радио выключены в
sleep/battery_cutoff(бюджет АКБ #5); опц. wake по сети — later. - Звонок при ACC-off: головблок — лишь hands-free; на shutdown HFP-аудио прекращается, звонок продолжается на телефоне (как при потере SCO §4) — активный звонок shutdown не блокирует.
- Реконнект: на boot/
accessoryConnectivity переподнимает известные 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(...); propertiesOnline(bool),State(offline/portal/limited/online+ модемsim_locked/no_sim/no_service),Type(wifi/modem/tether),SignalStrength. Расширение enumType(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); propertyCallState,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 |