Main-thread authenticatedXrpc calls share session with worker
Summary
Several components make authenticated PDS calls via authenticatedXrpc on the main thread, loading session directly from IndexedDB. If a main-thread XRPC call overlaps with a worker PDS call, both read/write the same OAuthSession in IndexedDB — same DPoP nonce field, same last-writer-wins race as the worker-internal issue.
Affected call sites
High risk (can race with cabinet operations)
Low risk (user-initiated, not concurrent with cabinet)
Root cause
authenticatedXrpc in lib/api.ts loads session from IndexedDB, creates a DPoP proof, makes the request, and handles token refresh — all on the main thread. The worker's session gate does the same thing independently. Both compete for the same IndexedDB session record.
Proposed fix
Migrate high-risk call sites to worker PDS methods (most already have WASM equivalents):
revokeGrant→worker.grantRevoke()(exists)listOutgoingGrants→worker.listGrantsRaw()+ client-side filteringShareDialoggrant creation →worker.documentFetchContentKey()+worker.grantCreate()(both exist)- Preview blob fetch →
worker.documentFetchContentKey()through gate + unauthenticatedgetBlob(blobs are public in atproto), or add a WASM export that returns full metadata createPendingShare→ needs new WASM export (no equivalent yet)
Low-risk call sites can remain on main thread for now.
Note on blob fetch
com.atproto.sync.getBlob may or may not require authentication depending on the PDS implementation. The Rust opake-core attaches auth headers to getBlob calls. The sharing.ts incoming grant flow fetches blobs without auth and it works for cross-PDS access. Testing needed to confirm whether the user's own PDS requires auth for getBlob.
No activity yet.