Skip to content

fix(parsers,lint,producer,cli): confine composition path lookups to the project - #7534

Merged
michaelwang11394 merged 4 commits into
mainfrom
harden-r3-paths
Nov 11, 2026
Merged

michaelwang11394 merged 4 commits into
mainfrom
harden-r3-paths

Conversation

@michaelwang11394

@michaelwang11394 michaelwang11394 commented Nov 11, 2026 •

Copy link
Copy Markdown
Contributor

What changed

Composition path lookups outside the render now stay inside the project folder, the same way the render already does.

  • Asset resolver (packages/parsers/src/assetResolution.ts): offers only files inside the project. A path that is still absolute after its leading ../ is clamped (an encoded //, a drive letter, a leading backslash) yields no candidate. This covers the lint stylesheet and script collectors, the Studio media scan, publish proxy baking and cloud offload, which read or upload what the resolver returns.
  • Windows absolute paths that render copies in: a new localAbsoluteAssetFile finds the local file a drive-letter src (C:\media\clip.mp4) names, as render does. It never looks at another computer's share, and it does nothing on macOS or Linux, where a src that starts with / is a project URL. Lint uses it, so a drive-letter src raises no new missing_local_asset error, and neither does a mask-image in the page's own CSS. resolveAuthoredAssetFile uses it too, so media-treatment and normalize-audio still find such a file. It only checks that the file exists; nothing is read into lint output.
  • Sub-composition walkers: the render's resolveCompositionSrc moves unchanged into @hyperframes/parsers/asset-resolution. Lint and the catalog-usage walk now use it, and keyframes gains a containment check. Lint reports a data-composition-src outside the project as "outside the project folder", as the render pre-flight already does.
  • Render compile probes (htmlCompiler.ts): the media-duration probe, the gsap existence check and the keyframe/VFR advisory skip a path on another UNC or device root. A project stored on a share still reads its own share, so a gsap script there is still used.
  • GIF/HEIC image prep: a //host or /\host image src is treated as a URL, not a share. Backslash UNC sources are still copied, as render supports them.

Valid in-project references resolve exactly as before. A side-by-side run of the old and new resolver gives the same candidates for in-project relative paths, leading /, ../ that stays inside, encoded names and absolute paths inside the project, under both POSIX and Windows rules, including for a project on a UNC share. Lint now also stops reporting a false "file does not exist" for a leading-slash or percent-encoded data-composition-src.

Not changed on purpose

  • On Windows, the Studio media scan no longer looks at a drive-letter video outside the project; the preview cannot load such a src (the browser reads C: as a URL scheme). The published output does not change: publish copies such a file into _ext/ with its own resolver, which this PR does not touch, and proxy baking then scans the rewritten _ext/ path, so it never baked these files before or after.
  • Scripts outside the project: lint does not read them. When a root composition loads one, lint cannot tell whether it registers the timeline, so it does not report missing_timeline_registry for that composition. Render still loads the script.
  • A UNC media src on a share other than the project's is still reported by lint, as it was before, because lint does not look at other computers' shares.

Testing

  • New tests in assetResolution.test.ts, assetResolution.win32.test.ts, lint/src/project.test.ts (including the unread-script case), lint/src/project.windowsAbsolute.test.ts, htmlCompiler.networkRoot.test.ts, keyframes.test.ts and catalogUsage.test.ts; each fails without its fix.
  • Existing suites pass: parsers 1481, lint 1305, htmlCompiler.test.ts 177, CLI resolver callers 200, studio-server mediaCodecMap 50.
  • Typecheck, oxlint, fallow and the comment ratchet are clean.
  • Not run on real Windows; Windows paths are tested with path.win32.

🤖 Generated with Claude Code

…he project

- The local asset resolver offers only files inside the project: a path
  that is still absolute after its leading `../` is clamped (an encoded
  `//`, a drive letter, a leading backslash) yields no candidate.
- Lint, the catalog-usage walk and `keyframes` read a
  data-composition-src only inside the project. Lint and the catalog
  walk resolve it with the render's own resolver, now shared from
  `@hyperframes/parsers/asset-resolution`, and lint reports one outside
  the project as the render pre-flight does.
- The render compile step does not look at a media, gsap script or image
  path on another UNC or device root, and the GIF and HEIC preparation
  treats a `//host/...` image src as a URL rather than a share.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Nov 11, 2026 •

Copy link
Copy Markdown
Contributor

Edit accuracy: accurate 267 (base branch 267), smooth 108 of those

The gate passes.
Smoothness is reported in the artifact, not gated. A case fails only if it fails 2 of 3 runs.

Quarantined, measured but not gated (8)

Unstable (1)

  • seqplainkeys-none-px-r0-root-z100: tracking 0.06, pressJump 0, drop 0, reload 0, render 0.03, renderKey -, undo false, teleport true / tracking 0.06, pressJump 0, drop 0, reload 0, render 0.03, renderKey -, undo true, teleport true / tracking 0.06, pressJump 0, drop 0, reload 0, render 0.03, renderKey -, undo true, teleport true

michaelwang11394 and others added 3 commits November 10, 2026 19:13
…es in

The shared asset resolver now offers only files inside the project. On
Windows a drive-letter src such as C:\media\clip.mp4 used to reach the
real file through the old fallback, and render still copies that file in.
Lint now accepts such a file for media and for CSS written in the page,
so it raises no new missing_local_asset or texture_mask_asset_not_found
error. The media-treatment and normalize-audio commands find it again.

The check never looks at another computer's share, and on macOS and
Linux a src that starts with / is still a project URL, so nothing
changes there.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…d on Windows

On Windows an absolute src outside the project is a drive-letter path,
which resolveCompositionSrc refuses, as the render pre-flight already
does. On POSIX the same src is a project URL and resolves inside the
project. The test now expects each platform's result.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… the project may hold

Lint no longer reads a script outside the project. When a root
composition loads such a script, lint cannot know whether the script
registers the timeline, so it no longer reports missing_timeline_registry
for that composition. Render still loads the script. A composition whose
scripts are all in the project is checked as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@heygengenesis heygengenesis Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: APPROVE · 0 blocker · 0 important · 0 nits · head 6e0d58f

What I checked:

  • The resolveCompositionSrc move changes nothing. staysInsideProject matches the old producer isPathInside: a path equal to the project counts as inside, and a leading .. segment or a path absolute after relative() counts as outside.
  • localAbsoluteAssetFile stays a no-op on POSIX. isNonRelativeUrl rejects every leading /, so resolveAuthoredAssetFile can't hand a host file like /etc/... to media-treatment or normalize-audio. On Windows it reaches only local drive files, which matches what render copies in. namesAnotherNetworkRoot keeps UNC and device paths on other roots out of every new stat.
  • The resolver clamp is fixed. A re-anchored candidate that is still absolute (for example C:/… after the leading ../ are stripped) used to escape through resolve(). It is now dropped.

— Genesis V2

@michaelwang11394
michaelwang11394 added this pull request to the merge queue Nov 11, 2026
Merged via the queue into main with commit 5a88c99 Nov 11, 2026
138 of 139 checks passed
@michaelwang11394
michaelwang11394 deleted the harden-r3-paths branch November 11, 2026 04:32
@miguel-heygen miguel-heygen mentioned this pull request Nov 11, 2026
3 of 4 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant