Commit Graph

95 Commits

Author SHA1 Message Date
Samuel Newman 4c2771eca3 fix session refresh persistence, 2fa login, bundle disposal, cross-tab labelers
Review fixes (PR #11182 round 1):
- PasswordSession fires onUpdated/onDeleted BEFORE committing its
  session data; thread the hook payload through to the provider instead
  of reading the live getter. Fixes rotated tokens never persisting
  (eventual forced logout) and expiry not logging out.
- getErrorName now gates on LexError, so LexAuthFactorError (a sibling
  of XrpcError) surfaces AuthFactorTokenRequired and email-2fa users
  get the code input.
- disposeBundle was a no-op; add a kill-switch closure around the
  session's injected fetch (covers the internal auto-refresh path) so a
  replaced session can't consume rotated refresh tokens. kill() also
  disarms the hooks so stale bundles can't dispatch into the reducer.
- cross-tab same-did rebuild now reapplies subscribed labelers to the
  fresh appview client (was built with an empty per-instance set).
- isAppLabeler reads Client.appLabelers instead of the hard-coded prod
  did, restoring test-env and regional-authority classification.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-30 18:18:56 +03:00
Samuel Newman ca5b8b6346 phase 4: delete the session bridge (SessionAgent, agent.ts, agentToLexClient) 2026-07-30 18:17:39 +03:00
Samuel Newman d052d14f2b phase 4 foundations: vendor missing lexicons, refreshSession api, toLex no-op purge, de-agent link-meta 2026-07-30 18:16:48 +03:00
Samuel Newman e7d349bc30 finish phase 3: type-only codemod and zero non-bridge @atproto/api imports
Task 8: codemod repointed 150 namespace-type files to #/lexicons
(AppBskyFeedDefs.PostView -> app.bsky.feed.defs.PostView, .Record -> .Main)
plus ~105 hand-fixed consumers (composer/video state, DebugMod, Profile,
onboarding, dialogs). DM_SERVICE_HEADERS deleted; last chat call sites on
the chat client. RichText.tsx flipped to SDK-only. Remaining @atproto/api
importers: the three session bridge files, the deliberate dual-world
matcher in lib/xrpc-error.ts, and test fixtures. toLex boundary casts are
TODO(phase4)-tagged for bridge removal.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-30 18:15:22 +03:00
Samuel Newman b1a4e1cd16 flip types/bsky sources to #/lexicons, add chat client and strict hook contracts
Phase 3 task 2: types/bsky sibling modules (post/profile/starterPack) now
source from generated #/lexicons with interim dual-world widening aliases
(TODO(phase4) markers). SessionBundle gains a chatClient proxied to
did:web:api.bsky.chat#bsky_chat via useChatClient(). usePdsClient() and
useChatClient() no longer fall back to the public appview when logged out -
they return a client that throws NotAuthenticatedError before any network
I/O; useMaybePdsClient()/useMaybeChatClient() cover logged-out-aware
callers. RichText pilot: useRichText.ts on @bsky.app/sdk/richtext with
detectFacets(pdsClient); RichText.tsx display sink accepts both worlds.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-30 18:07:26 +03:00
Samuel Newman bf8b6bc0c7 rework session layer on PasswordSession + three-client pattern
- PasswordSession (@atproto/lex-password-session) is now the single auth
  core; SessionAgent bridges it to the base Agent from @atproto/api so
  the ~148 useAgent() consumer files keep working unchanged
- SessionBundle carries {session, agent, accountClient, appviewClient};
  useLexClient() now returns the authed appview client, new
  useAppviewClient()/usePdsClient() hooks
- reducer: OpaqueSessionBundle, new replaced-current-bundle action for
  network-free cross-tab same-did sync (PasswordSession is immutable, so
  the bundle is rebuilt instead of mutated in place)
- moderation: AtpAgent.configure -> Client.configure + Agent.configure,
  per-account labelers on both the bridge and the appview client
- push-token unregistration uses temporary PasswordSessions
- hard-tail migrations: SignupQueued refresh via resumeSession shim,
  useBeginAgeAssurance scoped-token raw Client, useAccountEmailState
  reads currentAccount
- PDS routing preserved on the no-network resume fast path by
  synthesizing a minimal didDoc from the persisted pdsUrl

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-30 18:06:58 +03:00
Samuel Newman 105e68c12c add lex client seam, types/bsky schema helpers, pilot trending migration 2026-07-30 18:06:12 +03:00
Eric Bailey 690b8184a1 Refactor age assurance flags and contexts (#10794) 2026-06-08 15:34:51 -05:00
DS Boyce d0d00ba9f8 Address lint warnings (#10188) 2026-04-08 15:54:43 -07:00
Eric Bailey 60a0edbbe2 [APP-1960] Fix current session refresh bug (#10019) 2026-03-06 11:43:14 -06:00
Eric Bailey 7fd218c97d Update API package to fix stale session issues (#9998) 2026-03-04 18:27:12 -06:00
Spence Pope 9c29b2867a [APP-1882] fix email not updating in session state after email change (#9953) 2026-03-02 06:09:21 -08:00
Samuel Newman 93d2f3a8db Germ DM button (#9848)
* germ link (wip)

* add todos

* just yeet declaration for now

* ensure not proxied

* allow undo delete

* tweak styles

* ignore unknown values

* tweak styles

* fix boolean logic

* skip IAB

* fix mutationFn

* add link warning interstitial

* Logging and metrics

* Little more error handling

* Update copy

---------

Co-authored-by: Eric Bailey <git@esb.lol>
2026-02-11 17:51:19 -06:00
Samuel Newman 4f1d4821c5 Speed up startup by persisting some queries (#9594)
* persist startup queries

* Use IDB for query storage (#9687)

* Add storage abstraction for persisted query data

Introduce a platform-specific storage abstraction layer for react-query
persistence:
- Native: Uses MMKV for high-performance synchronous storage
- Web: Uses IndexedDB via the `idb` library for efficient async storage

This replaces the previous AsyncStorage implementation with more performant
platform-native solutions. The abstraction maintains API compatibility with
@tanstack/query-async-storage-persister.

* Refactor storage abstraction to use factory pattern

Change createPersistedQueryStorage to a factory function that accepts a
storage ID, allowing multiple isolated storage instances:
- Native: Each instance gets its own MMKV store
- Web: Each instance gets its own IndexedDB database

Adopt the factory pattern in:
- react-query.tsx: Uses 'persisted_queries' storage
- ageAssurance/data.tsx: Uses 'age_assurance' storage

This provides better separation between different query client caches
and allows each to be managed independently.

---------

Co-authored-by: Claude <noreply@anthropic.com>

* Refactor to use archival storage

(cherry picked from commit a773b40e41c96f821cd32260919ce1437c0fc3ab)

* Improve archive db types

(cherry picked from commit 80e4959ba2aa00c984c26aed2f7dfae1095720b0)

* rm idb

* clear on logout, bust on app version

* create abstraction for persisting queries, make gcTime infinite

* Rm abstraction

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Eric Bailey <git@esb.lol>
2026-02-02 11:55:01 -06:00
Eric Bailey 25a1ed1209 [APP-1782] Analytics migration (#9734)
* WIP

* Clean up growthbook code, integrate into init and sessions

* Move everything out of React

* Add metrics client

* Move to separate file

* Shared metadata cache

* Ensure we update metadata when session ID changes

* Ensure userMetadata is cleared when logging out

* WIP revamp

* Integrate feature gates into analytics context

* Clean up old code

* Fix useMeta util

* Some comments and cleanup

* Add logger to base analytics context

* Refactor current route handling

* Rip out LogEvent from navigation

* Update tracking endpoint

* Migrate toClout

* Clear out statsig client

* Add todo, reset logger readme

* Ope fix statsig noop

* Refactor logging in feed-feedback, add debug logging to metrics client

* Remove LogEvents alias for Metrics

* Prefer root package export

* Remove Metrics alias from logger

* [APP-1782] Migrate to new analytics APIs (#9735)

* Migrate logEvent to useAnalytics

* Migrate logger.metric to useAnalytics

* Migrate tricky spot, fix types

* Migrate remaining tricky spot

* Missed one

* Remove metric() from logger

* Migrate useGate to useAnalytics

* Remove all other StatSig mentions

* Update event payload

* Update logger tests

* Mock expo method

* Fix session ID bug

* Add session ID test

* Add test for metrics client

* Clarify intent

* Clean up core analytics file

* Clean up the call once utils

* Fix TODO

* Fix TODO

* Fix TODO

* Fix TODO

* Fix TODO

* Remove debug code

* Fix navigation context

* OK nav context is not working, todo

* Checkpoint: works but feels hacky

* Fix navigation context issue

* Improve feature API

* Improve metric logging

* Update logger tests
2026-01-22 15:33:45 -06:00
Eric Bailey 0589bd7d9e Move /platform/detection vars into /env (#9707)
* Add platform vars to env

* Replace /platform/detection with /env
2026-01-16 16:28:17 -06:00
Eric Bailey c4aef9f668 Age Assurance V2 (#9479)
* Age Assurance V2

* Tighten up test

* Add todos for sdk migration

* Align RQ versions

* Use useEffect for side effect

* Improve effects, memoize

* Standarize on birthdate

* Copy feedback

* Copilot

* Add support link

* Reove double ..

* Cleanup

* Remove redirect dialog

* Cleanup todos, add comments

* Update splash in main template too

* Mock some stuff

* Exhaustive checks

Co-authored-by: Samuel Newman <mozzius@protonmail.com>

* Exhaustive checks

Co-authored-by: Samuel Newman <mozzius@protonmail.com>

* Small fix to bday handling

* Add comment

* onboarding style tweak

sneaking this in sorry!

* rm unreachable breaks

* Put useIntentHandler back on web

* Remove misleading success set

* Align on birthdate

---------

Co-authored-by: Samuel Newman <mozzius@protonmail.com>
2025-12-04 15:20:00 -06:00
dan 885356256e [Fix Logouts] Persist accounts synchronously (#9109)
* Make persisting synchronous

* Initialize later so persisted is filled
2025-10-03 11:02:52 -05:00
Samuel Newman b2c56cbd6d Add displayName to contexts (#8814) 2025-08-14 01:12:31 +03:00
Samuel Newman 8fdcc3ee31 Replace resumeSession with getSession in the email check (#8670)
* replace resumeSession with getSession

* copy lil type tweak from the other PR

* Add partialRefreshSession to session API context, use session state to infer state further down tree

* Review

---------

Co-authored-by: Eric Bailey <git@esb.lol>
2025-07-23 11:52:38 -05:00
Samuel Newman 5ceaee5793 Instrument signup (#8037) 2025-03-27 20:17:07 +02:00
Samuel Newman f1d120d416 Takendown state + in-app takedown appeals (#7566)
* takendown screen

* add form, move button inline

* expect type error

* display error

* disable submit if too long

* move around all the ctas

* typos, rm layoutanimation, fix link

* use REASONAPPEAL
2025-01-23 22:33:28 +00:00
dan 356dad1932 Remove the environment indirections (#7089)
* Use raw underlying globals for environment

* Set dev EXPO_PUBLIC_ENV by exclusion
2024-12-13 17:16:53 +00:00
Hailey f68b15219f Remove Segment (#5518) 2024-09-27 14:01:57 -07:00
dan b6e515c664 Move global "Sign out" out of the current account row (#4941)
* Rename logout to logoutEveryAccount

* Add logoutCurrentAccount()

* Make all "Log out" buttons refer to current account

Each of these usages is completely contextual and refers to a specific account.

* Add Sign out of all accounts to Settings

* Move single account Sign Out below as well

* Prompt on account removal

* Add Other Accounts header to reduce ambiguity

* Spacing fix

---------

Co-authored-by: Paul Frazee <pfrazee@gmail.com>
2024-08-15 20:58:13 +01:00
Hailey 3c04d9bd84 subclass agent to add setPersistSessionHandler (#4928)
Co-authored-by: Dan Abramov <dan.abramov@gmail.com>
2024-08-12 19:43:06 -07:00
Hailey 7df2327424 Upgrade API, implement XRPC rework (#4857)
Co-authored-by: Matthieu Sieben <matthieu.sieben@gmail.com>
2024-08-12 14:00:15 -07:00
dan 686d5ebb53 [Persisted] Make broadcast subscriptions granular by key (#4874)
* Add fast path for guaranteed noop updates

* Change persisted.onUpdate() API to take a key

* Implement granular broadcast listeners
2024-08-06 01:30:52 +01:00
dan 4c48a1f14b [Session] Logging (#4476)
* Add session logging (console.log)

* Hook it up for real

* Send type separately
2024-06-20 15:47:56 -07:00
dan 7ddbc392c3 [Session] Convert account to session data explicitly (#4446)
* Extract a variable

* Extract sessionAccountToSession

* Convert account to session data on assignment
2024-06-19 02:47:50 +03:00
Eric Bailey 3e1f076891 [🙅] Disambiguation of the deactivation (#4267)
* Disambiguation of the deactivation

* Snapshot crackle pop

* Change log context

* [🙅] Add status to session state (#4269)

* Add status to session state

* [🙅] Add new deactivated screen (#4270)

* Add new deactivated screen

* Update copy, handle logout

* Remove icons, adjust padding

* [🙅] Add deactivate account dialog (#4290)

* Deactivate dialog

(cherry picked from commit 33940e2dfe0d710c0665a7f68b198b46f54db4a2)

* Factor out dialog, add to delete modal too

(cherry picked from commit 47d70f6b74e7d2ea7330fd172499fe91ba41062d)

* Update copy, icon

(cherry picked from commit e6efabbe78c3f3d9f0f8fb0a06a6a1c4fbfb70a9)

* Update copy

(cherry picked from commit abb0ce26f6747ab0548f6f12df0dee3c64464852)

* Sizing tweaks

(cherry picked from commit fc716d5716873f0fddef56496fc48af0614b2e55)

* Add a11y label
2024-06-04 02:10:43 +01:00
dan 9bd411c151 Replace getAgent() with reading agent (#4243)
* Replace getAgent() with agent

* Replace {agent} with agent
2024-05-28 16:37:51 +01:00
Dan Abramov 8938fc87a0 [Session] Dispose of stale agents immediately 2024-05-23 03:35:25 +01:00
dan 0c6bf276dd Replace updateCurrentAccount() with refreshSession() (#3910)
Replace updateCurrentAccount() with resumeSession()
2024-05-08 23:11:39 +01:00
dan 0910525e2e [Session] Code cleanup (#3854)
* Split utils into files

* Move reducer to another file

* Write types explicitly

* Remove unnnecessary check

* Move things around a bit

* Move more stuff into agent factories

* Move more stuff into agent

* Fix gates await

* Clarify comments

* Enforce more via types

* Nit

* initSession -> resumeSession

* Protect against races

* Make agent opaque to reducer

* Check using plain condition
2024-05-08 03:30:55 +01:00
dan 0c41b3188a [Session] Remove global agent (#3852)
* Remove logs and outdated comments

* Move side effect upwards

* Pull refreshedAccount next to usage

* Simplify account refresh logic

* Extract setupPublicAgentState()

* Collapse setStates into one

* Ignore events from stale agents

* Use agent from state

* Remove clearCurrentAccount

* Move state to a reducer

* Remove global agent

* Fix stale agent reference in create flow

* Proceed to onboarding even if setting date fails

---------

Co-authored-by: Eric Bailey <git@esb.lol>
2024-05-08 03:10:03 +01:00
dan 4a2d4253e5 [Session] Align state and global agent switchpoints (#3845)
* Adopt synced accounts unconditionally

* Remove try/catch around resuming session

* Move to login form on resume failure

* Restructure code flow for easier reading

---------

Co-authored-by: Eric Bailey <git@esb.lol>
2024-05-03 17:57:09 +01:00
dan 1e484c6318 [Session] Reset global agent on expire (#3838) 2024-05-03 13:46:34 +01:00
dan cdf7a1957a [Session] Rely on agent session change event for persisting resumed session (#3836)
* Rely on agent session change handler for resumption

* Add a fast path for noop resumes
2024-05-03 03:47:11 +01:00
dan c13685a0cf [Session] Fix stale emailAuthFactor and emailConfirmed on the client (#3835)
* Fix account refresh to not clobber falsy values

* Use ?? in more places
2024-05-03 02:52:37 +01:00
dan 0f827c3213 [Session] Track agent in state (#3833)
* Expand currentAccountDid into currentAgentState

* Inline all callsites of upsertAccount

* Inline all internal callsites of clearCurrentAccount

* Add agent to currentAgentState

* Collapse extra setStates

* Add TODOs
2024-05-03 02:04:36 +01:00
dan 6405ad7cba [Session] Call persist handler directly (#3828) 2024-05-02 23:05:53 +01:00
dan 1a07e23192 [Session] Extract selectAccount out (#3812) 2024-05-02 18:25:09 +01:00
dan 5ec945b762 [Session] Extract resumeSession out (#3811) 2024-05-02 18:17:53 +01:00
dan d61b366b26 [Session] Derive currentAccount from accounts + currentAccountDid (#3795)
* Derive currentAccount from accounts and currentAccountDid

* Add TODOs for divergence with __globalAgent
2024-05-01 17:35:27 +01:00
dan df9af92eb2 [Session] Use flag on state for persistence (#3793)
* Move isInitialLoad and isSwitchingAccounts out of main state

* Remove spreads, order object keys

* Track need to persist on state object

* Reoder state variables
2024-05-01 17:26:33 +01:00
dan 39807a8630 [Session] Refactor to prepare for V2 (#3781)
* Move types to another file

Co-authored-by: dan <dan.abramov@gmail.com>

* Move utilities out

Co-authored-by: dan <dan.abramov@gmail.com>

* Move PUBLIC_BSKY_AGENT

Co-authored-by: dan <dan.abramov@gmail.com>

* Move createPersistSessionHandler inline

Co-authored-by: dan <dan.abramov@gmail.com>

* Call configureModeration when clearing account too

This ensures that the app labelers get reset in a test environment.

Co-authored-by: dan <dan.abramov@gmail.com>

* Make guest configureModeration sync, non-guest async

* Extract isSessionExpired

Co-authored-by: dan <dan.abramov@gmail.com>

* Flip isSessionExpired condition

Co-authored-by: dan <dan.abramov@gmail.com>

* Extract agentToSessionAccount

Co-authored-by: dan <dan.abramov@gmail.com>

* Extract createAgent*

Co-authored-by: dan <dan.abramov@gmail.com>

* Simplify isSessionExpired

---------

Co-authored-by: Eric Bailey <git@esb.lol>
2024-05-01 02:55:43 +01:00
dan 66ad5543f1 [Session] Move deactivated field off the session object (#3780) 2024-05-01 01:36:56 +01:00
dan 339f26567a [Session] Consistently copy SessionAgent fields (#3779)
Co-authored-by: Eric Bailey <git@esb.lol>
2024-05-01 01:13:55 +01:00
dan 2b7d796ca9 Session fixes, pt. 1 (#3762)
* Update persisted schema for new source of truth, implement in existing session

(cherry picked from commit b1e5f12bae)

* Improve toasts, log caught error, during switch account

(cherry picked from commit fe0d150706)

* Handle thrown errors from initSession during login

(cherry picked from commit 2c85c04591)

---------

Co-authored-by: Eric Bailey <git@esb.lol>
2024-04-30 17:38:05 +01:00