docs: завершить Tier 1 (контракты) + ревью-фикс red-line CAN

- security-privacy: изоляция, capabilities, гейтинг по каналам, приватность/152-ФЗ;
  first-party = вшит в подписанный образ; рисковые комбинации (vehicle_read+network)
- plugin-sdk: манифест, точки расширения, коллизия интентов, host-allowlist
- hardware: RK3588, power-safe, периферия, HAL/BSP портирование
- ВАЖНО: уточнён red-line CAN (принцип #2 + hardware §4): «чтение» = без
  управляющих/actuator/write-передач; диагностические OBD read-запросы допустимы
  (иначе не прочитать DTC); listen-only — только пассивный сниффинг
- + автозащита питания, тепло, износ eMMC; кросс-доковые аннотации

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-20 20:28:52 +03:00
parent 3d13bb5827
commit fb27d8d2fe
5 changed files with 411 additions and 17 deletions
+142
View File
@@ -0,0 +1,142 @@
# Контракт: безопасность и приватность
> Модель изоляции, разрешений и приватности (152-ФЗ). Здесь **решаются открытые
> вопросы**, направленные из [ipc.md](ipc.md): гейтинг data-plane, экспорт объектов
> из песочницы, приватное хранилище, целостность манифеста.
Статус: **v1 (на ревью).**
Связано с: [architecture.md](../architecture.md) (§5,§7) · [ipc.md](ipc.md) · [plugin-sdk.md](plugin-sdk.md) · [principles.md](../principles.md) (#1,#2,#7) · домен F
---
## 1. Слои защиты (defense-in-depth)
| Слой | Что гарантирует |
|------|-----------------|
| **Архитектурный** | write-пути к CAN нет в системе → красные линии держатся даже при полном компромиссе (принципы #1, #2) |
| **Песочница** | bubblewrap (апы/плагины) + systemd-hardening (ядро) — ограничивает syscalls/FS/сеть |
| **Брокер/портал** | доступ к ресурсам только через capability-гейтинг (D-Bus-прокси + сокеты) |
| **Грант пользователя** | сторонние capabilities подтверждает пользователь |
> Ключевой инвариант: **сбежавший из песочницы плагин всё равно не запишет в CAN** —
> писать некуда. Песочница защищает данные и приватность, не красные линии.
## 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-сокет** (пропускается в песочницу) |
| `audio_in` (микрофон) | запись с микрофона — **высокочувствительно** | PipeWire-сокет + **runtime-грант + видимый индикатор**; сторонним — ограниченно |
| `network` | доступ в сеть (опц. **host-allowlist** в манифесте) | net-namespace + **runtime-грант** |
| `location` | GPS/положение | D-Bus (location) + **runtime-грант** |
| `gpu` (render) | GPU-ускорение (UI/ML) | bubblewrap пропускает `/dev/dri` |
| `storage` | приватное хранилище | bubblewrap **mount** `/data/apps/<id>/` |
> Чего нет в манифесте — физически недоступно: нет сокета, нет имени на шине, нет mount.
## 4. Гейтинг по каналам (закрывает routed-вопросы из ipc)
- **D-Bus** — фильтрующий per-app прокси из манифеста (детали — [ipc.md](ipc.md) §5).
- **PipeWire (аудио)** — bubblewrap пропускает pipewire-сокет только при `audio_*`.
*закрывает «гейтинг 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) — отдельный
промпт в момент использования
```
- **First-party** апы — авто-грант. *Что делает их first-party:* они **часть
подписанного read-only base-образа** (вшиты, не устанавливаются пользователем) —
это и есть якорь доверия, а не флажок в манифесте.
- **Сторонние** — устанавливаются в `/data`, **всегда** в песочнице и под
capability-гейтингом; install-time ревью + runtime-промпты на чувствительное.
## 6. Доверие и дистрибуция (целостность манифеста)
🟡 **Выбор на подтверждение:**
- **(рек., сейчас)** install-time approve + песочница: пользователь видит
capabilities и соглашается; защита — sandbox. Просто, достаточно для раннего этапа.
- **(задел)** **подпись манифеста** + keyring издателей — против подмены capabilities
при сторонней дистрибуции. → домен F (экосистема/«магазин»).
- **(опц.)** курируемый стор с ревью.
Рекомендую: сейчас — approve+sandbox; подпись/стор — когда включаем community-маховик.
*закрывает «целостность манифеста» (с явным заделом).*
## 7. Приватность / 152-ФЗ
**Принцип:** local-first; наружу — минимум и осознанно.
| Данные | Где обрабатываются | Уходит в облако? |
|--------|--------------------|------------------|
| Голос (аудио) | локально (STT/TTS) | **никогда** |
| Текст запроса | локально → онлайн-LLM при необходимости | только текст, только в онлайн-режиме |
| Данные машины (OBD/DTC) | локально | **в промпт онлайн-LLM** — только когда пользователь спросил и активен онлайн-режим; в офлайне не уходит вовсе |
| Память о водителе (`.md`) | локально | нет (без явного согласия) |
| Телеметрия | локально | **opt-in**, по умолчанию выключена |
- Онлайн-LLM — только **RU-провайдеры** (GigaChat/YandexGPT), данные в РФ (152-ФЗ).
- **Прозрачность:** в онлайн-режиме контекст машины уходит провайдеру в составе
промпта — это явно сообщается; офлайн-фолбэк держит всё на устройстве.
**Микрофон:** wake-word слушает постоянно, но **локально**; в обработку идёт только
после слова-активатора; включённый микрофон показывается **видимым индикатором**.
**Охват гарантий и рисковые комбинации.** Таблица выше описывает поведение
first-party (ассистент). Сторонний плагин с `network` **+** чувствительными данными
(`vehicle_read`/`location`) теоретически может слить их куда угодно — это **рисковая
комбинация**: требует заметного предупреждения при установке, по возможности —
host-allowlist сети. Системная приватность держится на **capability-контроле**, а не
только на политике ассистента.
---
## Открытые вопросы (найдено на self-review → роутинг)
- ◻️ **Отзыв и управление грантами.** Пользователь должен видеть и **отзывать**
выданные capabilities по каждому апу. → Settings/Shell + домен C.
- 🟡 **Цепочка доверия к base-образу.** Secure boot (якорь) — в [hardware.md](hardware.md) §3;
осталась вторая половина — **подписанные OTA**. → домен A.
-**Host-scoping сети.** → решено в [plugin-sdk.md](plugin-sdk.md) §3 (host-allowlist
в манифесте; голый `network: true` — повышенный риск).
- ◻️ **Локальный audit-log** чувствительного доступа (микрофон, сеть, гранты) —
локально, не телеметрия. → этот контракт + Settings.
---
## Журнал решений (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 |