-
Notifications
You must be signed in to change notification settings - Fork 0
Safety Gateway en
中文 | English
Maintained version: v0.51.2 | Last updated: 2026-07-06
SafetyGateway is the only channel from the general domain to the real-time domain in EnerOS's dual execution domain architecture. All commands from Agents / AI / planning optimization modules must pass through SafetyGateway's 7-stage decision pipeline, constraint validation, priority arbitration, and executor before being dispatched to the real-time domain. This page summarizes the type-level unbypassable mechanism; for the full decision record see ADR-0015.
| Goal | Implementation | Verification |
|---|---|---|
| General domain cannot directly call RT API | Type-level encapsulation + compile-time check |
clippy::disallowed_types rejects violations in CI |
| RT domain bans heap allocation / lock contention / dynamic dispatch |
NoAlloc marker + AllocTracker + lockfree default |
WCET framework + single-thread --test-threads=1 tests |
| Decisions are auditable and tamper-proof |
RepositoryAuditSink + HMAC-SHA256 chain |
HMAC chain break detection |
| Constraints cannot be downgraded | Constraint as Kernel Law | Compile-time trait seal + runtime rejection |
[Agent/AI/Planning] → [Auth] → [Validate] → [Constraint] → [Priority]
↓
[Decide] → [Execute] → [Audit]
| Stage | Responsibility | Key Type |
|---|---|---|
| Auth | API Key / JWT / mTLS authentication | AuthMiddleware |
| Validate | Type-level sealed command validation | Validated<Command> |
| Constraint | N-1 / thermal / voltage / frequency constraint validation | ConstraintEngine |
| Priority | Multi-Agent conflict priority arbitration | PriorityArbiter |
| Decide | Decision synthesis and signing | DecisionPipeline |
| Execute | Dispatch to real-time executor | RtExecutor |
| Audit | HMAC chain write to WORM audit log | RepositoryAuditSink |
#[derive(Debug, Clone)]
pub struct Validated<T>(T);
impl Validated<Command> {
/// Only SafetyGateway can construct. Newer versions tighten via 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-stage pipeline...
Ok(Validated::new(cmd))
}
}
// RT API only accepts Validated<Command>, not bare Command
pub fn rt_execute(cmd: Validated<Command>) { /* ... */ }External code cannot directly construct Validated<Command> — must go through SafetyGateway::submit.
clippy.toml bans Mutex / RwLock / Box::new / Vec::new etc. on real-time domain paths:
[[disallowed-types]]
path = "std::sync::Mutex"
reason = "RT domain: lock contention is non-deterministic"CI enforces cargo clippy --workspace --all-targets -- -D warnings; violations fail the build.
RT domain code is marked with NoAlloc trait; at runtime AllocTracker is injected to detect any heap allocation and panic:
pub trait NoAlloc {}
#[cfg(feature = "rt_check")]
pub struct AllocTracker { /* ... */ }
#[cfg(feature = "rt_check")]
impl AllocTracker {
pub fn install() -> Self { /* inject global allocator hook */ }
pub fn assert_no_alloc<F: FnOnce() -> R, R>(&self, f: F) -> R { /* ... */ }
}#[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 runs WCET tests with --test-threads=1 to avoid noise.
pub struct RepositoryAuditSink {
repo: AuditRepository,
hmac_secret: [u8; 32],
last_hash: Vec<u8>, // SHA-256 of previous entry
}
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(())
}
}Any tampering with historical records causes subsequent HMAC verification to fail.
-
AllocTrackerreentrancy bug bypassed in v0.49.1 via direct calls; full fix pending v0.52.0 -
HardwareWatchdogis not currently a trait; onlyCommandResultvariant asserted -
Validated::newcurrently uses#[doc(hidden)] pubinstead of sealed trait; tightening pending v0.52.0 - 67
unwrap/expectremain in non-test code (88 removed in v0.51.0; TODO v0.52.0) - WCET tests require
--test-threads=1
- ADR-0015 RT Type-Level Safety
- Dual Execution Domain — General vs. real-time domain comparison
- Main repo docs/developer-guide.md — 7-stage pipeline implementation details
- Main repo crates/eneros-gateway/ — source code
EnerOS Wiki | v0.51.2