Repository navigation
bug(slm-frontend): useAutobotApi names 21 main-backend paths the backend does not serve #15536
Description
Activity
- addedbugSomething isn't workingSomething isn't workingarea: api-contractWave 2 · cluster C — Frontend↔backend API contractWave 2 · cluster C — Frontend↔backend API contract
on Sep 2, 2026 Measured on
Dev_new_gui, then deferred — blocked by #15538Re-measured before building, with the extractor from the guard this issue's baseline lives in.
Measured vs claimed
Claim Measured Verdict 28 call sites in useAutobotApi.ts28 correct 21 distinct main-backend paths 21 correct main contract = 2195 paths 2196 +1, drift since filing the debt is pinned in a shrink-only _KNOWN_UNSERVEDbaselinethe baseline does not exist on Dev_new_guirefuted The other 30-site total the sweep reports on this tree is 28 here, plus
UserManagementSettings.vue:141(#15533) andTerminalTool.vue:180(#15236/#15230).
Resolved population: 127 call sites, 309 SLM routes, 2196 main routes.Why this is blocked, not merely large
repo_tests/slm_frontend_calls_reach_served_routes_test.pyis not onDev_new_gui. It
is on the unmerged PR #15538. Itstest_the_known_unserved_baseline_is_exactfails in both
directions, so any call fixed from this base leaves a stale entry behind and reddens #15538
the moment it lands.Dev_new_guihasrequired_status_checks.strict = false, so a stale
#15538 can merge without a rebase and take the base branch red with it.#15538 also edits
autobot-slm-frontend/src/views/settings/admin/UserManagementSettings.vue,
which is the only external caller of thegetUsers()half of this issue. So the collision is
at file level as well as at baseline level.Order of operations: merge #15538, then rebase, then fix this issue and lower the pin in the
same commit — which is what this issue's third acceptance criterion asks for and which is
only possible after #15538 lands.Per-call verdict — caller goes, or route should exist
Nearest served route taken from the generated main contract. Where a route is named, the fix
is to re-point the caller; where none is, the backend half was never built and that half is a
separate issue rather than a contract to invent here.Path called Sites Verdict Nearest served route /api/users2 re-point /api/user-management/users/api/users/{id}2 re-point /api/user-management/users/{user_id}/api/npu-workers1 re-point /api/npu/workers/api/npu-workers/{id}3 re-point /api/npu/workers/{worker_id}/api/npu-workers/load-balancing/config2 re-point /api/npu/load-balancing/api/npu-workers/{id}/pair1 re-point (shape differs: no id in path) /api/npu/workers/pair/api/npu-workers/{id}/restart1 route should exist none; /api/npu/workers/{worker_id}/loggingis the only sub-route/api/npu-workers/{id}/test1 route should exist none /api/mcp/serversand 4 sub-paths5 route should exist none; /api/mcp/serves bridges, tokens and tools, never a server registry/api/permissions/rules/{id}2 route should exist /api/permissions/rulesis a collection only — no item route for PATCH or DELETE/api/files/write1 needs a decision /api/files/uploadexists; whether write is upload is not answerable from the code/api/agents1 re-point /api/agent_config/agents(or/api/agent/agents/status)/api/voice/config2 route should exist none; the voice surface has 14 routes and no config /api/llm-providers/fallback-status1 route should exist none; there is no /api/llm-providers/*at all/api/monitoring/system1 re-point /api/monitoring/hardware/system/api/monitoring/hardware1 re-point /api/monitoring/hardware/{system,gpu,npu}— the caller must pick/api/batch/status1 re-point /api/batch-jobs/status— the neighbouringgetBatchJobsHealthin the same file was already re-pointed this way under #1042912 sites re-point, 14 wait on a backend half, 1 needs a product decision, 1 (
/api/files/write)
is the same. Verbs still need confirming per site against the contract; that is part of the
work, not part of this measurement.Note also that 18 of the 28 call sites have no caller anywhere in the SLM frontend
(getMCPServers,startMCPServer,stopMCPServer,restartMCPServer,getMCPServer,
getAgents,getVoiceConfig,updateVoiceConfig,getSystemMetrics,getHardwareInfo,
getBatchStatus,writeFile,updatePermissionRule,deletePermissionRule,getNPUWorker)
— they are unwired composable methods, not live buttons. The live ones aregetUsers,
createUser,updateUser,deleteUser, the NPU worker set andgetLLMFallbackStatus.Blocked by #15538. Delivered separately from this branch: #15527 in PR #15541.
Found while building the route-reachability guard for #15236 AC5. Not in that issue's
scope, so filed separately.
The defect
autobot-slm-frontend/src/composables/useAutobotApi.tsbuilds an axios client withbaseURL: getBackendUrl(), which returns/autobot-api. The deployed nginx template(
autobot-slm-backend/ansible/roles/slm_manager/templates/autobot-slm.conf.j2:404)proxies
/autobot-api/*to the main backend's/api/*.28 call sites on that client name 21 distinct paths the main backend does not serve.
Measured against the generated main-backend contract
(
autobot-frontend/src/types/generated/api.ts, 2195 paths) unioned with the mainbackend's WebSocket routes.
/api/users,/api/users/{id}/api/users/me/preferences; user CRUD is/api/user-management/users/.../api/npu-workersand 5 sub-paths/api/npu-workers/api/mcp/serversand 4 sub-paths/api/mcp/servers/api/permissions/rules/{id}/api/files/write/api/agents/api/agents/org,/api/agents/status— no bare collection/api/voice/config/api/llm-providers/fallback-status/api/monitoring/system/api/monitoring/hardware/api/monitoring/hardware/npu,/gpu,/system/api/batch/statusWhy this is live, not dead code
getUsers()was reached on every mount ofUserManagementSettings.vue, insideloadLegacyUsers(), whosecatchswallowed the 404 with the comment"Legacy API may not be available - not critical". The result was that the view's
currentUserwas permanentlynull, and the self-service password button opened anempty modal — that half is fixed in #15533. The other call sites have the same shape:
a caller that fails silently or surfaces a generic error.
Acceptance criteria
removed with the reason recorded, or the route is built and the issue that builds
it is named.
catch {}left swallowing a 404 from these calls without surfacing it._KNOWN_UNSERVEDinrepo_tests/slm_frontend_calls_reach_served_routes_test.pyin the same committhat fixes them — that baseline is exact and shrink-only.
Refs #15533, #15236, #15198, #15199.