Remove code that nothing imports or calls:
- web/doctor_chat.js (the ChatPanel class, superseded by the chat
island; only its import in doctor_ui.js remained), web/doctor_chat.css
and web/doctor_telemetry.js. ComfyUI still loaded these files as
extension scripts, but they had no module-level side effects.
- DoctorUI.triggerAIAnalysis and DoctorUI.updatePollInterval;
DoctorAPI.getHistory, DoctorAPI.verifyApiKey and DoctorAPI.chat;
renderContentPipeline.
- The first, shadowed PatternLoader.get_pattern_info definition (the
later one was always the one in effect).
- verify_routes.py, which could not run under package imports and
replaced sys.modules entries with mocks when imported.
The architecture guide lists only existing frontend modules, enforced by
a new test, and the import-scan skip lists no longer name the script.
The markdown and code-highlighting libraries were requested from the
absolute path /extensions/ComfyUI-Doctor/lib/. ComfyUI serves an
extension under its install folder name, so any other folder name got
404s and silently loaded unpinned copies from cdn.jsdelivr.net into the
ComfyUI origin; offline, assistant replies rendered as blank bubbles and
the failed load surfaced as an unhandled promise rejection.
Asset URLs are now resolved relative to the rendering module, and the
CDN fallback is removed. A missing asset logs one warning and the load
never rejects. The chat island shows a reply as plain text while marked
is unavailable and re-renders it as markdown once the assets settle.
The E2E test server also serves the extension under a lowercase install
folder, and the harness can load Doctor through a host-shaped
/extensions/<folder>/ entry. Host-asset tests cover both folder names,
missing assets and late asset loading, with CDN requests blocked.
- Let an inherited proxy on an unregistered host:port (e.g. localhost:7890)
through the connect-time resolver; registered host:port pairs stay checked.
- Accept underscores inside host labels so Docker service names such as
my_ollama can be approved.
- Refuse IPv4-compatible and site-local IPv6 for official providers and
judge NAT64/6to4/compatible forms by the IPv4 address they carry.
- Fix approved destinations when routes are registered instead of on the
first request.
- Static outbound check: exact path matching, import-alias and
TCPConnector detection, policy factory wiring, raw HTTP client imports,
no nosec for policy rules, fail closed on unparseable files.
- Settings: restore the model controls when the base URL is empty.
The analyze, chat, verify-key and model-list routes sent server-side
requests to a caller-supplied base URL guarded only by a pre-flight
denylist. Callers could choose arbitrary hosts and paths, reach shared
address space and metadata ranges, drive local LLM write APIs, and use
DNS rebinding to deliver server-held keys to loopback services.
Requests now select an entry of an immutable destination registry built
at startup from the built-in provider catalog, local Ollama/LM Studio,
and operator environment variables (DOCTOR_LLM_ALLOWED_BASE_URLS and the
existing base URL variables). Outbound URLs are built from the approved
entry, resolved addresses are checked at connect time inside the shared
connector, redirects are never followed or treated as success, and error
responses no longer reflect upstream bodies or network details. The UI
shows localized operator guidance, a static rule enforces disabled
redirects and policy-managed sessions, and .comfyignore keeps tests and
tooling out of the published archive.
Add a reusable backend harness that executes the real package entrypoint
host-style, serves the registered PromptServer routes on loopback through
aiohttp's test server, captures provider requests in-process, and refuses
non-loopback connects and unknown DNS lookups. Characterization tests pin
current handler behavior and the harness's process-state restoration.
Map /extensions/ComfyUI-Doctor/ onto web/ in the E2E server, confined to
web/, so vendored rendering assets load the way ComfyUI serves them and the
default lane no longer falls back to CDN downloads. A focused spec asserts
local asset loading, markdown rendering of a chat reply, and alias
confinement.
Refresh exact frontend lanes and relocated host contracts while preserving
Desktop settings behavior. Recognize first-party Switch nodes and optional
branches without suppressing required-input or broken-link diagnostics.
Revalidate canvas, workflow and target identity across focus navigation;
cancel stale requests on newer actions and sidebar teardown. Keep legacy
positioning and nested graph traversal covered by action-level regressions.
Validation: 75 source contracts, 84 frontend unit tests, Windows full gate
with 871 backend tests and 125 subtests, and 149 mocked browser E2E tests.
Seven existing backend skips remain. No live-host certification is claimed.
Standardize backend log identities and severity highlighting while keeping persisted logs ANSI-free. Restore the encoding-aware startup banner and emit its art as one tightly packed block.