Files
shturman/docs/contracts/ipc.md
T
kk0t9 b9500356b0 docs(v0.3): синхронизация швов power-safe + статус
Двунаправленные швы (спека v0.3 §10) после реализации Плана 7:
- domain B: banner «Реализация (v0.3)» (B01–B07, VM-модель abort/PONR=stop+umount+remount);
  §12 — MCU/supercap (B08/B09) → v0.4.
- ipc.md §3: Power оживлён из FSM (не mock); Sleep/Wake/RequestSleep зарезервированы.
- foundation §5.2: «Power-стаб» → реальный PowerFsm (проекции state/ignition/source из FSM);
  dev-mock кормит входы FSM.
- CLAUDE.md: статус v0.3 ГОТОВО; «Следующее» → v0.5 shell / v0.4 MCU-thermal.

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

18 KiB
Raw Blame History

Контракт: IPC (D-Bus)

Backbone связей: реестр D-Bus-сервисов, их интерфейсов и соглашений. Формализует карту связей из architecture.md §5 в конкретные контракты. К нему цепляются data-model, plugin-sdk и все домены.

Статус: v2 (на ревью). v2 — после ретро-ревью (10 находок). Связано с: architecture.md (§45) · data-model.md · plugin-sdk.md · security-privacy.md

Область: control plane (D-Bus). Аудио/видео/графика — НЕ здесь (PipeWire/Wayland, см. architecture §4).


1. Шина и топология

  • Одна системная шина устройства (Штурман — single-purpose appliance, системная шина и есть его шина) со строгой D-Bus-политикой.
  • Ядро-сервисы общаются на ней напрямую.
  • Песочные апы/плагины напрямую шину НЕ видят — каждому выдаётся фильтрующий D-Bus-прокси (паттерн xdg-dbus-proxy), настроенный App-Host'ом из capabilities манифеста (см. §5). Это реализация портал-модели из решения №5.

🟡 Мелкий выбор на подтверждение: системная шина устройства (рекомендую, проще) vs выделенный экземпляр dbus-daemon только для Штурмана (чище изоляция от хост-сервисов, но лишний компонент). Прокси-фильтрация даёт изоляцию в обоих случаях.

2. Соглашения

Аспект Правило
Well-known имя ru.shturman.<Service> (напр. ru.shturman.VehicleData)
Путь объекта /ru/shturman/<Service>
Интерфейс ru.shturman.<Service>NN = мажорная версия (напр. …VehicleData1)
Версионирование аддитивно внутри версии; ломающее → добавляется …2 рядом со старым …1; оба сосуществуют в окне поддержки (старые плагины работают без правок; EOL мажора синхронизируется с shturman_api в манифесте)
Ошибки ru.shturman.Error.<Name>: PermissionDenied, NotAvailable (PID не поддержан машиной — постоянно), Stale/Timeout (транзиентно: таймаут/устарело), ReadOnly, InvalidArgument, Unsupported
Действие метод
Изменение состояния сигнал
Текущее состояние property (+ стандартный PropertiesChanged)
Асинхронность всё async (zbus + tokio); долгие операции не блокируют
Стандартные интерфейсы org.freedesktop.DBus.{Properties,Introspectable,Peer}
Идентичность вызывающего по аутентифицированному соединению (sender → PID/cgroup → манифест, привязка App-Host'ом), НЕ по аргументу метода; подменить нельзя
Жизненный цикл клиент-состояния серверное состояние клиента (подписки, регистрации тайлов/интентов) снимается автоматически при исчезновении владельца имени (NameOwnerChanged) — крэш/рестарт не оставляет мусора

Полные сигнатуры (XML-интроспекция) фиксируются при реализации; здесь — реестр и ключевые члены.


3. Реестр сервисов — ядро (привилегированные)

ru.shturman.VehicleData — данные машины (READ-ONLY)

  • Методы (только чтение): ListSignals() → [(name, availability)], GetSignal(name) → (value, unit, ts, quality), Subscribe(names, desired_max_hz)/Unsubscribe(names), GetDtcs() → [(code, status, desc)].
  • Авторизация по имени сигнала — в самом сервисе: прокси (§5) не видит payload, поэтому vehicle_read:[…] enforce-ит VehicleData по идентичности вызывающего (sender → манифест), отвергая незаявленные имена PermissionDenied. Сигналы адресные: SignalChanged(name, value, ts, quality) шлётся только подписчику и только по Subscribe ∩ манифест; DtcsChanged([...]).
  • Частота: desired_max_hz — верхняя граница, которую готов принять подписчик, и вход в агрегатный опрос: фактический опрос PID = max() запрошенных, ограничен потолком шины (~10–20 Гц) и источником. Доставка индивидуально не троттлится — слабый клиент (приборка) прореживает сам. Имя desired_ подчёркивает: не гарантия «моей частоты».
  • Подписки привязаны к владельцу соединения — снимаются автоматически при крэше/рестарте; агрегатный опрос пересчитывается, опрос PID останавливается без живых подписчиков (бережёт скудный ELM327).
  • Таймаут/staleness: GetSignal имеет таймаут → Stale/Timeout (или stale-flag в quality), не виснет на медленном ELM327-PID. NotAvailable = PID не поддержан машиной (постоянно); Stale = транзиентно (двигатель заглушен/таймаут).
  • Properties (горячие): Speed, Rpm, CoolantTemp, ModuleVoltage (питание ЭБУ ≈ бортсеть, не клеммы АКБ), Online.
  • Методов записи нет — ни SetSignal, ни actuator-команд, ни clear-DTC. Архитектурная гарантия read-only (принцип #2). Типы — data-model.md.

ru.shturman.Power — питание и жизненный цикл (домен B)

  • Методы: GetPowerState() → state (enum off/accessory/running/shutting_down/sleep/battery_cutoff), RequestSleep() (внутр.).
  • Сигналы: AccChanged(on), ShutdownImminent(seconds, reason) (reason ∈ acc_off|under_voltage|thermal|battery_cutoff), ShutdownAborted() (re-power до PONR), Sleep(), Wake().
  • Properties: IgnitionState (off/accessory/running — канон; E зеркалит, не дублирует), Uptime (монотонные часы), PowerSource (vehicle_12v/holdup_cap/sleep_rail/low_battery).
  • Реализация (v0.3): состояние/сигналы оживлены из FSM (PowerFsm в shturman-power, не mock); ShutdownImminent/ShutdownAborted — из реальных переходов (abort до PONR + grace-таймер). Sleep/Wake/RequestSleep объявлены, но зарезервированы (v1/v2, B §7). Источник событий (ACC/voltage/thermal через MCU) → v0.4; в v0.3 кормит dev-mock.

ru.shturman.Settings — конфигурация и состояние

  • Методы: Get(key) → value, Set(key, value), List(prefix) → [key], Reset(key).
  • Сигналы: Changed(key, value).
  • Namespace изолирует сам сервис Settings по идентичности вызывающего (sender → app-id): Get/Set/List/Reset вне своего namespace → PermissionDenied (прокси этого не делает — не инспектирует строку key). Свой namespace — read/write по умолчанию (ambient, без отдельной capability).

ru.shturman.PermBroker — политика разрешений (привратник)

  • Идентичность — только из соединения (sender → манифест), никогда из аргумента (иначе спуфинг/проверка за чужой ап).
  • Методы: CheckCapability(cap) → bool (sender-scoped — ап спрашивает про СЕБЯ; кросс-ап форма доступна только привилегированным core по D-Bus-политике), RequestRuntimeGrant(cap) → granted (рантайм-промпт; целевой ап = sender).
  • Сигналы: GrantChanged(cap, granted) — адресно владельцу гранта (чужие не получают).
  • Статическая фильтрация — прокси + sandbox (§5, владеет App-Host); broker — политика и рантайм-согласия.

ru.shturman.AppHost — запуск/супервизия апов и плагинов

  • Методы: ListApps() → [(id, status)], LoadApp(id) (читает манифест /data/apps/<id>/, конфигурит sandbox+прокси+sender→манифест; затем доступен StartApp), StartApp(id), StopApp(id), UnloadApp(id) (снести sandbox/прокси/identity-binding), GetStatus(id) → status.
  • Сигналы: AppStarted(id), AppStopped(id), AppCrashed(id, reason), AppLoaded(id).
  • Установка/жизненный цикл плагинов — ru.shturman.PluginManager (ниже, домен F): зовёт LoadApp/UnloadApp после install/remove/update.

ru.shturman.PluginManager — установка/жизненный цикл плагинов (домен F)

  • Методы: InstallPlugin(pkg), RemovePlugin(id), UpdatePlugin(id), ListPlugins() → [(id, version, status)].
  • Сигналы: PluginInstalled(id), PluginRemoved(id), PluginUpdated(id) (+ эмит нормативных audit-записей, A §9).
  • Привилегированная операция — недоступна самим плагинам через прокси. Контракт детально — домен F.

ru.shturman.Connectivity — сеть (обёртка NM/MM)

  • Методы: GetStatus() → status, ListNetworks() → [...], Connect(id), Disconnect().
  • Сигналы: ConnectivityChanged(state), NetworkChanged(...).
  • Properties: Online (bool — «сервис ещё не поднят» ≠ «offline»), Type (wifi/modem/tether), State (offline/portal/limited/online + модем sim_locked/no_sim/no_service — домен G), SignalStrength.

ru.shturman.Location — GPS/положение (владелец — домен K)

  • Properties: Latitude, Longitude, Heading, Speed, FixQuality (enum no_fix/fix_2d/fix_3d/augmented/dead_reckoning), HDOP, satellites, ts; per-property quality для Speed/Heading (зануление у нуля — domain K §2).
  • Сигналы: LocationChanged(...), FixChanged(quality).
  • Источник — NMEA/gpsd (hardware §4); гейтится capability location. GPS-скорость — ОТСЮДА (не из VehicleData/E). До домена K — мок-стаб (dev fake-GPS).

4. Реестр сервисов — апы (на SDK)

ru.shturman.Assistant

  • Методы: SendText(query) → reply, StartListening(), StopListening(), RegisterIntents(handler_path) — привязывает handler к фразам из манифеста assistant_intents (фразы НЕ передаются в рантайме, иначе обходится install-ревью).
  • Сигналы: StateChanged(idle|listening|thinking|speaking), TranscriptUpdated(text), ReplyUpdated(text).
  • Контекст машины подмешивается ассистентом из VehicleData (см. architecture §5).

ru.shturman.Shell — UX-host (слот-модель, решение №6)

  • Методы: RegisterTile(decl), RegisterScreen(decl) → slot_token (для поверхности клиент предъявляет slot-token в Wayland slot-протоколе ru.shturman.shell_slot, не передаёт wl_surface по D-Bus — см. c-shell §4), RequestForeground(slot), ShowOverlay(decl).
  • Сигналы: ForegroundChanged(app), NavigatedTo(screen), DistractionModeChanged(level).
  • Декларативный вклад = данные (рендерит shell); богатый = Wayland-поверхность.

ru.shturman.Media / …Nav / …Phone

  • Свои интерфейсы (play/pause/route; navigateTo/cancel; dial/answer/hangup). Детали — в спеках доменов H/I/G; здесь — только факт регистрации на шине.

ru.shturman.Camera — камеры/виды (владелец — домен J)

  • Методы: ListSources(), SelectView(id).
  • Сигналы: ReverseEngaged(on) (источник — Power/GPIO, см. J §3).
  • Properties: SignalState per-source (live/no_signal/acquiring).
  • Видео — НЕ здесь (PipeWire/V4L2, data-plane); гейтится camera_in (security-privacy). До домена J — мок-стаб. Детали — domains/j-cameras-video.md.

5. Брокеринг доступа песочных апов (портал-паттерн)

  1. Манифест плагина декларирует capabilities (vehicle_read:[speed], network, assistant_intents…).
  2. App-Host поднимает плагин в bubblewrap и даёт ему фильтрующий D-Bus-прокси, сконфигурированный под эти capabilities.
  3. Прокси даёт грубую изоляцию — сервис/интерфейс/метод/сигнал (payload/аргументы НЕ инспектирует). Пример: vehicle_read:[speed]VehicleData (read) достижим, а Power, чужие апы и write-методы — нет. Тонкую авторизацию по конкретному имени сигнала / ключу настроек делает сам сервис по идентичности sender (см. VehicleData, Settings).
  4. Рантайм-согласия (сеть «сейчас») — через PermBroker.RequestRuntimeGrant.

Итог: плагин физически не может дотянуться до того, чего нет в манифесте. Детали модели — security-privacy.md.


6. Точки расширения через IPC

  • Интенты ассистента: плагин реализует ru.shturman.IntentHandler1.HandleIntent(intent_id, slots) → result и регистрируется через Assistant.RegisterIntents. Латентно-критичные интенты (громче, домой) ассистент обрабатывает локально без LLM.
  • Вклад в UI: плагин зовёт Shell.RegisterTile/RegisterScreen (декларативно или поверхностью).

Полные контракты SDK (манифест, биндинги, точки расширения) — plugin-sdk.md.


Открытые вопросы (найдено на self-review → роутинг в нужные доки)

Не теряем; решается в указанных документах.

  • Гейтинг data-plane, не только D-Bus. → решено в security-privacy.md §4 (PipeWire/Wayland гейтятся capability'ями через bubblewrap-сокеты). API-часть — в plugin-sdk.
  • Экспорт объектов из песочницы. → решено в security-privacy.md §4 (плагин OWN под префиксом ru.shturman.plugin.<id>.*).
  • Приватное хранилище апа. → решено в security-privacy.md §4 (storage → mount /data/apps/<id>/).
  • Коллизия интентов. → решено в plugin-sdk.md §5 (слоистая политика разрешения); тонкости LLM-роутинга — домен D.
  • 🟡 Целостность манифеста. Модель доверия — security-privacy.md §6; подпись/стор — задел домена F.
  • ◻️ Быстрый канал для приборки.architecture.md §4 + домен E (открыто).

Журнал решений (ipc)

Решение Выбор Дата
Топология шины системная шина устройства + фильтрующий прокси на ап (🟡 на подтверждение) 2026-06-16
Изоляция доступа апов портал-паттерн: per-app dbus-proxy из манифеста 2026-06-16
Соглашения имён/версий ru.shturman.*, версия в имени интерфейса; мажоры сосуществуют в окне поддержки (аддитивно) 2026-06-16
Enforcement грубо — прокси (сервис/метод); тонко (per-signal/per-key) — сам сервис по sender 2026-06-16
Идентичность только из аутентиф. соединения, не из аргумента; клиент-состояние снимается по NameOwnerChanged 2026-06-16
Location/GPS отдельный сервис ru.shturman.Location (домен K); GPS-скорость не через E 2026-06-16