Новый домен 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>
20 KiB
Контракт: безопасность и приватность
Модель изоляции, разрешений и приватности (152-ФЗ). Здесь решаются открытые вопросы, направленные из ipc.md: гейтинг data-plane, экспорт объектов из песочницы, приватное хранилище, целостность манифеста.
Статус: v2 (на ревью). v2 — после ретро-ревью (10 находок). Связано с: architecture.md (§5,§7) · ipc.md · plugin-sdk.md · principles.md (#1,#2,#7) · a-base-system · домены C, F
1. Слои защиты (defense-in-depth)
| Слой | Что гарантирует |
|---|---|
| Архитектурный | write-пути к CAN нет в системе → красные линии держатся даже при полном компромиссе (принципы #1, #2) |
| Песочница | bubblewrap (апы/плагины) + systemd-hardening (ядро) — ограничивает syscalls/FS/сеть |
| Брокер/портал | доступ к ресурсам только через capability-гейтинг (D-Bus-прокси + сокеты) |
| Грант пользователя | сторонние capabilities подтверждает пользователь |
Ключевой инвариант: сбежавший из песочницы плагин всё равно не запишет в CAN — писать некуда. Песочница защищает данные и приватность, не красные линии.
1a. Модель угроз (кого и чем закрываем)
| Адверсарий | Чем адресуем | Предел |
|---|---|---|
| Злонамеренный сторонний плагин | песочница + capability-гейтинг + рисковые комбинации (§7) | данные вне его storage не гарантированы без at-rest-шифрования |
| Сбежавший/скомпрометированный плагин | архитектурный слой (нет write-пути к CAN на нативном silent-CAN) | приватность чужих данных НЕ защищена |
| Багнутый/скомпрометированный first-party (авто-грант) | не ограничивается capability-контролем; доверие — подписанный образ (v4) | до v4 — trust-by-build |
| Сетевой MITM к онлайн-LLM | TLS + RU-провайдеры/152-ФЗ | что уходит в промпт — §7 |
| Supply-chain / подмена образа·манифеста | secure boot + подписанный OTA (v4) + install-id-check (§5) | задел; до v4 частично |
| Изъятый носитель (eMMC/SD) | at-rest fscrypt + OTP (a-base §3, v4) | до v4 — открыто |
Вне scope: украденное целиком самораз-блокирующееся устройство (headless-unlock из eFuse); баги в самих ядро-сервисах (Vehicle-Data/брокер); недоверенное железо/BSP/DBC; атаки на стороне RU-LLM-провайдера.
2. Песочница
- Апы/плагины — bubblewrap: mount/pid/net/user namespaces, seccomp-фильтр
syscalls, минимальный FS-вид,
no-new-privileges. Плагин видит только: свой код, разрешённые сокеты, своё приватное хранилище. - Ядро — systemd-hardening:
ProtectSystem,RestrictAddressFamilies,SystemCallFilter, и т.п. на доверенных юнитах. - WASM-тир для лёгких логических плагинов — задел (см. architecture §7).
3. Модель capabilities
Манифест декларирует, что апу/плагину нужно. Каждая capability открывает ровно один ресурс и гейтится на своём канале:
| capability | что открывает | канал / механизм гейтинга |
|---|---|---|
vehicle_read:[signals] |
чтение указанных сигналов | D-Bus-прокси: VehicleData, фильтр по списку |
assistant_intents:[…] |
регистрация интентов | D-Bus: Assistant.RegisterIntents + OWN IntentHandler |
ui_tiles / ui_screens |
вклад в UI | D-Bus: Shell.Register* (+ Wayland-сокет, если поверхность) |
audio_out |
воспроизведение | PipeWire Security Context + WirePlumber-политика: видны только playback-ноды (не capture, не monitor чужих выходов) |
audio_in (микрофон) |
запись с микрофона — высокочувствительно | per-node capture-разрешение, выдаётся в момент runtime-гранта (не голый сокет!); видимый индикатор; сторонним — ограниченно. Нужен PipeWire с Security Context (~0.3.65+) |
network |
доступ в сеть | net-namespace + runtime-грант. ⚠️ Строго — только бинарно on/off; host-allowlist требует forced-proxy/egress-firewall по SNI/Host (DNS-allowlist обходится прямым IP), иначе best-effort (§7) |
location |
GPS/положение | D-Bus ru.shturman.Location (ipc §3) + runtime-грант |
camera_in:[sources] (камера) |
захват видео с источников — высокочувствительно | per-node PipeWire Security Context + WirePlumber (video-ноды, default-deny), runtime-грант + видимый индикатор; /dev/videoN — только first-party; стороннему — узкий per-source грант |
gpu (render) |
GPU-ускорение (UI/ML) | bubblewrap пропускает /dev/dri |
storage |
приватное хранилище | bubblewrap mount /data/apps/<id>/ |
Чего нет в манифесте — физически недоступно: нет сокета, нет имени на шине, нет mount.
4. Гейтинг по каналам (закрывает routed-вопросы из ipc)
- D-Bus — фильтрующий per-app прокси из манифеста (детали — ipc.md §5).
- PipeWire (аудио) — проброс сокета сам по себе НЕ гейтинг (голый сокет открывает
все ноды сессии: любой capture-источник и monitor любого выхода). Гейтинг — per-node:
PipeWire Security Context (sandbox-id на соединении) + WirePlumber-политика (по умолчанию
только playback; capture/микрофон — по явному per-node гранту в момент
audio_in). Индикатор и runtime-грант (§7) enforce-ятся на слое PipeWire/WirePlumber, не на сокете. → закрывает «гейтинг data-plane». - Wayland (графика/UI) — wayland-сокет пропускается только при
ui_*с поверхностью. → закрывает «гейтинг data-plane». - Экспорт объектов из песочницы — прокси разрешает плагину OWN имена строго
под префиксом
ru.shturman.plugin.<id>.*, чтобы Assistant/Shell могли звать егоIntentHandler/UI-объекты. → закрывает «экспорт объектов». - Приватное хранилище —
storageмонтирует в песочницу только/data/apps/<id>/; чужие данные и системные пути не видны. → закрывает «приватное хранилище».
5. Жизненный цикл разрешения
declare (манифест) → install: пользователь видит запрошенные capabilities и
подтверждает → enforce (прокси + sandbox конфигурятся под манифест) →
runtime-грант для чувствительных (network / audio_in / location) — отдельный
промпт в момент использования
Кто что enforce-ит (две роли):
- Статически (в пути вызова): per-app D-Bus-прокси + bubblewrap-сокеты/mounts, настраивает App-Host из манифеста — физически блокирует незаявленное (ipc §5).
- Рантайм-гранты (чувствительные caps): Perm-Broker (
RequestRuntimeGrant, ipc §3) — владеет политикой и согласием, не статическим путём данных. (В architecture §7 «единственная дверь» = единый грантодатель/портал, не «брокер в каждом вызове».)
Жизненный цикл гранта: привязан к активной сессии; авто-снимается на
StopApp/AppCrashed (Perm-Broker — источник истины; App-Host закрывает ресурс —
PipeWire-capture/location). Для audio_in/location — while-in-use: отзыв/ре-промпт
при уходе в фон. Персист («всегда») — только по явному выбору; иначе TTL на простое.
- First-party апы — авто-грант. Якорь: они часть read-only base-образа. ⚠️ До v4 криптоподписи образа НЕТ (secure boot + подписанный OTA — v4, a-base §4): в v0–v3 якорь = trust-by-build / физический контроль (dev-ключи, eFuse не жжём).
- Сторонние — в
/data, всегда в песочнице; install-ревью + runtime-промпты. Целостность id при установке: App-Host/Perm-Broker отвергает плагин, чейidсовпадает с уже установленным или встроенным/first-party; manifest-id namespaceru.shturman.*(весь tree) зарезервирован за first-party/образом — сторонний id = свой reverse-DNS (dev.example.*). (D-Bus OWN-экспорт плагина — отдельный платформенный префиксru.shturman.plugin.<id>.*(§4), это не manifest-id, не путать.) ⚠️ Без подписи (§6) это ловит только случайные коллизии, НЕ намеренную подмену ещё-не-установленного легитимного id — аргумент за подпись раньше «маховика».
6. Доверие и дистрибуция (целостность манифеста)
🟡 Выбор на подтверждение:
- (рек., сейчас) install-time approve + песочница: пользователь видит capabilities и соглашается; защита — sandbox. Просто, достаточно для раннего этапа.
- (задел) подпись манифеста + keyring издателей — против подмены capabilities при сторонней дистрибуции. → домен F (экосистема/«магазин»).
- (опц.) курируемый стор с ревью.
Рекомендую: сейчас — approve+sandbox; подпись/стор — когда включаем community-маховик. → закрывает «целостность манифеста» (с явным заделом).
7. Приватность / 152-ФЗ
Принцип: local-first; наружу — минимум и осознанно.
| Данные | Где обрабатываются | Уходит в облако? |
|---|---|---|
| Голос (аудио) | локально (STT/TTS) | никогда |
| Текст запроса | локально → онлайн-LLM при необходимости | только текст, только в онлайн-режиме |
| Данные машины (OBD/DTC) | локально | в промпт онлайн-LLM — только онлайн, по запросу И при явном (отзываемом) согласии на весь исходящий промпт; офлайн — не уходит |
Память о водителе (.md) |
локально | нет (без явного согласия) |
| Контакты/журнал/SMS (PBAP/MAP, домен G) | локально (fscrypt) | нет (без явного согласия) |
| Телеметрия | локально | opt-in, по умолчанию выключена |
- Онлайн-LLM — только RU-провайдеры (GigaChat/YandexGPT), данные в РФ (152-ФЗ).
- Прозрачность: в онлайн-режиме контекст машины уходит провайдеру в составе промпта — это явно сообщается; офлайн-фолбэк держит всё на устройстве.
- Согласие, не только уведомление: при первом онлайн-использовании — явный отзываемый consent-гейт на ВЕСЬ исходящий промпт (данные машины + подмешанное: VIN, локация, память водителя). По умолчанию VIN и точную локацию из промпта исключаем, включаем только по отдельному гранту.
- 152-ФЗ — роли и основание: в BYO-схеме (креды пользователя) определить оператора/ обработчика ПДн и правовое основание передачи (→ legal-трек). Локализация ≠ покрытие 152-ФЗ: «данные в РФ» (где хранятся) ≠ основание на обработку/передачу (согласие).
Микрофон: wake-word слушает в состояниях running/accessory (гейт Power — не
безусловно always-on; в sleep/off выключен, риск разряда АКБ, принцип #5; домен B §7 / D §8),
всё локально; в обработку идёт только после слова-активатора; включённый микрофон — видимый индикатор.
Охват гарантий и рисковые комбинации. Таблица выше описывает поведение
first-party (ассистент). Сторонний плагин с network + чувствительными данными
(vehicle_read/location) теоретически может слить их куда угодно — это рисковая
комбинация: требует заметного предупреждения при установке. Host-allowlist —
best-effort (от случайной утечки, не от злонамеренного: обходится прямым IP без
forced-proxy, §3); строгая гарантия — только бинарный network on/off. Системная
приватность держится на capability-контроле, а не только на политике ассистента.
Открытые вопросы (найдено на self-review → роутинг)
- ◻️ Отзыв и управление грантами. Пользователь должен видеть и отзывать выданные capabilities по каждому апу. → Settings/Shell + домен C.
- 🟡 Цепочка доверия к base-образу. Secure boot (якорь) — в hardware.md §3; осталась вторая половина — подписанные OTA. → домен A.
- 🟡 Host-scoping сети. Host-allowlist — best-effort (DNS-allowlist обходится по IP); строго — только forced-proxy/egress-firewall по SNI/Host, иначе бинарный on/off. → §3/§7 + plugin-sdk §3.
- ✅ Локальный audit-log — нормативный (не опция): пишет домен A рядом с логированием
(a-base §9), в fscrypt-поддерево
/data(§3 там), durable через fsync. Факты доступа к чувствительному (audio_in/сеть/location) + cloud-egress (провайдер, время, capability — без payload). Просмотр/отзыв — UI домена C (не сервисru.shturman.Settings). - 🟡 Шифрование данных at-rest. Изъятая eMMC/SD = открытая утечка ПДн водителя
(память
.md, токены, app-storage); sandbox это не закрывает (модель §1–§6 — про работающую систему, не про физическое изъятие). → решено направлением в a-base-system.md §3 (fscrypt чувствительных поддеревьев, привязка к OTP/eFuse, v4 вместе с secure boot).
Журнал решений (security-privacy)
| Решение | Выбор | Дата |
|---|---|---|
| Изоляция | bubblewrap (апы) + systemd-hardening (ядро); WASM — задел | 2026-06-16 |
| Гейтинг ресурсов | per-capability на своём канале (D-Bus / PipeWire / Wayland / FS) | 2026-06-16 |
| Экспорт из песочницы | OWN под префиксом ru.shturman.plugin.<id>.* |
2026-06-16 |
| Хранилище | storage → mount /data/apps/<id>/ |
2026-06-16 |
| Доверие к манифесту | install-approve + sandbox сейчас; подпись/стор — задел (🟡) | 2026-06-16 |
| Приватность | local-first; в облако только текст; OBD в промпт лишь онлайн + по запросу + явное согласие; телеметрия opt-in | 2026-06-16 |
| Enforce-split | статически — прокси+sandbox (App-Host); рантайм-гранты — Perm-Broker; грант while-in-use, авто-снятие | 2026-06-16 |
| Аудио | per-node гейтинг (PipeWire Security Context + WirePlumber), не голый сокет; capture по гранту | 2026-06-16 |
| Сеть | строго — бинарно on/off; host-allowlist best-effort без forced-proxy | 2026-06-16 |
| Целостность id | install-time отказ при коллизии id; manifest-id ru.shturman.* зарезервирован за first-party (OWN-экспорт ru.shturman.plugin.<id>.* — отдельный платформенный префикс) |
2026-06-16 |
camera_in |
per-node гейтинг видео (PipeWire Security Context, как audio_in); /dev/videoN — only first-party |
2026-06-16 |
| Audit-log | нормативный, владелец — домен A (§9, fscrypt-поддерево); просмотр — UI домена C | 2026-06-16 |