* [web] Remove SubscriptionFormatters, format subscription dates in the frontend
Replace the server-formatted nextPaymentDueAt/nextPaymentDueDate/
trialEndsAtFormatted fields with the raw periodEnd date and format in
the React dashboard (same strings as before, English + UTC). Also
consolidate hand-rolled trial checks onto isInFreeTrial /
SubscriptionHelper.isInTrial.
* [web] Remove the now-unused dateformat dependency
* [web] Address review: payment-dates unit test, UTC dates in acceptance test
Add a dedicated unit test asserting the exact formatted strings from
formatPaymentDate/formatPaymentDateTime, and use explicit UTC timestamps
in the SubscriptionDashboard acceptance fixtures instead of
local-timezone Date constructors.
GitOrigin-RevId: 16ac4f1098b14ef9f1478d22cf39c1357ead7dea
* Fix negative AI quota countdown after reset period elapses
Backend (`FeatureUsageRateLimiter`, `TokenUsageRateLimiter`): once the
24h period had lapsed, `remainingUsage`/`remainingTokens` reset to the
full allowance but `resetDate` kept pointing at the old `periodStart +
24h` (i.e. in the past). Advance to `now + 24h` in that case.
Frontend (`NewPlanPaywall`, `ErrorGetPremium`): the "wait X hours and Y
minutes" copy computed `restoreTime - now` without clamping, so a past
`restoreTime` produced negative hours/minutes (users saw "wait -118
hours and -35 minutes"). Clamp to 0.
* Address PR review on quota reset fix
- Keep `resetDate` tied to the stored `periodStart + PERIOD` rather
than jumping to `now + PERIOD` when the period has lapsed. The
moving-target variant unnecessarily reinterpreted a stable field
(existing consumers such as `use-ai-access-gate` check whether the
reset date is in the past).
- Clamp `remainingUsage` / `remainingTokens` at 0 so a concurrent
over-usage never leaks a negative count.
- Align the boundary check with `_checkRateLimit` / `checkUsage`
(inclusive `<=`).
- Cover the period boundary and the clamp in unit tests for both
`FeatureUsageRateLimiter` and `WorkbenchRateLimiter`.
* Truncate test fixtures to whole seconds
`resetDate` is serialized with `Date.toString()`, which has second
resolution, so fixtures with a millisecond component failed the
boundary assertions.
* Revert code changes; keep tests that document the bug
The fixes masked the symptom (negative countdown) without addressing
the underlying issue, and it is not fully understood yet. Revert the
rate limiters and the writefull paywall components to their original
behaviour, and instead pin the current behaviour in tests:
- `it.fails` tests document that `remainingUsage`/`remainingTokens`
go negative when usage exceeds the allowance — these flip red when
the bug is fixed, at which point they should become plain `it`.
- The lapsed-period tests assert (with explanatory comments) that
`resetDate` keeps pointing at the end of the lapsed period, which is
the server-side ingredient of the negative-countdown support ticket.
* Reapply quota fixes
Restores the post-review state of the rate limiters (clamp remaining
counts at 0, inclusive period boundary, resetDate tied to periodStart)
and the writefull paywall components (clamp countdown at 0).
Tests intentionally untouched in this commit; the two `it.fails` tests
now need flipping to plain `it` in a follow-up.
* Flip bug-documenting tests to plain assertions
The clamp fixes are reapplied, so the `it.fails` tests now assert the
fixed behaviour directly. Trim the explanatory comments.
* Set resetDate to `Date.now() + PERIOD_IN_MILLISECONDS` instead of the expired/stale date.
Co-authored-by: Mathias Jakobsen <mathias.jakobsen@overleaf.com>
* Update lapsed-period tests for the fresh resetDate
`resetDate` is now `Date.now() + PERIOD` once the period has lapsed, so
assert an approximately-fresh date instead of the stale period end.
---------
Co-authored-by: Mathias Jakobsen <mathias.jakobsen@overleaf.com>
GitOrigin-RevId: ad39627ab9e5ceccb2a61443b2b7d39c68600594
* feat: adding in check for if the project could have had a png optimized as part of the compile-result-backend event
* feat: updating using new compile metrics to filter for only eligible project compiles
* move projectHasUnconvertedPngs to stats
* add e2e test for projectHasUnconvertedPngs
* add unit tests for compile-with-optimizable-pngs analytics event
---------
Co-authored-by: Brian Gough <brian.gough@overleaf.com>
GitOrigin-RevId: 97e9d184420c34fc1d3e9f6cfe63f6b916f0202f
* feat: cleaning up ai quota leftovers
fix: removing more straggler invos
* fix: featureUpdater still need analyticsId in the user projection
* feat: updating cypress tests to also check for fair usage text
GitOrigin-RevId: 09c1167106c144084c111beea56867f6aa4a0906
* Rename user-facing Papers reference manager text to ReadCube
* Rename Papers component and files name to Readcube
* Update locales from Papers to ReadCube
* Rename ID name from papers to readcube
* Fix a chinese locale to use ReadCube
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
GitOrigin-RevId: ee89e3f5da5bcf9987c0ee3e558b9ae1dab9372c
* [web] Add snapshot test for all annualDividedByTwelve values
Captures the 85 stored values into a JSON fixture and asserts the
effective value (stored field, or PlansHelper.roundedTwelfth(annual)
once the field is derived at runtime) matches. Verification harness for
the annualDividedByTwelve refactor.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* [web] Compute annualDividedByTwelve at runtime instead of hardcoding it
* [web] Update annualDividedByTwelve snapshot for the rounding rule
The runtime derivation reproduces 84 of the 85 historical values exactly.
The one difference is PEN assistant, which was historically stored
unrounded (350 / 12 = 29.1667) and now follows the round-up-to-0.05 rule
(29.20). The assistant add-on is unavailable, so this is not user-visible.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Remove `localizedAddOnsPricing` from test
* Add more sanity tests
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
GitOrigin-RevId: e60e8b3e90360817d4be3732243d242dc0cbb69e
* 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
* Add schemas for file restoration and label management in HistoryController
* Add request schemas for proxying to history API and resyncing project history
* prevent transforming version:null into version:0 with coerce
* move jsDoc comments above the handler
* check for undefined resyncProjectStructureOnly
* Add tests for restoreFileFromV2 and revertFile
* Set default value for resyncProjectStructureOnly in resyncProjectHistorySchema
GitOrigin-RevId: 7b8b8a4c3834b8c8a83f93052ab1f59e86c529a6
* [web] Remove redundant monthlyTimesTwelve from pricing tables
monthlyTimesTwelve was always exactly monthly * 12 in every pricing row,
and the value was only ever used to render the "billed monthly for a year"
strikethrough price in the compile-timeout paywall.
- Drop the stored field from the pricing tables
- Send raw monthly/annual numbers in ol-standardPlanPricing instead of
pre-formatted strings
- Format the prices (and derive the strikethrough as monthly * 12) in the
paywall modal via the frontend currency helper
No user-facing change: the displayed prices are identical.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* Remove `monthlyTimesTwelve` from script
* Remove comments
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
GitOrigin-RevId: b637208540b3b96180b1a3cc4417b09944c5d158
* [web] store ObjectIds in addUserToProject acceptance test helper
* [web] optimize project lookup for tpds operations
GitOrigin-RevId: 03db9fc450556072f177d56f640fcc6114b295d4
* [web] add endpoint for resolving a project for writes from tpds
* [web] return historyId from new endpoint for resolving projects
* [web] add zod validation to new endpoint for resolving projects
GitOrigin-RevId: 0e607e56442117a4150a08373169c44b53dd4fdf