A clicked path that points OUTSIDE the case directory goes through the attachment routes (the frontend's `_isExternalPreviewPath` sends every absolute path not under `workingDir` to `POST /attachments`), and those had the same local-`fs` assumption as file-raw: `realpathSync`/`fs.stat` on a path that only exists on the remote host, so the file never opened — the case the #415 report was actually about. - `registerExternalAttachment()` accepts `remote` and resolves through `remoteProbePaths` (canonical path, size/mtime, kind, plus the workspace root for the confinement check). Everything around it — blocklist, extension allowlist, workspace confinement, registry/dedupe — is now shared by both branches, so the remote path cannot drift from the local one. - The by-id routes (`raw`, `preview`, `thumbnail`), the metadata poll and the attachment history list resolve over ssh too. `raw` streams with the same Range contract as file-raw; `preview` (office) and `thumbnail` answer 400 for a remote record; an unreachable host answers 502, a vanished file 404. - Which host a record is read from follows the SESSION, never the path string: the same absolute path is a different file on each host, and a remote session never falls back to a local file with that name. - Codex generated artifacts keep force-workspace confinement for a remote case: the well-known artifact directories are anchored at THIS host's home, so only a file inside the remote workspace is trusted. Still local-only by design: writes, office conversion, thumbnails, the file tree/picker and tail-file.
2.1 KiB
aicodeman
| aicodeman |
|---|
| patch |
File previews, downloads and text reads now work in a remote (SSH) case.
A remote case's working directory is an absolute path on the remote host, but the
file routes resolved it with local fs — so a clicked path (or the File Viewer) always
failed as "File not found" even though the file existed and the session was clearly
working in that directory. GET /api/sessions/:id/file-raw, file-content,
file-preview and file-thumbnail now resolve and read through the same
buildSshConnectionArgs() connection the launch uses (src/remote-files.ts, one
realpath+stat probe per request returning both the file and the workspace root).
Clicked paths that point OUTSIDE the case directory (a remote /tmp scratchpad capture,
a screenshot elsewhere in the remote home) go through the attachment routes, which had
the same local-fs assumption: registration, the by-id raw stream, the metadata poll
and the attachment history list now resolve over ssh as well, so the click-path works
whether the file sits inside or outside the case. Which host a record is read from
follows the SESSION, never the path string — the same absolute path means a different
file on each host, and a remote session never falls back to a local file.
The guards are unchanged in strength: the workspace boundary is still enforced (now
resolved on the host that can actually resolve it), the sensitive-path blocklist and
the size cap (CODEMAN_MAX_DOWNLOAD_BYTES) still apply before any bytes are read, and
Range requests keep working, so remote <video>/<audio> seeking behaves like a
local file. An unreachable host is reported as 502 with the remote reason instead of
a misleading 404. Nothing is ever copied to the Codeman host.
Still not available for remote cases, and now said explicitly instead of 404-ing:
editing a file (edit=1 / PUT answer 400, the viewer hides its Edit affordance),
office-document previews and generated thumbnails (both need the bytes on the server's
disk), the file tree / path picker, and tail-file. Docker cases are unaffected (their
workspace is bind-mounted at the same absolute path).