Skip to content

Safety Gateway

EnerOS Bot edited this page Jul 5, 2026 · 1 revision

中文 | English

SafetyGateway 与实时类型层安全

维护版本:v0.51.2 | 最后更新:2026-07-06

SafetyGateway 是 EnerOS 双执行域架构中通用域 → 实时域的唯一通道。所有来自 Agent / AI / 规划优化模块的指令必须经过 SafetyGateway 的 7 阶段决策管线、约束校验、优先级仲裁与执行器才能下放到实时域。本页概述类型层不可绕过机制;完整决策记录请参阅 ADR-0015

设计目标

目标 实现机制 验证手段
通用域无法直接调用实时域 API 类型层封装 + 编译期检查 clippy::disallowed_types 在 CI 中拒绝违例
实时域禁止堆分配 / 锁竞争 / 动态分派 NoAlloc marker + AllocTracker + lockfree 默认 WCET 框架 + 单线程 --test-threads=1 测试
决策可审计、不可篡改 RepositoryAuditSink + HMAC-SHA256 链 HMAC 链断链检测
约束不可降级 Constraint as Kernel Law 编译期 trait seal + 运行时拒绝

7 阶段决策管线

[Agent/AI/规划] → [Auth] → [Validate] → [Constraint] → [Priority]
                                ↓
                          [Decide] → [Execute] → [Audit]
阶段 职责 关键类型
Auth API Key / JWT / mTLS 认证 AuthMiddleware
Validate 类型层密封的命令验证 Validated<Command>
Constraint N-1 / 热稳 / 电压 / 频率 约束校验 ConstraintEngine
Priority 多 Agent 冲突优先级仲裁 PriorityArbiter
Decide 决策合成与签署 DecisionPipeline
Execute 下放至实时执行器 RtExecutor
Audit HMAC 链写入 WORM 审计日志 RepositoryAuditSink

类型层不可绕过(v0.49.0+)

Validated newtype

#[derive(Debug, Clone)]
pub struct Validated<T>(T);

impl Validated<Command> {
    /// 仅 SafetyGateway 可构造。新版本通过 sealed trait 收紧
    pub fn new(cmd: Command) -> Self { Self(cmd) }
}

pub struct SafetyGateway { /* ... */ }
impl SafetyGateway {
    pub fn submit(&self, cmd: Command) -> Result<Validated<Command>, GatewayError> {
        // 7 阶段管线...
        Ok(Validated::new(cmd))
    }
}

// 实时域 API 仅接受 Validated<Command>,不接受裸 Command
pub fn rt_execute(cmd: Validated<Command>) { /* ... */ }

外部代码无法直接构造 Validated<Command>,必须经过 SafetyGateway::submit

clippy::disallowed_types RT 禁锁

clippy.toml 中禁用实时域路径上的 Mutex / RwLock / Box::new / Vec::new 等:

[[disallowed-types]]
path = "std::sync::Mutex"
reason = "RT domain: lock contention is non-deterministic"

CI 中 cargo clippy --workspace --all-targets -- -D warnings 强制执行,违例即编译失败。

NoAlloc + AllocTracker

实时域代码标记 NoAlloc trait,运行时 AllocTracker 注入后检测任何堆分配并 panic:

pub trait NoAlloc {}

#[cfg(feature = "rt_check")]
pub struct AllocTracker { /* ... */ }

#[cfg(feature = "rt_check")]
impl AllocTracker {
    pub fn install() -> Self { /* 注入全局分配器钩子 */ }
    pub fn assert_no_alloc<F: FnOnce() -> R, R>(&self, f: F) -> R { /* ... */ }
}

WCET 框架

#[cfg(feature = "rt_check")]
pub fn wcet_bench<F: FnOnce() -> R, R>(label: &str, budget: Duration, f: F) -> R {
    let start = Instant::now();
    let r = f();
    let elapsed = start.elapsed();
    if elapsed > budget {
        panic!("WCET violation: {} {:?} > {:?}", label, elapsed, budget);
    }
    r
}

CI 中以 --test-threads=1 跑 WCET 测试避免噪声。

RepositoryAuditSink HMAC 链

pub struct RepositoryAuditSink {
    repo: AuditRepository,
    hmac_secret: [u8; 32],
    last_hash: Vec<u8>,  // 前一条目的 SHA-256
}

impl AuditSink for RepositoryAuditSink {
    fn write(&mut self, entry: &AuditEntry) -> Result<()> {
        let chain_hash = hmac_sha256(&self.hmac_secret, &[&self.last_hash, &entry.encode()]);
        self.repo.append(&entry, &chain_hash)?;
        self.last_hash = chain_hash;
        Ok(())
    }
}

任何篡改历史记录都会导致后续 HMAC 校验失败。

已知限制(v0.51.2)

  • AllocTracker 重入 bug 在 v0.49.1 通过直接调用绕过,待 v0.52.0 彻底修复
  • HardwareWatchdog 当前不是 trait,仅 CommandResult 变体被断言
  • Validated::new 当前用 #[doc(hidden)] pub 而非 sealed trait,待 v0.52.0 收紧
  • 67 个 unwrap/expect 残留于非测试代码(v0.51.0 已移除 88 个,TODO v0.52.0)
  • WCET 测试需 --test-threads=1

相关文档

Clone this wiki locally