You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
fix: offer guarded file preview when log tail access is denied - #720
A terminal text-file link outside the session's working directory opens the floating log viewer, whose tail endpoint refuses that path. EventSource then reconnects, repeats the permission error, and replaces the status with “connection error”. There is no useful next action.
Stop reconnecting after a definitive path denial, retain permission needed, and offer Allow this file once for an absolute-path Codex link. Only clicking that button opens the existing guarded file preview. Upstream already registers external paths quietly through _registerExternalPreview; this PR reuses that flow, without a new endpoint, directory grant or backend policy bypass. Strict attachment confinement, secret-path/extension guards and remote canonical-path checks remain enforced; the preview can still refuse access.
Includes Chromium coverage for explicit approval and YAML rendering, server denial with no raw read, non-Codex behavior, one SSE request across the reconnect interval, originating-session binding, special characters in the path, read-only display and no page errors. Registers the browser test in its existing suite. Also verified 69 related attachment/path-guard/stream tests and static checks.
Tracked in fork issue #23. The deploying fork uses its existing one-file URI resolver; this upstream patch instead uses upstream's existing preview method.
Thanks for this, johoja12, and for the careful Chromium coverage. This PR stops the floating log viewer from reconnecting over and over after a tail-file permission denial, and adds an "Allow this file once" button that opens the file preview in Codex sessions.
The reconnect loop is a real bug: I ran your test against master's panels-ui.js and it fails with two tail requests where your change makes one. A few things need to change before this can merge:
src/web/public/panels-ui.js:6017: the mode === 'codex' check makes npm test fail.test/frontend-cli-no-id-branching.test.ts scans panels-ui.js and rejects new CLI-id branches (CLAUDE.md: no code outside stock.ts may branch on a CLI id). The denial, the reconnect loop and openFilePreview all behave the same in every mode, so please remove the condition instead of adding an allowlist entry.
The button covers a case that master no longer reaches. Since 7d46a9d, terminal-ui.js:2349-2357 sends any path outside the session's workingDir (and any ~/ path) straight to openFilePreview, which registers it through _registerExternalPreview. It never opens the log viewer (docs/architecture-invariants.md:410).
I checked this in Chromium with your fixture path, in both codex and claude sessions: one attachment POST, no tail-file request, no log viewer.
On master the button would only appear for paths that look like they are inside the workspace but get refused: a symlinked workspace, a symlink pointing out, or /ws/../x. In those cases openFilePreview takes the workspace route, not the external flow.
The test reaches the blocked state only by calling app.openLogViewerWindow(externalPath) directly (test/log-viewer-file-approval.browser.test.ts:83).
Please drop the button from this PR and keep the reconnect fix. Whether the log viewer should offer a preview fallback at all is a separate design question, and it is still open.
src/web/public/panels-ui.js:6009: close on any error that arrives before connected, not on one string. The route ends the response after every createStream failure (file-routes.ts:2706-2709), so these five errors loop the same way:
File does not exist
File not found or not accessible
File too large
Maximum 5 concurrent streams per session
Failed to spawn tail process
Track whether connected has arrived and close the EventSource on any earlier error. That covers all six cases and removes the dependency on the exact wording in file-stream-manager.ts:414.
Test cleanup.
Remove the /tmp/codeman-23-*.png screenshots (lines 99 and 110).
Remove the unused remote: { hostId: 'fixture' } on line 79. Every request is stubbed, so no remote path runs.
With the button gone, the test can check that reconnecting stops for the permission message and for one other pre-connect error, such as File does not exist.
Related but out of scope here: file-stream-manager.tsvalidatePath realpaths the file but not workingDir, so in a symlinked workspace every in-workspace tail is refused with this same message. validateSessionFilePath in route-helpers.ts already handles that case. If you want to take that on, it belongs in its own PR.
Once the gate is green and the PR is down to the reconnect fix, it is ready for another review.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A terminal text-file link outside the session's working directory opens the floating log viewer, whose tail endpoint refuses that path. EventSource then reconnects, repeats the permission error, and replaces the status with “connection error”. There is no useful next action.
Stop reconnecting after a definitive path denial, retain permission needed, and offer Allow this file once for an absolute-path Codex link. Only clicking that button opens the existing guarded file preview. Upstream already registers external paths quietly through
_registerExternalPreview; this PR reuses that flow, without a new endpoint, directory grant or backend policy bypass. Strict attachment confinement, secret-path/extension guards and remote canonical-path checks remain enforced; the preview can still refuse access.Includes Chromium coverage for explicit approval and YAML rendering, server denial with no raw read, non-Codex behavior, one SSE request across the reconnect interval, originating-session binding, special characters in the path, read-only display and no page errors. Registers the browser test in its existing suite. Also verified 69 related attachment/path-guard/stream tests and static checks.
Tracked in fork issue #23. The deploying fork uses its existing one-file URI resolver; this upstream patch instead uses upstream's existing preview method.