0.2.68 (unreleased)¶
Fall back to the plain theme selector fragment for HTMX requests when a theme omits the optional
select_theme.htmltemplate.Report missing soft-required theme templates as
cast.W002system check warnings, including configured themes and templates provided by custom loaders. Template syntax errors also produce warnings rather than aborting startup checks.Rename generic
Speaker N:cue prefixes as well as voice tags throughTranscript.rewrite_speaker_labels. Renamed prefixes become voice tags for subsequent renames and public speaker sanitization.Resolve Voxhelm API base and token as a pair from one configuration level. Incomplete pairs no longer inherit deployment credentials. Move mixed-level credentials to one level before upgrading; changing the Wagtail API base requires re-entering its token. Saving with both credential fields blank removes the site pair so deployment credentials can be used.
Exclude view-restricted pages from navigation links in blog, post and feed contexts, including for signed-in visitors. Pages beneath a restricted page are also omitted; member-only sites must supply their own navigation. Which pages are candidates for the navigation is unchanged.
Render shared feed descriptions with the blog/site default theme, ignoring visitor session, query and internal preview theme overrides.
Rate-limit comment posting. Both comment post views used to accept any number of comments from one client. They now allow
CAST_COMMENTS_POST_RATE_LIMITposts (default20) perCAST_COMMENTS_POST_RATE_WINDOWseconds (default600) per logged-in user or anonymous client address and answer further posts with429andRetry-After; the AJAX view returns the usual JSON error shape so the bundled script shows the message at the comment field. Previews are not counted, and0disables the limit. Sites behind a reverse proxy needREST_FRAMEWORK["NUM_PROXIES"]for the client address to be correct; see CAST_COMMENTS_POST_RATE_LIMIT.media_replace --yesnow exits withCommandError(non-zero status) when at least one replacement failed. It used to printerrors=<n>in the summary and still exit successfully, so scripts could not tell a failed or partial run from a clean one. The remaining paths are still attempted and the summary is still printed first. Automation that relied on the old exit status needs to handle the failure.Add
media_backup --refresh-changed.media_backupskips every path that already exists in the backup, so a file changed in place (for example bymedia_replace) kept its old bytes in the backup forever andmedia_restorewould have brought the old file back. The new option compares existing files by content (size as a shortcut for “different”, SHA-256 of both copies when the sizes match) and overwrites backup copies that differ. The new bytes are staged in the backup storage first and the previous copy is never deleted, so a production file that cannot be read, a staged copy that cannot be written, or a backup storage that does not overwrite existing names leaves the previous backup copy in place. If the final overwrite itself fails, what remains under the path depends on the backup storage backend: object storage keeps the previous object, a backend that writes in place (FileSystemStoragewithallow_overwrite) can leave a partial file. Failures are reported, the remaining paths are still processed, and the command exits non-zero. The default mode andmedia_restoreare unchanged.Send known-speaker voice references whenever a diarized transcript request names only the audio, such as
generate_transcripts --audio-id. The episode is now resolved from the audio when it belongs to exactly one episode; before, such requests silently ran without references and returned anonymous diarization labels only.Warn when known-speaker recognition is enabled but a diarized request sends no voice references.
generate_transcriptsprints the warning, and the service logs it oncast.voxhelm.servicefor queued requests.Name a guest without a voice reference when applying known-speaker suggestions. Before, such a guest’s lines stayed blank, and on episodes whose anonymous
Speaker Nlabels had approved contributor mappings a known-speaker re-run lost the guest’s name. When exactly one assigned contributor got no reference and exactly one diarization label is tied to no known speaker, the uncertain segments on that label now get the contributor’s name. Ambiguous cases still stay blank. The label map comes from Voxhelm’sraw_diarization_labelssummary or, for older sidecars, from the same confident-segment vote.recalc_video_postersnow exits withCommandError(non-zero status) when at least one poster could not be recalculated. It used to printerrors=<n>and still exit successfully. All videos are still attempted, healthy ones are saved, and the summary is printed first. Failed poster generation is now counted at all:Video.create_poster()logs and swallows errors so uploads succeed without a poster, which made the command reporterrors=0for them. The command asks for the error (create_poster(raise_errors=True), default unchanged) and also counts a video that ends up without a wanted poster. Automation that relied on the old exit status needs to handle the failure.styleguide_prefetch --with-renditionsno longer leavesCAST_STYLEGUIDE_GENERATE_RENDITIONSswitched on. The command changed the process-wide setting and never put it back, so aftercall_commandin a long-running process the styleguide kept generating renditions, also when the command had failed. The previous value (or the absence of the setting) is now restored on success and on failure.scripts/benchmark_typeahead.py(development benchmark, not shipped) checks its target before it migrates or writes.seedandallran the migrations, pointed the default Site at the page tree root and created the benchmark user before refusing a database with real Blogs. A read-only preflight now refuses first: any settings module other thanscripts.typeahead_benchmark_settings, Blogs outside thetypeahead-benchmark-prefix, pages outside those Blogs (other than the tree root and Wagtail’s untouched default home page), and user accounts other thantypeahead-benchmark. Empty, freshly migrated and previously seeded benchmark databases work as before.scripts/benchmark_feeds.pyseeds through the same check.Clear the cache before every test. A feed response cached by one test was served to a later test that requested the same feed URL, so
test_get_only_published_entriesfailed depending on the random test order.Protect
media_stalecleanup with a configurable minimum storage-file age (CAST_MEDIA_STALE_MIN_AGE_DAYS, default 7 days). Skip unknown ages, re-check age and exact database file references before each deletion, and report files skipped as too young or newly referenced. Listing remains the default; the command does not delete database rows.