ComfyUI-Manager/reports/scenario_intents.md
Dr.Lt.Data 4410ebc6a6
Some checks are pending
Publish to PyPI / build-and-publish (push) Waiting to run
Python Linting / Run Ruff (push) Waiting to run
fix(security): harden CSRF with Content-Type gate and expand E2E coverage (#2818)
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)
2026-04-22 05:04:30 +09:00

16 KiB

Scenario Intent Mapping

Generated: 2026-04-18 Definition of "intent": For each scenario — what real use case, user need, or protection concern does this scenario represent? Answers "why does this scenario matter, what is it there to prove?"

Intent categories used:

  • User capability — the user wants to accomplish task X
  • Data integrity — the system must not corrupt state
  • Security boundary — privilege / access must be enforced
  • Input resilience — bad input must not crash or mis-operate
  • Idempotency — operation can be retried safely
  • Observability — the caller needs accurate state visibility
  • Concurrency safety — parallel calls don't interfere
  • Recovery — system can recover from failure / bad state

Section 1 — Glob v2 Endpoints

1.1 Queue Management

POST /v2/manager/queue/task (install)

Scenario Intent
Success (CNR) User capability: install a registered pack at a specific version for reproducibility
Success (nightly/URL) User capability: install unreleased or private pack from arbitrary git URL
Success (skip_post_install + already disabled) Recovery: re-enable a previously disabled pack without full reinstall (optimization path)
Validation error (bad kind) Input resilience: prevent arbitrary op execution via malformed kind; ensure schema gate is the truth
Validation error (missing ui_id/client_id) Observability: every queued task must be traceable back to its originator
Invalid JSON body Input resilience: malformed bytes don't crash the server
Worker auto-start User capability: ease of use — installer doesn't need separate "start" call (legacy path does though)

POST /v2/manager/queue/task (uninstall)

Scenario Intent
Success User capability: remove a pack that's no longer needed or causing issues
Target not installed Idempotency: uninstall of non-present pack should not fail destructively

POST /v2/manager/queue/task (update)

Scenario Intent
Success User capability: upgrade to a newer release to get fixes/features
Already up-to-date Idempotency: safe to trigger update even when nothing new exists
Update fails mid-way Data integrity: don't leave pack in partially-updated state

POST /v2/manager/queue/task (fix)

Scenario Intent
Success Recovery: when dependencies drift or break, re-install them without re-cloning source
Missing deps pre-fix Recovery: fix should heal the environment

POST /v2/manager/queue/task (disable)

Scenario Intent
Success User capability: temporarily stop using a pack without losing it (reversible)
Already disabled Idempotency: re-disable is a no-op

POST /v2/manager/queue/task (enable)

Scenario Intent
Success User capability: restore a disabled pack to active use
Not disabled Idempotency: no-op when already active

POST /v2/manager/queue/install_model

Scenario Intent
Success User capability: download models from curated whitelist for model library
Missing client_id/ui_id Observability: every download is traceable
Invalid metadata Input resilience: malformed model requests rejected early
Not in whitelist Security boundary: prevent arbitrary URL downloads (supply-chain protection)
Non-safetensors + lower security Security boundary: block executable-format model files in lower-trust env

POST /v2/manager/queue/update_all

Scenario Intent
Success User capability: one-click update of all installed packs
Security denied Security boundary: bulk ops are more risky; require middle+ trust
Missing params Observability: must know who initiated bulk op
mode=local User capability: work offline using cached data
Desktop build Data integrity: don't self-update comfyui-manager in bundled builds
Empty active set Idempotency: safe to run on fresh install with nothing to update

POST /v2/manager/queue/update_comfyui

Scenario Intent
Success User capability: update ComfyUI core itself
Missing params Observability: traceability
stable=true explicit User capability: override policy for one-off stable update regardless of config

POST /v2/manager/queue/reset

Scenario Intent
Success Recovery: abort an in-progress batch; clear failed state
Already empty Idempotency: safe to call repeatedly as cleanup

POST /v2/manager/queue/start

Scenario Intent
Worker not running User capability: explicit trigger for the async worker
Already running Concurrency safety: don't spawn duplicate workers (data corruption risk)
Empty queue Idempotency: no error on empty queue

GET /v2/manager/queue/status

Scenario Intent
No filter Observability: dashboard view of overall progress
client_id filter Observability: per-client progress for multi-user UI
Unknown client_id Input resilience: unknown id returns 0s, not error

GET /v2/manager/queue/history

Scenario Intent
id=<batch_id> Observability: inspect an old batch for audit/debug
Path traversal Security boundary: prevent arbitrary file reads via history endpoint
ui_id filter Observability: detailed view for one task
client_id filter Observability: per-client history
Pagination Performance: avoid huge payload on long histories
Serialization failure Input resilience: fail cleanly (400) rather than crash

GET /v2/manager/queue/history_list

Scenario Intent
Success Observability: enumerate past batches
Empty Idempotency: no crash on empty history dir
Path inaccessible Input resilience: fail cleanly

1.2 Custom Node Info

GET /v2/customnode/getmappings

Scenario Intent
Success (mode=local/cache/remote) User capability: UI resolves "missing nodes in workflow" to recommend packs
mode=nickname User capability: shorter display names for UI
Missing mode Input resilience: require explicit mode choice

GET /v2/customnode/fetch_updates (deprecated)

Scenario Intent
Always 410 API contract: signal clients to migrate to queue-based flow; don't silently break

GET /v2/customnode/installed

Scenario Intent
mode=default Observability: current state for UI
mode=imported Observability: startup-time state for diff ("what changed since boot")
Empty Idempotency: no crash on empty install

POST /v2/customnode/import_fail_info

Scenario Intent
Known failed pack Recovery: show user exact traceback so they can decide fix vs report vs uninstall
Unknown pack Input resilience: 400 rather than empty success (distinguishable)
Missing fields / non-dict Input resilience: reject early

POST /v2/customnode/import_fail_info_bulk

Scenario Intent
cnr_ids list Performance: batch lookup for dialog that shows multiple failed packs at once
urls list Same, for git-URL-installed packs
Empty lists Input resilience: require at least one query
Null for unknown Observability: distinguish "no failure info" from "lookup failed"

1.3 Snapshots

GET /v2/snapshot/get_current

Scenario Intent
Success Observability: inspect system state before taking a snapshot
Failure Input resilience: fail cleanly

POST /v2/snapshot/save

Scenario Intent
Success User capability: persist current state for later rollback
Multiple saves Observability: each save is independently retrievable

GET /v2/snapshot/getlist

Scenario Intent
Success User capability: choose which snapshot to restore/delete
Empty Idempotency: no crash on empty snapshot dir

POST /v2/snapshot/remove

Scenario Intent
Success User capability: housekeeping (remove old snapshots)
Nonexistent target Idempotency: re-delete should not error
Path traversal Security boundary: prevent deleting files outside snapshot dir
Missing target Input resilience
Security denied Security boundary: middle security required

POST /v2/snapshot/restore

Scenario Intent
Success Recovery: rollback to a known-good state after bad update
Nonexistent Input resilience
Path traversal Security boundary
Security denied Security boundary: middle+ required (restore is destructive)

1.4 Configuration

GET /v2/manager/db_mode

Scenario Intent
Success Observability: UI shows current mode setting

POST /v2/manager/db_mode

Scenario Intent
Valid User capability: switch between online/local DB for different network conditions
Malformed Input resilience
Missing value Input resilience: don't silently set unknown/empty

GET/POST /v2/manager/policy/update

Same as db_mode: observability of current policy + user choice to change update strategy (stable vs nightly) + input resilience.

GET /v2/manager/channel_url_list

Scenario Intent
Success Observability: show available channels in UI dropdown
"custom" selected Input resilience: URL not in known list doesn't break display

POST /v2/manager/channel_url_list

Scenario Intent
Known name User capability: switch between upstream vs fork vs private channel
Unknown name Input resilience: silent no-op (don't crash on typo)
Malformed Input resilience

1.5 System

GET /v2/manager/is_legacy_manager_ui

Scenario Intent
Success User capability: frontend picks which UI variant to mount at page load

GET /v2/manager/version

Scenario Intent
Success Observability: display version in UI (troubleshooting / support)
Idempotent Data integrity: version doesn't change at runtime

POST /v2/manager/reboot

Scenario Intent
Success User capability: apply changes that require restart (snapshot restore, ComfyUI version switch)
CLI session mode Integration: cooperates with external process manager for clean restart
Security denied Security boundary: middle required (restart affects all users)

GET /v2/comfyui_manager/comfyui_versions

Scenario Intent
Success User capability: enumerate ComfyUI versions to pick one for rollback/upgrade
Git failure Input resilience: fail cleanly if ComfyUI isn't a git repo

POST /v2/comfyui_manager/comfyui_switch_version

Scenario Intent
Success User capability: switch ComfyUI to specific version (pin for reproducibility)
Missing params Observability
Security denied Security boundary: high+ required (massive blast radius — affects core behavior)

Section 2 — Legacy-only Endpoints

POST /v2/manager/queue/batch

Scenario Intent
Single-kind batch User capability: execute multiple operations of same type in one round-trip
Mixed-kind batch User capability: apply a workflow (uninstall-then-install = reinstall) atomically
Partial failure (failed list) Observability: distinguish which packs in the batch failed from ones that succeeded
Empty body Idempotency: no-op if nothing to do
update_all sub-key User capability: trigger bulk update as part of batch

GET /v2/customnode/getlist

Scenario Intent
Success User capability: populate Custom Nodes Manager dialog with full available pack catalog
skip_update=true Performance: fast load when user doesn't need remote fetch
Channel resolution Observability: user sees which channel data came from

GET /customnode/alternatives

Scenario Intent
Success User capability: recommend alternative packs when one is discontinued/unavailable

GET /v2/externalmodel/getlist

Scenario Intent
Success User capability: browse curated model catalog
installed flag per model Observability: which models already present
HuggingFace sentinel User capability: HF-hosted models via standard URL
Custom save_path User capability: custom model placement

GET /v2/customnode/versions/{node_name}

Scenario Intent
Known CNR User capability: pick a specific version to install (stability over latest)
Unknown pack Input resilience

GET /v2/customnode/disabled_versions/{node_name}

Scenario Intent
Has disabled User capability: see what versions are available to re-enable without fresh install
None Input resilience

POST /v2/customnode/install/git_url

Scenario Intent
Success User capability: install arbitrary git pack (for advanced users / private packs)
Already installed Idempotency
Clone failure Input resilience: bad URL returns error; no corrupt state
Security denied Security boundary: high+ required (arbitrary code execution risk)

POST /v2/customnode/install/pip

Scenario Intent
Success User capability: install pip packages needed by a pack
Security denied Security boundary: high+ required (arbitrary package execution risk)

GET /v2/manager/notice

Scenario Intent
GitHub reachable User capability: see latest Manager news/changelog inline
GitHub unreachable Input resilience: don't block UI on external service failure
Non-git ComfyUI Observability: warn user that their install is non-standard
Outdated ComfyUI Observability: warn user they're too old to be safe
Desktop variant User capability: correct footer for desktop distribution

Section 3 — Cross-cutting Scenarios

Some scenarios recur across many endpoints with consistent intent:

Scenario pattern Applies to Unified intent
Malformed JSON body all POST endpoints accepting JSON Input resilience — protect against corrupted bytes / wrong content-type
Missing required field all POST endpoints with schemas Input resilience + Observability (traceability fields mandatory)
Path traversal in target/id snapshot/remove, snapshot/restore, queue/history Security boundary — prevent arbitrary filesystem access
Security level denial (middle/middle+/high+) destructive endpoints Security boundary — tier privileged ops per deployment risk profile
Idempotent re-call on empty state queue/reset, history_list, snapshot/getlist, installed Idempotency — safe to poll or retry
Repeated read returns same value version, db_mode, policy/update Data integrity — config/runtime state is stable
Empty collection returned cleanly history, getlist, installed, alternatives Input resilience — empty is valid, not an error

Section 4 — Intent Coverage Summary

Intent category # scenarios Notes
User capability (positive user need) 62 The "happy paths"
Input resilience 32 Mostly 400s for bad input
Security boundary 15 Security levels + path traversal
Idempotency 14 No-op / retry safety
Observability 16 State visibility + traceability
Data integrity 8 Config/state stability
Recovery 5 Fix, restore, reset
Concurrency safety 2 Worker dedup

Total unique scenarios mapped: ~154 (matches Report A).


Section 5 — Why This Mapping Matters

For each scenario, the intent drives the TEST design:

  • User capability scenarios need end-to-end effect verification (feature works as promised)
  • Input resilience scenarios need negative tests (bad inputs rejected cleanly)
  • Security boundary scenarios need permission gate tests (403 proven per security level)
  • Idempotency scenarios need repeat-call tests (no state drift)
  • Observability scenarios need response-correctness tests (UI can trust the data)
  • Data integrity scenarios need consistency tests (no runtime mutation of constants)
  • Recovery scenarios need fault-injection tests (broken state → fix heals it)
  • Concurrency safety scenarios need parallel-call tests (no duplicate workers/tasks)

Gaps in current E2E suite are best understood by intent: missing tests are typically for security boundary (403 gates), input resilience edge cases (path traversal, missing value keys), and recovery (fix/restore). These are the hardest to reach in simple E2E but matter most for production safety.


End of Scenario Intent Mapping