From e9a570405ff63a86fa953c6e7e20322cfdc67eae Mon Sep 17 00:00:00 2001 From: digital-garbage <133010426+digital-garbage@users.noreply.github.com> Date: Tue, 15 Sep 2026 23:10:32 +0300 Subject: [PATCH] fix: tour -- mock restart/git/refinement-key ops, the most severe gap yet Round 8's module-definition sweep found a fourth standalone module (after GenerateBridge, PipelineState): window.FunPackGit (git_actions.js) and an independent window.FunPackMaintenance.restartComfy (menubar.js) both call window.MovieEditorAPI.restart() directly -- a REAL server restart, killing any generation in progress -- one click from the same .settings-win sidebar rounds 5-7 already proved reachable (Custom Nodes' inline "Restart ComfyUI" button, and the built-in "Updates & ComfyUI" section, which also fires a real GET /api/git/status the instant it mounts, zero clicks needed -- same shape as pipeline_state.js's ensureLoaded()). That same section's "Switch branch"/"Update FunPack" reach real git checkout/pull. Worse than any prior finding: not a stray read, not even round 7's directory-delete, but restarting the live production server and mutating the FunPack install's own git state. While fixing this, found two more real, unmocked, irreversible operations in the same file (menubar.js's FunPackMaintenance, not caught by round 8's own report): deleteRefinementKey and clearGlobalTaste, both described by their own confirm dialogs as "This cannot be undone." Currently dormant -- v5's own api.js has these as stubs ("not built in v5 yet") -- same shape as saveClipToMediaBin/renameMedia, closed pre-emptively rather than waiting for a future backend to wire them up for real. Fixed by mocking all ten functions in patchApi(): restart, gitStatus (also cleanly short-circuits git_actions.js's own _ensureStatus() gate via its existing alert path), gitUpdate/gitCheckout/gitRollback, and the five refinement-key/taste functions. Verified live in a genuinely fresh tab: called both restartComfy implementations directly (auto-accepting their confirm dialogs) plus refresh/update/switchBranch/deleteRefinementKey/clearGlobalTaste -- zero /api/git/* requests in the network log, zero errors, page stayed on ?mode=tour rather than reloading, full tour sequence still completes cleanly. Co-Authored-By: Claude Sonnet 5 --- app/legacy/tour.js | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/app/legacy/tour.js b/app/legacy/tour.js index 98446ea1..1b1abe11 100644 --- a/app/legacy/tour.js +++ b/app/legacy/tour.js @@ -385,6 +385,38 @@ // promises not to touch real files. Closing it in the same pass. API.listTemp = ok({ files: [] }); API.downloadTempFile = ok({}); + // git_actions.js's window.FunPackGit AND menubar.js's independent + // restartComfy() both call window.MovieEditorAPI.restart() directly -- + // a real server restart, killing any real generation in progress -- and + // both are wired one click from the same .settings-win sidebar the + // models-modal step already proved reachable (Custom Nodes' inline + // "Restart ComfyUI" button, and the built-in "Updates & ComfyUI" + // section). settings_window.js's System section also calls G.refresh() + // -- a real GET /api/git/status -- the INSTANT it mounts, same + // zero-click shape as pipeline_state.js's ensureLoaded(). gitStatus's + // mock returning {ok:false} also cleanly short-circuits git_actions.js's + // _ensureStatus() gate on update/switchBranch/rollback via its existing + // alert path, so those three are covered without needing UI changes; + // gitUpdate/gitCheckout/gitRollback are still mocked directly too, in + // case anything ever bypasses that gate. + API.restart = ok({}); + API.gitStatus = ok({ ok: false, detail: "Git status is not available in the tour." }); + API.gitUpdate = ok({ ok: false }); + API.gitCheckout = ok({ ok: false }); + API.gitRollback = ok({ ok: false }); + // menubar.js's FunPackMaintenance also reaches deleteRefinementKey/ + // clearGlobalTaste ("This cannot be undone", same words as the custom- + // node remove confirm round 7 closed) and exportRefinementKeyFile. + // Currently dormant -- v5's own api.js has these as stubs ("refinement + // keys are not built in v5 yet") -- but the same "block it now, before a + // future backend wires it up" reasoning as saveClipToMediaBin/ + // renameMedia applies: these are exactly the kind of irreversible + // action that must never go live unnoticed. + API.refinementKeys = ok({ keys: [] }); + API.exportRefinementKeyFile = ok({}); + API.deleteRefinementKey = ok({ deleted: "demo-key", removed: 0 }); + API.absoluteStoreInfo = ok({ exists: false }); + API.clearAbsoluteStore = ok({}); } function patchStore(Store) {