Files
kk0t9 fd5c5c2dd5 docs(v0.2): синхронизация швов boot-конвейера + статус
P6.5: CLAUDE.md — v0.2 ГОТОВО, следующее v0.3/v0.5 параллельно поверх v0.2.
a-base §4 — dev-VM Stage 0/1/2 = фазовые таргеты + shturman-splash (software-render),
U-Boot framebuffer/A-B/secure-boot — HW (VM↔HW-граница). v0.1-v0.6 спека §13 —
шов «shturman.target → зонтик; critical set → stage1.target».

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Alexander <akotenev2003@gmail.com>
2026-06-24 20:20:32 +03:00

267 lines
24 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Домен A — Базовая система / OS
> Фундамент, на котором всё работает: образ, read-only rootfs + overlay, быстрый
> boot, время, память, логи, watchdog/recovery, OTA, шифрование at-rest и
> board-support (BSP). Здесь живёт «power-safe с дня 1» (вместе с B).
Статус: **v2 (на ревью).** v2 — после adversarial-ревью (24 находки).
Связано с: [hardware.md](../contracts/hardware.md) · [architecture.md](../architecture.md) (§6 boot) · [security-privacy.md](../contracts/security-privacy.md) (trust anchor, at-rest) · [principles.md](../principles.md) (#5 power-safe, #3 offline) · домен B (power-lifecycle) · домен J (камеры)
---
## 1. Назначение и границы
- **Что делает:** собирает и сопровождает Linux-образ; обеспечивает надёжность
(read-only rootfs, watchdog, атомарные OTA с откатом, recovery), целостность
времени и памяти, и переносимость (BSP).
- **Границы:** строимся поверх Linux (vision допускает свой образ/ядро, если стоковое
не вытянет — но не самоцель); не реализуем прикладную логику.
- **Швы владения:** A = boot-инфра (Stage 0/1, initramfs, образ); B = питание/ACC/
graceful shutdown; J = источник видео/оверлей. Для раннего пути задней камеры (§4)
A даёт boot-инфраструктуру, J — сам вид.
## 2. База и сборка образа 🟡
- **(рек.) Debian/Armbian под RK3588**, ядро ближе к mainline — быстрый старт; хватает на v0–v3.
- **Альтернативы:** Yocto (эталонно-воспроизводимо, продакшн-стандарт, но крутая кривая) · Buildroot.
- 🟡 *Выбор:* Armbian/Debian старт; Yocto — продакшн-hardening позже.
- **Два разных артефакта «образ» (во избежание путаницы с roadmap):**
- **bring-up/base-образ** — для разработки в VM и на reference-плате (v0);
- **флешируемый релиз-образ** (RAUC-bundle, подписанный, secure-boot, OTA-ready) —
«первый продукт»/ретрофит, созревает к **v4** (см. roadmap, dev-environment L4).
- **Локаль базы (под принцип #10 i18n-ready, не RU-only):** системная `ru_RU.UTF-8`
(LANG/LC_*), `tzdata` в образе, **кириллические шрифты с полным покрытием глифов,
доступные до старта Shell** (splash/Stage 0, консоль — иначе mojibake), console keymap.
## 3. Хранилище: разметка, ФС, надёжность, шифрование
- **eMMC:** загрузчик (U-Boot/SPL/TF-A) + **A/B-слоты** + журналируемый `/data` (RW).
- **Единица A/B = весь загружаемый юнит: `kernel + dtb + initramfs + rootfs` в КАЖДОМ
слоте** (не только rootfs!). Иначе плохое OTA-обновление ядра уронит оба слота
(B грузится тем же сломанным ядром) и уничтожит гарантию отката. Выбор слота — U-Boot
по RAUC-переменной (extlinux/boot.scr или per-slot FIT).
- **Загрузчик (U-Boot/SPL/TF-A) — вне A/B:** обновляется отдельным редким fail-safe
механизмом (redundant copies / write-then-switch, верификация до commit). Это
**самая рискованная** OTA-операция, гейтится отдельно. Hold-up cap (hardware §3)
защищает флаш при shutdown, но **не** запись в boot-раздел — нужен write-then-switch.
- **Overlay:** upper/work overlayfs — **на volatile tmpfs**. Всё, что должно пережить
ребут/обесточивание, пишется ТОЛЬКО в журналируемый `/data` через Settings/State.
Персистентный overlay upper на «голом» разделе **запрещён** — overlayfs upper/work не
crash-consistent при резком power-loss (внёс бы corruption ровно в защищаемом сценарии).
- **ФС `/data` 🟡:** **f2fs** (рек. — flash-aware, log-structured, лучший wear и
power-cut behavior; объединяет §7-износ и power-safe в один выбор) vs **ext4**
(зрелее, проще recovery, лучше в U-Boot/initramfs). Power-safe mount-опции:
f2fs `fsync_mode=strict` / ext4 `data=ordered,barrier=1`. RO-rootfs — ext4/squashfs.
- **Durable-write контракт** (единственный писатель — Settings/State): `write-temp →
fsync(file) → rename → fsync(dir)`. Структурный RO-rootfs НЕ защищает содержимое
`/data` при резком обесточивании — атомарная запись защищает даже без graceful shutdown.
- **At-rest шифрование `/data` (v4, 🟡):** **fscrypt** на чувствительных поддеревьях
(память водителя `.md`, `/data/apps/<id>/`, audit-log, OAuth-токены провайдеров,
**dashcam-медиа (J §4)** — это и наполняет смыслом «защищённое хранилище» из d-assistant). Ключ привязан к
**OTP/eFuse** (тот же анкор, что secure boot), headless-unlock (без пароля — авто
стартует по ACC). Иначе изъятая eMMC/SD = открытая утечка ПДн (152-ФЗ). Связан с
secure boot → оба в v4.
- **Носитель `/data`:** прод — eMMC; SD — dev/опционально (на SD power-safe-гарантии
деградированы). Тир поддержки SD фиксируем в hardware §2.
## 4. Boot и быстрый старт
- **Фазы (по architecture §6, цель < 10 c) — splash ВНУТРИ Stage 0, ядро в Stage 1:**
- **Stage 0 (мгновенно):** U-Boot → splash (+ ранний низколатентный путь задней
камеры/парктроника, если включена задняя — boot-инфра здесь, см. §1 шов с J/B);
- **Stage 1 (~35 c):** ядро-минимум (шина + Power + Settings + Perm-Broker + App-Host) → **Shell с первым кадром**;
- **Stage 2 (фоном):** Vehicle-Data, Assistant, Media, Nav прогреваются после интерактива.
- Быстрый boot: минимальный initramfs, параллельный systemd, ленивые сервисы.
- **Dev-VM (v0.2 реализовано):** Stage 0/1/2 = фазовые systemd-таргеты под зонтиком `shturman.target`; splash —
`shturman-splash` (Slint software-render → `/run/shturman/splash.png`, `Before=shell` → до первого кадра); Stage 2 —
warmup-плейсхолдер (`After=shell`, деферред). U-Boot framebuffer-splash + A/B + secure-boot + ранний путь камеры —
HW (VM↔HW-граница, как overlay/A-B в v0.6). Тайминг <10 c — функц. в VM, вердикт на RK3588.
- **Secure boot (verified boot, v4):** анкор доверия — **хэш публичного ключа в OTP/eFuse,
прожиг НЕОБРАТИМ** (burn-once, без ротации). Приватный ключ — offline/HSM с
бэкапом (потеря = кирпич парка). **Dev-ключи ≠ prod**, на dev-платах eFuse НЕ жжём
(trust-by-build). Это **необратимая веха**, не «мягкий переключатель». Подпись FIT и
RAUC-bundle верифицируются против этого же анкора.
- **Бюджет boot и verified-boot:** проверка подписи FIT (хэш многомегабайтного образа)
добавляет время. `< 10 c` на dev меряется без проверки; при secure boot (v4) —
использовать HW-крипто RK3588, минимальный verified initramfs, и **отдельную CI-метрику
boot-с-secure-boot** (принцип #11: регрессии перфа — баги).
## 5. OTA-обновления 🟡
- **(рек.) RAUC**: атомарные **A/B**-обновления (юнит = kernel+dtb+initramfs+rootfs),
**подписанные** bundle, **откат** при сбое.
- **Anti-rollback (downgrade-защита, v4):** подпись гарантирует аутентичность, **не свежесть** → A хранит
**монотонный security-version-счётчик** (eFuse-fuse / U-Boot env, модель AVB rollback-index) и отвергает
валидно-подписанный, но **downgrade/replay**-бандл. Иначе скомпрометированный OTA-хост (домен L) откатил бы
парк на подписанную дырявую прошивку. A/B-откат (ниже) — failure-recovery, **не** downgrade-защита (разные вещи).
- **Handshake отката (обязателен, иначе откат не работает):**
- В **U-Boot env на eMMC** (не в overlay/`/data`): активный слот, «try»-слот,
счётчик попыток + `bootlimit`.
- После OTA слот = «try»; U-Boot инкрементит счётчик на каждый boot try-слота, при
достижении лимита — автооткат на прошлый good-слот.
- **Что считается успешной загрузкой:** systemd-юнит, срабатывающий по достижению
реального интерактива (**Shell первый кадр, Stage 1**), зовёт `rauc status mark-good`
→ сбрасывает счётчик. Это закрывает дыру «ядро загрузилось, но userspace повис».
- Порог попыток + health-timeout, чтобы hang/boot-loop (не только чистый crash)
тоже вызывал откат на следующем watchdog-ребуте.
- **Граница владения:** домен A владеет **механизмом применения, подписью и keyring**
бандла (RAUC, верификация на устройстве). **Сборку, хостинг и доставку (OTA-канал) —
домен L.** A только верифицирует подпись.
- 🟡 *Выбор:* RAUC vs Mender/swupdate/OSTree. Дельта-обновления — позже.
## 6. Watchdog и восстановление
- **Два watchdog, явно разведены:** on-SoC RK3588 WDT (пэтится из userspace через
`/dev/watchdog`) и внешний **MCU-копилот watchdog** (hardware §3). Система-of-record
для форс-ресета — определить в B; **единственный userspace-владелец `/dev/watchdog`**
(systemd `RuntimeWatchdogSec`), второй пэтящий клиент запрещён.
- **Закрыть дыру boot-окна:** WDT, покрывающий весь путь загрузки, должен быть
**вооружён до передачи управления в userspace** (U-Boot вооружает SoC WDT на таймаут
boot→первый health-check, либо MCU всегда вооружён и ждёт ранний keepalive). Кто шлёт
heartbeat в boot-окне — определить (U-Boot/early-init), иначе hang в U-Boot/раннем
ядре = вечное зависание, а не recovery.
- **Recovery:** сбой загрузки слота A (включая ядро/dtb) → грузимся с B; оба слота
исчерпали попытки → recovery-режим. Watchdog-ресет связан с bootcount/slot-switch (§5).
## 7. Время и синхронизация (RTC / NTP / GPS)
Платы класса RK3588 часто **без батарейного RTC** → после обесточивания часы стартуют
с 1970. Это ломает: (1) **TLS к онлайн RU-LLM** (cert «not yet valid»), (2) порядок/метки
логов и audit-log, (3) день/ночь по времени (Shell). Решение:
- Battery-RTC как требование reference-платы (hardware) — либо явный no-RTC план.
- Онлайн-синк: `systemd-timesyncd` (легче) / chrony.
- **GPS как offline-first источник UTC** (NMEA → gpsd → chrony **SHM**, ~десятки–сотни мс; PPS µs —
опц., hardware-зависим, см. k-sensors §2) — основной фолбэк без сети (#3). Время может быть валидно
без позиционного фикса (k-sensors §2).
- **Персист last-known-time в `/data`** (`fake-hwclock`) — **периодически + на синке + на graceful
shutdown** (владение → домен B §8), чтобы холодный boot/резкий обрыв не откатывали часы к 1970.
- **Boot-политика:** до любого TLS-egress к LLM часы должны быть «вменяемыми» (gated).
## 8. Память (zram / OOM)
Локальная квантованная LLM (llama.cpp) + smithay + PipeWire + ONNX STT/TTS + Vehicle-Data +
**видео-пайплайн** (DMABUF камер / VPU-кодирование dashcam, J §9) на 8–16 ГБ — реальное давление
на память. Базовая политика:
- **zram** (сжатый swap в RAM, lz4/zstd) — основной запас; даёт RAM без записи во
flash (служит и цели §10-износа).
- **Swap-на-flash (eMMC/SD) — запрещён** (убивает flash, нарушает §10).
- **OOM-политика:** `systemd-oomd`/earlyoom — защищаем kernel/Power/Shell/Perm-Broker
(Stage 1 critical set) **+ низколатентную заднюю камеру** (J §9); первыми жертвами — офлайн-LLM,
фоновые апы, **throttleable dashcam/surround** (J §9 — деградируют видимо, не stall).
- **cgroup `MemoryMax/MemoryHigh`** на App-Host и тяжёлые апы. 8 ГБ — впритык, 16 ГБ —
целевой для одновременной локальной LLM (см. выбор модели — d-assistant).
## 9. Логирование
- **journald `Storage=volatile`** (журнал в RAM/tmpfs, не `/var/log/journal` на flash) +
`RuntimeMaxUse`-лимит; Rust-`tracing` → journald под ту же политику. Это реализует §10
(иначе дефолт Debian/Armbian пишет per-event во flash — против §10).
- **Защита от log-storm:** `RateLimitIntervalSec`/`RateLimitBurst`.
- **Критичные события переживают power-cut:** kernel panic, результат OTA, watchdog-ресет,
причина recovery, итог ACC-off — пишутся сразу с `fsync` малым size-capped append в
`/data`; ядро `pstore/ramoops` (panic читается в recovery). Hold-up (hardware §3) →
финальный flush journald на ACC-off. Инвариант: после двойного сбоя rootfs recovery
имеет доступ к причине.
- Прод-телеметрия — отдельный opt-in путь (security-privacy §7), не системный журнал.
## 10. Тепло и износ eMMC
- **Тепло:** софт мониторит температуры SoC/платы (kernel thermal zones), throttling;
радиатор/корпус — hardware. RK3588 в горячем салоне греется.
- **Износ eMMC/SD:** минимизируем запись — journald volatile (§9), tmpfs для транзиентного,
zram вместо swap (§8), никакого спама в `/data`. Особенно важно на SD.
## 11. First-boot provisioning
На чистом `/data` (после прошивки/factory-reset) systemd first-boot юнит (gated
`ConditionFirstBoot=`/маркер в `/data`) **идемпотентно**: (1) создаёт структуру
`/data` (`/data/apps`, конфиг Settings, память ассистента, логи); (2) генерит
**persistent `machine-id` в `/data`** и биндит в `/etc/machine-id` (systemd на RO-rootfs
сам его не персистит); (3) сеет дефолтные настройки; (4) активирует BSP/vehicle-профиль
в рантайме. Перезапускаемо после factory-reset. (Ключ шифрования, если будет — хук сюда.)
## 12. Factory reset (сброс к заводским)
Атомарная очистка/реинициализация **только `/data`** (wipe поддеревьев apps-storage,
память водителя `.md`, **контакты/журнал (G, в apps-storage)**, токены, Settings, **telemetry-consent + буфер телеметрии + все opt-in-согласия (L §8)**, **dashcam-медиа
(J §4 — на отдельном носителе/разделе)**; RO base-образ/BSP/device-identity сохраняются).
Зачем: продажа/передача авто (стереть ПДн — security-privacy §7), recovery после порчи
конфигурации, UX-выход из неработоспособности. Из recovery-режима + подтверждение
(защита от случайного). Отличать от `Settings.Reset(key)` (один ключ). При шифровании
`/data` — может быть мгновенным crypto-erase (выброс ключа). Фаза: later/v4.
## 13. Board-support / BSP (портирование)
BSP = device tree (overlay) + конфиг HAL + per-vehicle DBC ([hardware.md](../contracts/hardware.md) §5,
[data-model.md](../contracts/data-model.md) §7). Сборка поддерживает несколько BSP; **один
reference-таргет — first-party**, остальное — порты.
## 14. Функции
| функция | MVP/later | зависит от | фаза |
|---------|-----------|------------|------|
| Bring-up/base-образ (Debian/Armbian RK3588) | **MVP** | hardware | v0 |
| Разметка RO-rootfs A/B (kernel+dtb+initramfs+rootfs) + overlay(tmpfs) + `/data` | **MVP (день 1)** | — | v0 |
| Флешируемый релиз-образ (RAUC-bundle, прошивка) | later | — | v4 |
| Быстрый boot (Stage 0/1/2, < 10 c) | **MVP** | architecture §6 | v0 |
| Splash (Stage 0) | **MVP** | — | v0 |
| First-boot provisioning (`/data` init, machine-id) | **MVP (день 1)** | — | v0 |
| Время: NTP (timesyncd) + fake-hwclock персист | **MVP** | B | v0 |
| Время: GPS как offline-first UTC (NMEA→gpsd→chrony) | **MVP** | hardware(GPS), **K** | v1 |
| **Память** (zram + OOM + cgroup-лимиты) | **MVP (день 1)** | — | v0 |
| **Логирование** (journald volatile + критичное в `/data` + pstore) | **MVP (день 1)** | — | v0 |
| eMMC write-minimization | **MVP (день 1)** | — | v0 |
| Тепловой мониторинг + базовый throttling (SoC) | **MVP** | hardware | v0 |
| Тепловой тюнинг (политики под горячий салон) | later | — | v1 |
| Hardware watchdog (вооружён в boot-окне) + recovery | **MVP** | hardware, B | v0 |
| systemd-таргеты/оркестрация | **MVP** | — | v0 |
| Board-support: один reference-BSP | **MVP** | hardware HAL | v0 |
| Локаль базы (ru_RU.UTF-8, tzdata, кириллич. шрифты, keymap) | **MVP** | — | v0 |
| Stage 0 boot-инфра раннего пути задней камеры | later | architecture §6, J/B | v2 |
| OTA (RAUC A/B incl ядро/dtb, signed, bootcount+mark-good, rollback) | later | — | v4 |
| Secure boot (verified boot, OTP-eFuse, key-mgmt) | later | hardware | v4 |
| At-rest шифрование `/data` (fscrypt, eFuse-bound) | later | secure boot | v4 |
| Factory reset (`/data` wipe) | later | recovery | v4 |
| Мульти-BSP (другие платы/авто) | later | hardware HAL | later |
| Свой kernel/dtb тюнинг (внутри A/B-слота) | as needed | — | ongoing |
## 15. Зависимости
- **Вниз:** hardware (SoC, eMMC, RTC, watchdog, secure-boot/eFuse, BSP/HAL, GPS).
- **Вбок:** B (graceful shutdown, ACC, save-on-shutdown времени, watchdog-владение —
вместе делают power-safe) · J (источник/оверлей задней камеры, boot-инфра — здесь) ·
L (OTA-канал доставки).
- **Вверх:** стабильная база + systemd-оркестрация + время/память/логи для всех.
## 16. Открытые вопросы
- 🟡 Сборка образа: Armbian/Debian (старт) vs Yocto (продакшн).
- 🟡 OTA-тул: RAUC (рек.) vs Mender/swupdate/OSTree.
- 🟡 ФС `/data`: f2fs (рек.) vs ext4.
- ◻️ Recovery-режим UX (что показываем при двойном сбое rootfs; запуск factory-reset отсюда).
- ◻️ Свой образ/ядро (vision допускает) — только если стоковое не вытянет; обосновать.
- ◻️ Battery-RTC на reference-плате vs no-RTC план — финализировать в hardware.
---
## Журнал решений (домен A)
| Решение | Выбор | Дата |
|---------|-------|------|
| База | Debian/Armbian RK3588 старт; Yocto — продакшн-опция (🟡) | 2026-06-16 |
| Единица A/B | весь boot-юнит (kernel+dtb+initramfs+rootfs) на слот; загрузчик — вне A/B, отдельный fail-safe | 2026-06-16 |
| Overlay | upper/work на volatile tmpfs; персист только через `/data` | 2026-06-16 |
| ФС `/data` | f2fs (рек.) / ext4; power-safe mount-опции + atomic write (fsync/rename) (🟡) | 2026-06-16 |
| Boot-фазы | splash в Stage 0, ядро в Stage 1 (по architecture §6) | 2026-06-16 |
| OTA | RAUC A/B + bootcount/bootlimit + mark-good (Shell-кадр); A=механизм/подпись/**anti-rollback**, L=канал; downgrade-защита ≠ failure-откат (🟡) | 2026-06-16 |
| Secure boot | OTP-eFuse, необратим; dev-ключи ≠ prod, на dev не жжём; v4 | 2026-06-16 |
| Доверие | secure boot (анкор) + подписанный OTA; в dev — trust-by-build, полное — v4 | 2026-06-16 |
| Watchdog | SoC WDT + MCU; вооружён в boot-окне; единственный userspace-владелец | 2026-06-16 |
| Время | NTP + GPS-fallback + fake-hwclock; TLS gated на «вменяемые» часы | 2026-06-16 |
| Память | zram; swap-на-flash запрещён; OOM-политика + cgroup-лимиты | 2026-06-16 |
| Логи | journald volatile + критичное fsync в `/data` + pstore/ramoops | 2026-06-16 |
| At-rest | fscrypt чувствительных поддеревьев `/data`, eFuse-bound; v4 | 2026-06-16 |
| Портируемость | BSP (DT + HAL + DBC); один reference-таргет first-party | 2026-06-16 |