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
//! Cross-subdomain secure folder — apex-side encrypted store (SCAFFOLD).
//!
//! ## What this is
//! A folder the OWNER can read/write from ANY of their subdomains. OPFS is
//! per-origin sandboxed, so there is no natural shared store: a file written
//! on `a.localharness.xyz` is invisible to `b.localharness.xyz`. The only
//! origin every one of the owner's identities resolves to is the APEX
//! (`localharness.xyz`), which already holds the master seed
//! ([`super::wallet_store`]). So the shared folder lives in **apex OPFS**
//! under `.lh_shared/`, ENCRYPTED-AT-REST under a seed-derived AES-256-GCM
//! key ([`super::encryption::sharedfs_key_from_entropy`]). Plaintext never
//! touches disk.
//!
//! ## What ships here (the scaffold)
//! The APEX-SIDE storage helpers + data types only:
//! - [`SharedEntry`] — a listed shared-folder entry (name + byte size).
//! - [`apex_write`] / [`apex_read`] / [`apex_list`] / [`apex_delete`] —
//! read/write/list/delete the seed-encrypted `.lh_shared/` folder from the
//! apex origin (where the seed is first-party). These power both an
//! apex-local shared-folder UI and the round-trip broker below.
//! - [`seal_file_for`] — the round-trip authorization boundary: returns a
//! shared file ECIES-sealed to a subdomain's ephemeral key, but ONLY if
//! this device's seed OWNS the requesting name on-chain (mirrors
//! [`super::seed_pull`]'s `seal_seed_for`).
//!
//! ## What is DEFERRED (NOT shipped — see `design/` / CLAUDE.md)
//! - The mount-routing branches that drive the top-level apex round-trip
//! (`?sharedfs_read=1` on apex, `?sharedfs_in=1` on the tenant) — the
//! transport must reuse [`super::seed_pull`]'s **top-level navigation**
//! pattern, NEVER an iframe (the cross-origin signer iframe is
//! partition-dead on mobile — CLAUDE.md hard gotcha).
//! - WRITE FROM A SUBDOMAIN (the inverse round-trip + URL-fragment payload
//! chunking). v1 is apex-write + subdomain-READ.
//! - The OPFS-panel `[pull from shared]` button + wiring the pulled bytes
//! into the editor/display panel.
//!
//! This module deliberately does NOT advertise a finished feature: it is the
//! durable, encrypted apex store + the authorization seal, which the
//! deferred round-trip wiring builds on without reopening the crypto design.
use crate;
/// Directory in apex OPFS holding the owner's shared folder, sibling of
/// `.lh_wallet`. Every file under here is sealed at rest with the
/// seed-derived [`super::encryption::sharedfs_key_from_entropy`] key.
const SHARED_DIR: &str = ".lh_shared";
/// One entry in the shared folder, as surfaced to a listing UI / a
/// `sharedfs_list` round-trip manifest. `size` is the DECRYPTED logical
/// size when known, else the on-disk ciphertext length.
pub
/// Reject anything that could escape `.lh_shared/`. The path component
/// arrives from a subdomain URL in the round-trip, so this guard is
/// load-bearing: no traversal, no absolute paths, no nesting (flat folder
/// for v1), non-empty, bounded length.
/// Full apex-OPFS path for a shared file. Caller MUST have passed the name
/// through [`path_is_safe`] first.
/// Derive the at-rest seal key from the loaded master wallet's seed. Returns
/// `None` when this origin holds no seed (a non-apex / visitor device) — the
/// caller then has nothing to read or write.
async
/// Apex-side WRITE: seal `plaintext` under the seed key and store it at
/// `.lh_shared/<name>`. Must run on the apex origin (where the seed lives).
/// Returns `Err` on an unsafe name, a missing seed, or an OPFS failure.
pub async
/// Apex-side READ: load `.lh_shared/<name>` and decrypt it under the seed
/// key. Returns `Ok(None)` when the file does not exist (or isn't our
/// ciphertext); `Err` only on an unsafe name or a missing seed.
pub async
/// Apex-side LIST: enumerate `.lh_shared/` as [`SharedEntry`] rows (files
/// only, sorted by name). An absent folder lists as empty. Reading the
/// folder needs no seed (names + sizes aren't secret); decrypting any file
/// still does.
pub async
/// Apex-side DELETE: remove `.lh_shared/<name>`. Idempotent-ish — a missing
/// file surfaces the backend's delete error, which the caller may ignore.
pub async
/// Round-trip authorization boundary (apex side). Given a requesting
/// subdomain `to`, a shared-file `path`, and the subdomain's ephemeral
/// compressed-SEC1 public key `epk` (hex), return the file's plaintext
/// **ECIES-sealed to `epk`** — but ONLY if this device's seed OWNS `to`
/// on-chain. A visitor's apex (a different seed) or a non-owned name yields
/// `None`, so the requester learns nothing. Mirrors
/// [`super::seed_pull`]'s `seal_seed_for` exactly.
///
/// The returned ciphertext is safe to ride a URL fragment back to the
/// subdomain (decryptable only by the ephemeral private key the subdomain
/// stashed before navigating). The mount-routing that performs the actual
/// top-level navigation is the DEFERRED half (see the module doc).
pub async