@adapt-toolkit/mufl 0.10.10 → 0.10.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -247,6 +247,83 @@ loads libraries key_storage, address_document_types
|
|
|
247
247
|
if m_account == NIL { m_account -> create_account(). }
|
|
248
248
|
return m_account as bin.
|
|
249
249
|
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// =====================================================================================
|
|
253
|
+
// LOCAL SESSION PERSISTENCE (core 0.11, Signal-model restart survival). The Olm account +
|
|
254
|
+
// per-peer session pickles are opaque, pickle_key-SEALED `bin` (the pickle_key is re-derived
|
|
255
|
+
// deterministically from this identity's stable SIGN secret on every boot — see pickle_key).
|
|
256
|
+
// These two calls let the host round-trip that sealed state through a LOCAL-ONLY sidecar so a
|
|
257
|
+
// daemon restart RESUMES the exact ratchet instead of re-minting a fresh account (the cause of
|
|
258
|
+
// the post-restart desync). INV-4 is preserved: this material is written to a local sidecar
|
|
259
|
+
// (never the portable export blob, never a peer/broker), exactly like the identity.key secret.
|
|
260
|
+
// The blob is opaque sealed bytes — no raw secretkey type crosses the serializer.
|
|
261
|
+
//
|
|
262
|
+
// import_sessions MUST run on boot BEFORE the first account()/encrypt_to (which would lazily
|
|
263
|
+
// create a fresh account); with a live m_account present, account() returns it and no
|
|
264
|
+
// regeneration happens.
|
|
265
|
+
// Persist ONLY the Olm account + LIVE per-peer sessions. m_staged is DELIBERATELY excluded
|
|
266
|
+
// (Dev-1 reconcile): it is transient in-flight migration state held for at most the commit
|
|
267
|
+
// window; a restart mid-migration drops it and the existing migration sweep supersedes the
|
|
268
|
+
// stalled rotation with a fresh offer — cleaner than restoring a staged session the peer may
|
|
269
|
+
// already have discarded. The live session (m_sessions) is what carries steady-state traffic
|
|
270
|
+
// and MUST survive; that is what this persists.
|
|
271
|
+
fn export_sessions (_) -> ( $v -> int, $account -> bin+, $sessions -> (global_id ->> bin) )
|
|
272
|
+
{
|
|
273
|
+
return ( $v -> 1, $account -> m_account, $sessions -> m_sessions ).
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// Restore a previously exported bundle into the hidden session state. Version-guarded so a
|
|
277
|
+
// future layout bump degrades to "no restore" (a fresh account is then lazily minted, and the
|
|
278
|
+
// self-heal fallback re-establishes) rather than mis-parsing. m_staged is left empty (a
|
|
279
|
+
// pending migration re-drives via the sweep).
|
|
280
|
+
//
|
|
281
|
+
// VALIDATED, FAIL-BY-ABORT (finding C, CodexFullReview redo): every pickle (account AND
|
|
282
|
+
// each session) is proved to unseal under pickle_key BEFORE anything is assigned — a blob
|
|
283
|
+
// whose STRUCTURE survived the outer safe-cast can still carry garbled sealed bytes, and
|
|
284
|
+
// assigning those un-validated turns later uses (my_bundle / encrypt_to / decode) into
|
|
285
|
+
// hard aborts (the reproduced cyclic BAD_PICKLE). A corrupt pickle makes the probe below
|
|
286
|
+
// raise the engine's HARD error (BAD_PICKLE is a CEvalError, NOT a provisional — it cannot
|
|
287
|
+
// be caught in MUFL), which FAILS THE WHOLE TRANSACTION: the caller MUST run this in a
|
|
288
|
+
// DEDICATED transaction (a2a commit_e2e_restore) so the failure rolls back atomically
|
|
289
|
+
// (nothing assigned) and the HOST observes it as that transaction's typed failure —
|
|
290
|
+
// cleanly distinguished from wire-decode errors because nothing else runs in that txn.
|
|
291
|
+
// Probe results are BOUND and guarded (abort WHEN) so they cannot be elided as dead code
|
|
292
|
+
// — the unguarded bare-statement probes of the first attempt validated nothing.
|
|
293
|
+
// An account-NIL blob with sessions present is structurally impossible for a genuine
|
|
294
|
+
// export (sessions exist only under an account) and aborts too.
|
|
295
|
+
// Returns the restored session count; never returns on a corrupt blob (the txn dies).
|
|
296
|
+
fn import_sessions (blob: ( $v -> int, $account -> bin+, $sessions -> (global_id ->> bin)+ )) -> int
|
|
297
|
+
{
|
|
298
|
+
if (blob $v) != 1 { return 0. }
|
|
299
|
+
acct = blob $account.
|
|
300
|
+
sess is (global_id ->> bin)+ = blob $sessions.
|
|
301
|
+
nsess is int = 0.
|
|
302
|
+
if sess != NIL { sc (sess?) -- ( -> ) { nsess -> nsess + 1. } }
|
|
303
|
+
abort "e2e::import_sessions: account NIL with sessions present (corrupt export)" WHEN acct == NIL && nsess > 0.
|
|
304
|
+
if acct != NIL
|
|
305
|
+
{
|
|
306
|
+
// Unpickles the sealed account under pickle_key — hard BAD_PICKLE on garbled
|
|
307
|
+
// bytes. The raw bundle is >= 101 bytes by layout (see my_bundle); binding +
|
|
308
|
+
// guarding the result keeps the probe live.
|
|
309
|
+
aprobe = _e2e_account_bundle (acct as bin) (pickle_key()).
|
|
310
|
+
abort "e2e::import_sessions: account pickle failed validation (short bundle)" WHEN (_binlen aprobe) < 101.
|
|
311
|
+
}
|
|
312
|
+
if sess != NIL
|
|
313
|
+
{
|
|
314
|
+
sc (sess?) -- ( -> s)
|
|
315
|
+
{
|
|
316
|
+
sprobe = _e2e_session_id s (pickle_key()).
|
|
317
|
+
abort "e2e::import_sessions: session pickle failed validation (bad session id)" WHEN (_binlen sprobe) != 32.
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
if acct != NIL { m_account -> acct as bin. }
|
|
321
|
+
if sess != NIL { m_sessions -> sess?. }
|
|
322
|
+
return nsess.
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
hidden
|
|
326
|
+
{
|
|
250
327
|
|
|
251
328
|
// The idempotent pre-key re-delivery result (a live- or staged-session replay). No
|
|
252
329
|
// plaintext, no state change — the session lives; the wrapper drops it (or, for a
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adapt-toolkit/mufl",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.12",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE",
|
|
6
6
|
"description": "The MUFL toolchain: prebuilt `mufl` (REPL) and `mufl-compile` (compiler) engine binaries plus the MUFL stdlib, meta, and transactions trees they need at run time. Linux x64 only; the binaries are proprietary (AEFL) — see LICENSE and NOTICE.",
|