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>
24 KiB
Домен 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 · architecture.md (§6 boot) · security-privacy.md (trust anchor, at-rest) · 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-опции: f2fsfsync_mode=strict/ ext4data=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 (~3–5 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-ребуте.
- В U-Boot env на eMMC (не в overlay/
- Граница владения: домен 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(systemdRuntimeWatchdogSec), второй пэтящий клиент запрещён. - Закрыть дыру 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 §5, 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 |