Skip to content

[pull] main from Comfy-Org:main - #50

Merged
pull[bot] merged 5 commits into
Penguinjanator:mainfrom
Comfy-Org:main
Aug 18, 2026
Merged

[pull] main from Comfy-Org:main#50
pull[bot] merged 5 commits into
Penguinjanator:mainfrom
Comfy-Org:main

Conversation

@pull

@pull pull Bot commented Aug 18, 2026

Copy link
Copy Markdown

See Commits and Changes for more details.


Created by pull[bot] (v2.0.0-alpha.4)

Can you help keep this open source service alive? 💖 Please sponsor : )

MaanilVerma and others added 5 commits August 18, 2026 16:49
## Summary

Adds the missing test coverage for the cloud sign-in and sign-up
surface. Four files had no tests at all.

## Changes

- **What**: Tests only, no product code.

Previously uncovered: the `beforeEnter` route guards and their
`switchAccount` escape hatch, `usePostAuthRedirect`, the sign-in
password schema, and the terms notice. The rest extends existing files
rather than duplicating their setup.

Covered here: route guards on both `/cloud/login` and `/cloud/signup`,
post-auth redirect precedence and its open-redirect guard, password
boundaries and character classes, the terms notice and its outbound-link
safety, the sign-in form's validation states and autofill attributes,
the turnstile gate on sign-up, and the insecure-context warning for
self-hosted HTTP origins.

- **Breaking**: None.

## Review Focus

The route-guard tests drive both `/cloud/login` and `/cloud/signup`
through the same `describe.for`. Those guards are byte-identical
duplicates, so testing one would leave the other free to regress.

One assumption from the plan turned out to be wrong, and the test pins
the real behaviour instead: a pristine sign-in button is **enabled**,
not disabled. PrimeVue leaves `$form.valid` undefined until a field is
touched, so submitting a pristine form is what surfaces the errors.

`globalThis.isSecureContext` is `undefined` under happy-dom rather than
`true`, so the insecure-context test stubs the *secure* case. The value
is a setup-time snapshot, so the stub has to precede mount.

## Testing

90 tests. Every one was mutation-checked: the behaviour it pins was
broken in the source, the test confirmed failing, then reverted. **No
survivors.**

| Area | Cases | Representative mutation → result |
| --- | --- | --- |
| Password + email schema | 19 | drop any one complexity regex → that
case fails; move the refine `path` → mismatch fails |
| Open-redirect guard | 7 | read the last repeated query entry instead
of the first → fails; decode fallback returns a `/` path → fails |
| Post-auth redirect | 7 | `router.replace` → `push` → fails; drop the
OAuth-resume early return → deep-link precedence fails |
| Route guards | 19 | negate `isLoggedIn` → both routes fail; `if
(!to.query.switchAccount)` → `if (true)` → escape hatch fails |
| Terms notice | 5 | drop `rel="noopener noreferrer"` → fails; hard-code
any locale fragment → fails |
| Sign-in form | 12 | drop `:disabled="!$form.valid"` → fails;
`current-password` → `new-password` → fails |
| Sign-up form | 15 | remove `useThrottleFn` → double-submit fails; make
`resetTurnstile` a no-op → fails |
| Login view | 6 | insecure-context warning `v-if="false"` → fails;
force the webview notice → fails |

Three guards are unkillable in isolation and die only once the outer
gate is also removed, which is the signature of defence-in-depth rather
than dead code: `CloudSignInForm.onSubmit`'s `event.valid`,
`SignUpForm.onSubmit`'s `waitingForTurnstile`, and both forms' loading
gate behind `Button`'s `disabled || loading`.

No e2e spec. The two flows worth driving end to end — the deep-link
round trip and the already-signed-in redirect — are pinned closer to the
logic in `usePostAuthRedirect.test.ts` and
`onboardingCloudRoutes.test.ts`, the latter on both routes. A browser
spec added a slower path to the same assertions.

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: CodeRabbit <noreply@coderabbit.ai>
Co-authored-by: Christian Byrne <cbyrne@comfy.org>
## Summary

Inspecting a video saved under a subfolder shows an empty player,
because the assets lightbox builds its media URL from a subfolder the
sidebar discarded.

## Changes

- **What**: `AssetsSidebarTab` built every gallery `ResultItemImpl` with
`subfolder: ''` and overrode only the `url` getter. Images resolve
through `preview_url` and were unaffected; `ResultVideo` uses
`vhsAdvancedPreviewUrl`, which is rebuilt from `urlParams` — i.e. from
the discarded subfolder. Extracted `getAssetSubfolder` (reads
`preview_url`, falls back to `user_metadata`, mirroring how
`getAssetType` resolves the type) and used it when building gallery
items and in `getAssetUrl`.

Measured against a local backend — same file, same name, only the
address differs:

| Request | Response |
| --- | --- |
| `viewvideo?filename=clip.webm&type=output&subfolder=` (file at output
root) | 200, 910017 b |
| `viewvideo?filename=clip.webm&type=output&subfolder=sub` (file in
`sub/`) | 200, 910017 b |
| `viewvideo?filename=clip.webm&type=output&subfolder=` (file in `sub/`)
| **204, 0 b** |

The endpoint handles subfolders correctly; only the URL the lightbox
constructed failed. This also matches the 204 independently reported in
#7192, and explains why the same videos play from Job History (which
builds result items from real queue data) and why the bug only appears
with a `filename_prefix` containing a directory.

## Review Focus

`getAssetSubfolder` prefers `preview_url` over `user_metadata` because
`preview_url` is already the trusted source for the `url` getter and for
`getAssetType`. `getAssetUrl` previously read `user_metadata` only; that
path is preserved as the fallback, so its behaviour is unchanged when
`preview_url` carries no subfolder.

Not addressed here, to keep this focused: the same constructor
hard-codes `type: 'output'`, which is wrong for imported (input) videos.
`ResultItem['type']` is a narrow union while `getAssetType` returns
`string`, so that needs its own change. Every case reported in #7192 is
an output.

Fixes #7192
## Summary

Bump the avatar image versions for four technologists on the Forward
Deployed Creatives (FDCT) page to their latest uploaded assets.

## Changes

- **What**: Updated `avatarSrc` for Doug Hogan (`_v2`), Chris V.
(`_v2`), Rob Losch (`_v3`), and Robert Paige (`_v4`) in
`apps/website/src/data/fdct.ts`.

## Review Focus

Verify each new asset URL resolves on media.comfy.org.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
## Summary

Fitting a group to its nodes now leaves all four group borders on the
grid when snap-to-grid is enabled, instead of landing at arbitrary
sub-grid offsets.

## Changes

- **What**: `LGraphGroup.resizeTo` expands the fitted bounds out to the
nearest grid lines when `LiteGraph.alwaysSnapToGrid` is set. The
expansion lives in a new pure helper, `expandRectToGrid` in
`measure.ts`, alongside `snapPoint`.

## Review Focus

The rect is only ever grown, never shrunk — left/top floor, right/bottom
ceil — so the requested padding is never eaten and nothing that was
inside the group before the call ends up outside it. Rounding to nearest
would have been closer to `snapPoint`'s existing behaviour but can pull
a border inside the padding it just added.

Gated on `alwaysSnapToGrid` rather than on `getSnapToGridSize()` alone:
that getter returns `CANVAS_GRID_SIZE` regardless of the setting, so
using it by itself would snap groups for users who have snap-to-grid
switched off.

Applies to every fit path, since all of them funnel through `resizeTo` —
context menu, more-options menu, `useCoreCommands`, and `useFrameNodes`.

Fixes #1185
…le part (#14472)

Writes down the state-modelling conventions we keep re-explaining in
review, and
adds one lint rule for the part that is mechanically checkable.

### Why

Reviews of anything with a beginning and an end — a wizard, an upload,
an
onboarding flow — keep converging on the same handful of points: several
independent booleans that must agree, values stored that could be
derived, and
effects used to keep two pieces of internal state in sync rather than to
talk to
something outside the app. Each time it gets re-argued from scratch on
the PR,
which is slow for the reviewer and unpleasant for the author, who
reasonably
asks why nobody said so earlier.

`docs/guidance/state-and-effects.md` is glob-loaded on `src/**/*.ts` and
`src/**/*.vue`, so it applies automatically rather than needing to be
found.

### What it says

One state value as a discriminated union instead of N booleans, named
events
rather than assignment scattered across call sites, a pure transition
function so
one place owns the rules, `computed` for anything derivable, and effects
reserved
for synchronising outward. Plus the Vue mapping — state to Pinia,
transition to a
pure function, derivation to `computed`, synchronisation to `watch`.

It deliberately does **not** recommend a state-machine library. There is
no
XState or `createMachine` precedent anywhere in `src/`, and a
hand-rolled union
with a pure `reduce` gets the same guarantees without the dependency.

### The lint rule

`no-restricted-syntax` flagging `getBoundingClientRect`,
`getComputedStyle` and
`querySelector*` inside a `computed`. A derivation that measures the DOM
runs a
layout read on every recompute and cannot be unit-tested without a
browser.

It ships at **`warn`, not `error`**, because there are exactly four
pre-existing
instances and this PR does not fix them:

| File | Count |
| ---- | ----- |
| `src/components/maskeditor/BrushCursor.vue` | 2 |
| `src/components/breadcrumb/SubgraphBreadcrumb.vue` | 1 |
| `src/components/topbar/WorkflowTabs.vue` | 1 |

Promote to `error` once those derive from stores instead. I verified the
count
against `main` at the current head rather than trusting the number I
first wrote.

### Scope

Docs and lint config only — no runtime code, no behaviour change.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
@pull pull Bot locked and limited conversation to collaborators Aug 18, 2026
@pull pull Bot added the ⤵️ pull label Aug 18, 2026
@pull
pull Bot merged commit e5da708 into Penguinjanator:main Aug 18, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants