Files
orca/config/scripts/vitest-node-runtime-files.mjs
T
Brennan Benson 81ed8c0feb feat(runtime-files): the host serves a chat's scratch folder as a file root (#28397)
* fix(files): never write through a dangling symlink

A path that doesn't exist yet was authorized by walking up to the nearest
existing folder. A dangling symlink fails realpath with ENOENT, so the walk
stepped over it and approved the link's own path; the write then followed
the link and created its target outside the allowed folders. The walk now
continues from the link's target, and returns that real destination.

* refactor(native-chat): rename the chat visuals folder to the chat scratch folder

The per-chat folder agents write into is the chat's scratch space, not only
a visuals folder. Its root becomes <state>/chat-scratch/<hash> (the hash is
unchanged) and the agent variable becomes ORCA_CHAT_SCRATCH_DIR. The old
ORCA_CHAT_VISUALS_DIR is never set and is still stripped from what every
agent child inherits, Pi included. The visuals skill names the new variable
and says the folder is temporary.

* test(native-chat): keep the delivery test to the rename

The launch parity snapshot already pins that every agent drops the
pre-rename variable.

* fix(files): refuse any dangling symlink in the missing-path walk

Following a dangling link by hand resolved relative targets against the
lexical parent, not the link's real folder: through a folder link the walk
could loop forever or authorize the wrong file. Refuse instead: realpath
can't say where a dangling link leads, but a write would follow it.

* feat(runtime-files): the host serves a chat's scratch folder as a file root

File commands accept `path:<this host's chat-scratch root>/<32 hex>` and
resolve it only when it names this host's own folder, at the file-commands
seam so the selector never reaches chat placement. They authorize against
the project roots plus the chat-scratch root, refuse files.open/openDiff
for the folder, and agentSession.readVisual's ok results carry the file's
absolute path so a client can build the selector.

* test(runtime-files): name the readVisual helper's parameter type

* test(files): drop the loop case that duplicated the dangling-link refusal

* test(runtime-files): run the readVisual RPC test, which opens a real SQLite store, under Node

* test(runtime-files): put the same-suffix folder inside the authorized root so only the selector refuses it

* test(runtime-files): wait for the stores to close before removing the state folder
2026-10-14 10:49:52 -07:00

119 lines
6.9 KiB
JavaScript

import { SQLITE_RUNTIME_INCLUDE } from './vitest-sqlite-runtime-files.mjs'
// SQLite publication, native bindings, worker IPC, socket liveness, and V8 retention use Node.
export const NODE_RUNTIME_INCLUDE = [
'config/scripts/vitest-sqlite-runtime-boundary.test.ts',
'config/scripts/cloud-security-history-workflow.test.mjs',
'config/scripts/skill-recipe-shell.test.mjs',
'src/main/ssh/ssh-relay-endpoint-incumbent-shell.integration.test.ts',
'src/main/ssh/ssh-remote-commands.test.ts',
'src/packages/process-host/src/run-process.test.ts',
'tests/e2e/cursor-quota-transport.unit.test.ts',
'tests/e2e/helpers/electron-process-shutdown.unit.test.ts',
'src/main/ai-vault-search/session-search-index-writer.test.ts',
'src/main/ai-vault/session-scanner-unlimited-dedup.test.ts',
// Disk checkpoints require Node's iterable writeFile semantics.
'src/main/ai-vault/session-parse-cache-checkpoint.test.ts',
'src/main/ai-vault/session-parse-cache-save-lane.test.ts',
'src/main/ai-vault/session-parse-cache-metadata-checkpoint.test.ts',
// Electron main bridges streams with Node's implementation.
'src/main/host/electron-http-client.test.ts',
'src/main/daemon/daemon-init-provider-installation.test.ts',
'src/renderer/src/components/terminal-pane/pty-input-write-queue.test.ts',
'src/renderer/src/lib/react-commit-cascade-observer.test.ts',
'src/renderer/src/lib/react-commit-cascade-telemetry.test.ts',
...SQLITE_RUNTIME_INCLUDE,
'src/cli/**/*.test.ts',
'src/main/persistence/**/*.test.ts',
'src/main/persistence*.test.ts',
'src/main/sqlite/**/*.test.ts',
'src/main/orca-profiles/**/*.test.ts',
'src/main/managed-data-accounts/**/*.test.ts',
'src/main/quit-path-durable-write-blocking.test.ts',
'src/main/automations/automation-worker-durability.test.ts',
'src/**/*.node-pty.test.ts',
'src/**/node-pty-*.test.ts',
'src/**/*.live-shell.test.ts',
'src/**/*real-pty*.test.ts',
'src/**/*-native.test.ts',
'src/**/*retention*.test.ts',
'src/**/*lifetime*.test.ts',
'src/**/*memory*.test.ts',
'src/**/*allocation*.test.ts',
'src/**/*expiry*.test.ts',
'src/renderer/src/lib/flatten-retained-slice.test.ts',
'src/shared/own-retained-string.test.ts',
// Times V8 string flattening, which is what Electron main runs.
'src/main/runtime/terminal-tail-redraw-wall-time.test.ts',
'src/main/agent-hooks/server-transport-interference.test.ts',
'src/main/plugins/plugin-worker-supervision.integration.test.ts',
'src/main/usage/usage-scan-worker-event-loop.test.ts',
// Asserts Node's spawn-failure close signal and that a dead worker closes its children's pipes.
'src/main/worker-thread-child-process/worker-thread-child-process.test.ts',
'src/main/computer/macos-native-provider-client.test.ts',
'src/main/ai-vault-search/session-search-schema.test.ts',
'src/main/ai-vault-search/session-search-fts5-contract.test.ts',
'src/main/foreign-sqlite-readers/**/*.test.ts',
'src/main/browser/*cookie*.test.ts',
// Playwright's CDP transport needs Node's WebSocket implementation.
'src/main/browser/browser-popup-compatibility.electron.test.ts',
'src/main/browser/browser-popup-native-compatibility.electron.test.ts',
'src/main/browser/browser-popup-background-compatibility.electron.test.ts',
'src/main/ai-vault/session-scanner-devin-db.test.ts',
'src/shared/workspace-session-salvage.test.ts',
'src/main/git/repo-detection.test.ts',
'src/renderer/src/components/browser-pane/annotate/browser-grab-toast-owner-cleanup.test.tsx',
'src/main/window/native-chat-paste-files.test.ts',
'src/main/computer/desktop-script-serve-channel.test.ts',
'src/main/providers/local-pty-child-process-verdict.test.ts',
'src/main/providers/working-directory-validation.test.ts',
'src/main/pty/posix-pty-process-groups.integration.test.ts',
'src/shared/ephemeral-vm-recipe-output-capture.test.ts',
'src/main/gitlab/gitlab-known-host-retirement.test.ts',
'src/main/window/main-window-updater-deferred-setup.test.ts',
'src/renderer/src/lib/pane-manager/pane-dom-focus-class-sync-lifecycle.test.ts',
'src/renderer/src/components/terminal-pane/terminal-pane-host-state-memo.test.ts',
'src/renderer/src/components/automations/use-automation-runs-dashboard-payload.test.tsx',
'src/renderer/src/components/right-sidebar/parent-pr-checks-projection-selector.test.ts',
'src/renderer/src/store/github/cache-persistence.test.ts',
'src/main/native-chat/agent-session-journal/**/*.test.ts',
'src/main/native-chat/agent-session-wire/structured-agent-session-status-feed.test.ts',
'src/main/native-chat/agent-session-wire/structured-agent-session-status-feed-conversation-name.test.ts',
'src/main/native-chat/agent-session-wire/structured-agent-session-status-first-input-identity.test.ts',
'src/main/native-chat/agent-session-wire/structured-agent-session-outgrown-child.test.ts',
'src/main/native-chat/agent-session-wire/structured-agent-session-permission-mode.test.ts',
'src/main/native-chat/structured-chat-naming-command-first.test.ts',
'src/main/native-chat/structured-chat-naming-status-hook.test.ts',
'src/main/runtime/agent-session-conversation-name-store.test.ts',
'src/main/runtime/structured-session-mail-redrive-wiring.test.ts',
'src/main/runtime/rpc/ws-transport.test.ts',
'src/main/runtime/rpc/dispatcher-transport-parity.test.ts',
'src/main/runtime/rpc/methods/structured-agent-session-visual.test.ts',
// Bun resolves 'ws' to its built-in client, which bypasses the patched package.
'src/main/runtime/rpc/ws-empty-payload-frame-write.test.ts',
'src/shared/remote-runtime-client.test.ts',
'src/shared/remote-runtime-connect-bound.test.ts',
// Bun's built-in ws client ignores maxPayload; the product opener only runs on Node.
'src/shared/remote-runtime-request-websocket.test.ts',
'src/shared/remote-runtime-subscription-connect-bound.test.ts',
'src/main/codex/codex-shared-server-probe.test.ts',
'src/main/opencode/opencode-launch-model-context-supervision.test.ts',
'src/main/hermes/hermes-config-remote-adapter.test.ts',
'src/renderer/src/lib/monaco-languages/monarch-upstream-mdx-recursion.test.ts',
'src/main/ipc/orca-profiles-switch-persistence.test.ts',
'src/main/ipc/settings-delayed-response.test.ts',
'src/main/runtime/structured-agent-session-startup-tab-restore.test.ts',
'src/main/runtime/structured-agent-session-windowless-layout-host.test.ts',
'src/shared/remote-runtime-shared-control-connection.test.ts',
'src/main/runtime/relay/relay-control-client.test.ts',
'src/main/ipc/filesystem-watcher-ignore-real.test.ts',
'src/main/ipc/runtime-environment-preference.test.ts',
'src/main/ipc/runtime-environment-transport-routing-tailscale-hint.test.ts',
'src/renderer/src/components/emulator-pane/emulator-device-frame-visibility.test.tsx',
'src/main/claude/claude-agent-sdk-contract-pins.test.ts',
'config/scripts/profile-state-worker-smoke.test.mjs',
'config/scripts/process-host-dev-rebuild.test.ts',
'config/scripts/vitest-node-runtime-boundary.test.ts',
'config/scripts/vitest-node-runtime-pool.test.ts'
]