* [editor-core] share the pieces the editor, real-time and history-v1 all need
Project-level history-OT has the browser, real-time and history-v1 all reason
about the same changes, so the rules they reason with move into the shared
library rather than being reimplemented on each side.
- `origin/editor_origin.js` plus `EDITOR_ORIGIN_KIND` and its schema entry: the
origin an editor client's change carries, holding the editorId that scopes a
change's timestamp.
- `change_identity.js`: how a submission is recognised when it comes back, so a
resend of a change that already landed is deduplicated rather than applied
twice.
- `rebase.js`: transforming a change onto concurrent ones, in the same order on
both sides, which is what lets the server acknowledge a change with only the
version it landed at.
- `text_file_defaults.js`: the doc-vs-file extension lists, now read from here
by web's settings instead of being spelled out again.
- `blob_string_length.js`: the string length of a blob, used by history-v1's
blob store and by web when it writes an uploaded file into history.
- `file_tree_diff.js`: file-tree operations to a diff, used by
project-history's FileTreeDiffGenerator.
- `Blob.EMPTY_HASH`, so callers can answer for the empty blob without storing
it.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* [project-history] build the file-tree diff with the shared helper
FileTreeDiffGenerator's hand-rolled walk over add/edit/move/delete operations
becomes a call to `buildFileTreeDiff` from overleaf-editor-core, so the editor
and project-history read a file-tree change the same way. Adds the unit tests
the decaffeinated original never had.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* [web] read the editable-file lists from overleaf-editor-core
web's settings spelled out the text extensions and editable filenames that
decide whether a file becomes a doc, and every other service that has to make
that call carried its own copy. The lists now live in overleaf-editor-core and
web builds settings.textExtensions and settings.editableFilenames from them,
keeping the ADDITIONAL_TEXT_EXTENSIONS override for Server CE/Pro on top.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* [history-v1] read a blob's string length from overleaf-editor-core
Two copies of getStringLengthOfFile lived here, the one in recover_zip.js
carrying a TODO asking for exactly this. Both now import the shared
implementation, which the blob store keeps re-exporting for backupArchiver.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
GitOrigin-RevId: 31948332f416f56848e3b0dfb5142a4c9f93f508
* Delete library data when an expired deleted user is cleaned up
* Refactor MongoDB session handling
* Remove transaction handling from deleteAllLibraryDataForUser function
* use findUserIdsToKeep rather than filterDanglingUserIds
GitOrigin-RevId: 9e82f6bf943809b55a8b042d9240f99dbc635711
Server Pro/CE admins can set a custom header logo via OVERLEAF_HEADER_IMAGE_URL,
but the same image is used for both the light and dark navbar themes. A logo
with good contrast on one background can be hard to see on the other (e.g. a
dark logo on the dark dashboard navbar).
Add two optional env vars, OVERLEAF_HEADER_IMAGE_URL_LIGHT and
OVERLEAF_HEADER_IMAGE_URL_DARK, each falling back to OVERLEAF_HEADER_IMAGE_URL
when unset, so existing configurations are unaffected. The light/dark fallback is
resolved server-side and exposed to the frontend as customLogo (light-effective)
and customLogoDark (dark-effective); the two theme-aware navbars (project
dashboard and library) pick between them using the existing overall-theme hook,
so the logo tracks both the user's theme setting and live OS theme changes.
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
GitOrigin-RevId: 587a5679c650717cba6251e6d612146f434e8730
* Fix dark-mode white flash when navigating between dashboard and library
* Use userSettings object in layout-base.pug
* Move initial theme styles in a new file
* Sanitize data-initial-theme with a generic getInitialTheme helper
* Add getInitialTheme stub
GitOrigin-RevId: 80812093bbf75dc2a6f6f24710324a31a1930265
* Relax split test import schema to allow staging export fields
The staging split test export includes fields (variant.active, version.__v,
splitTest.customerIoEnabled) that aren't otherwise written by the app but
are present in Mongo exports. The strict zod schema was rejecting the
import; mark these as optional so a staging export can be imported into a
local dev environment.
* [web] allow split-test import in dev-env and CI
* [web] ensure that the zod schema for split-tests covers all fields
---------
Co-authored-by: Thomas Mees <thomas.mees@overleaf.com>
GitOrigin-RevId: eab633e8498e351a64dc9a9dad85759e80744da0
Two of the B2B request schemas flagged in #36577 reject bodies we don't
want to reject:
- POST /manage/groups/:id/settings/sso: the group settings frontend
spreads the SSO config document it fetched from the GET route back into
the POST body, so the request carries `_id`, `__v`, `validated`,
`enabled` and `useSettingsUKAMF` that the handler recomputes or ignores.
- POST /manage/groups/:id/invites: an internal script sends an unsupported
`expiresAt` alongside the email; the handler only reads `email`.
Swap z.strictObject() for z.object() on both, with a comment on each
explaining why it's deliberately non-strict.
GitOrigin-RevId: 5ff94ded579bdda07efc59d9ceb1d495964a912d
Stop rejecting unrecognized request fields in the Dropbox, GitHub-sync, git-bridge and reference-manager APIs
GitOrigin-RevId: 5efdee90830b2a48172f839da8e59ef938746f65
* [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
* feat: gating labs experiments behind premium compile feature
* feat: move filtering to the labs module, and only propogate experiments that user can opt into on the FE
GitOrigin-RevId: 984aa0339c7dc8d61f0f6830780a599508306d5e
* Move bulk bibtex download to a server-side streaming endpoint
* Wrap download fetch errors in FetchError and parse the error body
* Refactor library references download to use GET request and stream response
* Remove MAX_DOWNLOAD_IDS limit from downloadIdsSchema and related test
* fix merge conflict
GitOrigin-RevId: dee2bae8bfb982cd1b79bbd21c9f1b90e8cff1a4
* [docstore] use more realistic test stubs for ranges
* [monorepo] define ranges schemas in @overleaf/ranges-tracker
* [ranges-tracker] add legacy orderedRejections field in tracked-changes
* [monorepo] resolve @overleaf/ranges-tracker subpath imports in typescript
* [real-time] validate comment thread ids and tracked change id seeds
* [ranges-tracker] require ObjectId ids and tracked change metadata in ranges
* [monorepo] require ObjectId tracked change ids on the accept routes
* [web] use ObjectId comment thread ids in the DocumentController tests
GitOrigin-RevId: 58b20dec311d85b917ef63f9efbe745a265a2de6
* feat: adding 2025 and 2026 incremental compiles options
* feat: remove dmtcp from compiler list and autoselect checkpointing version with labs inclusion
* feat: updating seccomp profile for checkpointing
* feat: disable non-premium dmtcp compiles, and align checkpoint version detection between clsi and web
* feat: adding in reminder of checkpoint experiment, and using session based split test retrieval
* Increase Packer build.sh timeout from 1h15m to 1h30m as build takes approx 1h
* fix: moving checkpointing check from tag name based to hasCheckpointing flag set as part of allowed_images, and removing uneeded seccomp rule
* feat: move variant/ image selection to CLSI, and have web control only what options to set for a compile. removing uneeded extra variants from webs list of allowed images
* feat: adding compile timer as a query string as well
---------
Co-authored-by: Tim Gibbon <tim.gibbon@overleaf.com>
GitOrigin-RevId: cdbdf76a62dcd5a585925f18d64b6cb9cd6ed373
* feat(web): add pro-value-framing split test copy
Serve quantified, benefit-led plan differentiators on the plans and
interstitial pages to the `enabled` variant of the `pro-value-framing`
split test, in place of the vague "increased/max AI allowance" and
"10/unlimited collaborators" framing.
The variant changes the bullet set and order as well as the strings, so
it swaps in its own short feature list rather than remapping keys: Pro
leads with "Everything in Standard, plus:", Free gains Error Assist and
"Compile simple projects". The plans page comparison table mirrors the
card wording in its AI allowance row.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* test(web): assert plan copy numbers against plan features
Check the quantified claims in the plan copy against the SaaS plan
features: the collaborator limits, and the "24x" compile timeout claims
as the ratio of the paid to the free compileTimeout. The "2x more AI
usage" claim is checked against the allowance tooltips, since the
allowances themselves come from AI_*_QUOTA_GRANT and are not available
in the unit test environment.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* Remove overly contrasted color in card
* Remove redundant `makeUISettings2026`
* Simplify valueFramingOverrides
* Fix types
* Revert changes to the table, replace `2x_more_ai_usage` to `2x_the_ai_allowance`
* Remove oververbose PlansValueFraming.test.mjs
* Revert "Remove overly contrasted color in card"
This reverts commit 8e83a0c523c4ebfe8a40a04023f1801080d0e412.
* Apply suggestions from code review
GitOrigin-RevId: 25b0736af47a3a32f4e1dd108ab0eb14c1bc13e3
The paused branch of getFormattedRenewalDate formatted the reactivation
date in the viewer's local timezone with a hand-rolled format literal,
while the surrounding dates are UTC. Compute the reactivation date in
UTC and format it with formatPaymentDate.
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
GitOrigin-RevId: 1f1679c1988c696c16c78bd11152d6a39a20c4e1