1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
//! Observer host — capability-bounded WASM sandbox for L2 projection
//! observers (E15 — Observer Capability Confinement).
//!
//! ## Spec anchor
//!
//! - **E15 Observer Capability Confinement** — Runtime axiom:
//! - **E15.a** observer panic is contained at the sandbox boundary; the
//! host catches the trap and emits an `ObserverQuarantine` event. No
//! native unwind reaches the L0 chain (L0 A22 strengthening).
//! - **E15.b** observer side-effects route exclusively through host-
//! declared capability tokens; direct syscalls and `wasi-{fs, sockets,
//! clocks, random}` are rejected at module-load.
//! - Observer path — L2 projection observers operate *post-commit*
//! on already-chained data; they cannot mutate chain state.
//!
//! ## Chain-non-affecting invariant (cryptographer-anchored firm contract)
//!
//! Observer execution is *chain-non-affecting* by construction. Four
//! clauses establish the invariant; together they ensure observer panic /
//! capability-deny / module compromise cannot affect L0 chain integrity:
//!
//! 1. **No chain-mutation host-fn**: every binding under `arkhe:observer/*`
//! is a side-effect to a non-chain destination (PG projection, metric
//! sink, KMS rotation receipt). No binding calls `Op::EmitEvent`,
//! `Op::SpawnEntity`, or any chain-head-write primitive.
//! 2. **Effect signature is chain-orthogonal**: every host-side
//! [`capability_linker::ObserverCapability`] impl carries its effect to
//! a layer *outside* the chain (projection / metric / vault). Enforced
//! by the trait signature shape — the impl receives no chain reference.
//! 3. **Quarantine emission is host-supervised**: when an observer wasm
//! traps, the *host* generates the `ObserverQuarantine` event. The
//! observer *triggers* the emission via its trap, but does not
//! *generate* it — the cryptographic chain anchor is host-owned.
//! 4. **Panic isolation preserves chain progression**: the wasmtime trap
//! is caught at the host's invoke boundary; chain progression
//! continues independently. The chain hash of the next tick is
//! unaffected by observer existence or panic-state.
//!
//! ## L0↔Runtime boundary surface
//!
//! `observer_host/` is a *Runtime-layer* concept. It uses no L0 source —
//! the L0 [`KernelObserver`](arkhe_kernel::KernelObserver) trait is
//! referenced only as a conceptual anchor (`observer_host` exposes the
//! same `KernelEvent` observation pattern but inside a capability-bounded
//! WASM sandbox).
//!
//! ## Surface
//!
//! - [`ObserverHost`] trait + [`NoopObserverHost`] (default when sandbox-
//! backed observer is not feature-gated).
//! - [`ObserverContext`] / [`ObserverError`] / [`ObserverTrapClass`].
//! - [`ObserverCapToken`] enum (`#[non_exhaustive]`) — currently a single
//! variant `PgWrite`; additional capabilities can be added without
//! breaking external matchers.
//! - `WasmtimeObserverHost` (feature `tier-2-observer-host-v2`) —
//! wasmtime preview-2 sandbox with fuel-metered execution + capability-
//! bounded `arkhe:observer/*` host-fn dispatch.
/// Capability tokens an enabled observer may request from the host.
///
/// `#[non_exhaustive]` — additive expansion is non-breaking. Currently
/// a single variant (`PgWrite`); additional capabilities (KMS / metric /
/// etc.) can be added without breaking external matchers.
///
/// `Ord` / `PartialOrd` are required so `ObserverCapToken` can live in a
/// deterministic [`std::collections::BTreeSet`] (the host's per-observer
/// capability set — deterministic iteration matters for the call-time
/// capability check audit log).
// SealedCapToken safeguard. The observer `ObserverCapToken` enum
// implements both the private `Sealed` marker (only reachable from
// `arkhe-forge-platform`) and the public
// `wasm_runtime_common::ObserverCapTokenSealed` trait. External crates
// cannot satisfy the `Sealed` bound, so the observer-cap-token universe
// is closed at the host-defining crate boundary — preserving the E15.b
// chain-non-affecting clause at compile-time (observer side-effects
// route exclusively through observer-declared capabilities, never
// through hook surfaces or unknown external types).
//
// Compiled only when at least one wasmtime feature is enabled (matches
// `wasm_runtime_common`'s feature gate).
/// Observer execution context — opaque to observers themselves; managed
/// by the host. Carries only the capability set; observers are read-only
/// sinks and do not mutate the submission pipeline (cf. hook host's
/// `ExtraBytesBuilder` thread).
///
/// **Chain-non-affecting clause 2 enforcement** (cryptographer-anchored):
/// this struct intentionally does NOT carry a reference to chain state,
/// chain head, or any Op-emit primitive. The borrow-checker enforces
/// that observer code can never construct a chain mutation through
/// `ctx`. Future field additions must preserve this invariant.
// `ObserverTrapClass` is re-exported from `arkhe-forge-core::event` —
// single source of truth lives in core because the value enters the L0
// chain via the `ObserverQuarantine` event. Re-export keeps the
// platform-side API surface stable for callers that imported from
// `arkhe_forge_platform::observer_host::ObserverTrapClass`.
pub use ObserverTrapClass;
/// Observer execution outcome.
/// Capability-bounded observer host — runs a registered observer module
/// against a `KernelEvent` stream with side-effects gated by the
/// configured capability set.
///
/// # Backends
///
/// The runtime selects between two backends:
/// - [`NoopObserverHost`] (always available) — pass-through that
/// returns `Ok(())` without invoking any wasm.
/// - `WasmtimeObserverHost` (feature `tier-2-observer-host-v2`) —
/// wasmtime preview-2 sandbox with fuel-metered execution +
/// capability-bounded `arkhe:observer/*` host-fn dispatch.
/// Pass-through host — returns `Ok(())` without invoking any observer
/// logic. Default when sandbox-backed observer is not feature-gated.
;