Comments should explain the code as it is, not narrate the change that produced
it. Drops "the old X" / "now" / "no longer" framing and a stale version pin in
favour of concrete names and the live constraints.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
`createAccount` and `login` abandoned the factory's returned bundle when a
newer task had already aborted them. The factories return an ARMED bundle, so
that session kept auto-refreshing and rotating refresh tokens server-side for
an account the app was no longer tracking; for signup the void-fired
post-signup writes kept its agent live too. Dispose in both abort branches,
matching `resumeSession`.
Also document why disposal of a replaced bundle is deferred to the post-commit
effect rather than done inline.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
`getErrorName` erased the typed error classes by flattening everything to a
string code. Anchor on the classes instead: `LexAuthFactorError` for the login
2FA branch, `XrpcResponseError` for the signup error codes.
`@atproto/lex-client` stays a direct dependency because `XrpcResponseError` is
used at runtime for `instanceof`. It is already in the runtime graph via
`@atproto/lex-password-session`, so the direct declaration adds no bundle
weight; it makes the import legal under pnpm's strict layout and pins the
version so both packages share one `LexError` identity.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Replace the AtpAgent-owned session lifecycle with PasswordSession-backed
bundles, dispatched through the bridge agent. The provider, reducer and
factories now hold a `{session, agent, service}` bundle whose identity gates
session events, so a stale session can no longer log out the current account
or restore its tokens after a switch.
Behavioural changes that come with the new auth core:
- token rotation is read from the hook payload (PasswordSession fires before
committing its live getter), so refreshes persist the new tokens
- replaced bundles are disposed rather than mutated, since PasswordSession has
no in-place patch; cross-tab syncs rebuild instead
- the expiry rescue path prefers a newer persisted generation over logging
every tab out
Post-signup writes keep main's agent.* call style; createAccount synthesizes
the email/active fields the thinner lex output omits.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Session-account conversion, the network-aware fetch wrapper, and the
expiry-rescue candidate picker were tangled into agent.ts and util.ts.
Pulling them into agent-agnostic modules lets the upcoming session
layer share them.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The per-account labeler cache was the only async dependency in
configureModerationForAccount. MMKV-backed sync reads let session
setup apply labelers in the same tick. No AsyncStorage backfill: the
cache is rewritten on every preferences fetch.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>