Release 0.78.3 - #3884
Closed
odlbot wants to merge 10 commits into
Closed
Release 0.78.3#3884odlbot wants to merge 10 commits into
odlbot wants to merge 10 commits into
Conversation
* Update dependency youtube-transcript-api to >=1.2.4,<1.3 * Migrate to youtube-transcript-api instance API v1.2.0 removed the static list_transcripts/get_transcript methods that were deprecated in v1.0.0; the instance method list() is the replacement. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018S52vCvVmYyY7Q3ji519Nn --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Tobias Macey <tmacey@mit.edu> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* hedge requests * tests * switch default hedging delay to 0 * change default delay * change default delay * Isolate and bound hedged embedding request capacity Address review feedback that abandoned losing requests could occupy the shared pool and make later primary requests queue behind them. - split the primary and speculative requests into separate thread pools - bound each pool with a semaphore so submissions are rejected rather than queued: a full primary pool runs the request inline, a full hedge pool skips the backups - give every hedged provider call an explicit timeout so losers release their worker - cover pool saturation, inline fallback, and concurrent saturation in tests Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix ssl_cert_reqs * Address PR feedback on embedding request hedging - fail loudly with RuntimeError instead of returning None when every hedged request is abandoned - drop the duplicated hedge_count/hedge_delay defaults, embed_query always passes them explicitly - log when backups are fired and whether the primary or a backup won, so the hedge delay can be tuned from prod - cover EMBEDDING_HEDGE_COUNT=1 (short circuits to unhedged) and =3 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
page-components/TiptapEditor embeds both VideoResourcePlayer and PodcastEmbedPlayer, but both lived in app-pages, which the import/no-restricted-paths zone in frontends/.eslintrc.js forbids page-components from importing. eslint-plugin-import 2.29 missed it; 2.31 (in #3851) reports all four. Moving only the two player entry points would have relocated the violation rather than fixed it, since each pulls in siblings, so each cluster moved with the modules it needs: page-components/VideoPlayer/ VideoResourcePlayer, VideoJsPlayer, YouTubeIframePlayer, videoSources page-components/PodcastEmbedPlayer/ PodcastEmbedPlayer, useAudioPlayer, usePlaybackRecovery, AudioPlayer.styled Only what the players need moved. The old shared.styled.ts keeps its seven page-chrome exports and gives up NoVideoMessage and ScreenReaderOnly; PodcastPlayer stays on the podcast page and now imports the hooks from page-components, which is an allowed direction. getEpisodeAudioUrl went to common/podcasts.ts instead of either player folder: the listing page and the embed player both need it, and common/ is already where this kind of pure helper lives. helpers.ts re-exports it so its existing importers and tests are untouched. Claude-Session: https://claude.ai/code/session_01FyJ72HRTyQf6jVYmw3GZSt Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
* updating serializer * render metadata doc as context * update tests * truncate content to model limits * fix and test update * Revert "fix and test update" This reverts commit 2964009. * address code review comments. add checksum versioning * make course numbers consistent markdown * make course numbers a md list * fixed sorting so the checksums are consistent * adding test to lockdown the checksum diff * fix sparse hash so rare terms are not dropped
* Add the refund request hook and its test fixtures
`useCreateRefundRequest` wraps the refund request endpoint and invalidates the
order's receipt on settle: a successful request moves the order's
`refund_status` to `requested`, and the card that renders it has to follow.
The order factory grows the three fields the receipt now returns, and defaults
to `eligible` rather than `false`. A freshly purchased order is refundable, so
tests should opt in to the states that are unusual rather than out of an
arbitrary one.
* Show the refund status on the receipt
Adds the refund card to the receipt's right-hand column, under the order
summary, where the design places it. On mobile that column already comes
first, so it needs no reordering.
The card renders whatever `refund_status` the API reports: the deadline while
the order is still eligible, a notice that the window has closed, the date a
request was made, why one was declined, or the amount that was refunded.
Orders that were never refundable — unfulfilled ones and B2B contract orders —
report `ineligible`, and the card is left out rather than shown empty.
All of that comes from the single status field. Deriving it here instead would
mean restating the refund window, the B2B rule and the duplicate-request check
that MITx Online already applies when it accepts or rejects a request, and the
two would eventually disagree.
Two labels depart from the design, both because the date underneath the status
is not the date the design assumed:
- A submitted request is labelled "Requested", not "Processed". Nothing has
been processed yet, and telling a learner otherwise invites a support ticket.
- A declined request is also labelled "Requested". The design says "Reviewed",
but no review timestamp is stored — only the submission date.
The button is only rendered when a handler is passed, which nothing does yet.
It arrives with the dialog it opens.
Hidden from print, like the other page actions.
* Note the pending source for the declined card's date
mitxonline 170fb603c adds refund_reviewed_on, which is the date this card
should show. The branch client predates it, so the submission date stands in
and is labelled honestly until the client is rebuilt.
* Date the declined card by when it was reviewed
The new client carries `refund_reviewed_on`, so the declined card can show
the date the request was actually decided rather than the date it was
submitted. That restores the design's "Reviewed {date}".
* Add the refund request dialog
Wires the card's Request Refund button to the dialog the design specifies,
in both its forms. Inside the refund window it collects one of seven preset
reasons; past the window there are no presets, the request goes for review
rather than straight through, and the wording says approval is not
guaranteed.
The consequences warning follows `has_free_audit`: refunding normally drops
the learner to the audit track, but a course without one leaves their
dashboard entirely.
Validation mirrors what the API accepts, so the learner is told what is
missing rather than meeting a 400: a reason inside the window, free text
whenever no preset explains the request, and consent either way.
Two things worth noting for anyone changing this later. The required asterisk
is rendered rather than set through `required`, because that marks the input
required to the browser and native validation then blocks submit before
formik reports anything. And the mutation uses `mutate` rather than
`mutateAsync`, since a rejected request is already surfaced through `isError`
and awaiting it leaves the rejection for formik to warn about.
* Keep the receipt reachable after a refund
The dashboard hid the Receipt menu item for exactly the order a learner is
most likely to go looking for: a refunded one. Two independent gates did it.
`getReceiptMenuItem` required a verified enrollment. A refund moves the learner
back to audit, so the link disappeared the moment the refund landed. Enrollment
mode was the wrong question — whether an order exists is the only thing that
matters, and the lookup below already answers it. Someone who reached the
verified track without paying has no order, so they still get no link.
`useOrderIdForResource` then matched fulfilled orders only, which a refunded
order is not. Its comment already anticipated this: "revisit when the refund
section is built".
Found by seeding a refunded order and looking at the dashboard, which is the
only place either gate is visible.
* Move "Other" to the end of the refund reasons
The design puts "Other" fourth, with three more specific reasons after it, so
both the tab order and the rendered column read as though the list restarts.
It now comes last. The options themselves are unchanged.
The radio grid also flows down its first column before starting the second, as
the design does. It was filling row by row, which paired options across a row
that have nothing to do with each other and put the list in an order that
matched neither the design nor the markup.
* Look up the receipt regardless of enrollment mode
The Receipt item was still missing on a refunded course. Removing the mode
check from `getReceiptMenuItem` was not enough: both cards decide whether to
run the lookup at all, and passed a null resource id for anything not on the
verified track. A refund returns the learner to audit, so the lookup never ran
and there was no order id to build the link from.
Both now pass the id unconditionally. Every card shares one `orders/history`
query, so this is the same single request it always was.
Enrollment cards therefore always fetch order history, which is why the
ProgramAsCourseCard suite needed the mock it had never required before.
* build(deps): pin mitxonline-api-axios to 2026.8.31-1
Carries the refund fields this branch consumes (refund_status,
refund_deadline, refund_requested_on, refund_reviewed_on, has_free_audit)
alongside hubspot_form_id from main.
* Address review feedback on the refund request dialog
- Validate and submit the free-text reason only when it is on screen, so a
hidden field cannot block submission or send text the learner abandoned.
- Announce field errors through role="alert" and move focus to the first
failing field on submit.
- Clear a field's error as soon as it changes, rather than leaving stale text.
- Let the browser skip its own validation UI (noValidate) while keeping
required on the inputs it applies to.
- Cap the reason text at 1000 characters, state the limit in the help text,
and announce the counter politely.
- Opt out of the global mutation error toast: this dialog reports a rejected
request inline, beside the button it came from.
* Cover the refund dialog's error recovery and focus behaviour
Each test fails if its behaviour regresses: dropping the abandoned free
text, clearing one field's error without clearing the others, and moving
focus to the first field that failed rather than leaving it on submit.
* Gate the refund card behind the self-service-refunds flag
The card is the only way into the refund dialog, so gating it at the mount
point covers the whole flow. `useFeatureFlagEnabled` is undefined until the
flags arrive, which keeps the card hidden rather than showing it and then
taking it away.
* Say why the reason group's requirement rides in the label
The description sibling is not associated with the group, so a requirement
stated there would be silent to a screen reader.
* Test that refunded orders still resolve a receipt
The states this branch added to RECEIPT_STATES had no coverage: stripping
Refunded and PartiallyRefunded passed the entire suite, including all 518
CoursewareDisplay tests, so the regression could return unnoticed.
* Sum every refund on the completed card
A partially refunded order reports the same completed status, and an order
can carry several refund transactions, so naming only the first understated
what was returned and dated the card by an arbitrary one.
* Say the consent checkbox is required, and note the single-line assumption
smoot-design's Checkbox takes no required prop and forwards nothing to its
input, so the requirement goes in the label, as it does for the reason group.
The dialog reads line 0 for the audit warning and the title while refunding
the whole order. mitxonline can model several lines but no checkout has ever
produced one, so the assumption is recorded rather than handled.
* build(deps): bump smoot-design to 6.34.0
Adds the required prop on RadioChoiceField.
* Mark the reason group required with the new smoot-design prop
Replaces the "(required)" label text, which was a stand-in while
RadioChoiceField had no way to set aria-required on the group.
* Let the consent checkbox grow to fit its wrapped label
smoot-design's Checkbox fixes its container at 24px, which assumes a
single-line label. This one wraps, so the text overflowed the box and the
inline error sat too close to it.
* Confirm a refund request outright after it is submitted
The panel behind the dialog re-renders from the invalidated receipt, but a
changed panel is not an acknowledgement. A success alert says the request
landed.
Copy promises no email on purpose: the only notification mitxonline sends on
a request goes to customer service, not the learner.
* Bound Renovate to the service versions we actually run Renovate had no ceiling on the datastore images, so it kept proposing majors we cannot deploy: #2758 targets postgres 18 while ol-mitlearn-db-production is on 15.17, and #2395 targets OpenSearch 3.8 while opensearch-mitlearn-producti is on OpenSearch_3.3 (both read from the AWS APIs on 2026-08-31). The ceilings keep those out of the queue until the managed services move first. qdrant was on :latest, which Renovate cannot track at all. Pinning it to the 1.18 series ties the local server to what qdrant-client ~=1.18.0 targets. pinDigests comes from config:best-practices and regenerates a "Pin dependencies" PR against the compose files every few months (#3809, #2985, both closed unmerged). Turning it off for the docker-compose manager only leaves Dockerfiles and GitHub Actions digest-pinned. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FyJ72HRTyQf6jVYmw3GZSt * Split the postgres ceiling by manager A single postgres rule covered both consumers: the CI service image in .github/workflows/ci.yml (github-actions manager, currently 15) and the local compose image in docker-compose.services.yml (docker-compose manager, currently 16). With one <16 ceiling the compose image sat above its own allowed range, so Renovate offered it nothing at all -- not even 16.x patches -- which is not what leaving local dev on 16 was meant to mean. CI keeps <16 so it tests against prod's engine. Compose gets <17, which tracks 16.x and still keeps 17 and 18 out. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FyJ72HRTyQf6jVYmw3GZSt --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
* Take the canonical page URL from learn_url The video, playlist, podcast and episode pages each rebuilt their canonical URL from (id, parent, title), slugifying the title locally. They now read it from the resource's learn_url, so the backend is the only thing that decides how a resource's URL is spelled. Playlists and podcasts have no parent, so they use learn_url as given. Videos and episodes take only its slug: a video in several playlists, or an episode in several podcasts, is legitimately viewable under any of them, so the parent segment stays resolved against the request. Their canonical *tag* is learn_url regardless, which points every context at one URL per resource. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * run linting --------- Co-authored-by: Ahtesham Quraish <ahtesham.quraish@arbisoft.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Co-authored-by: Ahtesham Quraish <ahtesham.quraish@192.168.1.167>
odlbot
force-pushed
the
release-candidate
branch
from
September 2, 2026 09:04
b3029ab to
c870405
Compare
OpenAPI ChangesNo changes detected Unexpected changes? Ensure your branch is up-to-date with |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Ahtesham Quraish
Tobias Macey
Carey P Gumaer
Shankar Ambady
Matt Bertrand
renovate[bot]