fix: un second doc_subscribe tuait le premier, et les inbox n'étaient lues qu'à la connexion

This commit is contained in:
Sylvain Duchesne
2026-08-17 11:11:04 +02:00
parent 6dfdf2f036
commit 935cce4d7b
14 changed files with 1284 additions and 115 deletions
@@ -25,6 +25,8 @@ import { setAccessLog } from "./access-log";
import { inspectOutbox } from "./outbox-log";
import { startConnect } from "../emulated-verifier/connect";
import { cancelScheduledInboxProcessing } from "../emulated-verifier/inbox-processor";
import { stopObservingInboxes } from "../emulated-verifier/inbox-observer";
import { resetDocSubscriptions } from "../surface/subscribe";
import { resetSharedWalletSession, sharedWalletSession } from "./session";
/**
@@ -191,6 +193,13 @@ let caps = new CapRegistry(capsHolder);
// @provenance configure kind=invention level=none ref=none — same — the whole call disappears at migration, when the consumer initialises the real SDK directly
export function configure(c: EventuallyConfig): void {
// Whatever the PREVIOUS SDK was driving stops here. A document subscription belongs to
// the `ng` that opened it and an inbox observation to the identity that was connected
// through it, so carrying either into a fresh configuration would leave listeners
// attached to a verifier nobody is talking to any more — and, on the observation, work
// that files for an identity this call is about to clear.
resetDocSubscriptions();
stopObservingInboxes();
cfg = c;
// Not taken from the config: an application never supplies its own identity — upstream
// it comes FROM the wallet a person opened. Accepting one here would also let a caller
@@ -224,6 +233,12 @@ export function resetConfig(): void {
// no longer has an `ng` to read or write with, and report a failure about a session that
// no longer exists. See `emulated-verifier/inbox-processor.ts`.
cancelScheduledInboxProcessing();
// …and so does the continuous observation, for the same reason and one more: it is a set
// of live document subscriptions, which the un-configured library has no `ng` to cancel
// through. Both go before the subscriptions themselves, so nothing is left holding a
// torn-down fan-out.
stopObservingInboxes();
resetDocSubscriptions();
// The hand-over goes with it, for the same reason: it is made of the config's injected
// `init`, so leaving it behind would let a revived barrier delegate to the PREVIOUS
// application's SDK.
@@ -350,6 +365,13 @@ export function adoptCurrentUser(id: PrincipalId | null): boolean {
*/
export function setCurrentUser(id: PrincipalId | null): void {
const changed = adoptCurrentUser(id);
// The PREVIOUS identity stops being watched the moment it stops being connected —
// including on `null`, which is a disconnection and not merely "no new work". An
// observation applies what arrives by resolving the current holder at each step, so one
// left running past a switch would read the old identity's registers under the new one
// and file the old one's capabilities into the new one's ring. Whoever connects next
// starts their own. See `emulated-verifier/inbox-observer.ts`.
if (changed) stopObservingInboxes();
// Connecting a user is what triggers inbox processing — the library's job, not
// the app's. Fire-and-forget: this setter is synchronous and every consumer calls
// it from synchronous code, so the work announces itself through the cap