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
// SPDX-License-Identifier: Apache-2.0
//! Heddle's content-addressed mount.
//!
//! `mount` is the platform-agnostic core (and Linux FUSE shell) that
//! exposes a heddle thread as a directory tree. Reads walk the
//! Merkle DAG lazily; writes (eventually) flow into a per-thread
//! overlay that drains to a heddle commit on `heddle capture`.
//!
//! The architecture is:
//!
//! ```text
//! PlatformShell trait ← thin platform adapters
//! (FuseShell, FSKitShell, ProjFsShell, NfsShell)
//! ↓
//! ContentAddressedMount ← pure Rust core
//! ↓
//! crates/repo + crates/objects (already exists)
//! ```
//!
//! Three of those adapters are per-OS (FUSE on Linux, FSKit on
//! macOS, ProjFS on Windows). [`NfsShell`] is the universal
//! fallback: it stands up an in-process NFSv3 server and asks the
//! host's built-in NFS client to mount it. The CLI's mount
//! lifecycle prefers the native adapter and falls back to NFS
//! when the native one is unavailable at runtime.
//!
//! See [`PlatformShell`] for the trait every adapter implements,
//! and [`ContentAddressedMount`] for the heddle-aware core.
// Out-of-process FUSE worker (heddle#190 / spike heddle#88).
// `worker` exports the [`worker::Supervisor`] type the CLI's mount
// lifecycle uses to spawn `heddle-fuse-worker` subprocesses, plus
// the [`worker::run_worker`] entrypoint the binary calls. Linux +
// `fuse` only — the feature gate matches the binary's
// `required-features`.
// Re-export the fuser background-session type so callers (notably the
// CLI's mount lifecycle and daemon registry) don't have to take a
// direct fuser dep just to hold onto a live mount.
pub use BackgroundSession;
pub use crateFSKitShell;
pub use crateFuseShell;
pub use crate;
pub use crate;
pub use crate::;
/// NOT a stable public API. Re-exports the `pub(crate)` witness
/// substrate so a `compile_fail` doctest can pin the brand-isolation
/// invariant for Codex PR #217 r2 (`crates/mount/src/pending.rs`
/// finding `3293832936`). Hidden from rendered docs; consumers must
/// not depend on this module.
///
/// # Brand isolation (post heddle#208 r2)
///
/// The substrate brands `Pending`, `Witness`, and `KernelForgetWitness`
/// with an invariant `'brand` lifetime that's introduced per call via
/// [`core::Pending::with_brand`]. Witnesses minted under one `'brand`
/// cannot be passed to methods on a `Pending` carrying a different
/// `'brand` — the cross-instance bug Codex flagged on r1 stops
/// type-checking.
///
/// The doctest below is the executable proof. It compiles against
/// the pre-brand substrate (r1; cross-instance use is allowed —
/// THE BUG) and fails to compile against the post-brand substrate
/// (r2; brand mismatch — THE FIX).
///
/// ```compile_fail
/// use mount::__pending_substrate_for_doctest::*;
/// let mut p1 = Pending::default();
/// let mut p2 = Pending::default();
/// p1.with_brand(|p1_branded| {
/// p2.with_brand(|p2_branded| {
/// // `w` carries p1_branded's brand. Pre-fix it's
/// // `Witness<'_, LiveNonZero>` (no brand); post-fix it's
/// // `Witness<'_, 'brand_of_p1, LiveNonZero>`.
/// let w = p1_branded
/// .witness_live_nonzero(0)
/// .expect("doctest never runs — compile_fail");
/// // Pre-fix: `peek_witness` accepts any `&Witness<'_, S>`.
/// // Compiles → `compile_fail` assertion fails → RED.
/// // Post-fix: `peek_witness` on `Pending<'brand_of_p2>`
/// // wants `&Witness<'_, 'brand_of_p2, S>`. Brand
/// // mismatch → fails to compile → assertion holds → GREEN.
/// //
/// // `peek_witness` takes `&self` + `&Witness` (not consuming)
/// // so the proof stays orthogonal to the borrow-checker
/// // constraint introduced by `_borrow: PhantomData<&'p mut ()>`
/// // on the witness — that's a separate spike-doc question
/// // the retrofit issues will address, not this PR.
/// let _ = p2_branded.peek_witness(&w);
/// });
/// });
/// ```
///
/// # Constructor bypass (post heddle#208 r3)
///
/// r2 brand-isolated `Witness` cross-instance use *inside* `with_brand`,
/// but the `witness_*` constructors were still callable directly on
/// `&mut Pending<'brand>`. Because `MountInner` stores
/// `Pending<'static>`, an internal caller could mint
/// `Witness<..., 'static, _>` without going through `with_brand` at all
/// — and two distinct `Pending<'static>` values share the `'static`
/// brand, so witnesses crossed between them (Codex PR #217 r2 finding
/// `3293898540`).
///
/// r3 closes that hole by moving every `witness_*` (and `peek_witness`)
/// onto a sealed `BrandedPending<'p, 'brand>` wrapper whose only
/// constructor is `Pending::with_brand`. The doctest below is the
/// executable proof. It compiles against r2 (constructors live on
/// `Pending<'brand>`; direct mint succeeds → THE BUG) and fails to
/// compile against r3 (constructors are unreachable outside
/// `with_brand` → THE FIX).
///
/// ```compile_fail
/// use mount::__pending_substrate_for_doctest::*;
/// let mut p1 = Pending::default();
/// let mut p2 = Pending::default();
/// // Pre-r3: `Pending::witness_live_nonzero` exists on `Pending<'brand>`
/// // so this compiles; `w` ends up `Witness<'_, 'static, _>`.
/// // Post-r3: `Pending` no longer has any `witness_*` method — this
/// // call refers to a non-existent name and fails to compile.
/// let w = p1
/// .witness_live_nonzero(0)
/// .expect("doctest never runs — compile_fail");
/// // Pre-r3: `Pending::peek_witness` accepts `&Witness<'_, 'static, _>`
/// // (both `p2` and `w` carry the `'static` brand). Compiles →
/// // the cross-instance bypass exists → `compile_fail`
/// // assertion fails → RED.
/// // Post-r3: even if you somehow had a witness in scope, `peek_witness`
/// // is on `BrandedPending` now, so this also fails to compile.
/// let _ = p2.peek_witness(&w);
/// ```
///
/// # Witness-gated transitions (heddle#209)
///
/// The retrofit issues that consume the substrate (heddle#209 / #210 /
/// #211 / #212) add FSM-transition methods on
/// [`crate::pending::BrandedPending`] whose entry-point gating mirrors
/// the [`crate::pending::BrandedPending::witness_*`] constructors:
/// they live on `BrandedPending`, which can only be obtained via
/// [`core::Pending::with_brand`]. Direct callers in `core.rs` (or
/// future external callers) cannot reach the transitions on
/// [`core::Pending`] itself.
///
/// The doctest below pins that entry-point discipline for the first
/// retrofitted transition (`transition_to_orphan`, heddle#209). It
/// compiles only if `Pending::transition_to_orphan` exists as a
/// directly-callable method — and it doesn't, so the doctest fails
/// to compile and the `compile_fail` assertion holds (GREEN).
///
/// ```compile_fail
/// use mount::__pending_substrate_for_doctest::*;
/// let mut p = Pending::default();
/// // `transition_to_orphan` lives on `BrandedPending`, not on
/// // `Pending`. A direct call on `Pending` is the bypass shape:
/// // post-retrofit it fails to compile (the method doesn't exist on
/// // `Pending`), so the `compile_fail` assertion holds → GREEN.
/// let _ = p.transition_to_orphan(0);
/// ```
///
/// The same entry-point discipline applies to the witness-gated
/// kernel-forget retrofit (heddle#211): `kernel_forget_inode` lives
/// on [`crate::pending::BrandedPending`], not on [`core::Pending`].
/// A direct call on `Pending` is the bypass shape — pre-retrofit
/// the forget logic was inlined in `MountInner::invalidate` with no
/// FSM gate, and the natural drive-by "add a method on `Pending`"
/// would re-open the same r11 #3 race. The doctest below pins the
/// post-retrofit discipline: `Pending::kernel_forget_inode` does not
/// exist as a directly-callable method, so this fails to compile
/// and the `compile_fail` assertion holds (GREEN).
///
/// ```compile_fail
/// use mount::__pending_substrate_for_doctest::*;
/// let mut p = Pending::default();
/// // `kernel_forget_inode` lives on `BrandedPending`, not on
/// // `Pending`. A direct un-witnessed call on `Pending` is the
/// // bypass shape that would re-introduce r11 #3 (drop hot[id]
/// // without first checking the FSM). Post-retrofit the method
/// // doesn't exist on `Pending`, so the call fails to compile and
/// // the `compile_fail` assertion holds → GREEN.
/// let _ = p.kernel_forget_inode(0);
/// ```