wasm4pm-compat 26.6.5

Minimal paper-complete, feature-capped Rust process-evidence crate. Start with compatibility. Graduate to execution.
Documentation
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
//! # Causal Consistency Law
//!
//! Typed markers for causal ordering in object-centric event logs.
//! Cross-object causality must be mutually consistent — this module
//! provides the witness markers for verified causal chains.
//!
//! ## What this module IS
//!
//! - Structure-only typed shapes for causal links, causal chains, and the
//!   causal consistency verdict of an object-centric log.
//! - A zero-cost [`crate::causality::CausalOrderWitness`] tag that names the authority under
//!   which causal ordering has been established.
//! - A [`crate::causality::CausallyOrderedEvidence`] envelope that distinguishes evidence with
//!   verified causal ordering from evidence without it at the type level.
//!
//! ## What this module is NOT
//!
//! - **Not** a causal ordering algorithm. No happens-before derivation, no
//!   cycle detection, no topological sort. Those concerns graduate to `wasm4pm`.
//! - **Not** a replacement for [`crate::evidence::Evidence`]. Causal ordering
//!   is orthogonal to the `Raw → Admitted` lifecycle — layer them as needed.
//!
//! ## The Chicago TDD doctrine applied here
//!
//! Per the process-mining Chicago TDD doctrine: the declared causal order is
//! not the real causal order until the event log proves it. A value tagged
//! `CausallyOrderedEvidence<T>` asserts the log-derivable causal order is
//! consistent; that assertion must be backed by evidence that can be mined.
//! Graduate to `wasm4pm` when you need the mining to run.
//!
//! ## Graduation
//!
//! When you need to derive causal ordering (e.g. from a Heuristics Miner or
//! a direct-follows relation), detect cycles, or verify mutual consistency
//! across object types, graduate to `wasm4pm`. The causal witness travels
//! with the evidence into the engine.

use core::marker::PhantomData;

/// Witness that causal ordering has been verified for this evidence.
///
/// This is a zero-sized marker. Presence of this witness as a type parameter
/// means the evidence has passed through a causal ordering check. It does not
/// run the check — it names the authority. Graduate to `wasm4pm` to execute.
///
/// This is structure only. See [`crate::causality`]. Graduate to `wasm4pm`
/// when causal ordering derivation must execute.
pub struct CausalOrderWitness;

/// A causal link between two events with a direction.
///
/// `From` and `To` are type-level event markers naming the cause and the
/// effect. The link is directional: `CausalLink<A, B>` means "A causes B".
/// This shape is zero-cost — no runtime data beyond `PhantomData`.
///
/// This is structure only. See [`crate::causality`]. Graduate to `wasm4pm`
/// when the causal link must be derived or validated from log evidence.
pub struct CausalLink<From, To> {
    _from: PhantomData<From>,
    _to: PhantomData<To>,
}

impl<From, To> CausalLink<From, To> {
    /// Construct a typed causal link shape.
    ///
    /// # Examples
    ///
    /// ```ignore
    /// use wasm4pm_compat::causality::CausalLink;
    ///
    /// struct PlaceOrder;
    /// struct ConfirmOrder;
    ///
    /// let _link: CausalLink<PlaceOrder, ConfirmOrder> = CausalLink::new();
    /// ```
    pub fn new() -> Self {
        Self {
            _from: PhantomData,
            _to: PhantomData,
        }
    }
}

impl<From, To> Default for CausalLink<From, To> {
    fn default() -> Self {
        Self::new()
    }
}

/// A causal chain — ordered sequence of causally-linked events.
///
/// `LENGTH` is a compile-time constant naming the number of causal links in
/// the chain. A chain of length 0 is vacuously consistent; a chain of length
/// 1 is a single causal link; longer chains form ordered sequences.
///
/// This is a structure-only envelope — no link list is stored at this layer.
/// Graduate to `wasm4pm` when the chain contents must be inspected or verified.
///
/// This is structure only. See [`crate::causality`]. Graduate to `wasm4pm`
/// when chain verification must execute.
pub struct CausalChain<const LENGTH: usize> {
    _private: (),
}

impl<const LENGTH: usize> CausalChain<LENGTH> {
    /// Construct a typed causal chain shape of the given length.
    ///
    /// # Examples
    ///
    /// ```ignore
    /// use wasm4pm_compat::causality::CausalChain;
    ///
    /// let _chain: CausalChain<3> = CausalChain::new();
    /// ```
    pub fn new() -> Self {
        Self { _private: () }
    }

    /// The number of causal links in this chain.
    ///
    /// # Examples
    ///
    /// ```ignore
    /// use wasm4pm_compat::causality::CausalChain;
    ///
    /// assert_eq!(CausalChain::<5>::new().length(), 5);
    /// ```
    pub const fn length(&self) -> usize {
        LENGTH
    }
}

impl<const LENGTH: usize> Default for CausalChain<LENGTH> {
    fn default() -> Self {
        Self::new()
    }
}

/// Causal consistency verdict for an object-centric log.
///
/// This is the structural verdict shape — a label produced after a causal
/// ordering check has been performed (or attempted). It does not perform
/// the check; that graduates to `wasm4pm`.
///
/// ## Variants
///
/// - [`Consistent`](crate::causality::CausalConsistency::Consistent) — all cross-object causal
///   chains form a strict, cycle-free partial order.
/// - [`HasCycles`](crate::causality::CausalConsistency::HasCycles) — at least one causal cycle
///   was detected (e.g. `e1 → e2 → e1`), violating the posets constraint.
/// - [`HasContradictions`](crate::causality::CausalConsistency::HasContradictions) — at least
///   two causal links contradict each other.
/// - [`Unknown`](crate::causality::CausalConsistency::Unknown) — causal consistency has not yet
///   been established (the log has not been mined).
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum CausalConsistency {
    /// All cross-object causal links are mutually consistent.
    Consistent,
    /// At least one causal cycle was detected.
    HasCycles,
    /// At least one contradictory causal ordering claim was found.
    HasContradictions,
    /// Causal consistency has not yet been established.
    Unknown,
}

impl core::fmt::Display for CausalConsistency {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        match self {
            Self::Consistent => write!(f, "causally-consistent"),
            Self::HasCycles => write!(f, "has-causal-cycles"),
            Self::HasContradictions => write!(f, "has-causal-contradictions"),
            Self::Unknown => write!(f, "causal-consistency-unknown"),
        }
    }
}

/// Evidence with verified causal ordering.
///
/// Wrapping a value in `CausallyOrderedEvidence<T>` asserts at the type level
/// that causal ordering has been established for `T`. A function demanding
/// `CausallyOrderedEvidence<T>` cannot be called with unordered evidence.
///
/// The `_witness: PhantomData<CausalOrderWitness>` field is zero-cost — it is
/// a compile-time-only tag.
///
/// This is structure only. See [`crate::causality`]. Graduate to `wasm4pm`
/// when causal ordering derivation must execute.
pub struct CausallyOrderedEvidence<T> {
    /// The inner evidence value.
    pub inner: T,
    _witness: PhantomData<CausalOrderWitness>,
}

impl<T> CausallyOrderedEvidence<T> {
    /// Wrap `inner` as causally-ordered evidence.
    ///
    /// # Examples
    ///
    /// ```ignore
    /// use wasm4pm_compat::causality::CausallyOrderedEvidence;
    ///
    /// let ev = CausallyOrderedEvidence::new(42u32);
    /// assert_eq!(ev.inner, 42);
    /// ```
    pub fn new(inner: T) -> Self {
        Self {
            inner,
            _witness: PhantomData,
        }
    }
}

// ── One-way-door: Unknown → Consistent ────────────────────────────────────
//
// The problem: `CausalConsistency::Consistent` is a plain enum variant —
// anyone can write `CausalConsistency::Consistent` without going through any
// verification. This is the same unchecked-admission problem that
// `evidence.rs` solves with `Evidence<T, Admitted, W>::sealed()`.
//
// The solution: a sealed `ConsistencyVerified<T>` envelope. The only public
// path to *carrying* `CausalConsistency::Consistent` inside an envelope is
// through the `VerifyCausalConsistency` trait. Callers can still use
// `CausalConsistency::Consistent` as a plain value (it's a public enum), but
// code that demands `ConsistencyVerified<T>` cannot be satisfied by direct
// construction — the `_seal` field is module-private.
//
// Graduate to `wasm4pm` for the actual consistency-checking implementation.

/// Proof obligation token produced by a `VerifyCausalConsistency` impl.
///
/// A `ConsistencyProof` token can only be constructed by code with access to
/// the private `ConsistencyProof { _seal: () }` constructor — i.e., by impls
/// of `VerifyCausalConsistency` that reside in this module or are granted
/// `pub(crate)` access. External crates cannot forge this token.
///
/// This is the same sealing idiom used by [`crate::evidence::Evidence`] for
/// the `Raw → Admitted` transition.
pub struct ConsistencyProof {
    /// Module-private seal — prevents external forgery.
    _seal: (),
}

impl ConsistencyProof {
    /// Construct a proof token. `pub(crate)` — only this crate can mint one.
    pub(crate) fn new() -> Self {
        Self { _seal: () }
    }
}

/// An evidence value paired with a verified `CausalConsistency` verdict.
///
/// `ConsistencyVerified<T>` can only be constructed via
/// [`crate::causality::VerifyCausalConsistency::verify`]. The inner value is accessible via
/// `.inner`; the verdict via `.verdict()`.
///
/// ## Chicago TDD Rank-2 Oracle
///
/// This envelope enforces: *"All cross-object dependencies respect temporal
/// ordering."* Code demanding `ConsistencyVerified<T>` cannot receive an
/// unverified value — the `ConsistencyProof` token seals the door.
///
/// ## Graduation
///
/// The `wasm4pm` crate provides a `VerifyCausalConsistency` impl that runs
/// actual causal ordering derivation (Heuristics Miner, cycle detection,
/// topological sort). This crate provides only the law surface.
pub struct ConsistencyVerified<T> {
    /// The inner evidence value.
    pub inner: T,
    verdict: CausalConsistency,
    /// Module-private proof token — cannot be forged by external crates.
    _proof: ConsistencyProof,
}

impl<T> ConsistencyVerified<T> {
    /// Construct a verified envelope. `pub(crate)` — callers outside this
    /// crate must go through `VerifyCausalConsistency::verify`.
    pub(crate) fn new(inner: T, verdict: CausalConsistency, proof: ConsistencyProof) -> Self {
        Self {
            inner,
            verdict,
            _proof: proof,
        }
    }

    /// The causal consistency verdict established by the verifier.
    ///
    /// If the verifier produced [`crate::causality::CausalConsistency::Consistent`], all
    /// cross-object causal chains are certified cycle-free.
    ///
    /// ## Examples
    ///
    /// ```
    /// use wasm4pm_compat::causality::{CausalConsistency, VerifyCausalConsistency, UnknownVerifier};
    ///
    /// let verifier = UnknownVerifier;
    /// let verified = verifier.verify(true);
    /// assert_eq!(verified.verdict(), CausalConsistency::Unknown);
    /// assert!(!verified.is_consistent());
    /// ```
    ///
    /// True iff the verdict is [`crate::causality::CausalConsistency::Consistent`].
    pub fn verdict(&self) -> CausalConsistency {
        self.verdict
    }

    /// True iff the verdict is [`crate::causality::CausalConsistency::Consistent`].
    pub fn is_consistent(&self) -> bool {
        self.verdict == CausalConsistency::Consistent
    }
}

/// One-way-door trait for the `Unknown → Consistent` transition.
///
/// An impl of this trait is the *only* way to produce a
/// `ConsistencyVerified<T>` value. The `wasm4pm` crate provides the impl
/// that runs actual causal ordering derivation; this crate defines only the
/// law surface.
///
/// ## Rank-2 Oracle contract
///
/// Implementors must satisfy: *"If `verify` returns
/// `CausalConsistency::Consistent`, all cross-object event dependencies in
/// the evidence respect temporal ordering and contain no cycles."*
///
/// ## Forgery prevention
///
/// A caller cannot construct `ConsistencyVerified<T>` directly — the
/// `ConsistencyProof` field is module-private. The trait impl is the only
/// minting path.
pub trait VerifyCausalConsistency<T> {
    /// Run the causal consistency check and return a sealed verdict.
    ///
    /// The returned `ConsistencyVerified<T>` carries the verdict established
    /// by this impl. The verdict may be `Unknown` if the check cannot be
    /// performed (e.g. insufficient evidence), `Consistent` if all ordering
    /// constraints hold, or a failure variant if they do not.
    ///
    /// Graduate to `wasm4pm` for the real algorithm.
    fn verify(&self, evidence: T) -> ConsistencyVerified<T>;
}

/// A pass-through verifier that always returns `CausalConsistency::Unknown`.
///
/// This is the compat-layer stand-in: it satisfies the type law (returns a
/// sealed `ConsistencyVerified`) without running any algorithm. It is the
/// correct default for the structure-only layer.
///
/// Replace with a real `wasm4pm` verifier when causal ordering must execute.
pub struct UnknownVerifier;

impl<T> VerifyCausalConsistency<T> for UnknownVerifier {
    fn verify(&self, evidence: T) -> ConsistencyVerified<T> {
        ConsistencyVerified::new(
            evidence,
            CausalConsistency::Unknown,
            ConsistencyProof::new(),
        )
    }
}

// ── Rank-2 oracle tests ────────────────────────────────────────────────────
//
// These tests live in the crate because only crate-internal code can mint
// ConsistencyProof::new() and therefore ConsistencyVerified with any verdict.
// This verifies: the seal works; Consistent can be produced internally;
// external code cannot forge it (verified by compile-fail fixture).
#[cfg(test)]
mod tests {
    use super::*;

    /// A stub verifier that always claims Consistent — models what a real
    /// wasm4pm causal ordering impl would return after running cycle detection.
    struct AlwaysConsistentVerifier;

    impl<T> VerifyCausalConsistency<T> for AlwaysConsistentVerifier {
        fn verify(&self, evidence: T) -> ConsistencyVerified<T> {
            // Only callable from within the crate (pub(crate) seal).
            ConsistencyVerified::new(
                evidence,
                CausalConsistency::Consistent,
                ConsistencyProof::new(),
            )
        }
    }

    /// Rank-2 oracle: "All cross-object dependencies respect temporal ordering."
    ///
    /// A verifier that claims Consistent must produce a sealed envelope;
    /// the verdict must be Consistent; is_consistent() must return true.
    #[test]
    fn rank2_oracle_consistent_verdict_is_sealed() {
        let verifier = AlwaysConsistentVerifier;
        let result: ConsistencyVerified<u64> = verifier.verify(99u64);
        assert_eq!(result.verdict(), CausalConsistency::Consistent);
        assert!(result.is_consistent());
        assert_eq!(result.inner, 99u64);
    }

    /// Rank-2 oracle: Unknown verifier must NOT produce Consistent.
    ///
    /// The compat-layer stand-in (UnknownVerifier) must never claim ordering
    /// is established when no algorithm ran.
    #[test]
    fn rank2_oracle_unknown_verifier_stays_unknown() {
        let verifier = UnknownVerifier;
        let result: ConsistencyVerified<&str> = verifier.verify("raw-evidence");
        assert_eq!(result.verdict(), CausalConsistency::Unknown);
        assert!(!result.is_consistent());
    }

    /// Rank-2 oracle: HasCycles and HasContradictions are mintable internally,
    /// preserving the full verdict surface for wasm4pm engine impls.
    #[test]
    fn rank2_oracle_failure_verdicts_are_sealed() {
        struct CycleVerifier;
        impl<T> VerifyCausalConsistency<T> for CycleVerifier {
            fn verify(&self, evidence: T) -> ConsistencyVerified<T> {
                ConsistencyVerified::new(
                    evidence,
                    CausalConsistency::HasCycles,
                    ConsistencyProof::new(),
                )
            }
        }

        let result: ConsistencyVerified<i32> = CycleVerifier.verify(-1);
        assert_eq!(result.verdict(), CausalConsistency::HasCycles);
        assert!(!result.is_consistent());
    }

    /// Rank-2 oracle: ConsistencyProof is zero-sized (no runtime overhead).
    #[test]
    fn consistency_proof_is_zero_sized() {
        assert_eq!(core::mem::size_of::<ConsistencyProof>(), 0);
    }
}