Release 0.81.3 - #4013
Open
odlbot wants to merge 11 commits into
Open
Release 0.81.3#4013odlbot wants to merge 11 commits into
odlbot wants to merge 11 commits into
Conversation
* fix(widgets): remove the unused RSS Feed widget type Per team confirmation on hq#13473, the RSS Feed widget was a channels/Open-Discussions-era feature with no current way to add one -- verified independently: the widget-list feature's frontend surface (hooks/widget_lists) has no consuming component anywhere in the frontend, so no widget type, RSS included, is reachable through any current UI. The backend registry (get_widget_classes) still fully accepted and processed RSS widgets via the API, though, including its unvalidated server-side feedparser.parse(url) fetch -- the SSRF reported in hq#13473. Rather than adding an SSRF allow-list to a feature nobody can reach or create, remove it outright: - widgets/serializers/rss.py and its tests (_fetch_rss, RssFeedWidgetConfigSerializer, RssFeedWidgetSerializer) - the registry entry in widgets/serializers/utils.py (get_widget_classes/get_widget_type_mapping/get_widget_type_names now only expose Markdown/URL/People) - the now-dead WIDGETS_RSS_CACHE_TTL setting (no env var override anywhere in mit-learn or ol-infrastructure) - the type_rss factory trait and the RSS entry in the available-widgets test fixture - regenerated openapi/specs/v0.yaml and the v0 TypeScript client to drop "RSS Feed" from the widget_type enum Markdown/URL/People widget types are untouched -- this is scoped to the specific dead, vulnerable feature this issue is about, not the broader (also currently frontend-unreachable) widget-list feature. Fixes mitodl/hq#13473 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * fix(openapi): acknowledge the intentional RSS Feed enum removal oasdiff correctly flags removing "RSS Feed" from widget_type's enum as a breaking change for PATCH/PUT /api/v0/widget_lists/{id}/ -- which is the intended effect here, not an oversight. Verified locally with the same tufin/oasdiff invocation the CI job runs (base=origin/main, head=this branch): passes with exit 0 once these entries are added. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * fix(widgets): reject unsupported widget_type in update() instead of crashing Sentry review feedback on this PR: WidgetListSerializer.update() looked up the serializer class for a widget's widget_type and called it unconditionally. If the type isn't in the registry -- which, after this PR, "RSS Feed" now isn't -- the lookup returns None and calling it raises an unhandled TypeError: 'NoneType' object is not callable, a 500 instead of a clean validation error. Confirmed this is a pre-existing bug in update() (the read path, get_widgets, already guarded against unknown widget_type; update() never did), not something specific to RSS -- reproduced the exact TypeError directly against the current registry to confirm. This PR's removal of "RSS Feed" from the registry just makes it newly reachable for a value that used to be valid, so any client still sending it would now hit this crash instead of a clean rejection. Raise ValidationError instead when the widget_type has no matching serializer class (covers missing types too, not just unsupported ones). New parametrized test covers an unsupported string, "RSS Feed" specifically, and a missing widget_type key. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
…entFileViewSet (#3999) ContentFileViewSet.private_fields only listed "content", so anonymous and non-privileged callers could read a ContentFile's LLM-generated .summary and .flashcards -- a full AI-condensed summary and ready-made study flashcards distilled from the same gated course material -- even though .content itself was correctly hidden. 1,823 of 191,818 rows in QA already have populated values being served this way today. summary/flashcards were added to the model in March 2025; the private_fields=["content"] gate was added afterward in June 2025 and just never included them. Derive private_fields from the existing CONTENT_FILE_LARGE_FIELDS constant (content, summary, flashcards) -- which already groups these three as equivalent-sensitivity elsewhere in the codebase -- instead of a separate hardcoded list, so they can't drift apart again the next time an LLM-derived field is added. Fixes mitodl/hq#13461 Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
…ublished control bar (#4009) * Lay the published control bar out like the edit one It is the same bar in the same place, but the two looked unrelated: the published view ran the full width of the window with its buttons against the left edge and the status against the right, while edit mode puts the status at the left end and the actions at the right, both lined up with the breadcrumb and the text. The published view now reuses the same `ActionRow`, so it carries the article's 890px column and cannot drift from edit mode when that column changes. Also drops the flex wrapper around the read-only toolbar. It set gap and margin on a `position: fixed` child, which it could not lay out either way, and now that the button group uses the same container inside the row its presence there was actively misleading. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Require an SEO title and description before publishing They are what a search result and a link preview show, and without them the page head falls back to the title and whatever the body happens to open with -- which is the thin description the SEO rules single out. So publishing now insists on both: the press opens the settings drawer instead, and resumes once they are written. Held to the same rule as topics, and implemented the same way, for the same reason -- it has to be the publish and not the save, because a draft writes itself every couple of seconds and autosave cannot stop to ask. Unlike topics this applies to news as well: news has no topics section, so the SEO fields are the only thing its publish can wait on. The drawer refuses to save while a publish is waiting on it and still has not got what it needs. Saving closes the drawer and closing forgets the press, so allowing it would drop the publish with nothing on screen to say why -- a hole the topics rule had too. `awaitingTopicsForPublish` becomes `awaitingSettingsForPublish`, since it now covers either requirement, and the resume tests what the drawer just handed over rather than state that has not landed. `!topicsRequired` in that test is what keeps news from stranding: its drawer sends no `topics` at all, so a bare length check would never resume. Messages key on whether the content is published rather than on whether the save is refused. The two used to coincide and no longer do -- a draft's save is refused too while a publish waits -- and telling a draft it is published would simply be wrong. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Refuse the settings save while a required field is blank The drawer marked both SEO fields required, put an asterisk on each label, and said an SEO title and description were needed to publish -- then let Save Settings through with both empty. Same for topics. The refusal now follows the requirement, on a draft as much as on something public. That collapses `topicsMayNotBeEmptied` and `seoMayNotBeEmptied` into `topicsRequired` and `seoRequired`: the two were always going to agree, and a second prop that only ever restated the first was the reason the button and the label could disagree in the first place. `contentIsPublished` stays, since it still picks which sentence a section shows. A draft's *content* is untouched by this -- autosave keeps writing it, and only the drawer's own settings wait on being complete. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Ahtesham Quraish <ahtesham.quraish@arbisoft.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
* Fall back to the original image before the default image The image optimizer fetches remote images server-side, and some hosts block that (e.g. bot protection answering 403) while still serving the same image to browsers. useImageWithFallback went straight from the failed optimized image to the default image, so those resources lost their images. It now retries the original with next/image's `unoptimized` first, and only falls back to the default if that fails too. Every image using the hook passes the new `unoptimized` value through. Also type byImageSrc's error functions with their real arguments so the queries accept the `nextJsOriginalSrc` option in TypeScript. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Skip the original-image retry when the image was already unoptimized Next.js serves some images unoptimized regardless of the prop, e.g. SVGs and data: URLs. For those, the "original" retry rendered the same <img>, no second error fired, and the image stayed broken instead of falling back to the default. onError now checks the failed element's src and goes straight to the fallback when it was already the original. Also move VideoCard's hand-rolled optimized-then-placeholder fallback onto useImageWithFallback so its thumbnails get the original-image retry. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Derive the fallback stage from src during render Replace the useEffect that reset the stage when src changed with state that records which src failed. Any other src starts at its initial stage in the same render, so a new src can no longer render once with the previous src's stage (e.g. loading unoptimized, or twice). Adds a test that records every render to check this. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* feat(warehouse): read the warehouse catalog and schema from settings Every BaseWarehouseETLTask pinned its view to ol_data_lake_production.ol_warehouse_production_integrations, so RC had no way to run a warehouse-pull task against QA data. Tasks now declare a bare table_name and view_name composes it with WAREHOUSE_CATALOG and WAREHOUSE_SCHEMA, which default to the production pair. Each part is checked on its own because a dotted setting would still pass iter_rows's check once joined, but address a different catalog. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fa1mSBw5fudATLND9pAqTM * fix(warehouse): reject subclasses that pin view_name A subclass assigning view_name as a class attribute shadows the property and skips WAREHOUSE_CATALOG/WAREHOUSE_SCHEMA without any error, which is the pattern the open ownership-guard PR and the closed Cohort 1 task PR both use. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fa1mSBw5fudATLND9pAqTM --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* adding initial working implementation * styling changes * fix tests * style fixes * prompt cleanup * fix tests * start fresh thread on first message and update prompt * make summary prompt configurable/overridable via env var * Refactor environment variable handling in tests Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Refactor response retrieval and error handling Refactor response handling to check for error messages and improve readability. Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Stabilize frontend tests for CI Co-authored-by: shanbady <196425+shanbady@users.noreply.github.com> * Restore unsubscribe authorization guard Co-authored-by: shanbady <196425+shanbady@users.noreply.github.com> * Fix CarouselV2 test lint import Co-authored-by: shanbady <196425+shanbady@users.noreply.github.com> * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Stabilize product page React tests Co-authored-by: shanbady <196425+shanbady@users.noreply.github.com> * Stabilize async frontend tests Co-authored-by: shanbady <196425+shanbady@users.noreply.github.com> * Fix CoursePage test formatting Co-authored-by: shanbady <196425+shanbady@users.noreply.github.com> * remove number badges * moving prompt to learn-ai and using separate route for search summary agent * add timeout for test * Update frontends/main/src/page-components/SearchDisplay/AiSearchOverview.tsx Co-authored-by: Matt Bertrand <mrbertrand@gmail.com> * fix test --------- Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: shanbady <196425+shanbady@users.noreply.github.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Matt Bertrand <mrbertrand@gmail.com>
OpenAPI Changes9 changes: 6 error, 0 warning, 3 info Unexpected changes? Ensure your branch is up-to-date with |
This branch has not been deployed
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.
Shankar Ambady
Matt Bertrand
Tobias Macey
Carey P Gumaer
Ahtesham Quraish
Sar