Defense-in-depth over GET→POST alone: reject the three CORS-safelisted simple-form Content-Types (x-www-form-urlencoded, multipart/form-data, text/plain) on 16 no-body POST handlers (glob + legacy) to block <form method=POST> CSRF that bypasses method-only gating. Move comfyui_switch_version to a JSON body so the preflight requirement applies. Split db_mode/policy/update/channel_url_list into GET(read) + POST(write). Tighten do_fix (high → high+) and gate three previously-ungated config setters at middle. Resynchronize openapi.yaml (27 paths, 30 operations, ComfyUISwitchVersionParams as a shared $ref component). Add E2E harness variants, Playwright config, CSRF/secgate suites, 39-endpoint coverage, and a CHANGELOG. Breaking: legacy per-op POST routes (install/uninstall/fix/disable/update/ reinstall/abort_current) are removed; callers already use queue/batch. Legacy /manager/notice (v1) is removed; /v2/manager/notice is retained. Reported-by: XlabAI Team of Tencent Xuanwu Lab CVSS: 8.1 (AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:H)
4.7 KiB
Legacy UI — Channel Combo DOM Mapping Note
Date: 2026-04-20
Context: WI-OO Item 3 follow-up — bloat sweep dev:ci-022 B8 "Channel dropdown"
test was title-mismatched (filter /Cache|Local|Channel/ matched DB combo's
option text, not the Channel combo itself). This record documents the correct
DOM locators for any future reactivation.
Scope: Record only. No test code added; no audit impact.
1. Source Locations
| Artifact | Path | Lines | Role |
|---|---|---|---|
| Channel combo creation + registration | comfyui_manager/js/comfyui-manager.js |
960-986 | Creates the <select>, installs title attr, fetches options from API, mounts into the settings panel via createSettingsCombo |
| Settings row wrapper | comfyui_manager/js/comfyui-gui-builder.js |
15-27 | Exports createSettingsCombo(label, content) that wraps the combo in the label/input row |
2. DOM Structure
| Field | Value |
|---|---|
| Tag | <select> |
| Classes | cm-menu-combo p-select p-component p-inputwrapper p-inputwrapper-filled |
title attribute |
"Configure the channel for retrieving data from the Custom Node list (including missing nodes) or the Model list." (set at L961) |
| Options source | /v2/manager/channel_url_list — populated asynchronously at L963-984 |
| Option texts | Channel URL names (e.g. default, recent, custom URLs); NOT the word "Channel" |
| Label wrapper | div.setting-item > div.flex.flex-row.items-center.gap-2 > div.form-label.flex.grow.items-center > span.text-muted with textContent: "Channel" (from createSettingsCombo) |
| Render timing | Select element itself: sync at menu build time. Options: async after channel_url_list fetch resolves |
3. Why the Original hasText: /Cache|Local|Channel/ Filter Failed
The removed test used hasText to find the Channel dropdown, but that matcher
searches the element's rendered text (its <option> children's text in the case
of a <select>). The Channel combo's options are channel URL names — they do
not contain the words Cache, Local, or Channel.
In contrast, the DB (datasrc) combo located a few lines above
(comfyui-manager.js:957, built from this.datasrc_combo which seeds options
Cache / Local / Remote) did contain those literals, so the filter
silently resolved to the wrong <select>. The test asserted visibility, which
passed against the DB combo, masking the mismatch until WI-OO's audit exposed
it as B8 title-mismatch bloat.
4. Stable Selector Candidates
Ordered by robustness (most stable first):
-
Title attribute (recommended) — unique per L961
select[title^="Configure the channel"]The leading prefix
Configure the channelappears nowhere else in the managed panel. Safe against minor title copy edits as long as the opening phrase is preserved. -
Label-based scope — DOM-structure dependent
.setting-item:has(span.text-muted:text-is("Channel")) selectWorks as long as
createSettingsCombokeeps its current wrapper shape and the exact label text"Channel". -
Class-only — NOT unique Classes
cm-menu-combo p-select ...are shared with the DB, Update-Policy, and Share combos. Using classes alone will match multiple elements and is brittle.
5. Async-Population Note
Options for the Channel combo are populated via an async fetchApi call to
/v2/manager/channel_url_list at L963. Two testing consequences:
- A visibility assertion on the
<select>resolves immediately — the element is appended synchronously at L960 and mounted at L986. - An assertion about option count or specific option values MUST wait for the
fetch to resolve. Use
expect.poll(or equivalent) with a reasonable timeout (≥5s) rather than an immediatetoHaveCountcheck.
6. Proposed Test Skeleton (Reference Only)
Not added to any spec — kept here for future activation.
test('shows Channel dropdown (async-populated)', async ({ page }) => {
await openManagerMenu(page);
const dialog = page.locator('#cm-manager-dialog').first();
const channelCombo = dialog.locator('select[title^="Configure the channel"]');
await expect(channelCombo).toBeVisible();
await expect.poll(
async () => await channelCombo.locator('option').count(),
{ timeout: 5000 }
).toBeGreaterThan(0);
});
7. Decision
Test not added. This aligns with the post-bloat-sweep net-removal direction established by WI-OO: re-introducing a Channel-dropdown visibility test would re-expand the surface the sweep explicitly trimmed. The record is preserved here so that, if future coverage expansion prioritizes the settings panel, reactivation needs only copy the skeleton above and choose selector option 1 from §4.