1.34.0 — H.265 video on upload, one rendition job at a time, per-account code limits, sign-out-everywhere
Editorial identity incomplete
2026-10-10
Video uploads now produce a full H.265 mp4 automatically, and every job engine runs at most one rendition job at a time so uploads can never starve ordinary work. Rendition sizes, formats and codecs are admin-configurable through three settings plus a read-only options endpoint. One-time codes are rate-limited per account with 429s, a password reset or change signs the account out everywhere, and the own-password-change response returns new tokens the client must adopt. Framework no-save fields now apply to every model.
Breaking
- Changing your own password through the account save now returns top-level
tokensand invalidates the old ones. Clients must adopt the new tokens or the user is logged out. auth/sms/loginnow requires aloginbouncer token where bouncer enforcement is on. Custom clients must fetch one first.id,pk,createdanduuidare refused on save for every model, even those that declare their ownNO_SAVE_FIELDS. DeclareALLOW_SAVE_FIELDSto hand backcreatedoruuid. A postedidis ignored silently, not 400.mojo_secrets,secretandsettingare no longer accepted in a FileManager request body.- A setting's group is fixed at creation. Changing it returns 400. A create through the active group that names another group returns 403.
- A FileManager's AWS role on a store that uses platform credentials can be set only by a superuser, whichever key carries it. Roles already stored are not undone.
- Setting a group's link address or moving a group between trees needs signed-in global
manage_groupsorgroups. Group API keys and sub-group managers get 403. - Moving a group within a tree needs member save rights on both the old and new parent.
- Assistant tools refuse a caller-supplied
graph.describe_modelnow returns a singleserializationblock. Models wanting a richer assistant view declareGRAPHS["ai"]. - The assistant context endpoint opens a row only for a caller who may read it. Anything else is a 404.
BaseRenderer.get_rendition_optionsandget_automatic_rendition_rolesare now instance methods. The old classmethods aredefault_rendition_optionsanddefault_automatic_roles. Renderer subclasses setconfig_categoryto be overridable.- A file's
metadata.expires_atwithout a timezone is refused with 400 over the API. - A webhook
dispatch()with an idempotency key over 255 characters raisesValueError. - A confined credential naming an unknown, inactive or foreign group in
?group=gets 403 instead of falling through. - A settings-file
APIKEY_PERMS_PROTECTIONmap is a floor a settings row cannot remove or loosen. A malformed map blocks API-key permission grants until repaired.
Added
FILEMAN_RENDITIONS_IMAGE,_VIDEOand_DOCUMENTsettings, global or per group, override any rendition's size, format, quality or codec and choose which roles run on upload. Values are validated on save with messages naming the field, and numeric options are capped.GET /api/fileman/renditions/optionsdescribes every rendition role, its defaults, allowed values and limits for an admin UI.JOBS_CHANNEL_LIMITScaps how many jobs a channel may hold on one engine. The jobs CLI takes--channel-limits, and heartbeats report the caps.JOBS_ENGINE_RESERVED_WORKERSholds back worker slots that only thepriorityand box-direct channels may claim, so deploys start while workers are busy.- Per-account one-time-code limits:
CODE_ATTEMPT_LIMIT,CODE_ATTEMPT_WINDOW,CODE_SEND_LIMIT,CODE_SEND_WINDOW,TOTP_ATTEMPT_DAILY_LIMIT. Over the limit returns 429 withRetry-After. SMS_OTP_LENGTHsets the SMS code length, 6 to 10.AUTH_HANDOFF_REQUIRE_PKCEand PKCE onPOST /api/auth/handoff. With the setting atnative, handoffs to app destinations must carry a code challenge.User.end_sessionssigns an account out everywhere: rotates the auth key, revokes OAuth grants, drops websockets.auth/manage/throttleaccepts every per-account bucket, andclear_rate_limitfor an account clears all of them.reconcile_fileman_public_access --groupsand--managerre-check group-scoped stores.RestMeta.ALLOW_SAVE_FIELDSandModel.get_no_save_fields().- Edge nginx serves
.webmanifestasapplication/manifest+json.
Changed
- A video upload builds its thumbnails, the 10-second preview and a full
video_mp4again. The mp4 is H.265 at CRF 28; Chrome and Safari play it, Firefox does not. Set{"video_mp4": {"codec": "h264", "bitrate": "2000k"}}for H.264, or addvideo_webmto_automaticfor a fallback. - Every engine consuming
renditionsruns one rendition job at a time by default. SetJOBS_CHANNEL_LIMITSto{"renditions": 0}to lift it. An explicit dict replaces the default rather than merging with it. - Engines with 8 or more workers reserve 2 for priority work by default, 4 to 7 reserve 1. Set
JOBS_ENGINE_RESERVED_WORKERS=0for the old behaviour. - Video thumbnails and transcodes scale into a bounding box, keeping aspect ratio and never upscaling. Output dimensions may differ from before.
- A password reset or change, an admin temporary password, or a session revoke signs the account out everywhere.
- Re-sending a login, reset or sign-up code inside its lifetime re-sends the same code. Sends are capped at 5 per 15 minutes, and a refused send returns the normal success answer.
ALLOW_PHONE_CHANGE=Falsealso refuses clearing a phone number. Removing a verified number sends thephone_removed_notifyemail.- A deploy whose coordination lease is lost is reported as
failedwith reasonlease_expired_before_startorlease_expired_mid_canary.supersededis used only when a successor is seen. WS_MAX_CONNECTIONScounts live connections only. The server ping is the presence heartbeat; do not disable it in production.- Bouncer no longer learns or enforces automatic user-agent, fingerprint or
/24subnet signatures. Manual signatures still apply.BOUNCER_LEARN_UA_THRESHOLD,BOUNCER_LEARN_UA_TTLandBOUNCER_LEARN_FP_THRESHOLDare no longer read. - Assistant searches on a model whose search fields include a sensitive field are refused entirely.
- Webhook fan-out keys longer than 64 characters are hashed. The fan-out job's real outcome is
metadata.result, not its job status. - Document preview
max_pagesis now applied. Imagequalityapplies to WEBP. - Releases are published as a wheel only. No source archive is built.
Fixed
- A model declaring
NO_SAVE_FIELDSsilently madeidwritable, so a postedidcould re-target a save at another row. - A file admin could set an assume-role on a platform-credential store by posting it inside
secretsorsettings. - Image format
jpgraised inside Pillow and silently dropped the rendition. - A file's metadata save over the API hit a two-argument signature and errored.
- Expired-file cleanup reads a timezone-less expiry as UTC and survives one bad file.
- A dead websocket no longer counts against the connection cap, and a disconnect of any kind cleans up its Redis state.
- A stale password-reset answer no longer reveals whether an account exists.
Upgrade notes
- Workers need ffmpeg with
libx265, or everyvideo_mp4rendition lands as a failed row. Expect minutes of CPU per uploaded video, one at a time per engine. - Load the new
phone_removed_notifyemail template withseed_email_templates, or the removal notice fails silently. - Re-render edge nginx config to pick up the
.webmanifesttype. - Existing automatic bouncer signatures stop being enforced on upgrade. Their rows remain.
- A
{}settings row that used to wipe the file'sAPIKEY_PERMS_PROTECTIONno longer does. - The packaged Admin bundle and its pinned manifest hash ship together. A mismatch stops Django at import.
- No migrations in this release.