mirror of
https://github.com/rennf93/roboco.git
synced 2026-08-03 07:23:24 +02:00
fix(github-app): PAT fallback covers every mint failure; video/motion/x cleanups
mint_installation_token now wraps JWT build + HTTP + parsing so raw httpx/jwt failures surface as GitHubAppError and the existing PAT fallback catches them all (a GitHub outage no longer crashes git operations for App-bound projects). The PEM is validated at credential-set time instead of first mint, and the installation-token cache is cleared when credentials are deleted. Also: the video preview root resolves symlinks like its sibling route (frames under a symlinked workspaces_root no longer false-404), the tracked dangling motion/node_modules symlink is removed and the gitignore gains a slash-less entry that actually matches symlinks, changelog caption input strips GHSA refs like PR refs, and the edit-project dialog hides the GitHub App section for auto-detected gitlab.com projects and warns before a save that would clear both auth sources.
This commit is contained in:
@@ -1456,18 +1456,33 @@ async def test_preview_frame_non_ceo_is_forbidden(db_session: AsyncSession) -> N
|
||||
app.dependency_overrides.clear()
|
||||
|
||||
|
||||
def test_resolve_preview_path_confines_frame_orientation_traversal(
|
||||
tmp_path: Path,
|
||||
def test_previews_root_confines_frame_orientation_traversal_through_symlink(
|
||||
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
|
||||
) -> None:
|
||||
"""The preview-frame route composes ``f"{orientation}/{filename}"`` before
|
||||
calling ``_resolve_preview_path`` — same confinement the composition-HTML
|
||||
proxy uses, applied to a task's .previews/ dir instead of its read-clone."""
|
||||
root = (tmp_path / "roboco-x" / ".previews" / "abcd1234").resolve()
|
||||
(root / "vertical").mkdir(parents=True)
|
||||
frame = root / "vertical" / "frame-01-of-1-at-0.5s.png"
|
||||
"""Drives the REAL ``_previews_root`` -> ``_resolve_preview_path`` chain
|
||||
(the preview-frame route composes ``f"{orientation}/{filename}"`` before
|
||||
calling ``_resolve_preview_path``) with an UNRESOLVED, symlinked
|
||||
``workspaces_root`` — the container-mount shape. Before ``_previews_root``
|
||||
resolved its own path, the ``is_relative_to`` confinement check compared a
|
||||
resolved candidate against an unresolved root and 404'd every legit
|
||||
frame; this proves a real frame under the symlink still serves while
|
||||
traversal is still rejected."""
|
||||
real_root = tmp_path / "real-workspaces"
|
||||
real_root.mkdir()
|
||||
symlinked_root = tmp_path / "workspaces-symlink"
|
||||
symlinked_root.symlink_to(real_root)
|
||||
monkeypatch.setattr(cfg, "workspaces_root", str(symlinked_root))
|
||||
|
||||
task_id = uuid4()
|
||||
project_slug = "roboco-x"
|
||||
frame_dir = real_root / project_slug / ".previews" / task_id.hex[:8] / "vertical"
|
||||
frame_dir.mkdir(parents=True)
|
||||
frame = frame_dir / "frame-01-of-1-at-0.5s.png"
|
||||
frame.write_bytes(b"png")
|
||||
secret = tmp_path / "secret.png"
|
||||
secret.write_bytes(b"nope")
|
||||
|
||||
root = video_module._previews_root(project_slug, task_id)
|
||||
assert (
|
||||
video_module._resolve_preview_path(root, "vertical/frame-01-of-1-at-0.5s.png")
|
||||
== frame.resolve()
|
||||
|
||||
Reference in New Issue
Block a user