bvisor 0.9.0

Sync-first boundary supervisor: platform-agnostic boundary contract (types + fail-closed planner) with real Linux (landlock/seccomp/cgroups) and Wasm (wasmi/WASI) confinement backends. ZERO OS code, ZERO BatPak writes in the Backend trait.
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
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
//! [`SimBackend`] — a [`Backend`] that LIES deterministically.
//!
//! Sibling of batpak's fault framework (`crates/core/src/store/fault.rs`):
//! [`LieMode`] is the sibling of `FaultMode`, [`LieInjector`] the sibling of
//! `FaultInjector`. One seeded PRNG is advanced ONCE per consultation, so the
//! same seed yields the same lie sequence (`crates/core/src/store/sim/`).
//!
//! The monster performs a (simulated) dangerous effect, records the REAL effect
//! into the harness-owned [`GroundTruth`], and SEPARATELY constructs a possibly
//! LYING [`BoundaryReportBody`]. It never grades itself: the [`GroundTruth`]
//! handle the harness holds is the independent record the oracle diffs against.
//!
//! INVERSION RULE (from the recovery matrix): a backend may DENY MORE than asked
//! (fail-closed always legal); it may never REPORT LESS DANGER THAN OCCURRED.
//! The hide-danger lies ([`Lie::DropOrphanFromReport`], [`Lie::DropDeniedAttempt`],
//! [`Lie::AutoCommitButReportFalse`]) are illegal in every mode.

use crate::contract::backend::Backend;
use crate::contract::budget::{BudgetAvailability, BudgetProfile};
use crate::contract::budget_witness::BudgetWitnesses;
use crate::contract::capability::{Enforcement, EvidenceClaim, EvidenceSet, SupportVerdict};
use crate::contract::host_control::HostControl;
use crate::contract::ids::BackendId;
use crate::contract::plan::{BoundaryPlan, BoundaryRequirement, Workload};
use crate::contract::report::{
    BoundaryFinding, BoundaryReportBody, CaptureRefs, DeniedAttempt, ExitStatus, ObservedFact,
    Outcome, BOUNDARY_REPORT_SCHEMA_VERSION,
};
use crate::contract::support::{
    BackendProfile, BackendProfileSnapshot, RequirementKind, SupportMatrix,
};
use crate::sim::ground_truth::{GroundTruth, Lie};
use crate::sim::Prng;
use batpak::store::{Clock, SimClock};
use std::collections::BTreeMap;
use std::sync::Mutex;

/// One mode of the monster: an honest backend, or a single deterministic lie.
///
/// Sibling of `FaultMode`. `Honest` is the GREEN control: the report matches the
/// GroundTruth exactly. Every other mode tells exactly the one lie named, mapped
/// 1:1 to the [`Lie`] (and thence to the Gn) that catches it.
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub enum LieMode {
    /// Tell the truth: the report matches the GroundTruth (the control).
    Honest,
    /// Tell exactly one lie.
    Lie(Lie),
}

impl LieMode {
    /// A stable digest/label token discriminating each mode.
    #[must_use]
    pub fn token(self) -> u64 {
        match self {
            LieMode::Honest => 0x0000_0001,
            LieMode::Lie(lie) => 0x1000_0000 | (lie as u64),
        }
    }

    /// A short stable label for this mode.
    #[must_use]
    pub fn label(self) -> String {
        match self {
            LieMode::Honest => "honest".to_string(),
            LieMode::Lie(lie) => format!("lie:{}:{lie:?}", lie.gate()),
        }
    }
}

/// Trait for choosing which lie the monster tells on a given consultation.
///
/// Sibling of `FaultInjector`. Implementors inspect the run context and return
/// the [`LieMode`] to apply. A seeded implementor ([`SeededLiar`]) advances a
/// PRNG once per consultation, so the same seed yields the same lie sequence.
pub trait LieInjector: Send + Sync {
    /// Decide the lie mode for this consultation. Called once per `execute`.
    fn consult(&self) -> LieMode;
}

/// A seeded liar: advances a splitmix64 PRNG once per consultation and picks a
/// lie from the catalogue (or `Honest`). Same seed ⇒ same lie sequence.
pub struct SeededLiar {
    prng: Mutex<Prng>,
    catalogue: Vec<LieMode>,
}

impl SeededLiar {
    /// Seed the liar over the FULL catalogue (Honest + every lie).
    #[must_use]
    pub fn new(seed: u64) -> Self {
        Self {
            prng: Mutex::new(Prng::new(seed)),
            catalogue: full_catalogue(),
        }
    }

    /// Seed the liar over a restricted catalogue (e.g. one mode).
    #[must_use]
    pub fn over(seed: u64, catalogue: Vec<LieMode>) -> Self {
        let catalogue = if catalogue.is_empty() {
            vec![LieMode::Honest]
        } else {
            catalogue
        };
        Self {
            prng: Mutex::new(Prng::new(seed)),
            catalogue,
        }
    }
}

impl LieInjector for SeededLiar {
    fn consult(&self) -> LieMode {
        let draw = match self.prng.lock() {
            Ok(mut prng) => prng.next_u64(),
            // A poisoned lock is the supervisor faulting; fall back to Honest so
            // the monster never panics (panic is denied workspace-wide).
            Err(poisoned) => poisoned.into_inner().next_u64(),
        };
        let idx = usize::try_from(draw % self.catalogue.len() as u64).unwrap_or(0);
        self.catalogue.get(idx).copied().unwrap_or(LieMode::Honest)
    }
}

/// A one-shot liar that always returns a FIXED mode — the sibling of
/// `OneShotInjector` for the deterministic per-gate grid scenarios.
pub struct OneShotLiar {
    mode: LieMode,
}

impl OneShotLiar {
    /// Always tell exactly this mode.
    #[must_use]
    pub fn new(mode: LieMode) -> Self {
        Self { mode }
    }
}

impl LieInjector for OneShotLiar {
    fn consult(&self) -> LieMode {
        self.mode
    }
}

/// The full lie catalogue plus the Honest control.
fn full_catalogue() -> Vec<LieMode> {
    let mut modes = vec![LieMode::Honest];
    for lie in [
        Lie::ClaimEnforcedButAllowRead,
        Lie::ClaimEnforcedButAllowNet,
        Lie::WriteEscapesQuarantine,
        Lie::SpawnDespiteDeny,
        Lie::DropOrphanFromReport,
        Lie::ProxyInheritedFd,
        Lie::AutoCommitButReportFalse,
        Lie::SkipSealing,
        Lie::DropDeniedAttempt,
        Lie::MisreportEnforcementDepth,
        Lie::CrashMidBoundary,
    ] {
        modes.push(LieMode::Lie(lie));
    }
    modes
}

/// The monster. Claims a deep support matrix (so `plan()` admits anything), then
/// LIES at execution time according to its [`LieInjector`]. Performs simulated
/// effects only — ZERO real OS code — and records the REAL effect into a
/// harness-owned [`GroundTruth`] the oracle later diffs against the report.
pub struct SimBackend {
    id: BackendId,
    support: SupportMatrix,
    injector: Box<dyn LieInjector>,
    /// The honest seven-dimensional budget profile the monster declares (it enforces
    /// every dimension via a simulated mechanism).
    budget: BudgetProfile,
    /// The deterministic clock that witnesses wall time. The honest simulation
    /// advances it by `simulated_wall_micros` per run, so `execute` reads a real,
    /// replayable elapsed wall from the public [`batpak::store::Clock`] seam.
    /// Core's canonical [`SimClock`] — bvisor no longer carries a duplicate
    /// `Clock` impl.
    clock: SimClock,
    /// The simulated workload's modeled wall consumption (µs) the honest run advances
    /// the clock by. Default `0` (an instant simulation consumes 0 simulated wall);
    /// tests set it to witness a within-budget run or trip the wall limit.
    simulated_wall_micros: u64,
    /// The harness-owned independent record. `Mutex` only because `execute`
    /// takes `&self`; the harness reads it back via [`SimBackend::ground_truth`].
    truth: Mutex<GroundTruth>,
}

/// The honest budget profile the monster declares: it ENFORCES every dimension via a
/// simulated mechanism, witnesses resource usage, and offers ample headroom — so a
/// budgeted spec ADMITS on Sim (the positive reference) where it is refused on the
/// all-`Unsupported` Inert floor. The lie modes misreport at EXECUTION, not here.
fn sim_budget_profile() -> BudgetProfile {
    let enforced = |available: u64, mechanism: &str| {
        let mut evidence = EvidenceSet::new();
        evidence.insert(EvidenceClaim::ResourceUsage);
        BudgetAvailability {
            available,
            enforcement: Enforcement::Enforced,
            evidence,
            mechanism: mechanism.to_string(),
        }
    };
    BudgetProfile {
        wall_micros: enforced(60_000_000, "sim_timer"),
        cpu_micros: enforced(60_000_000, "sim_cpu_accountant"),
        resident_bytes: enforced(1u64 << 32, "sim_mem_accountant"),
        process_count: enforced(64, "sim_process_table"),
        handle_count: enforced(1024, "sim_descriptor_table"),
        storage_bytes: enforced(1u64 << 32, "sim_storage_quota"),
        network_bytes: enforced(1u64 << 30, "sim_network_meter"),
    }
}

impl SimBackend {
    /// The stable id of the sim backend.
    pub const ID: &'static str = "sim";

    /// Construct the monster with a lie injector. Its support matrix claims
    /// `Enforced` for every requirement kind, so `plan()` admits anything and the
    /// lie surfaces at execution time, not at admission.
    #[must_use]
    pub fn new(injector: Box<dyn LieInjector>) -> Self {
        Self {
            id: BackendId::new(Self::ID),
            support: deep_support(),
            injector,
            budget: sim_budget_profile(),
            clock: SimClock::new(),
            simulated_wall_micros: 0,
            truth: Mutex::new(GroundTruth::new()),
        }
    }

    /// Set the simulated workload's modeled wall consumption (µs) — the amount the
    /// honest run advances its deterministic clock by, and thus the witnessed
    /// `wall_micros` usage. Tests use this to witness a within-budget run or trip the
    /// wall limit.
    #[must_use]
    pub fn with_simulated_wall_micros(mut self, micros: u64) -> Self {
        self.simulated_wall_micros = micros;
        self
    }

    /// Take a SNAPSHOT of the harness-owned GroundTruth recorded during the most
    /// recent `execute`. This is the INDEPENDENT record the oracle diffs against
    /// the backend's self-reported body — the monster never grades itself.
    #[must_use]
    pub fn ground_truth(&self) -> GroundTruth {
        match self.truth.lock() {
            Ok(truth) => truth.clone(),
            Err(poisoned) => poisoned.into_inner().clone(),
        }
    }

    /// Record an effect into the harness-owned GroundTruth.
    fn record(&self, f: impl FnOnce(&mut GroundTruth)) {
        match self.truth.lock() {
            Ok(mut truth) => f(&mut truth),
            Err(poisoned) => f(&mut poisoned.into_inner()),
        }
    }

    /// Reset the GroundTruth before a fresh run (so consecutive `execute` calls
    /// on the same backend do not accumulate).
    fn reset_truth(&self) {
        match self.truth.lock() {
            Ok(mut truth) => *truth = GroundTruth::new(),
            Err(poisoned) => *poisoned.into_inner() = GroundTruth::new(),
        }
    }
}

/// The monster's deep verdict: `Enforced` with FULL evidence, so `plan()` admits
/// any spec (any enforcement + any evidence requirement) and the lie surfaces at
/// execution time, never at admission.
fn deep_verdict() -> SupportVerdict {
    SupportVerdict::new(
        Enforcement::Enforced,
        [
            EvidenceClaim::TerminalOutcome,
            EvidenceClaim::CapturedStreams,
            EvidenceClaim::ResourceUsage,
            EvidenceClaim::AllowedActions,
            EvidenceClaim::DeniedAttempts,
            EvidenceClaim::FilesystemDelta,
            EvidenceClaim::ProcessTree,
            EvidenceClaim::NetworkActivity,
            EvidenceClaim::ArtifactLineage,
            EvidenceClaim::MechanismAttestation,
        ]
        .into_iter()
        .collect(),
    )
}

/// A deep support matrix: every requirement kind claims the deep verdict so
/// `plan()` admits any spec against the monster.
fn deep_support() -> SupportMatrix {
    let mut best = BTreeMap::new();
    for kind in [
        RequirementKind::Filesystem,
        RequirementKind::NetworkDenyAll,
        RequirementKind::NetworkAllowList,
        RequirementKind::ChildSpawnDenyNewTasks,
        RequirementKind::ChildSpawnAllowThreads,
        RequirementKind::ChildSpawnAllowDescendants,
        RequirementKind::Environment,
        RequirementKind::InheritedFdsNone,
        RequirementKind::InheritedFdsOnly,
        RequirementKind::LaunchWorkload,
        RequirementKind::CaptureStreams,
        RequirementKind::TempRoot,
        RequirementKind::ExposePath,
        RequirementKind::CommitArtifact,
        RequirementKind::DiscardArtifact,
        RequirementKind::Kill,
        RequirementKind::ListOutputs,
    ] {
        best.insert(kind, deep_verdict());
    }
    SupportMatrix::from_best_case(best)
}

/// The deep machine ceiling (matches the family best-case: all Enforced).
fn deep_ceiling() -> BackendProfile {
    let mut ceiling = BTreeMap::new();
    for kind in [
        RequirementKind::Filesystem,
        RequirementKind::NetworkDenyAll,
        RequirementKind::NetworkAllowList,
        RequirementKind::ChildSpawnDenyNewTasks,
        RequirementKind::ChildSpawnAllowThreads,
        RequirementKind::ChildSpawnAllowDescendants,
        RequirementKind::Environment,
        RequirementKind::InheritedFdsNone,
        RequirementKind::InheritedFdsOnly,
        RequirementKind::LaunchWorkload,
        RequirementKind::CaptureStreams,
        RequirementKind::TempRoot,
        RequirementKind::ExposePath,
        RequirementKind::CommitArtifact,
        RequirementKind::DiscardArtifact,
        RequirementKind::Kill,
        RequirementKind::ListOutputs,
    ] {
        ceiling.insert(kind, deep_verdict());
    }
    BackendProfile::from_ceiling(ceiling)
}

impl Backend for SimBackend {
    fn id(&self) -> BackendId {
        self.id.clone()
    }

    fn support(&self) -> &SupportMatrix {
        &self.support
    }

    fn probe(&self) -> BackendProfileSnapshot {
        let mut probed = BTreeMap::new();
        probed.insert("backend".to_string(), "sim".to_string());
        probed.insert("confinement".to_string(), "simulated".to_string());
        BackendProfileSnapshot {
            backend: self.id.clone(),
            probed,
            budget: self.budget.clone(),
        }
    }

    fn profile(&self, _snap: &BackendProfileSnapshot) -> BackendProfile {
        deep_ceiling()
    }

    fn classify(&self, req: &BoundaryRequirement, profile: &BackendProfile) -> SupportVerdict {
        self.support.classify(req, profile)
    }

    fn execute(&self, plan: &BoundaryPlan) -> BoundaryReportBody {
        self.reset_truth();
        let mode = self.injector.consult();
        let mut run = RunState::new();

        // Witness WALL TIME from the public Clock seam: the honest run advances the
        // deterministic clock by the modeled wall, so this delta is real + replayable.
        let launched_mono_ns = self.clock.now_mono_ns();
        // The monster performs its (simulated) dangerous effects, recording the
        // REAL effect to GroundTruth and applying the lie to the report.
        self.simulate(plan, mode, &mut run);
        let wall_micros =
            u64::try_from((self.clock.now_mono_ns() - launched_mono_ns) / 1_000).unwrap_or(0);

        run.into_body(plan, &self.id, &self.probe(), wall_micros)
    }
}

impl SimBackend {
    /// Drive the simulated run for `mode`, recording REAL effects to GroundTruth
    /// and applying the lie to `run` (the report-in-progress).
    fn simulate(&self, plan: &BoundaryPlan, mode: LieMode, run: &mut RunState) {
        match mode {
            LieMode::Honest => self.simulate_honest(plan, run),
            LieMode::Lie(lie) => self.simulate_lie(plan, lie, run),
        }
    }

    /// The honest control: every real effect is also observed in the report, and
    /// the run reaches a terminal that is sealed.
    fn simulate_honest(&self, _plan: &BoundaryPlan, run: &mut RunState) {
        // Model the workload's wall consumption by advancing the deterministic clock;
        // `execute` reads the resulting elapsed and witnesses the wall budget.
        // Core's SimClock takes a signed delta; the modeled wall is a u64, so
        // saturate at i64::MAX (the clock clamps anyway and never regresses).
        self.clock
            .advance_us(i64::try_from(self.simulated_wall_micros).unwrap_or(i64::MAX));
        self.record(GroundTruth::reached_terminal);
        run.outcome = Outcome::Completed;
        run.exit = Some(ExitStatus::Code(0));
        // Mechanism honesty: claim exactly what was done (no confinement here).
        run.mechanism_override = Some("sim:honest:no-confinement".to_string());
    }

    /// Apply exactly one lie: do the dangerous thing (record it to GroundTruth)
    /// but hide it in the report.
    fn simulate_lie(&self, plan: &BoundaryPlan, lie: Lie, run: &mut RunState) {
        self.record(GroundTruth::reached_terminal);
        run.outcome = Outcome::Completed;
        run.exit = Some(ExitStatus::Code(0));

        match lie {
            Lie::ClaimEnforcedButAllowRead => {
                self.record(|t| t.served_secret("secret.key"));
                // Report stays silent → diff catches G1.
            }
            Lie::ClaimEnforcedButAllowNet => {
                self.record(|t| t.opened_socket("10.0.0.1:443"));
                // Report stays silent → diff catches G2.
            }
            Lie::WriteEscapesQuarantine => {
                self.record(|t| t.wrote_outside_quarantine("/etc/passwd"));
                // Report stays silent → diff catches G3.
            }
            Lie::SpawnDespiteDeny => {
                self.record(|t| t.spawned_child(4242));
                // Report stays silent → diff catches G4.
            }
            Lie::DropOrphanFromReport => {
                self.record(|t| t.live_pid(9001));
                // Report omits the orphan → diff catches G5 (hide-danger).
            }
            Lie::ProxyInheritedFd => {
                self.record(|t| t.inherited_fd_reachable(7));
                // Report omits the leak → diff catches G6.
            }
            Lie::AutoCommitButReportFalse => {
                // The backend auto-promoted bytes OUT of quarantine — an act it
                // has no authority to do (commit is a host disposition). It then
                // stays SILENT in the report (no "artifact_committed" observation),
                // so no disposition ever governs the artifact → diff catches G7.
                self.record(|t| t.committed_artifact("out.bin"));
            }
            Lie::SkipSealing => {
                // The run REACHES a terminal (GroundTruth recorded it above) but
                // no report is sealed: the grid drops the report (`sealed=false`)
                // so the oracle catches "terminal without a seal" (G8).
            }
            Lie::DropDeniedAttempt => {
                self.record(|t| t.denied_attempt("network:DenyAll"));
                // Report omits the denial → diff catches G9 (hide-danger).
            }
            Lie::MisreportEnforcementDepth => {
                // Actually did nothing real, but claims a deep mechanism.
                self.record(|t| t.enforcement_depth("none/no-confinement"));
                run.mechanism_override = Some("sim:landlock_abi4+pivot_root".to_string());
            }
            Lie::CrashMidBoundary => {
                // Crashed BEFORE a terminal (GroundTruth records no terminal),
                // but the backend still seals a report claiming Completed. The
                // oracle catches the sealed-terminal-for-a-crashed-run lie (G11).
                self.reset_truth();
                run.outcome = Outcome::Completed;
            }
        }

        // Mirror the plan's admitted requirements into the report findings so the
        // report is otherwise well-formed (the lie is the only divergence).
        let _ = plan;
    }
}

/// The report-in-progress plus the seal-existence axis.
struct RunState {
    outcome: Outcome,
    exit: Option<ExitStatus>,
    observed: Vec<ObservedFact>,
    denied: Vec<DeniedAttempt>,
    /// G10: override the admitted mechanism strings in the report.
    mechanism_override: Option<String>,
}

impl RunState {
    fn new() -> Self {
        Self {
            outcome: Outcome::Completed,
            exit: None,
            observed: Vec::new(),
            denied: Vec::new(),
            mechanism_override: None,
        }
    }

    /// Finalize the report body from the plan + run state.
    fn into_body(
        mut self,
        plan: &BoundaryPlan,
        backend: &BackendId,
        profile: &BackendProfileSnapshot,
        wall_micros: u64,
    ) -> BoundaryReportBody {
        let mut admitted = plan.admitted.clone();
        if let Some(mechanism) = &self.mechanism_override {
            for a in &mut admitted {
                a.mechanism = mechanism.clone();
            }
        }
        let mut findings = Vec::new();
        for a in &admitted {
            findings.push(BoundaryFinding::RequirementAdmitted {
                requirement: a.requirement.clone(),
                enforcement: a.enforcement,
            });
        }
        // Honest backends observe LaunchWorkload; keep that so the body is
        // structurally plausible regardless of the lie.
        if plan.admitted.iter().any(|a| {
            matches!(
                a.requirement,
                BoundaryRequirement::HostControl(HostControl::LaunchWorkload)
            )
        }) {
            self.observed.push(ObservedFact {
                kind: "workload_launched".to_string(),
                detail: workload_detail(&plan.workload),
            });
        }

        BoundaryReportBody {
            schema_version: BOUNDARY_REPORT_SCHEMA_VERSION,
            plan_id: plan.plan_id,
            backend: backend.clone(),
            profile: profile.clone(),
            outcome: self.outcome,
            admitted,
            observed: self.observed,
            denied: self.denied,
            exit: self.exit,
            captured: CaptureRefs::default(),
            // WALL TIME is witnessed from the deterministic Clock seam (the first
            // execution-slice counter). CPU + the OS-counter dimensions remain
            // genuinely unwitnessed until their counters land. Lie modes will later
            // misreport these and GroundTruth will catch the mismatch.
            budget: BudgetWitnesses::with_wall(&plan.budgets, wall_micros),
            artifacts: Vec::new(),
            findings,
        }
    }
}

/// A stable workload detail string for the launch observation.
fn workload_detail(workload: &Workload) -> String {
    match workload {
        Workload::Process { exe, .. } => format!("sim launched process {exe}"),
        Workload::Wasm { module_ref } => format!("sim launched wasm {module_ref}"),
    }
}

/// Whether the run SEALS a report body — the seal-existence axis the grid uses
/// to set the `sealed` flag without re-running.
///
/// - [`Lie::SkipSealing`] (G8): the run REACHED a terminal but NO report is
///   sealed → `false`. The oracle catches "terminal without a seal".
/// - [`Lie::CrashMidBoundary`] (G11): the run did NOT reach a terminal but the
///   backend SEALS a report claiming `Completed` anyway → `true`. The oracle
///   catches "sealed terminal report for a run that never terminated".
#[must_use]
pub(crate) fn run_seals(mode: LieMode) -> bool {
    !matches!(mode, LieMode::Lie(Lie::SkipSealing))
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn seeded_liar_same_seed_same_sequence() {
        let a = SeededLiar::new(0x1234);
        let b = SeededLiar::new(0x1234);
        for _ in 0..16 {
            assert_eq!(a.consult(), b.consult(), "same seed ⇒ same lie sequence");
        }
    }

    #[test]
    fn one_shot_liar_is_fixed() {
        let liar = OneShotLiar::new(LieMode::Lie(Lie::SpawnDespiteDeny));
        assert_eq!(liar.consult(), LieMode::Lie(Lie::SpawnDespiteDeny));
        assert_eq!(liar.consult(), LieMode::Lie(Lie::SpawnDespiteDeny));
    }

    #[test]
    fn run_seals_only_when_not_seal_suppressing() {
        assert!(run_seals(LieMode::Honest));
        assert!(run_seals(LieMode::Lie(Lie::SpawnDespiteDeny)));
        assert!(
            !run_seals(LieMode::Lie(Lie::SkipSealing)),
            "G8 seals nothing"
        );
        assert!(
            run_seals(LieMode::Lie(Lie::CrashMidBoundary)),
            "G11 seals a (lying) terminal report"
        );
    }

    // The positive reference: the honest monster ENFORCES every budget dimension, so a
    // budgeted spec ADMITS on Sim where the all-Unsupported Inert floor must refuse.
    #[test]
    fn honest_sim_admits_a_budget_that_the_inert_floor_refuses() {
        use crate::backend::inert::InertBackend;
        use crate::contract::budget::{
            budget_admit, BudgetFailure, BudgetRefusal, BudgetRequest, BudgetRequirements,
            DerivedMinimums, MinGuarantee,
        };

        // A modest limit within every dimension's Sim capacity (process_count = 64
        // is the smallest), so only the GUARANTEE distinguishes Sim from the floor.
        let dimension = || {
            let mut evidence = EvidenceSet::new();
            evidence.insert(EvidenceClaim::ResourceUsage);
            BudgetRequest {
                limit: 8,
                guarantee: MinGuarantee::Mediated,
                evidence,
            }
        };
        let request = BudgetRequirements {
            wall_micros: dimension(),
            cpu_micros: dimension(),
            resident_bytes: dimension(),
            process_count: dimension(),
            handle_count: dimension(),
            storage_bytes: dimension(),
            network_bytes: dimension(),
        };
        let derived = DerivedMinimums::default();

        // Honest Sim enforces every dimension -> admits (the positive reference).
        let sim = SimBackend::new(Box::new(OneShotLiar::new(LieMode::Honest)));
        let admitted = budget_admit(&request, &sim.probe().budget, &derived, [0u8; 32]);
        assert!(
            admitted.is_ok(),
            "honest sim admits a Mediated-guarantee budget: {admitted:?}"
        );

        // The Inert floor is all-Unsupported -> refuses on the first dimension's guarantee.
        let inert = InertBackend::new();
        let refused = budget_admit(&request, &inert.probe().budget, &derived, [0u8; 32]);
        assert!(
            matches!(
                refused,
                Err(BudgetRefusal {
                    failure: BudgetFailure::GuaranteeInsufficient,
                    ..
                })
            ),
            "the Inert floor cannot guarantee any budget: {refused:?}"
        );
    }

    // The honest monster witnesses WALL TIME from the public Clock seam — a real,
    // replayable measurement — not the old fabricated ObservationUnavailable.
    #[test]
    fn honest_sim_witnesses_wall_time_within_budget_and_trips_when_over() {
        use crate::contract::budget::{BudgetRequirements, MinGuarantee};
        use crate::contract::budget_witness::BudgetFinding;
        use crate::contract::host_control::HostControl;
        use crate::contract::ids::BackendId;
        use crate::contract::plan::{BoundarySpec, EvidenceRequirements, Workload};
        use crate::contract::registry::{BackendRegistry, BoundaryPlanner, BoundaryRunner};
        use std::sync::Arc;

        let spec = BoundarySpec {
            workload: Workload::Process {
                exe: "true".to_string(),
                args: Vec::new(),
            },
            capabilities: Vec::new(),
            controls: vec![HostControl::LaunchWorkload],
            // Wall limit 50 us (within Sim capacity); the others uniform.
            budgets: BudgetRequirements::uniform(50, MinGuarantee::Mediated),
            evidence: EvidenceRequirements::default(),
        };

        // A run modeling 40 us of wall -> WITHIN the 50 us budget.
        let within = run_wall(&spec, 40);
        assert_eq!(within.budget.wall_micros.observed_usage, 40);
        assert_eq!(
            within.budget.wall_micros.finding,
            BudgetFinding::WithinLimit
        );
        // cpu stays genuinely unwitnessed (no CPU counter yet) — earned, not lazy.
        assert_eq!(
            within.budget.cpu_micros.finding,
            BudgetFinding::ObservationUnavailable
        );

        // A run modeling 90 us -> OVER the 50 us budget: the wall limit tripped.
        let over = run_wall(&spec, 90);
        assert_eq!(over.budget.wall_micros.observed_usage, 90);
        assert_eq!(
            over.budget.wall_micros.finding,
            BudgetFinding::LimitReachedEnforced
        );

        fn run_wall(
            spec: &BoundarySpec,
            wall_micros: u64,
        ) -> crate::contract::report::BoundaryReportBody {
            let backend = SimBackend::new(Box::new(OneShotLiar::new(LieMode::Honest)))
                .with_simulated_wall_micros(wall_micros);
            let mut registry = BackendRegistry::new();
            registry.register(Arc::new(backend));
            let plan = BoundaryPlanner::new(&registry)
                .plan(spec, &BackendId::new(SimBackend::ID))
                .expect("honest sim admits");
            BoundaryRunner::new(&registry)
                .run(&plan)
                .expect("run seals")
                .body
        }
    }
}