fix(settings): the plugin catalog is fetched by a scheduled task, never by a page load
CI / lint (push) Successful in 2s
CI / integration (push) Successful in 55s
CI / unit (push) Successful in 1m27s
CI / publish (push) Successful in 1m32s

The operator's ruling (Background Jobs, 2026-10-08): a Steward page reads
stored records; the sources are contacted by scheduled collection. An audit
of every GET handler, HTMX fragment, widget poll and MCP read tool found one
page load that reached out: Settings -> Plugins' catalog fragment fetched
each plugin repository (5 min cache, 10 s timeout each, retried on every
load when unreachable).

plugin_catalog_refresh ticks every minute and fetches a repository whose
copy is missing or older than an hour, waiting 5 min after a failure;
saving repositories clears the cache, so the next tick fetches. The
fragment only reads the cache and says which repositories are not fetched
yet. Refresh is now a POST that fetches at once, as does install.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-08 10:09:52 -04:00
co-authored by Claude Opus 5.5
parent 5f04f6af66
commit de3958a362
5 changed files with 201 additions and 88 deletions
+20
View File
@@ -477,6 +477,26 @@ def _register_core_tasks(app: Quart) -> None:
)
)
# Fetch the plugin catalog from the configured repositories as each copy
# falls due (plugin_index.refresh_due), so Settings → Plugins only reads
# what is stored (Background Jobs ruling, 2026-10-08). The repositories are
# read on every tick, so an edit in Settings is fetched within a minute.
async def run_catalog_refresh():
from .core.plugin_index import refresh_due, repo_urls
from .core.settings import get_all_settings
async with app.db_sessionmaker() as db:
settings = await get_all_settings(db)
await refresh_due(repo_urls(settings))
app._task_registry.append(
ScheduledTask(
name="plugin_catalog_refresh",
coro_factory=run_catalog_refresh,
interval_seconds=60,
run_on_startup=True,
)
)
# Fire due Ansible schedules (recurring playbook runs). Checks every minute;
# each schedule's own interval gates whether it actually runs.
async def run_ansible_schedules():