fix(review): manifest deny_unknown_fields + каталог сигналов в sdk::vehicle
- deny_unknown_fields: опечатка в ключе capability (граница доверия F §3) не проглатывается. - VEHICLE_SIGNALS → shturman_sdk::vehicle (single source; валидатор берёт оттуда). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Signed-off-by: Alexander <akotenev2003@gmail.com>
This commit is contained in:
@@ -5,6 +5,7 @@ pub mod connect;
|
||||
pub mod manifest;
|
||||
pub mod power;
|
||||
pub mod settings;
|
||||
pub mod vehicle;
|
||||
|
||||
pub use connect::connect;
|
||||
pub use manifest::Manifest;
|
||||
|
||||
@@ -6,6 +6,7 @@ use serde::Deserialize;
|
||||
|
||||
/// Корень манифеста (`manifest.yaml`).
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct Manifest {
|
||||
pub plugin: Plugin,
|
||||
#[serde(default)]
|
||||
@@ -15,6 +16,7 @@ pub struct Manifest {
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct Plugin {
|
||||
/// reverse-DNS id; `ru.shturman.*` закрыт за first-party (проверяет валидатор, F §3).
|
||||
pub id: String,
|
||||
@@ -29,6 +31,7 @@ pub struct Plugin {
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct Capabilities {
|
||||
/// Только сигналы из каталога data-model (проверяет валидатор).
|
||||
#[serde(default)]
|
||||
@@ -46,6 +49,7 @@ pub struct Capabilities {
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct Network {
|
||||
/// host-allowlist (намерение; строгая гарантия — forced-proxy, plugin-sdk §3).
|
||||
#[serde(default)]
|
||||
@@ -53,6 +57,7 @@ pub struct Network {
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct ExtensionPoints {
|
||||
#[serde(default)]
|
||||
pub tiles: Vec<Tile>,
|
||||
@@ -61,6 +66,7 @@ pub struct ExtensionPoints {
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct Tile {
|
||||
pub id: String,
|
||||
#[serde(default)]
|
||||
@@ -68,6 +74,7 @@ pub struct Tile {
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct Intents {
|
||||
/// Путь объекта `IntentHandler` (все фразы → сюда, plugin-sdk §2).
|
||||
pub handler: String,
|
||||
@@ -138,4 +145,19 @@ plugin:
|
||||
fn rejects_malformed_yaml() {
|
||||
assert!(Manifest::from_yaml(": : not yaml : :").is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rejects_unknown_field() {
|
||||
// опечатка в ключе capability на границе доверия (F §3) не должна молча проглатываться
|
||||
let bad = r#"
|
||||
plugin:
|
||||
id: dev.example.x
|
||||
name: "x"
|
||||
version: 0.1.0
|
||||
shturman_api: "1"
|
||||
capabilities:
|
||||
vehicl_read: [speed]
|
||||
"#;
|
||||
assert!(Manifest::from_yaml(bad).is_err());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
//! Каталог стандартных сигналов машины (data-model §4) — single source для валидатора манифеста
|
||||
//! и будущих потребителей (домен E, v2). Алиасы; точные VSS-пути — в домене E.
|
||||
|
||||
/// Алиасы стандартных OBD-II сигналов (data-model §4). `vehicle_read` манифеста — только отсюда.
|
||||
pub const SIGNALS: &[&str] = &[
|
||||
"speed",
|
||||
"rpm",
|
||||
"engine_load",
|
||||
"coolant_temp",
|
||||
"intake_temp",
|
||||
"maf",
|
||||
"throttle",
|
||||
"intake_pressure",
|
||||
"fuel_level",
|
||||
"module_voltage",
|
||||
"ambient_temp",
|
||||
"oil_temp",
|
||||
"fuel_rate",
|
||||
"run_time",
|
||||
"mil_on",
|
||||
"dtc_count",
|
||||
"distance_mil",
|
||||
];
|
||||
|
||||
/// Является ли `alias` стандартным сигналом каталога.
|
||||
pub fn is_known(alias: &str) -> bool {
|
||||
SIGNALS.contains(&alias)
|
||||
}
|
||||
@@ -2,27 +2,6 @@
|
||||
|
||||
use shturman_sdk::Manifest;
|
||||
|
||||
/// Каталог стандартных сигналов (data-model §4). `vehicle_read` допускает только их.
|
||||
const VEHICLE_SIGNALS: &[&str] = &[
|
||||
"speed",
|
||||
"rpm",
|
||||
"engine_load",
|
||||
"coolant_temp",
|
||||
"intake_temp",
|
||||
"maf",
|
||||
"throttle",
|
||||
"intake_pressure",
|
||||
"fuel_level",
|
||||
"module_voltage",
|
||||
"ambient_temp",
|
||||
"oil_temp",
|
||||
"fuel_rate",
|
||||
"run_time",
|
||||
"mil_on",
|
||||
"dtc_count",
|
||||
"distance_mil",
|
||||
];
|
||||
|
||||
/// Поддерживаемые мажоры API (plugin-sdk §7).
|
||||
const SUPPORTED_API: &[&str] = &["1"];
|
||||
|
||||
@@ -55,9 +34,9 @@ pub fn validate(m: &Manifest) -> Vec<String> {
|
||||
));
|
||||
}
|
||||
|
||||
// vehicle_read только из каталога data-model
|
||||
// vehicle_read только из каталога data-model (single source — shturman_sdk::vehicle)
|
||||
for sig in &m.capabilities.vehicle_read {
|
||||
if !VEHICLE_SIGNALS.contains(&sig.as_str()) {
|
||||
if !shturman_sdk::vehicle::is_known(sig) {
|
||||
errs.push(format!("vehicle_read '{sig}' нет в каталоге data-model"));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user