Control actions now require the change permission. Custom admin views only
ran through AdminSite.admin_view(), which checks is_staff and nothing else,
so any staff user could revoke tasks, shut down workers, and send new tasks.
Task and Worker gained a change permission; view is monitoring-only.
Fix stored XSS on the dashboard. Chart data was rendered with |safe, so a
task name or worker hostname containing </script> could inject markup. The
data now goes through the json_script filter.
The event listener stopped reconnecting after the first broker failure. The
flush timer shared the listener's stop event, so shutting it down also
cancelled the reconnect loop.
The unfold app shipped no migrations and could not find its templates, so
migrate django_celeryx failed and every page raised TemplateDoesNotExist.
The unfold dashboard raised AlreadyRegistered by importing the standard
admin module for its filters. The filters moved to admin/filters.py.
Detail views passed a hand-built dict as opts, which broke unfold template
tags that read opts.app_label in Python. They pass the model _meta now.
override_settings(CELERYX=...) left the cached settings dataclass in place.
A setting_changed receiver now invalidates it.
get_db_alias() no longer rebuilds the settings dataclass on every database
access.
The stand-in querysets silently ignored unsupported filter() lookups and
returned unfiltered rows. They raise NotImplementedError instead.
Task and worker list queries are capped at 1000 rows with a warning, instead
of loading the whole table into memory.
Workers that were killed, crashed, or died while the listener was down stayed
"online" forever. Celery only emits worker-offline on a graceful shutdown, so
liveness now falls back to heartbeat age.
Worker control commands were sent without reply=True, so a command the
worker rejected (shrinking a busy pool) was reported as a success.
The worker pool tab showed max-concurrency, which does not change on grow or
shrink, making both look like no-ops. It shows the live process count now.
Update dev dependencies (mypy 2.3.1, ruff 0.16.4, ty 0.0.73, pytest 9.1.1,
django-stubs 6.1.0, and others). prometheus-client is now a dev dependency, so
the metrics tests actually run.
Document the permission model, the security caveats around task arguments,
and the unauthenticated metrics endpoint.