Skip to content

Commit 761e8c6

Browse files
author
Arnaud Riess
committed
docs: reworked requirements and specification
1 parent 5238a6b commit 761e8c6

3 files changed

Lines changed: 58 additions & 61 deletions

File tree

docs/FUTURE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ let b = memory.load_i32(dynamic_offset as usize)?;
8686

8787
## 3. Temporal Isolation (Fuel-Based Execution)
8888

89-
Spatial isolation (implemented) prevents memory corruption. **Temporal isolation** prevents CPU time starvation — equally critical for safety standards (ISO 26262 requires both).
89+
Spatial isolation (implemented) prevents memory corruption. **Temporal isolation** prevents CPU time starvation — equally important for systems that need both memory and timing guarantees.
9090

9191
### 3.1 The Fuel Model
9292

docs/REQUIREMENTS.md

Lines changed: 49 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,11 @@ herkos is a compilation pipeline that transforms WebAssembly modules into memory
1515

1616
## 2. Problem Statement
1717

18-
Industry standards for functional safety (e.g., ISO 26262) and security require **freedom from interference** between software modules of different criticality levels. In practice this means:
18+
Systems that mix components of different trust or criticality levels require **freedom from interference** — the guarantee that one module cannot corrupt the state of another. In practice this means:
1919

20-
- An ASIL-B rated component shall not be able to corrupt the memory of an ASIL-D component
20+
- A higher-criticality component shall not be corruptible by a lower-criticality one
2121
- An untrusted third-party library shall be contained so it cannot reach outside its sandbox
22-
- Modules at different security or safety levels shall have provable isolation boundaries
22+
- Modules at different trust levels shall have provable isolation boundaries
2323

2424
This isolation is typically achieved through hardware mechanisms (MMU, MPU) or hypervisors. While effective, these approaches are:
2525

@@ -65,10 +65,10 @@ memory.grow instruction adds pages at runtime up to the declared maximum.
6565
```{req} Compile-Time Memory Sizing
6666
:id: REQ_MEM_COMPILE_TIME_SIZE
6767
:status: open
68-
:tags: memory, no_std, const-generic
69-
The maximum memory size shall be fixed at compile time via a const generic parameter
70-
(MAX_PAGES). No heap allocation is permitted for memory backing storage. The entire
71-
backing array shall be statically sized.
68+
:tags: memory, no_std, static-sizing
69+
The maximum memory size for each module shall be fixed at compile time. No heap
70+
allocation is permitted for memory backing storage. All memory shall be statically
71+
sized.
7272
```
7373

7474
```{req} Bounds-Checked Memory Access
@@ -84,9 +84,8 @@ an error (WasmTrap::OutOfBounds), never panic or invoke undefined behavior.
8484
:id: REQ_MEM_GROW_NO_ALLOC
8585
:status: open
8686
:tags: memory, memory.grow, no_std
87-
memory.grow shall not perform heap allocation. Growth is a counter increment plus
88-
zero-fill of new pages within the pre-allocated backing array. Returns previous
89-
page count on success, -1 on failure.
87+
memory.grow shall not perform heap allocation. New pages shall be zero-initialized
88+
within pre-allocated storage. Returns previous page count on success, -1 on failure.
9089
```
9190

9291
### 4.2 Module Representation
@@ -104,9 +103,9 @@ This distinction is the primary mechanism for spatial isolation.
104103
:id: REQ_MOD_GLOBALS
105104
:status: open
106105
:tags: modules, globals
107-
Mutable Wasm globals shall be represented as typed struct fields in a generated
108-
Globals struct. Immutable globals shall be Rust const items. No dynamic lookup
109-
or enum indirection.
106+
Mutable Wasm globals shall have statically typed, per-instance storage. Immutable
107+
globals shall be compile-time constants. Global access shall be resolved statically,
108+
with no dynamic lookup.
110109
```
111110

112111
```{req} Indirect Call Table
@@ -124,35 +123,35 @@ validate the type signature before dispatch.
124123
:id: REQ_CAP_IMPORTS
125124
:status: open
126125
:tags: imports, traits, capabilities
127-
Wasm module imports shall become Rust trait bounds on a generic host parameter.
128-
Each group of related imports maps to one trait. If a module does not import a
129-
capability, the trait bound shall not exist — no code path to call it.
126+
Wasm module imports shall be statically checked capabilities. Related imports
127+
shall be grouped into discrete capability sets. If a module does not import a
128+
capability, no code path to invoke it shall exist.
130129
```
131130

132131
```{req} Exports as Trait Implementations
133132
:id: REQ_CAP_EXPORTS
134133
:status: open
135134
:tags: exports, traits
136-
Wasm module exports shall become trait implementations on the transpiled module
137-
struct. This enables inter-module linking via trait composition.
135+
Wasm module exports shall be exposed as statically typed interfaces on the
136+
transpiled module. This shall enable inter-module linking via interface composition.
138137
```
139138

140139
```{req} Zero-Cost Dispatch
141140
:id: REQ_CAP_ZERO_COST
142141
:status: open
143142
:tags: traits, dispatch, performance
144-
All capability dispatch shall use monomorphization (no vtables, no trait objects
145-
in the hot path). If a module does not import a capability, zero code for that
146-
capability is generated.
143+
Capability dispatch shall incur zero runtime overhead compared to direct function
144+
calls. If a module does not import a capability, no code for that capability shall
145+
be generated.
147146
```
148147

149148
```{req} WASI Support via Standard Traits
150149
:id: REQ_CAP_WASI
151150
:status: open
152151
:tags: wasi, imports, traits
153-
WASI (WebAssembly System Interface) support shall be implemented as a standard
154-
set of traits (WasiFd, WasiPath, WasiClock, WasiRandom, etc.) shipped by
155-
herkos-runtime. The host implements whichever subset it supports.
152+
WASI (WebAssembly System Interface) support shall be provided as a standard set
153+
of capability interfaces shipped with the runtime. The host provides whichever
154+
subset it supports.
156155
```
157156

158157
### 4.4 Transpilation
@@ -161,26 +160,25 @@ herkos-runtime. The host implements whichever subset it supports.
161160
:id: REQ_TRANS_FUNCTIONS
162161
:status: open
163162
:tags: transpilation, functions
164-
Each Wasm function shall be transpiled to a Rust function. Module state (memory,
165-
globals, table) is threaded through as parameters. Capabilities become trait bounds
166-
on a generic host parameter.
163+
Each Wasm function shall be transpiled to a Rust function with explicit access to
164+
module state (memory, globals, table) and granted capabilities.
167165
```
168166

169167
```{req} Control Flow Mapping
170168
:id: REQ_TRANS_CONTROL_FLOW
171169
:status: open
172170
:tags: transpilation, control-flow
173-
Wasm control flow (block, loop, if, br, br_if, br_table) shall map to Rust control
174-
flow structures using labeled blocks and breaks. No goto or unsafe control flow.
171+
Wasm control flow (block, loop, if, br, br_if, br_table) shall map to safe Rust
172+
control flow structures. No goto or unsafe control flow.
175173
```
176174

177175
```{req} Safe Indirect Call Dispatch
178176
:id: REQ_TRANS_INDIRECT_CALLS
179177
:status: open
180178
:tags: transpilation, indirect-calls, safety
181-
Indirect calls (call_indirect) shall use static match dispatch over function indices,
182-
not function pointers, vtables, or dynamic dispatch. The match enumerates all
183-
functions matching the expected type signature. 100% safe Rust.
179+
Indirect calls (call_indirect) shall be dispatched using only safe Rust — no
180+
function pointers, no unsafe dispatch. The dispatch mechanism shall validate type
181+
signatures and enumerate only functions matching the expected type.
184182
```
185183

186184
```{req} Structural Type Equivalence
@@ -189,7 +187,7 @@ functions matching the expected type signature. 100% safe Rust.
189187
:tags: transpilation, types
190188
Type checks in call_indirect shall use structural equivalence: two type indices
191189
match if they have identical parameter and result types, regardless of index.
192-
The transpiler shall build a canonical type index mapping at transpile time.
190+
Type equivalence shall be resolved at transpile time.
193191
```
194192

195193
```{req} Self-Contained Output
@@ -206,8 +204,7 @@ only Result<T, WasmTrap> for error handling.
206204
:status: open
207205
:tags: transpilation, determinism
208206
Generated output shall be identical regardless of CPU, thread count, execution order,
209-
or random seed. No non-deterministic collection types (e.g., HashMap iteration order).
210-
Enables reproducible builds and auditable output.
207+
or random seed. Enables reproducible builds and auditable output.
211208
```
212209

213210
### 4.5 Error Handling
@@ -216,9 +213,10 @@ Enables reproducible builds and auditable output.
216213
:id: REQ_ERR_TRAPS
217214
:status: open
218215
:tags: error-handling, traps
219-
Wasm traps shall map to a WasmTrap enum returned as Result::Err. Trap types:
220-
OutOfBounds, DivisionByZero, IntegerOverflow, Unreachable, IndirectCallTypeMismatch,
221-
TableOutOfBounds, UndefinedElement. No exceptions, no panics, no unwinding.
216+
Wasm traps shall be reported as typed, structured errors. The following trap
217+
categories shall be distinguished: out-of-bounds memory access, division by zero,
218+
integer overflow, unreachable code, indirect call type mismatch, table out-of-bounds,
219+
and undefined table element. No exceptions, no panics, no unwinding.
222220
```
223221

224222
### 4.6 Platform Constraints
@@ -229,7 +227,7 @@ TableOutOfBounds, UndefinedElement. No exceptions, no panics, no unwinding.
229227
:tags: no_std, embedded
230228
herkos-runtime and all transpiled output shall be #![no_std]. No heap allocation
231229
without the optional alloc feature gate. No panics, no format!, no String in the
232-
runtime or generated code. Enables embedded and safety-critical targets.
230+
runtime or generated code. Enables resource-constrained and embedded targets.
233231
```
234232

235233
## 5. Non-Functional Requirements
@@ -249,29 +247,29 @@ guaranteed.
249247
```{req} Freedom from Interference
250248
:id: REQ_FREEDOM_FROM_INTERFERENCE
251249
:status: open
252-
:tags: isolation, safety-critical, iso26262
253-
No module at a lower criticality level (e.g., ASIL-B) can corrupt the state of a
254-
module at a higher criticality level (e.g., ASIL-D), per ISO 26262 Part 6 and
255-
IEC 61508. Enforced via spatial isolation (memory ownership) and capability
256-
enforcement (trait bounds).
250+
:tags: isolation, freedom-from-interference
251+
No module shall be able to corrupt the state of another module. This property
252+
— commonly known as "freedom from interference" — shall be enforced via spatial
253+
isolation and capability enforcement. Note: herkos is not qualified to any
254+
safety standard. It provides an isolation mechanism, not a certified safety case.
257255
```
258256

259257
```{req} Spatial Isolation via Memory Ownership
260258
:id: REQ_ISOLATION_SPATIAL
261259
:status: open
262260
:tags: isolation, memory, type-system
263-
Each module shall operate on its own IsolatedMemory instance. The Rust type system
264-
shall structurally prevent any cross-module memory access — there shall be no pointer,
261+
Each module shall operate on its own isolated memory. The type system shall
262+
structurally prevent any cross-module memory access — there shall be no pointer,
265263
offset, or API that allows one module to reach another module's linear memory.
266264
```
267265

268266
```{req} Capability Enforcement via Traits
269267
:id: REQ_ISOLATION_CAPABILITY
270268
:status: open
271269
:tags: isolation, capabilities
272-
Capabilities shall be enforced via Rust trait bounds on the host parameter. A module
273-
can only perform operations that it was explicitly granted at instantiation. Missing
274-
capabilities shall cause compile errors, not runtime failures.
270+
Capabilities shall be statically enforced at compile time. A module can only perform
271+
operations that it was explicitly granted at instantiation. Missing capabilities
272+
shall cause compile errors, not runtime failures.
275273
```
276274

277275
### 5.2 Determinism
@@ -308,9 +306,8 @@ modules.
308306
:id: REQ_PERF_MONO_BLOAT
309307
:status: open
310308
:tags: performance, monomorphization, binary-size
311-
The runtime and transpiler shall apply the outline pattern (generic shell, non-generic
312-
core) to prevent binary size explosion from monomorphization. Binary size shall be
313-
a tracked metric.
309+
The runtime and transpiler shall mitigate binary size explosion from generic code
310+
specialization. Binary size shall be a tracked metric.
314311
```
315312

316313
### 5.4 Security

docs/SPECIFICATION.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -918,21 +918,21 @@ IR building and code generation are embarrassingly parallel — each function is
918918
│ Parse │ (sequential)
919919
└────┬─────┘
920920
921-
┌─────────────┼─────────────
922-
▼ ▼
921+
┌─────────────┼───────────┐
922+
▼ ▼ ▼
923923
┌──────────┐ ┌──────────┐ ┌──────────┐
924924
│ IR Build │ │ IR Build │ │ IR Build │ (parallel)
925925
│ func_0 │ │ func_1 │ │ func_N │
926926
└────┬─────┘ └────┬─────┘ └────┬─────┘
927-
928-
927+
928+
929929
┌──────────┐ ┌──────────┐ ┌──────────┐
930930
│ Codegen │ │ Codegen │ │ Codegen │ (parallel)
931931
│ func_0 │ │ func_1 │ │ func_N │
932932
└────┬─────┘ └────┬─────┘ └────┬─────┘
933-
934-
└─────────────┼─────────────┘
935-
933+
934+
└────────────────────────┘
935+
936936
┌──────────┐
937937
│ Assemble │ (sequential)
938938
└──────────┘
@@ -958,7 +958,7 @@ Activation heuristic: use `rayon` parallel iterators when the module has 20+ fun
958958

959959
- **Memory corruption**: buffer overflows, use-after-free — prevented by bounds-checked access and Rust's ownership system
960960
- **Unauthorized resource access**: files, network, system calls — prevented by trait-based capability enforcement
961-
- **Cross-module interference**: freedom from interference per ISO 26262 Part 6 — enforced by memory ownership isolation
961+
- **Cross-module interference**: freedom from interference — enforced by memory ownership isolation
962962
- **ROP attacks**: no function pointers in generated code — all dispatch is static match
963963

964964
### 7.2 Not Protected Against (current scope)

0 commit comments

Comments
 (0)