Skip to content

Commit b8fbb2f

Browse files
committed
Fix: seal causal posture typestates
1 parent 6ac5387 commit b8fbb2f

3 files changed

Lines changed: 28 additions & 3 deletions

File tree

CHANGELOG.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -667,7 +667,9 @@ Applied, Rejected, Obstructed}` with receipt evidence and typed contract
667667
and `BraidMemberRef` so external consumers can handle public braid results.
668668
- `warp-core` shared-strand settlement handles now re-enter the live registry
669669
path before planning or settling, and crate-internal settlement helpers reject
670-
stale handles that no longer match registered strand state.
670+
stale handles that no longer match registered strand state. `CausalPostureState`
671+
is sealed to Echo's marker types so external crates cannot add typestate
672+
implementations outside the runtime posture gate.
671673
- `warp-wasm` settlement publication now maps non-`Shared` strand admission
672674
rejection to the stable `INVALID_STRAND` ABI error code instead of
673675
collapsing the lawful posture denial into `ENGINE_ERROR`.

crates/warp-core/src/revelation.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,15 +73,25 @@ pub enum CausalPosture {
7373
#[deprecated(note = "Use CausalPosture")]
7474
pub type RevelationPosture = CausalPosture;
7575

76+
mod posture_state_seal {
77+
pub trait Sealed {}
78+
}
79+
7680
/// Trait representing compile-time typestate for causal posture.
77-
pub trait CausalPostureState: Clone + std::fmt::Debug + PartialEq + Eq {
81+
///
82+
/// This trait is sealed to Echo's marker types. Runtime posture validation
83+
/// remains the authority for settlement admission.
84+
pub trait CausalPostureState:
85+
Clone + std::fmt::Debug + PartialEq + Eq + posture_state_seal::Sealed
86+
{
7887
/// Returns the runtime CausalPosture value for this typestate, or None if dynamic.
7988
fn causal_posture() -> Option<CausalPosture>;
8089
}
8190

8291
/// Marker struct representing the Shared causal posture.
8392
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
8493
pub struct Shared;
94+
impl posture_state_seal::Sealed for Shared {}
8595
impl CausalPostureState for Shared {
8696
fn causal_posture() -> Option<CausalPosture> {
8797
Some(CausalPosture::Shared)
@@ -91,6 +101,7 @@ impl CausalPostureState for Shared {
91101
/// Marker struct representing the AuthorOnly causal posture.
92102
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
93103
pub struct AuthorOnly;
104+
impl posture_state_seal::Sealed for AuthorOnly {}
94105
impl CausalPostureState for AuthorOnly {
95106
fn causal_posture() -> Option<CausalPosture> {
96107
Some(CausalPosture::AuthorOnly)
@@ -100,6 +111,7 @@ impl CausalPostureState for AuthorOnly {
100111
/// Marker struct representing the Scratch causal posture.
101112
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
102113
pub struct Scratch;
114+
impl posture_state_seal::Sealed for Scratch {}
103115
impl CausalPostureState for Scratch {
104116
fn causal_posture() -> Option<CausalPosture> {
105117
Some(CausalPosture::Scratch)
@@ -109,6 +121,7 @@ impl CausalPostureState for Scratch {
109121
/// Representation of causal posture whose type is dynamic/erased at compile-time.
110122
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
111123
pub struct DynamicPosture;
124+
impl posture_state_seal::Sealed for DynamicPosture {}
112125
impl CausalPostureState for DynamicPosture {
113126
fn causal_posture() -> Option<CausalPosture> {
114127
None

docs/design/0028-strand-typestates-proof-envelopes-and-evolving-braids/design.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,13 @@ All four key gaps from the Echo codebase gap analysis now have current E1 surfac
4747
We define the typestate traits and marker structs to represent the four causal posture states:
4848

4949
```rust
50-
pub trait CausalPostureState: Clone + std::fmt::Debug + PartialEq + Eq {
50+
mod posture_state_seal {
51+
pub trait Sealed {}
52+
}
53+
54+
pub trait CausalPostureState:
55+
Clone + std::fmt::Debug + PartialEq + Eq + posture_state_seal::Sealed
56+
{
5157
fn causal_posture() -> Option<CausalPosture>;
5258
}
5359

@@ -56,24 +62,28 @@ pub struct AuthorOnly;
5662
pub struct Scratch;
5763
pub struct DynamicPosture;
5864

65+
impl posture_state_seal::Sealed for Shared {}
5966
impl CausalPostureState for Shared {
6067
fn causal_posture() -> Option<CausalPosture> {
6168
Some(CausalPosture::Shared)
6269
}
6370
}
6471

72+
impl posture_state_seal::Sealed for AuthorOnly {}
6573
impl CausalPostureState for AuthorOnly {
6674
fn causal_posture() -> Option<CausalPosture> {
6775
Some(CausalPosture::AuthorOnly)
6876
}
6977
}
7078

79+
impl posture_state_seal::Sealed for Scratch {}
7180
impl CausalPostureState for Scratch {
7281
fn causal_posture() -> Option<CausalPosture> {
7382
Some(CausalPosture::Scratch)
7483
}
7584
}
7685

86+
impl posture_state_seal::Sealed for DynamicPosture {}
7787
impl CausalPostureState for DynamicPosture {
7888
fn causal_posture() -> Option<CausalPosture> {
7989
None

0 commit comments

Comments
 (0)