docs(safety): новый контракт Tier-1 — граница не-safety-critical + энфорсмент red-lines + driver-distraction, после adversarial-ревью (8 находок) + швы (principles #2 Mode 0A, README×2)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-23 19:04:18 +03:00
parent dad0b8c33c
commit b1818e0955
4 changed files with 168 additions and 2 deletions
+1 -1
View File
@@ -19,7 +19,7 @@
- [tech-stack.md](tech-stack.md) — канонический технический стек (Rust-first) и крейты.
### Tier 1 — сквозные контракты (соединительная ткань)
- [contracts/](contracts/README.md) — IPC, модель данных, plugin-SDK, безопасность, железо.
- [contracts/](contracts/README.md) — IPC, модель данных, plugin-SDK, безопасность/приватность, safety (граница+distraction), железо.
### Инфраструктура разработки
- [dev-environment.md](dev-environment.md) — как вести разработку изолированно, с Mac.
+1
View File
@@ -11,6 +11,7 @@
| `data-model.md` | VSS-подобная таксономия сигналов машины + общие типы данных. |
| `plugin-sdk.md` | API расширения: манифест, capability-модель, точки расширения (экраны, тайлы, интенты, доступ к данным). *Рантайм плагинов — домен F.* |
| `security-privacy.md` | Sandboxing плагинов, модель разрешений, обработка данных, 152-ФЗ. |
| `safety.md` | Граница «не safety-critical» + структурный энфорсмент red-lines (CAN read-only) + driver-distraction-политика. *Комплемент security-privacy: вред/отказы, не злоумышленник.* |
| `hardware.md` | Целевой таргет (RK3588), топология питания, периферия + **HAL/board-support API** для портирования на другое железо/авто. |
> Важный нюанс: **plugin-SDK** (API, тут) и **домен F «Plugin host»** (рантайм,
+165
View File
@@ -0,0 +1,165 @@
# Контракт: безопасность (граница и driver-distraction)
> Сводный документ о **безопасности**: где проходит граница «не safety-critical»,
> как она держится технически, и как минимизируется единственная реальная
> safety-поверхность системы — **отвлечение водителя**. Правило для всех доменов.
Статус: **v1 (черновик на ревью).**
Связано с: [principles.md](../principles.md) (#1/#2/#4/#5/#6) · [security-privacy.md](security-privacy.md) (угрозы/приватность) · домены [C](../domains/c-shell-ux.md) (владелец distraction), [E](../domains/e-vehicle-data.md) (CAN), [B](../domains/b-power-lifecycle.md) (питание/MCU), [J](../domains/j-cameras-video.md) · [hardware.md](hardware.md)
---
## 1. Назначение и рамки claim
- **Что это:** граница безопасности проекта + политика снижения отвлечения. Превращает
заявленные красные линии (#1/#2) в **защищённый аргумент** и до-определяет distraction
(которое в доменах размечено, но числа/список были открыты — C §7).
- **Что это НЕ:** это **не** functional-safety по ISO 26262 / ASIL, **не** заявка на
сертификацию и **не** обещание, что система безопасна как safety-устройство. Мы
сознательно остаёмся **вне** safety-critical (#1) — именно поэтому «safety **НЕ**
заявляем» проходит сквозняком (напр. камера заднего вида — [hardware §4](hardware.md)).
- **Отличие от security-privacy:** там — **злоумышленник** (конфиденциальность/целостность,
модель угроз §1a). Здесь — **физический вред и отказы** (не-адверсариальные): можем ли
навредить вождению или машине и как этого не делаем. Линзы разные, доки дополняют друг друга.
- **Якоря-принципы:** #1 (не safety-critical), #2 (CAN read-only), #6 (driver-distraction).
## 2. Красные линии — свод и энфорсмент
### 2.1 Чего система НИКОГДА не делает
Не управляет и не вмешивается в узлы, влияющие на динамику/защиту: **двигатель, тормоза,
ABS/ESP, рулевое, подушки, трансмиссия** — и **любой** actuator. Нет управляющих интеграций;
в системе нет actuator-путей (#1).
### 2.2 Read-only CAN — точный смысл
Никаких *state-changing* передач: не шлём управляющих/actuator-команд, не пишем в память
ECU, не делаем сброс DTC (Mode 04) и UDS-write. Допустимы стандартные диагностические
**read-запросы** OBD-II — любой read-сервис без *state-changing* (напр. Mode 01/03/07/09/0A) —
протокол физически шлёт кадр-запрос, иначе DTC не прочитать. Пассивный сниффинг (listen-only) не передаёт ничего. (Полная формулировка — #2.)
### 2.3 Как это держится (структурно — со скоупом по транспорту)
- **Нет средства записи в принципе:** на D-Bus и в SDK **не существует** метода/capability
записи или actuator-вызова — нечего вызвать (security-privacy §3, [ipc](ipc.md)). Гарантия
структурная (отсутствие пути), а не рантайм-проверка.
- **Единственный владелец CAN — Vehicle-Data** (E); нативный CAN в пассивном режиме —
listen-only.
- **Граница гарантии по транспорту:** «ноль TX / писать некуда» — **физический** инвариант
только на **нативном CAN в silent-режиме**. На **ELM327** (живой путь для старых не-CAN авто —
простые Lada/ретрофит, E §3) адаптер сам полноценный CAN-узел, поэтому red-line там держится
**software-дисциплиной** (нет write-кода/метода/cap в Vehicle-Data), а не физикой; при
компрометации Vehicle-Data инъекция кадров теоретически возможна — [hardware §4](hardware.md),
[security-privacy §1a](security-privacy.md). Где нужна жёсткая гарантия — адаптер без TX.
- **Условность «безобидности» опроса:** активный TX — ограниченный, **motion-aware**,
fail-safe (снижаем интенсивность/набор PID в движении; backoff/стоп при аномалиях шины) —
[E §5a](../domains/e-vehicle-data.md).
- **Не оставляем ECU в открытой сессии:** на `ShutdownImminent` (B §4) — немедленное гашение
активного OBD-TX и закрытие ISO-TP-сессий — [E §5b](../domains/e-vehicle-data.md).
- **MCU — fail-safe-авторитет:** не подчиняется слепо power-командам SoC; ни одно SoC-сообщение
не может (а) снять питание **на ходу**, (б) держать вечно и разрядить АКБ (B §5/§7).
- **Ревью-гейт фич:** каждая фича проходит проверку «не управляет ли узлом» (#1) — процессное
правило, не код.
## 3. Hazard-анализ (лёгкий)
Не FMEA уровня сертификации — рабочая карта «опасность → стойка → митигация».
| Опасность | Наша стойка | Митигация | Владелец |
|-----------|-------------|-----------|----------|
| **Отвлечение водителя** | главная safety-поверхность | distraction-политика (§4) | C |
| Помеха живой powertrain-шине от активного опроса | read **условен** | motion-aware TX, prefer listen-only, backoff/стоп | E §5a |
| ECU оставлен в открытой диаг-сессии | не допускаем | гашение TX + закрытие ISO-TP на `ShutdownImminent` | E §5b |
| Камера з/в воспринята как **safety-устройство** | **safety НЕ заявляем** | явный дисклеймер + fail-safe «нет сигнала» | J, hw §4 |
| Введение в заблуждение (stale показан как live; неверная трактовка DTC) | честность данных | staleness-флаги, «скорость/данные неизвестны», `unavailable``stale`; объяснения — справочные, не приговор | E, C, D |
| Повреждение ФС при срыве питания | power-safe by design | RO-rootfs+overlay, graceful shutdown, запись только в `/data` (#5) | A, B |
| Ложный shutdown/reset в движении (мис-трактовка cold-crank/просадки рейла) | не допускаем | held-пороги ниже brown-out (НЕ rate-of-change); приоритет crank; ride-through cold-crank до ~6 В | B §3/§4, hw §3 |
| Питание снято не вовремя (на ходу) / разряд АКБ (не заведётся) | MCU не исполняет слепо power-команды SoC | MCU fail-safe-авторитет (не cut на ходу, не держать вечно); battery-cutoff выше operating-brown-out | B §5/§7 |
| Плагин пытается сделать что-то «опасное» | физически не может (нет D-Bus/SDK write-метода) | песочница + нет CAN-write-cap; UI в слотах shell. *(Физ. инвариант шины — лишь на нативном silent-CAN; на ELM327 = software-дисциплина, hw §4)* | F, sec-priv, E |
## 4. Driver-distraction — политика
Консолидация [C §7](../domains/c-shell-ux.md) + до-определение порогов/списка (были открыты).
**Владелец — Shell (C)**; правило едино для всех апов и плагинов.
### 4.1 Модель и уровни
- Состояние публикуется как `DistractionModeChanged(level)` (Shell, [ipc §4](ipc.md)).
- **Уровни (v1):** `parked` (полный UI) и `driving` (ограничения §4.4). Поле `level`
**расширяемо** до промежуточного `low_speed` позже (по UX-тестам) — 🟡.
### 4.2 Источник скорости, арбитраж, fail-safe
- **Источник:** GPS (`ru.shturman.Location`, K) **с v1**; уточняется OBD-скоростью (E) в v2.
C потребляет **занулённую/quality-флагнутую** `Speed` (не сырой Doppler-шум на стоянке).
- **Арбитраж GPS↔OBD (v2):** правило авторитетности и поведение при расхождении/устаревании.
- **Fail-safe:** при неизвестной/устаревшей скорости (тоннель/нет фикса/stale OBD) — гейт
**консервативно в `driving`** (к безопасности) + видимая пометка «скорость неизвестна».
- **Гистерезис/дебаунс:** раздельные пороги on/off — джиттер не мигает режимами.
### 4.3 Пороги *(🟡 — дефолты под подтверждение, финал на реальном HMI)*
- Вход в `driving` — выше **~5 км/ч**; выход в `parked` — ниже **~3 км/ч** (гистерезис).
- Неизвестная/устаревшая скорость → `driving`.
### 4.4 Что блокируется / разрешено в движении *(🟡 — список под подтверждение)*
- **Блокируется:** ввод текста с клавиатуры; видео на экране водителя; длинные списки и
мелкие цели; многошаговые настройки; ручной ввод назначения; всё, что требует долгого взгляда.
- **Разрешено:** голос/PTT (первичный путь); крупные одно-тап тайлы; now-playing-транспорт;
turn-by-turn-ведение; приём/сброс входящего звонка; back/home; навигация по UI **рулём** без касания (C §9).
### 4.5 Glance-бюджет
Для всего разрешённого в движении — design-цель **≤ 2 c одиночный взгляд / ≤ 12 c задача**
(эвристика NHTSA Visual-Manual как **референс дизайна**, не как claim соответствия).
### 4.6 Энфорсмент (центральный — плагины не обходят)
- Shell — **Wayland-хост** UI всех апов/плагинов и маршрутизатор ввода (C §9); ограничения
накладывает **централизованно** по `level`, чужой UI живёт в слотах и не может их обойти.
- SDK **(◻️ задел)** — предполагается отдавать плагину текущий `level` для адаптации UI (не для
обхода); точка доставки (подписка на `DistractionModeChanged` через прокси под `ui_*`, либо
отдельный read-only level-канал) **ещё не специфицирована** в plugin-sdk — см. §8.
## 5. Регуляторный контекст *(без claim соответствия)*
- **EMC / UNECE R10 (e-mark):** ретрофит-головблок — электроника в авто. Соответствие/
установка — ответственность **установщика/пользователя**; проект проектируется «не мешать»,
но **гомологацию не заявляет**. Тепловой/механический конверт — [hardware §1a](hardware.md).
- **Distraction-дизайн** опирается на **NHTSA Visual-Manual Guidelines** и **Euro NCAP** как
**референсы** (§4.5), не как сертификацию.
- **Ответственность ретрофита** на конкретное авто — пользователя; проект даёт **документацию**
(см. «документированный ретрофит», [roadmap](../roadmap.md) v4), не сертификат.
- **152-ФЗ / приватность** — отдельная плоскость: [security-privacy §7](security-privacy.md).
## 6. Поведение при отказах (свод fail-safe)
Единая стойка #4 (**деградируй, не падай**), сведённая по доменам:
| Отказ | Поведение | Домен |
|-------|-----------|-------|
| Неизвестна/устарела скорость | distraction → консервативно `driving` | C §7 |
| Падение CAN-транспорта (bus-off/линк) | `Online=false`; сигналы → `unavailable` (не `stale`); авто-recovery; без краха | E §5b |
| Нет видеосигнала камеры | frame-watchdog → состояние «нет сигнала» (fail-safe), без зависшего кадра | J |
| Срыв навигации (no-route/битые тайлы/GPS-loss) | отказ-пути, без краха | I §12 |
| Срыв питания | power-safe в обе стороны: anti-corruption (RO-rootfs/overlay, graceful) И anti-ложное-срабатывание (held-триггеры не rate-of-change, crank-приоритет, ride-through) | B, A (#5) |
| Недоступна зависимость апа | «нет данных», ап не крэшит | все (#4) |
## 7. Зависимости / связи
- **Принципы:** #1/#2 (граница), #4 (graceful degradation), #5 (power-safe), #6 (distraction).
- **C** — владелец distraction (HMI, уровни, энфорсмент). **E** — энфорсмент read-only CAN +
motion-aware опрос. **B** — power-safe, MCU-авторитет, `ShutdownImminent`. **J/I** — fail-safe.
- **security-privacy** — комплементарна (угрозы/приватность ≠ hazard/вред). **hardware** — §1a
(конверт), §4 (камера-дисклеймер, CAN-периферия).
- **SDK** (◻️ задел) — доставка distraction-`level` плагину пока не специфицирована (§8); **ipc** — сигнал `DistractionModeChanged`.
## 8. Открытые вопросы
- 🟡 **Точные пороги (км/ч) и полный список блокируемого** — финализировать на реальном HMI (v1→v2).
- 🟡 **Промежуточный уровень `low_speed`** (graded vs бинарный) — по UX-тестам.
- ◻️ **Глубина регуляторного анализа** под конкретные рынки (РФ/ЕС) — к релизу/стору.
- ◻️ **Формат «документированного ретрофита»** (roadmap v4) — гайд по установке + разграничение ответственности.
- ◻️ **Доставка distraction-`level` плагину** — точка в plugin-sdk не специфицирована (подписка на `DistractionModeChanged` под `ui_*` vs отдельный read-only level-канал; отразить в security-privacy §3).
## Журнал решений (safety)
| Решение | Выбор | Дата |
|---------|-------|------|
| Рамка claim | non-safety-critical; **НЕ** ISO 26262; «граница + distraction-митигация» | 2026-06-23 |
| Энфорсмент read-only | **структурный** (нет write-метода/cap), а не рантайм-чек; физ.-инвариант «ноль TX» — лишь на нативном silent-CAN, на ELM327 (старые авто) = software-дисциплина (hw §4); VehicleData — единственный владелец CAN | 2026-06-23 |
| Distraction-уровни | бинарный `parked`/`driving`, поле `level` расширяемо до `low_speed` | 2026-06-23 |
| Пороги distraction | ON >~5 км/ч, OFF <~3 км/ч (гистерезис); unknown/stale → `driving` (числа — 🟡) | 2026-06-23 |
| Регуляторика | R10 / NHTSA / Euro NCAP как **референсы**, не claim; гомологация = установщик | 2026-06-23 |
+1 -1
View File
@@ -20,7 +20,7 @@
- **Почему:** безопасность + юридическая чистота. Это то, что делает проект подъёмным для малой команды.
- **Точный смысл «чтения»:** мы НИКОГДА не шлём управляющих/actuator-команд, не пишем
в память ECU, не делаем сброс DTC (Mode 04) и UDS-write — никаких *state-changing*
передач. При этом стандартные диагностические **read-запросы** OBD-II (Mode 01/03/07/09)
передач. При этом стандартные диагностические **read-запросы** OBD-II — любой read-сервис без *state-changing* (напр. Mode 01/03/07/09/0A)
допустимы и необходимы: протокол физически отправляет кадр-запрос, иначе DTC не
прочитать. Пассивный сниффинг (listen-only) не передаёт ничего.
- **Как держим:** в Vehicle-Data нет кода управляющих/write-команд; он единственный