Files
ServerKit/backend/tests
Juan DenisandClaude Opus 5 7e051ddac6 feat(plugins): let extensions contribute doctor checks
The sweep was a fixed sequence of core producers, so an extension had nowhere
to say "the thing I manage is unhealthy, and here is what to do about it" — on
the page an operator opens to ask exactly that. A plugin now registers a
provider and its checks appear beside the core ones, with a working Repair
button, and no frontend change: the panel's status pill, repair button and diff
toggle all key off fields rather than a known list of check ids.

Because these run third-party code, the registry gives them two things core's
own producers don't have:

- an error boundary. run() calls its producers bare — each hand-rolls its own
  try/except and anything that escapes 500s the whole sweep. A provider that
  raises becomes one warning attributed to the plugin instead.
- a time budget. Nothing bounds a core producer today, so a hung one hangs the
  synchronous POST /doctor/run for whoever asked. A provider that overruns is
  reported as a warning and the sweep moves on. Note the executor is shut down
  with wait=False on purpose: its context manager joins the worker on exit,
  which would have made the timeout worthless — a test pins that down.

Providers run in a worker thread with the app context carried across, so a
check can query the database the way a core one does.

Contributed keys are namespaced, statuses outside ok/warn/fail are reported as
warnings rather than rendering as a blank pill, and a check claiming to be
repairable without a registered handler is demoted — showing a button that
dispatches nowhere is the state two core checks are already in, and it isn't
worth reproducing. Repairs route back through the registry, which is itself the
allowlist: a crafted ref for an unregistered namespace reaches nothing.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-25 13:56:09 -04:00
..