Commit Graph
68 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
Anna Claire Fields b8339c5b4a history-v1: handle ERR_STREAM_PREMATURE_CLOSE in streamZip (#36135)
GitOrigin-RevId: 963b65583da58034afe304206f6e0c66e9186b06
2026-09-17 11:49:33 +00:00
Jakob Ackermann 49969f6e0d [history-v1] adopt strict zod types and extend test coverage (#36089)
GitOrigin-RevId: 7bdffe2c05c7c17be6eb3e4296d8df05d650c53e
2026-09-17 11:49:08 +00:00
Jakob Ackermann 275d381656 [monorepo] remove some dead code (#35901)
* [history-v1] remove unused duplicate file from swagger migration

* [web] drop unused ?scribtex_path

* [github] update path to security middleware in history-v1

* [dependency-management] update .jenkinsIncludeFile

GitOrigin-RevId: 8c59d0d1e3e9108a8498e33e4768992ecd342f00
2026-09-17 11:41:07 +00:00
Jakob Ackermann a77a4782cc [history-v1] add setContent endpoint (#35799)
* [history-v1] add setContent endpoint

* [history-v1] refactor setContent to return a change+v

* [history-v1] make typescript happy

GitOrigin-RevId: e2cb0281367c01aa9cd842f250f2016d591ec0fc
2026-09-17 11:39:09 +00:00
Mathias Jakobsen d8f167dec2 Merge pull request #35293 from overleaf/mj-zod-history-ot
[real-time] Allow history-ot operations in real-time

GitOrigin-RevId: 4b1b9e4c1a214edf49c5eface46a4d309ba41b0d
2026-09-17 11:31:49 +00:00
Jakob AckermannandBrian Gough 84c6a68eae [web] enforce size limit on individual files when cloning project (#35211)
* [web] enforce size limit on individual files when cloning project

Co-authored-by: Brian Gough <brian.gough@overleaf.com>

* [web] improve test coverage

* [agents] speed up running frontend tests

* [web] gracefully handle project too large error

---------

Co-authored-by: Brian Gough <brian.gough@overleaf.com>
GitOrigin-RevId: c7b35a3a9688e15a9bb51c61816da82d39e0d29d
2026-09-17 11:20:03 +00:00
Jakob Ackermann d610f404e7 [history-v1] increase timeout for downloading the latest content as zip (#34045)
Remove the default timeout as it's too low and a big footgun.

GitOrigin-RevId: 42e26a2a288ad3e38252bc98b909a4bc8b10f70c
2026-05-28 08:06:47 +00:00
Jakob Ackermann 7c50dc9990 [history-v1] add endpoint for downloading latest zip (#33181)
* [history-v1] add endpoint for downloading latest zip

* [web] address review feedback

* [web] tests: do not overwrite db.projects.overleaf, extend it

* [web] set includeReferer flag from downloading zip

GitOrigin-RevId: e63e549f004230086f82eccf03b43fd62bde6071
2026-05-13 08:06:53 +00:00
Mathias Jakobsen 4173c98c48 Merge pull request #32892 from overleaf/mj-history-file-metadata
[history-v1] Add missing properties to zod schemas

GitOrigin-RevId: e16faf56a9b294516152383585493b38685b8d15
2026-04-21 08:05:22 +00:00
Jakob Ackermann 5a6c066847 [web] allow admins to clone projects with ranges and entire history (#32739)
* [web] add consistent aria-label to editing/reviewing toggle

* [docstore] add endpoint for getting all docs with ranges

* [history-v1] fix schema of chunkId when deleting old history chunk

* [web] skip duplicate project lookup for resolving rootDocPath

* [web] ignore new limits for root doc path when making debug copy

* [web] allow admins to clone projects with ranges and entire history

* [web] fix tests

* [history-v1] re-order params for cloning project

* [web] fix duplicate import of logger after merge

* [project-history] re-order params for cloning project history metadata

GitOrigin-RevId: 7fa35b4f90885dd453150a348d491ba0ec8de412
2026-04-15 08:05:49 +00:00
Jakob Ackermann 7a4ee32af3 [history-v1] fix missing linked file metadata when adding file (#32524)
* [overleaf-editor-core] rename stats field for file metadata

* [history-v1] fix missing linked file metadata when adding file

* [history-v1] address review feedback

* [saas-e2e] remove extra login call

GitOrigin-RevId: 178254993f9a9803b160ad8bb661f480144a3cf2
2026-03-31 08:08:14 +00:00
Anna Claire Fields ee4b5f515c Handle ERR_STREAM_UNABLE_TO_PIPE alongside ERR_STREAM_PREMATURE_CLOSE (#31174)
GitOrigin-RevId: bbf49237b177d7a58a9b13efc6f38f5eecfb745c
2026-02-03 09:05:50 +00:00
Tim Down 64da16f0d1 Merge pull request #28670 from overleaf/td-rename-validate-req
Rename validateReq to parseReq

GitOrigin-RevId: a935aaa3f89495e164ce5d10b0bd80436571440f
2026-01-15 09:05:09 +00:00
Anna Claire Fields 06a0cf2391 Merge pull request #30339 from overleaf/acf-migration5-cleanup
(5) Remove swagger dependencies from history-v1

GitOrigin-RevId: d3d79dd9d3c8ccb59d6a59aeede7186daf18bdb0
2025-12-18 09:05:37 +00:00
Anna Claire Fields 65c164c73d Merge pull request #30053 from overleaf/acf-migration4-controllers-and-params
(4) Update controllers and tests for Zod migration

GitOrigin-RevId: 876fd64f96e1f5d7244ac1d45053c7db9857d46b
2025-12-16 09:06:44 +00:00
Anna Claire Fields 56c98ac99c Merge pull request #29968 from overleaf/acf-migration3-express-routes
(3) Create Express routes (replaces swagger-router)

GitOrigin-RevId: e27973b630509312b198be899148310e69b94777
2025-12-08 09:05:20 +00:00
Anna Claire Fields c1dc70fc92 Merge pull request #29966 from overleaf/acf-migration2-security-middleware
(2) Create Express authentication middleware (replaces swagger-security)

GitOrigin-RevId: 0a15ec7ca601430a1ae00c7f81da456948650a0c
2025-12-04 09:06:06 +00:00
Anna Claire Fields c25e49782f Merge pull request #29965 from overleaf/acf-migration1-validation
Add Zod validation (replaces swagger-validator + swagger-metadata)

GitOrigin-RevId: 2e4ed742e401bdfe49c6f7dc9d0fceeba20cfc7f
2025-12-03 09:06:15 +00:00
Eric Mc Sween 98069966ba Merge pull request #28672 from overleaf/em-reapply-restore-optimization
Reapply file restore optimization

GitOrigin-RevId: c4479141d890e3e0af746f406a0186bf21f3d918
2025-09-25 08:05:25 +00:00
Domagoj Kriskovic e9b1c63ed7 Revert "File restore optimization - using snapshot timestamp and file paths (#28546)"
This reverts commit 376a53e1f927cb56544e6782b47d80345655038c.

GitOrigin-RevId: 8e4ab1d4042fec8df1b62ab1c5418d873dc6f5eb
2025-09-24 08:06:06 +00:00
Domagoj KriskovicandEric Mc Sween 005eba7502 File restore optimization - using snapshot timestamp and file paths (#28546)
* Use snapshot timestamp, remove request for paths at version

* Add timestamp to core Snapshot object

* Avoid mutating function argument

* Explain assumption about editable files

* snapshot.toRaw() in getContentAtVersion

* fix project-history acceptance test

* fix history_v1 test

* fix web tests

* Include the snapshot timestamp in stored chunks

---------

Co-authored-by: Eric Mc Sween <5454374+emcsween@users.noreply.github.com>
GitOrigin-RevId: 376a53e1f927cb56544e6782b47d80345655038c
2025-09-24 08:06:02 +00:00
Mathias Jakobsen 6c6048002b Merge pull request #28595 from overleaf/revert-28594-revert-28533-mj-blob-ranges-maxsize
[web+history-v1] Retry: Use range request for binary blobs in project snapshot

GitOrigin-RevId: defc279c9918695135962d65603a2941c5c4b033
2025-09-22 08:05:23 +00:00
Mathias Jakobsen 67d10e96bd Merge pull request #28594 from overleaf/revert-28533-mj-blob-ranges-maxsize
Revert "[web+history-v1] Use range request for binary blobs in project snapshot"

GitOrigin-RevId: 580491611a1b43104846f8509dd1e920f8077c9c
2025-09-22 08:05:15 +00:00
Mathias Jakobsen 6c79ce97cc Merge pull request #28533 from overleaf/mj-blob-ranges-maxsize
[web+history-v1] Use range request for binary blobs in project snapshot

GitOrigin-RevId: e72a2d481bf163b3e85361b42e30e82cf867f1cf
2025-09-22 08:05:04 +00:00
Brian Gough fd82788e61 Merge pull request #28506 from overleaf/bg-size-limits
add size check when cloning project (logging only)

GitOrigin-RevId: 1f56ed80a2d05b28c44fab8532d751ad8e758943
2025-09-18 08:05:52 +00:00
Brian Gough 386e133766 Merge pull request #28436 from overleaf/bg-load-changes-directly-from-redis-buffer
load changes directly from redis buffer for getChanges requests

GitOrigin-RevId: 99673c47a137ff4222d331fa88eb6e5103270551
2025-09-12 08:07:35 +00:00
Jakob Ackermann f8d69d05af [web] display project history blob size on admin pages (#28351)
* [history-v1] add endpoint for getting blob stats of projects

* [web] display project history blob size on admin pages

* [web] break down history storage size by text and binary blob

GitOrigin-RevId: bfa4d56cf2c503d03005c13a0f7ac38158156cd2
2025-09-10 08:06:19 +00:00
Brian Gough 8fab1b54a3 Merge pull request #27025 from overleaf/bg-delete-redis-buffer-when-project-deleted
delete redis buffer when project deleted

GitOrigin-RevId: eef7b6fdeb04cb556ae47794379d83e659f89b2e
2025-07-11 08:06:08 +00:00
Jakob Ackermann cf472f54d0 [history-v1] use POST requests for expiring redis buffer from cron (#26568)
* [history-v1] use POST requests for expiring redis buffer from cron

(cherry picked from commit 15780ac54e36b96e1aed9fd9eb6dfe9d4fbf842f)

* [history-v1] remove double claim of expire job

GitOrigin-RevId: 8b2eab07006a5819a47eed3f646b2a4d75f86e5b
2025-07-08 08:05:47 +00:00
Eric Mc Sween a38eefd2ab Merge pull request #26559 from overleaf/em-redis-buffer-delete
Delete project from redis buffer when expiring

GitOrigin-RevId: 66c48adc388a4a4e0b1b54b581dc945a38a41356
2025-06-30 08:05:20 +00:00
Andrew Rumble 392037efd6 Improve types and export functions we want to use
GitOrigin-RevId: 25fd93214f88c425bee23d43de113cf754f89524
2025-06-25 08:06:18 +00:00
Eric Mc Sween 1042092144 Merge pull request #26547 from overleaf/em-revert-expiry-post
Revert "use POST requests for expiring redis buffer from cron"

GitOrigin-RevId: 95e9fd1be7b73699d6fac24035437d467c273d0a
2025-06-19 08:06:58 +00:00
Eric Mc Sween 150dfd6cba Merge pull request #26539 from overleaf/jpa-post
[history-v1] use POST requests for expiring redis buffer from cron

GitOrigin-RevId: 51c9a25b998e581ed20c0e113bd4989537a1e6ef
2025-06-19 08:06:50 +00:00
Eric Mc Sween f68bf5a69f Merge pull request #26477 from overleaf/em-redis-buffer-resync
Handle invalid content hash when persisting changes

GitOrigin-RevId: 5259190396c8c261cad1abcd5de66314c1e871fb
2025-06-18 08:06:17 +00:00
Eric Mc Sween 0f330ef6a3 Merge pull request #26393 from overleaf/bg-history-redis-gradual-rollout
add gradual rollout mechanism for history-v1 rollout

GitOrigin-RevId: 5fa69f5c3874bd5df1f31fdd3115e4ba6a0dab51
2025-06-17 08:06:00 +00:00
Brian Gough 92731848ac Merge pull request #26352 from overleaf/bg-history-redis-add-flush-endpoint
add flush endpoint to history-v1

GitOrigin-RevId: b2ca60f7d040459f9c542e4e87147b9eecc9f596
2025-06-13 08:06:37 +00:00
Brian Gough 8a90173aa7 Merge pull request #26271 from overleaf/bg-history-redis-deployment-refactor
introduce history-v1 buffering levels

GitOrigin-RevId: 7709935a5ceb19ef6c5723ded647217b7399759a
2025-06-12 08:05:39 +00:00
Brian Gough b290e93441 Merge pull request #26270 from overleaf/bg-history-redis-commit-change-manager
replace redis logic in persistChanges with new commitChanges method

GitOrigin-RevId: e06f9477b9d5548fa92ef87fb6e1f4f672001a35
2025-06-11 08:07:45 +00:00
Brian Gough cb350ecc65 Merge pull request #25907 from overleaf/bg-history-redis-persist-buffer
add a `persistBuffer` method to history-v1

GitOrigin-RevId: 71a34e48e9ebe378e2f765f3216023e505a58a5d
2025-06-04 08:06:06 +00:00
Jakob Ackermann 4aaf411cd2 [misc] improve logging in history system (#26086)
* [project-history] tag all the errors

* [history-v1] log warnings for unexpected cases

GitOrigin-RevId: 3189fa487eee88985688ff990ec101daad0d13b1
2025-06-04 08:05:50 +00:00
Eric Mc Sween c18b3f95b2 Merge pull request #25492 from overleaf/em-paginate-changes-1
Paginate history changes endpoint

GitOrigin-RevId: 2b48044d64244404efcd2e090b682c1f571a5567
2025-05-22 08:08:09 +00:00
Miguel Serrano 85533a36e9 [history-v1] Disable backups on CE/SP (#25591)
Disables backup when `backupStore` is not present,
as it's the case for CE/SP

GitOrigin-RevId: a920f041c639e599084fa97d2ef2643a01da70e3
2025-05-19 12:26:30 +00:00
Eric Mc Sween 391fca9e83 Merge pull request #25361 from overleaf/em-load-latest-raw
Rename loadLatestRaw() to getLatestChunkMetadata()

GitOrigin-RevId: e089dcfa57cbbc43df8666b51eca0d81d595a5a7
2025-05-09 08:06:14 +00:00
Eric Mc Sween 5717ea7f5c Merge pull request #25306 from overleaf/em-redis-buffer-read-operations
Add changes from Redis when reading chunks from the chunk store

GitOrigin-RevId: c0ebf0669b91eb2efc5d1091d025e81efdff9fe4
2025-05-09 08:06:09 +00:00
Brian Gough 6eada92966 Merge pull request #25406 from overleaf/em-content-hash-validation-resync
Resync project when content hash validation fails

GitOrigin-RevId: ea9b5a78f89c55276fd67835bc262717bc778e92
2025-05-09 08:05:12 +00:00
Brian Gough 4464320757 Merge pull request #25224 from overleaf/em-disable-chunk-buffer
Bypass chunk buffer when loading the latest chunk

GitOrigin-RevId: 98a15b496b0d52802f9b61cefb60a7b8df653fb2
2025-05-02 08:05:17 +00:00
Brian Gough cedc96bdd7 Merge pull request #24906 from overleaf/bg-history-redis-read-cache
implement read cache for history-v1 chunks

GitOrigin-RevId: 128de7e9380fd489f68d5045d3333a27018845c2
2025-04-16 08:06:18 +00:00
Eric Mc Sween 397a546095 Merge pull request #24895 from overleaf/em-fix-history-changes
Properly serialize changes returned by the history changes endpoint

GitOrigin-RevId: a85fd8aede9316100d2cec901c1ab9b7d1faa9bb
2025-04-15 08:06:19 +00:00
Eric Mc Sween 3aa579f232 Merge pull request #24736 from overleaf/em-history-get-changes
Endpoint for getting history changes

GitOrigin-RevId: b96afed0492522d62df9c24390f76e5490afbb44
2025-04-11 08:05:48 +00:00