Commit Graph
28963 Commits
Author SHA1 Message Date
Jakob AckermannandClaude Opus 5 04871d6049 [editor-core] extract more shared utils (#36954)
* [editor-core] share the blob hash and the doc-vs-file rule

The git blob hash and the rule that decides whether a file is a doc or a binary
file both have to reach the same answer in every service that writes to history,
so they move into overleaf-editor-core rather than being spelled out again on
each side.

blob_utils takes over lib/blob_string_length.js: hashing and the string-length
rule answered two halves of the same question -- what history needs to know
about content before it can store it -- and each carried the same warning about
staying off index.js, which is bundled for the browser. One module states it
once, and blobForFile joins them, describing content on disk as the blob it
amounts to. The hashing functions are flat rather than a namespace of their own:
in a module that also holds the string-length rule, a bare fromStream says
nothing about what it makes. history-v1's blob store and recover_zip follow the
module to its new name.

file_type_detector holds the doc-vs-file rule, Node-only and deep-imported for
the same reason. It takes textExtensions, editableFilenames and maxDocLength as
configuration rather than reading settings: the limit is web's 2 MiB and not
editor-core's own 3 MiB, and the surrogate check covers both halves of a pair
where editor-core's covers the high half.

buildSetContentOperations' test spelled the blob header out for itself, with the
separator as a literal NUL byte, which had git reading the file as binary. It
hashes through blobHashFromString now, so it does not spell the header at all.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* [editor-core] name the client a change came from on the origin itself

`EditorOrigin` carried an `editorId` that only an editor change could have. What
the id is for -- recognising a change again, so history does not apply a resend
twice and the client does not apply its own change back -- is a property of the
client that submitted it rather than of what it did, so it moves onto `Origin` as
an optional `historyClientId` and `EditorOrigin` goes.

- `Origin` takes `(kind, historyClientId)` and answers `getHistoryClientId()`;
  `dropHistoryClientId()` is what the chunk store uses to strip the id from all
  but a client's latest change, which now leaves the rest of the origin alone --
  a restore that a client submitted stays a restore.
- `toRaw` is built a layer at a time: the base writes the kind and the id, a
  subclass spreads that and adds the fields it owns.
- The named kinds are their own schemas and discriminate on `kind`, so a payload
  claiming one is checked against that shape and the error says what it got
  wrong. The catch-all cannot join them -- its kind is any string -- so it sits
  alongside and is refined to refuse the named kinds, which it used to swallow:
  `{kind: 'restore'}` validated as a kind and nothing else, then read back as a
  restore that recorded nothing about what it restored.
- `lib/origin/*.js` gains `// @ts-check`. Without it the annotations in there
  were decorative: the lazily required subclasses were `any`, so nothing handed
  to them was checked, and `fromRaw` narrows with `in` to drop the catch-all
  variant, which a kind check cannot.

The callers that stamp the id -- real-time's handshake flag, web's applyChange
body -- come with the rest of the branch.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* [editor-core] recognise a change a writer that is not an editor placed

The counterpart of `isSameEditorChange` for writers that are not an editor
client: an integration that commits a batch on a user's behalf has to recognise
that batch coming back, because a lost response does not say whether the commit
landed and resubmitting one that did applies its removes twice.

It compares the same three fields, and for the same reason -- a rebase rewrites a
change's operations but leaves its origin, authors and timestamp alone -- with
the timestamp compared as a point in time rather than as a string, so that two
spellings of the same instant cannot read as different changes. github-sync is
the first caller, and comes with the rest of the branch.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* [editor-core] load an editable file's content, or say it has none

Only an editable file has content: any other kind is bytes addressed by hash, and
hollow data records the size of content it does not have. Both answer
`getContent()` with null, so every caller that wants the content of a doc loaded
it, checked the data's class, and reached for its own error when the check failed.
`File#loadEager` does that once and answers the data that always has the content.

`buildSetContentOperations` takes a `ReadWriteBlobStore` -- everything but
looking a blob up by hash, which is all it takes to build operations over content
-- so a caller holding a store that cannot answer `getBlob` can still use it. Its
metadata argument is `FileMetadata` rather than `Object`, which is what the schema
already says a file's metadata is.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* [editor-core] say that a pair of operations that do not fit is unprocessable

compose and transform threw a bare Error when the two operations do not describe
the same content. Everything that answers a client for these -- history-v1's
import routes, the git-bridge push, project-history's resync -- decides on
UnprocessableError, so a bare Error reached them as an internal failure: a 500,
which reads as worth retrying, for a pair that fails the same way every time.
A client that resubmits on a 500 resubmits forever.

The guards that cannot be reached through the API keep their bare Error: a
TextOperation composed with something that is not one, and the branch whose
message says it should not happen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* [history-v1] hash blobs with the rule editor-core holds

storage/lib/blob_hash.js was a bluebird-era implementation of the same git blob
hash editor-core holds, exported from the storage barrel and used across the
storage layer, the api and the tests. All of it reads the shared rule now, and
the test that existed only to check the copy is gone -- editor-core's suite
covers the same non-ASCII case.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
GitOrigin-RevId: 5a0c1e9a06170a0164c01a26a7bb2d205726d531
2026-09-17 12:07:15 +00:00
Miguel Serrano 3f171d500f [CE] Update dependencies on Dockerfile-base (#36996)
Bump REBUILD_AFTER to trigger a dependency install

GitOrigin-RevId: fa6b969778e696ea57f2e9ec1fada040b205b83e
2026-09-17 12:07:12 +00:00
Jakob Ackermann 7cebd46047 [monorepo] fix error code for failed ESM import (#36946)
GitOrigin-RevId: 3576cba8f3b18c749b45b8f4baaaaaeb8d598c6a
2026-09-17 12:06:56 +00:00
Jakob Ackermann 2317fd6edb [web] remove generic analytics service proxy (#36934)
GitOrigin-RevId: 19b3613b7cc84e73ad556067da1b3cd2f956e1c5
2026-09-17 12:06:50 +00:00
Eric Mc Sween e136bcad05 Merge pull request #36937 from overleaf/em-tpds-app-ts-refs
Point the third-party-datastore deployment at app.ts

GitOrigin-RevId: b0013f02d91a98dbc382c23ea781ec07efdf1eb5
2026-09-17 12:06:33 +00:00
Jakob AckermannandClaude Opus 5 6caa5fc3a3 [monorepo] read empty content from its hash, in a shared blob store base (#36831)
The hash of empty content is a property of the content rather than of anything
stored: every project's empty file has it, whether or not a blob was ever written
under it, and a file may reference it before anything has. Eight blob stores were
each paying a lookup -- a database query, an HTTP request, a read of a cache that
offline mode may be the only thing standing in for -- to be told what the hash
already says, and clsi had already reinvented the answer on its own.

overleaf-editor-core gains BlobStoreBase, which answers getString for that hash
and delegates the rest to the fetchString its subclasses provide. getObject comes
with it: four stores spelled out the same JSON.parse of getString, and a fifth
wrapped it in a log line.

Adopted by history-v1's BlobStore, BackupBlobStore, HashCheckBlobStore and
recover_zip's RecoveryBlobStore, by project-history's BlobStore, by clsi's
BlobStore, and by web's HistoryBlobStore, SimpleBlobStore and FrontendBlobStore.
history-v1 keeps its own answers in getStream, getBlob and getBlobs, which no
other store implements. Writing and copying a blob are untouched, so a project
that wrote empty content still has a blob for it and a read answers the same
either way.

Two paths could not handle a project holding a tracked change or a comment at
all. Loading such a file needs the ranges blob its rangesHash points at, and
hashing one again needs to write it back, so a store missing getObject or
putObject fails outright:

- recover_zip died on `blobStore.getObject is not a function`, making every such
  project unrecoverable. The test covering it asserts a tracked delete is absent
  from the zip, which the script already asked for and never reached.
- GET /projects/:project_id/latest/hashed_content returned 500 from the same
  cause, then would have hit a missing putObject in snapshot.store.
  HashCheckBlobStore becomes a class over the base and gains putObject.

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
GitOrigin-RevId: c84f62465beff6cf77ffac26aa772984e1b554cb
2026-09-17 12:06:30 +00:00
Jakob Ackermann 7608d738a6 [monorepo] speed up development in Codespaces (#36912)
* [monorepo] put volumes of ephemeral test containers on tmpfs

* [github] reduce IOWAIT in codespaces

* [monorepo] avoid yarn exec wrapper process for dev-env services

* [monorepo] exec from sh -c wrappers in dev-env services

* [github] reduce bloat with overlay2 storage driver

* [monorepo] reduce memory usage with yarn pnp

* [monorepo] add retries to docker builds

* [monorepo] fix formatting for .pnp.register.mjs

* [server-ce] test: fix re-use of users across reconfiguring

* [monorepo] adopt incoming resolve context conditions

GitOrigin-RevId: fe5d810a064f15cf8ca9f8a292b91ac054a578b0
2026-09-17 12:06:24 +00:00
Jakob Ackermann 5cbf586b70 [web] log failed create/refresh actions for linked files (#36925)
GitOrigin-RevId: 127ca0fe976d704468842107f6fe6d0200acdb6c
2026-09-17 12:06:21 +00:00
Jakob AckermannandClaude Opus 5 7ae8db6b12 [editor-core] extract shared pieces for history-ot in editor (#36828)
* [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
2026-09-17 12:06:17 +00:00
Eric Mc Sween 2024f85941 Merge pull request #36842 from overleaf/em-tpds-typescript
Convert third-party-datastore to TypeScript

GitOrigin-RevId: 028172063d0cfe03c0f105f48ab66020c79ea50e
2026-09-17 12:06:14 +00:00
Domagoj Kriskovic a9ad734cf4 [web] Delete library data when a deleted user expires (#36781)
* 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
2026-09-17 12:05:57 +00:00
ThomasandClaude Opus 4.8 42b29f0107 Support separate header logo images for light and dark themes (#36362)
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
2026-09-17 12:05:54 +00:00
ilkin-overleaf b4b12caf48 Merge pull request #36833 from overleaf/ii-workspaces-collection
[web] Create workspaces collection indexes

GitOrigin-RevId: a84d404e660e6c19eb288712bcf020e1ba4a90d0
2026-09-17 12:05:51 +00:00
Antoine Clausse 09c564fbc4 [web] Cleanup plans-2026-phase-1 - phase 5: unused files in pricing pages (#36688)
* Remove unused Pug files related to Pricing

* `make cleanup_unused_locales`

* Remove unused `descriptionMobile`

* `make cleanup_unused_locales`

* Remove dead CSS

* Remove non-EN dead keys

* Remove "ai-assist" dead CSS

* Remove "ai-assist" listeners

* Remove `plans-new-tabs` and related

* Remove dead SCSS variables

* Remove more dead CSS (mobile)

GitOrigin-RevId: 08c452f66fe5b4d5bca4bb8cf2171254f960bc71
2026-09-17 12:05:47 +00:00
Jessica Lawshe 24802e485b Merge pull request #35956 from overleaf/jel-domain-grace-period-notification
[web] Combine grace period and failed verification notififcations on group domains table

GitOrigin-RevId: 0178421af235ee59a9b8c3a521ac1a8e87c744a6
2026-09-17 12:05:34 +00:00
Jessica Lawshe 69b585caf7 Merge pull request #36752 from overleaf/jel-group-sso-email-check
[web] Stop enforcing requested email for group SSO matches linked account

GitOrigin-RevId: 4988ecf76069d531e3aea892d07a134252c30323
2026-09-17 12:05:30 +00:00
roo hutton e6ceb4fec4 Merge pull request #36864 from overleaf/rh-36644-cancel-spinner-fallback
Fix cancellation flow if downgrade upsell plan is not available

GitOrigin-RevId: c34f7f37057d5e0c08cbdd5f8524a7c5f00ae8b4
2026-09-17 12:05:27 +00:00
Eric Mc Sween b19f7fb6ad Merge pull request #36873 from overleaf/em-remove-duplicate-citation-key-helper
Remove inaccurate citation key helper text

GitOrigin-RevId: 91cff6c47f27980910e059084b14809586f5dae4
2026-09-17 12:05:23 +00:00
David 5e615cd261 Merge pull request #36620 from overleaf/copilot/fix-default-trash-view
Default Trash nav item to the current location

GitOrigin-RevId: 939284aecc4a002394430e9e2850125825d599de
2026-09-17 12:05:20 +00:00
John Lees-Miller df5c9fd8ea Merge pull request #36881 from overleaf/jlm-recurly-stripe-payment-heal-review
Heal migrated payment methods before renewal

GitOrigin-RevId: 72e33e73b3ca0b771ff0124e8a59e12118922573
2026-09-17 12:05:09 +00:00
Jessica Lawshe 5523f0a6e9 Merge pull request #36700 from overleaf/tm-institutions-api-timeout-abort-handling
Handle client-side v1 timeouts gracefully in InstitutionsAPI, bump reconfirmation-lapsed timeout to 60s

GitOrigin-RevId: ecb2b61e257fdd41cadb353da3af98fec0cdf617
2026-09-17 12:04:40 +00:00
Jessica Lawshe 700bc74f22 Merge pull request #35969 from overleaf/jel-domains-table-internal-admin
[web] Group domains table for internal admins

GitOrigin-RevId: 8c16a22502e333d9c604b322ba66703f9c17d100
2026-09-17 12:04:34 +00:00
Jessica Lawshe 09cd43eb17 Merge pull request #36011 from overleaf/jel-domain-capture-sales-email
[web] Weekly domain capture digest email

GitOrigin-RevId: 6682d1d7fcbb179615dbc009d2da8266113a3b4b
2026-09-17 12:04:28 +00:00
Andrew Rumble 52f25234cd Merge pull request #36462 from overleaf/lg-security-mongoose
[Security upgrade] bump mongoose to 8.24.1 in web

GitOrigin-RevId: 89373303435aec06c2e1efde1dd54f1d70c4dfe1
2026-09-17 12:04:17 +00:00
David 90be47c5e1 Merge pull request #36649 from overleaf/dp-cleanup-library-feature-flag
Remove the overleaf-library feature flag

GitOrigin-RevId: ebeabd43c9e44dbc2344b4e8e7e5b9095fcc86e0
2026-09-17 12:04:13 +00:00
Domagoj Kriskovic 6c802c03a6 Fix dark-mode white flash when navigating between dashboard and library (#36785)
* 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
2026-09-17 12:04:10 +00:00
Eric Mc Sween 2bbdc22496 Merge pull request #36844 from overleaf/em-document-migration-tags
Document the auxiliary and nonblocking migration tags

GitOrigin-RevId: ad16fe6b4f3e13606fff1d18f543cca0c2268ee2
2026-09-17 12:03:59 +00:00
Malik Glossop 2a489d6517 Merge pull request #35985 from overleaf/mg-history-ot-comments-preserve
HistoryOT - Preserve comments on cut/paste/undo

GitOrigin-RevId: 3c53da9abe599ab80ccc20960a46c6380d597831
2026-09-17 12:03:53 +00:00
Malik Glossop 183c054991 Merge pull request #36411 from overleaf/mg-writefull-countdown
Use shared ceiling time value for writefull paywall countdowns

GitOrigin-RevId: de77dd274028db58d23044e8aaea9cf0ad570037
2026-09-17 12:03:49 +00:00
Malik Glossop 863e33af78 Merge pull request #35982 from overleaf/mg-history-ot-comments
HistoryOT - Fix comments being dropped and crashing on detached ranges

GitOrigin-RevId: 0906a55a51a6fda9ac828efcbe72989573161261
2026-09-17 12:03:46 +00:00
Anna Claire Fields 19d97a75c6 [web] log the failing tag colour in the validation rollout (#36858)
GitOrigin-RevId: 9fa5a7bc380edf85a1b266e10c5add495744619b
2026-09-17 12:03:42 +00:00
Brian Gough 7aa941794e Merge pull request #36860 from overleaf/bg-allow-integer-in-sync-requests
Allow integer values for h and v parameters in proxySyncPdf

GitOrigin-RevId: 66f303a5940f6976dcfe27ebf90da8a9ec24e98a
2026-09-17 12:03:37 +00:00
Jakob Ackermann 9b44fd075b [monorepo] downgrade ranges ids back to strings for now (#36857)
GitOrigin-RevId: 6c85715bc85adc2f641bfd0e9f3bb6a8f2c839c2
2026-09-17 12:03:33 +00:00
Jakob AckermannandClaude Opus 5 91bf8f13ba [validation-tools] add a throw+log mode to parseReq (#36821)
REQ_VALIDATION_MODE=enforce-log rejects schema failures exactly as 'enforce'
does, but logs them first at instrumented call sites, so the visibility built
for the 'log' rollout (sanitized issues, caller trace, logFields values, per
schema/signature dedup) survives moving out of 'log' mode.

opts no longer change the outcome in this mode: logOnly does not suppress the
throw, the error is classified from the primary schema (not the fallback), and
fallbackSchema is only re-parsed to tag the log entry -- 'enforced-fallback-
passed' marks a rejection the looser pre-refinement schema would have avoided,
i.e. one the tightened schema newly introduces.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
GitOrigin-RevId: 0743322990e6c570ffbae166b4586285a18221df
2026-09-17 12:03:25 +00:00
Jakob AckermannandThomas Mees e276104da8 Relax split test import schema to allow staging export fields (#36832)
* 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
2026-09-17 12:03:21 +00:00
Thomas 0e7eff712c [web] [b2b] mark selected schemas as non-strict (#36780)
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
2026-09-17 12:03:15 +00:00
Jimmy Domagala-Tang 8ab6005580 feat: updating userId to nullish and explaining why for reject changes (#36803)
GitOrigin-RevId: 6f7a46893b9ab32d8f726ad6ba928eb4e0175813
2026-09-17 12:03:12 +00:00
Brian Gough 538d04ddb8 Merge pull request #36664 from overleaf/lg-wordcount-sync-resources
[clsi] sync project resources for word count

GitOrigin-RevId: fe96c936e7aba22ab94416a102dcb7e4835e1256
2026-09-17 12:03:09 +00:00
Anna Claire Fields 285bcd4315 [editor-core] accept the legacy source_project_display_name on project_file (#36837)
GitOrigin-RevId: bebbba328ecdd04ac4df06f66e6b0b1f8a41276f
2026-09-17 12:03:05 +00:00
Eric Mc Sween 6590b33321 Merge pull request #36792 from overleaf/em-zod-validation-cleanup
Stop rejecting unrecognized request fields in the Dropbox, GitHub-sync, git-bridge and reference-manager APIs

GitOrigin-RevId: 5efdee90830b2a48172f839da8e59ef938746f65
2026-09-17 12:03:02 +00:00
Eric Mc Sween c55411ee99 Merge pull request #36802 from overleaf/em-migrations-auxiliary-tags
[migrations] tag the auxiliary library migrations for saas

GitOrigin-RevId: cfe1169af24b36d6dcb352b4e0f79b250d74a1a0
2026-09-17 12:02:53 +00:00
f671c3dc59 [web] read a linked project file's source from history (#36817)
* [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
2026-09-17 12:02:47 +00:00
34d57a87f9 Add contextual pointers to the AI assistant in the editor gutter (#36643)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: jessdomanska <87976015+jessdomanska@users.noreply.github.com>
GitOrigin-RevId: 0df858dae9673868f02ca32cea024fe89794b544
2026-09-17 12:02:41 +00:00
Olzhas Askar bb7dfcd588 Merge pull request #36767 from overleaf/oa-express-types
[web] Express req/res/next types

GitOrigin-RevId: 30b4822e2ee55976331d049f8109f7098914973c
2026-09-17 12:02:38 +00:00
Olzhas Askar e9206d2b95 Merge pull request #36312 from overleaf/oa-unhardcode-homepage
[web] Unhardcode homepage

GitOrigin-RevId: 7ae0b66b5db57998ad1bd1988766d45e096620f7
2026-09-17 12:02:34 +00:00
Eric Mc Sween eb98741f03 Merge pull request #36693 from overleaf/em-node-24-version-metadata
[monorepo] bring stale Node version declarations up to 24.18.1

GitOrigin-RevId: 07d08e32920f05f02b817950eed25030d3b82ce4
2026-09-17 12:02:26 +00:00
Jimmy Domagala-Tang 1c0bc6c50a [web] Gate labs experiments behind premium compiles (#36339)
* 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
2026-09-17 12:02:23 +00:00
Jessica Lawshe 2c8e2781c7 Merge pull request #35038 from overleaf/th-add-v1-blocked-domain
Add 'passmail' to the list of domains blocked in v1

GitOrigin-RevId: 6c12800d03af0ad838f60a13fcf7d77d321b03c6
2026-09-17 12:02:17 +00:00
Jessica Lawshe 49a00ef0e2 Merge pull request #36310 from overleaf/jel-confirm-existing-email
[web] Check if domain captured by group when showing confirm email UI

GitOrigin-RevId: bb6add82e083497c8036739d877610a47e35ecfd
2026-09-17 12:02:03 +00:00
Jakob Ackermann f62b8525f2 [web] gracefully handle empty relativePath in uppy uploads (#36773)
GitOrigin-RevId: 640094f69cf53ba9f33a5bdc3b6d532547431d01
2026-09-17 12:01:55 +00:00