From b1818e0955d009b4a6c8160f542e979f08b16e96 Mon Sep 17 00:00:00 2001 From: Alexander Date: Tue, 23 Jun 2026 19:04:18 +0300 Subject: [PATCH] =?UTF-8?q?docs(safety):=20=D0=BD=D0=BE=D0=B2=D1=8B=D0=B9?= =?UTF-8?q?=20=D0=BA=D0=BE=D0=BD=D1=82=D1=80=D0=B0=D0=BA=D1=82=20Tier-1=20?= =?UTF-8?q?=E2=80=94=20=D0=B3=D1=80=D0=B0=D0=BD=D0=B8=D1=86=D0=B0=20=D0=BD?= =?UTF-8?q?=D0=B5-safety-critical=20+=20=D1=8D=D0=BD=D1=84=D0=BE=D1=80?= =?UTF-8?q?=D1=81=D0=BC=D0=B5=D0=BD=D1=82=20red-lines=20+=20driver-distrac?= =?UTF-8?q?tion,=20=D0=BF=D0=BE=D1=81=D0=BB=D0=B5=20adversarial-=D1=80?= =?UTF-8?q?=D0=B5=D0=B2=D1=8C=D1=8E=20(8=20=D0=BD=D0=B0=D1=85=D0=BE=D0=B4?= =?UTF-8?q?=D0=BE=D0=BA)=20+=20=D1=88=D0=B2=D1=8B=20(principles=20#2=20Mod?= =?UTF-8?q?e=200A,=20README=C3=972)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 --- docs/README.md | 2 +- docs/contracts/README.md | 1 + docs/contracts/safety.md | 165 +++++++++++++++++++++++++++++++++++++++ docs/principles.md | 2 +- 4 files changed, 168 insertions(+), 2 deletions(-) create mode 100644 docs/contracts/safety.md diff --git a/docs/README.md b/docs/README.md index 39353b3..89229db 100644 --- a/docs/README.md +++ b/docs/README.md @@ -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. diff --git a/docs/contracts/README.md b/docs/contracts/README.md index 8b8572d..3be0af7 100644 --- a/docs/contracts/README.md +++ b/docs/contracts/README.md @@ -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»** (рантайм, diff --git a/docs/contracts/safety.md b/docs/contracts/safety.md new file mode 100644 index 0000000..3222ed3 --- /dev/null +++ b/docs/contracts/safety.md @@ -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 | diff --git a/docs/principles.md b/docs/principles.md index 3419f01..c987611 100644 --- a/docs/principles.md +++ b/docs/principles.md @@ -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-команд; он единственный