--- type: knowledge summary: Deciding which identity acts needs no session; connecting does — conflating them deadlocks one way and silently breaks sharing the other --- # Settling is not connecting Two acts of different nature hide behind "sign in": - **`settle`** — decide which identity is acting, from the URL, from storage, or by asking at the `barrier`, then persist it. Pure DOM and storage. **No session required.** - **connect** — restore what was shared with that identity and drain its inbox. **Requires a live session.** They must stay apart, and the reason is not tidiness. ## Why they cannot be one call `init()` hands the page over synchronously when the page is top-level, so nothing placed after it runs. The `barrier` must therefore appear **before** `init()`. But an identity cannot connect before `init()` either: connecting reaches the application's session thunk, which only `init()`'s own callback resolves. Await the whole of sign-in before `init()` and it deadlocks; call it after and the `barrier` never appears. The way out is that only *half* of it has that dependency. Settling is awaited by this package's `init()` wrapper before it delegates; connecting stays in the published call, awaited where a session exists. **The ordering invariant is carried by the composition, not by a documented call order** — which is why an application must call this package's `init`, not the one it injected. A note telling callers to order two calls correctly is not a mechanism. ## The failure this cost Settling once reached the session, because recording who is acting also fired the connection. In the reference application `init()` is called *from inside the executor that builds the session promise*, so the thunk could not answer by construction. It threw, the account lookup answered null, and the connection run abandoned **without restoring or draining** — having already registered itself as in flight. The published call then joined that dead run and resolved having done nothing. Symptom: a document shared with someone did not open for them. No error, just unreadable content. Nothing had changed in the connection logic. What changed was *when* the identity was recorded. Before the split, nothing recorded an identity during module evaluation: a session existed, the run was healthy, and joining it was harmless. Hence the shape of the fix — recording who acts and starting to connect are separate operations, and the session-free half only records. To validate: the session thunk must never be called while settling. ## The lesson worth keeping A "session-free" half that calls something which fires a session lookup is not session-free. When splitting on a dependency, check what the *side effects* of each remaining call reach, not only what the call itself does.