* [web] read a linked project file's source from history
Behind the `linked-file-from-history` flag, a linked `project_file` import reads
the source out of the source project's latest history snapshot rather than out of
its file tree in mongo, where docs and files are two kinds of thing.
- `ProjectFileAgent` gains `_importFromHistory` alongside the existing
`_importFromProject`, and the flag picks between them. The snapshot only holds
what has reached history, so the source project is flushed through
document-updater and project-history first. A file that is editable is loaded
eagerly, which applies the edit operations sitting on top of its blob; one that
is not keeps its hash and is streamed. The file is promisified on the way.
- `History/HistoryOTContentManager.mjs` reads the latest chunk and rolls its
changes into a snapshot, retrying the read. `History/HistoryBlobStore.mjs` is
the blob store overleaf-editor-core asks for while loading a file.
- `LinkedFilesController` resolves the flag, including from the referer: the
import endpoints have no query string of their own. Every agent takes the
assignment so that the ones that do not read it still pass it along.
- `linked-file-from-history.spec.ts` drives the flag from the editor url, over
three imports from another project: a file uploaded to the source project and
then refreshed from it, an edit the source project has only made in its editor,
and a binary file. Both sources produce the same file, so which one was read is
asserted in the acceptance tests rather than here.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* [saas-e2e] add test coverage for tracked-delete in linked file source
* Apply suggestions from code review
Co-authored-by: Mathias Jakobsen <mathias.jakobsen@overleaf.com>
---------
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Mathias Jakobsen <mathias.jakobsen@overleaf.com>
GitOrigin-RevId: 3907d6d399e4b5315e68bf833663c06bc72f4011
* Validate id types in LinkedFiles getSourceProject
Require source_project_id and v1_source_doc_id to be primitives before
querying Mongo, rejecting anything else with BadDataError.
* Validate refreshLinkedFile request params and body
Route refreshLinkedFile through parseReq with a schema requiring
project_id and file_id to be ObjectIds and typing the request body.
* Use well-formed ObjectIds in LinkedFilesController tests
Give the shared test setup valid ObjectId project_id/parent_folder_id
so parseReq passes and the controller logic is actually exercised, and
fail the tests if next is called unexpectedly.
* Use ObjectId file ids in v1 linked-file acceptance fixtures
The refresh route now validates file_id as an ObjectId, so the v1
not-imported fixtures need well-formed ids to reach the refuse-to-refresh
path (409) instead of failing id validation (404).
GitOrigin-RevId: d78b3664e825c6bb25ab2e363e5094b9212db307
* Throwing 429 errors when ref manager responds with 429
* respecting the APIs retry-after first
* Handle 429 on linked file refresh path
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Show rate-limited message on linked file refresh
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Consolidate backoff helpers into ProviderBackoffStore
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Fix EX 0 crash, null guard, BackoffProvider type, test fixes
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Add unit tests for rate limiting implementation
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* update ZoteroProviderTests for new signedGet return shape
getCollections now returns { collections, backoff, retryAfter } instead
of a bare array. getUsersItemsChanges reads backoff/retryAfter from the
signedGet return tuple, not from response.headers (extraction moved to
the transport layer in OAuth1Transport).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix tpr-webmodule unit test regressions
ZoteroSyncClient: collectionsResponseSchema now requires backoff/retryAfter
as number|null; stub responses were missing these fields causing ZodError.
Assertions updated since getCollections returns CollectionsResult (object)
not a bare array.
ReferencesApiController: vi.doMock for @overleaf/fetch-utils was missing
RequestFailedError; the three 429 propagation tests inline-import it from
the mocked module.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* address PR review comments
- ReferencesApiController: add fallback 500 status and optional-chain
response in all catch blocks where err.response may be absent
- OAuth1Transport: guard Number(header) with Number.isFinite to prevent
NaN propagating as backoff/retryAfter when header value is non-numeric
- ZoteroProvider: same Number.isFinite guard for lastModifiedVersion
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix prettier formatting in ZoteroSyncManager.test.mjs
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* show rate-limited message in groups modal and Write & Cite
use-provider-groups: detect 429/rateLimited response and set error to
'rate_limited' instead of generic 'loading_groups'
file-tree-import-bibliography: add rate_limited key to all three
providers' translation maps so the import modal renders the rate-limited
message when groups loading is blocked
reference-manager-source: add RateLimitedError, throw it on 429 from
search, block further searches and show a toast notification
toasts: add write-and-cite:rate-limited toast and showRateLimitedToast()
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fixup! fix tpr-webmodule unit test regressions
* fixing CI failures
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
GitOrigin-RevId: 158c2b92c557caacef337b89f68c91c47569151f
* [web] always provide an analyticsId when registering new users
* [web] add recordEventForMongoUser and use it during login
* [web] use recordEventForMongoUser/recordEventForSession where possible
* [web] use session cache for analyticsId when refreshing features
* [web] add setUserPropertyForMongoUser and use it where possible
* [web] use setUserPropertyForSessionInBackground where possible
* [web] use mongo user for analyticsId when setting utm user properties
* [web] admin-panel: user updated user when sending events
* [web] enforce labsProgram being populated on user object
Co-authored-by: Andrew Rumble <andrew.rumble@overleaf.com>
* [web] revert FeaturesUpdater.refreshFeatures change
* [web] labs: move session maintenance into handler
* [web] analyticsMiddleware: ensure that all users have labsProgram field
* [web] migrate a few more events to recordEventForSession
* [migrations] mark back-fill of db.users.analyticsId as required
* [web] setUserPropertyForSessionInBackground: throw early
---------
Co-authored-by: Andrew Rumble <andrew.rumble@overleaf.com>
GitOrigin-RevId: 19c26bc36abd8c11f0a8f458d25abfb7cbda0bb7