parasor 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +208 -0
- package/THIRD-PARTY-NOTICES.md +138 -0
- package/bin/parasor.mjs +3 -0
- package/node_modules/@parasor/shared/dist/client.d.ts +8 -0
- package/node_modules/@parasor/shared/dist/client.d.ts.map +1 -0
- package/node_modules/@parasor/shared/dist/client.js +2 -0
- package/node_modules/@parasor/shared/dist/client.js.map +1 -0
- package/node_modules/@parasor/shared/dist/drops.d.ts +24 -0
- package/node_modules/@parasor/shared/dist/drops.d.ts.map +1 -0
- package/node_modules/@parasor/shared/dist/drops.js +2 -0
- package/node_modules/@parasor/shared/dist/drops.js.map +1 -0
- package/node_modules/@parasor/shared/dist/file-uploads.d.ts +56 -0
- package/node_modules/@parasor/shared/dist/file-uploads.d.ts.map +1 -0
- package/node_modules/@parasor/shared/dist/file-uploads.js +13 -0
- package/node_modules/@parasor/shared/dist/file-uploads.js.map +1 -0
- package/node_modules/@parasor/shared/dist/ide-commands.d.ts +8 -0
- package/node_modules/@parasor/shared/dist/ide-commands.d.ts.map +1 -0
- package/node_modules/@parasor/shared/dist/ide-commands.js +59 -0
- package/node_modules/@parasor/shared/dist/ide-commands.js.map +1 -0
- package/node_modules/@parasor/shared/dist/pane-commands.d.ts +7 -0
- package/node_modules/@parasor/shared/dist/pane-commands.d.ts.map +1 -0
- package/node_modules/@parasor/shared/dist/pane-commands.js +47 -0
- package/node_modules/@parasor/shared/dist/pane-commands.js.map +1 -0
- package/node_modules/@parasor/shared/dist/pane-model.d.ts +63 -0
- package/node_modules/@parasor/shared/dist/pane-model.d.ts.map +1 -0
- package/node_modules/@parasor/shared/dist/pane-model.js +89 -0
- package/node_modules/@parasor/shared/dist/pane-model.js.map +1 -0
- package/node_modules/@parasor/shared/dist/panes.d.ts +33 -0
- package/node_modules/@parasor/shared/dist/panes.d.ts.map +1 -0
- package/node_modules/@parasor/shared/dist/panes.js +2 -0
- package/node_modules/@parasor/shared/dist/panes.js.map +1 -0
- package/node_modules/@parasor/shared/dist/runtime.d.ts +180 -0
- package/node_modules/@parasor/shared/dist/runtime.d.ts.map +1 -0
- package/node_modules/@parasor/shared/dist/runtime.js +2 -0
- package/node_modules/@parasor/shared/dist/runtime.js.map +1 -0
- package/node_modules/@parasor/shared/dist/state.d.ts +192 -0
- package/node_modules/@parasor/shared/dist/state.d.ts.map +1 -0
- package/node_modules/@parasor/shared/dist/state.js +10 -0
- package/node_modules/@parasor/shared/dist/state.js.map +1 -0
- package/node_modules/@parasor/shared/dist/terminal.d.ts +191 -0
- package/node_modules/@parasor/shared/dist/terminal.d.ts.map +1 -0
- package/node_modules/@parasor/shared/dist/terminal.js +174 -0
- package/node_modules/@parasor/shared/dist/terminal.js.map +1 -0
- package/node_modules/@parasor/shared/dist/types.d.ts +13 -0
- package/node_modules/@parasor/shared/dist/types.d.ts.map +1 -0
- package/node_modules/@parasor/shared/dist/types.js +13 -0
- package/node_modules/@parasor/shared/dist/types.js.map +1 -0
- package/node_modules/@parasor/shared/dist/worktree-local-files.d.ts +14 -0
- package/node_modules/@parasor/shared/dist/worktree-local-files.d.ts.map +1 -0
- package/node_modules/@parasor/shared/dist/worktree-local-files.js +41 -0
- package/node_modules/@parasor/shared/dist/worktree-local-files.js.map +1 -0
- package/node_modules/@parasor/shared/dist/ws-events.d.ts +152 -0
- package/node_modules/@parasor/shared/dist/ws-events.d.ts.map +1 -0
- package/node_modules/@parasor/shared/dist/ws-events.js +2 -0
- package/node_modules/@parasor/shared/dist/ws-events.js.map +1 -0
- package/node_modules/@parasor/shared/package.json +13 -0
- package/package.json +61 -0
- package/server/agent-detector/agent-state-store.d.ts +23 -0
- package/server/agent-detector/agent-state-store.d.ts.map +1 -0
- package/server/agent-detector/agent-state-store.js +110 -0
- package/server/agent-detector/agent-state-store.js.map +1 -0
- package/server/agent-detector/detector.d.ts +80 -0
- package/server/agent-detector/detector.d.ts.map +1 -0
- package/server/agent-detector/detector.js +219 -0
- package/server/agent-detector/detector.js.map +1 -0
- package/server/agent-detector/event-map.d.ts +25 -0
- package/server/agent-detector/event-map.d.ts.map +1 -0
- package/server/agent-detector/event-map.js +136 -0
- package/server/agent-detector/event-map.js.map +1 -0
- package/server/agent-detector/manual-agent-tracker.d.ts +19 -0
- package/server/agent-detector/manual-agent-tracker.d.ts.map +1 -0
- package/server/agent-detector/manual-agent-tracker.js +123 -0
- package/server/agent-detector/manual-agent-tracker.js.map +1 -0
- package/server/agent-detector/output-eligibility.d.ts +3 -0
- package/server/agent-detector/output-eligibility.d.ts.map +1 -0
- package/server/agent-detector/output-eligibility.js +39 -0
- package/server/agent-detector/output-eligibility.js.map +1 -0
- package/server/application/files/errors.d.ts +28 -0
- package/server/application/files/errors.d.ts.map +1 -0
- package/server/application/files/errors.js +55 -0
- package/server/application/files/errors.js.map +1 -0
- package/server/application/files/local-filesystem.d.ts +36 -0
- package/server/application/files/local-filesystem.d.ts.map +1 -0
- package/server/application/files/local-filesystem.js +171 -0
- package/server/application/files/local-filesystem.js.map +1 -0
- package/server/application/files/project-file-queries.d.ts +16 -0
- package/server/application/files/project-file-queries.d.ts.map +1 -0
- package/server/application/files/project-file-queries.js +126 -0
- package/server/application/files/project-file-queries.js.map +1 -0
- package/server/application/integrations/errors.d.ts +16 -0
- package/server/application/integrations/errors.d.ts.map +1 -0
- package/server/application/integrations/errors.js +31 -0
- package/server/application/integrations/errors.js.map +1 -0
- package/server/application/integrations/hook-notify.d.ts +32 -0
- package/server/application/integrations/hook-notify.d.ts.map +1 -0
- package/server/application/integrations/hook-notify.js +118 -0
- package/server/application/integrations/hook-notify.js.map +1 -0
- package/server/application/integrations/open-url.d.ts +11 -0
- package/server/application/integrations/open-url.d.ts.map +1 -0
- package/server/application/integrations/open-url.js +23 -0
- package/server/application/integrations/open-url.js.map +1 -0
- package/server/application/ports.d.ts +11 -0
- package/server/application/ports.d.ts.map +1 -0
- package/server/application/ports.js +2 -0
- package/server/application/ports.js.map +1 -0
- package/server/application/workspace/errors.d.ts +21 -0
- package/server/application/workspace/errors.d.ts.map +1 -0
- package/server/application/workspace/errors.js +21 -0
- package/server/application/workspace/errors.js.map +1 -0
- package/server/application/workspace/pane-commands.d.ts +47 -0
- package/server/application/workspace/pane-commands.d.ts.map +1 -0
- package/server/application/workspace/pane-commands.js +193 -0
- package/server/application/workspace/pane-commands.js.map +1 -0
- package/server/application/workspace/project-commands.d.ts +34 -0
- package/server/application/workspace/project-commands.d.ts.map +1 -0
- package/server/application/workspace/project-commands.js +81 -0
- package/server/application/workspace/project-commands.js.map +1 -0
- package/server/application/workspace/project-queries.d.ts +21 -0
- package/server/application/workspace/project-queries.d.ts.map +1 -0
- package/server/application/workspace/project-queries.js +216 -0
- package/server/application/workspace/project-queries.js.map +1 -0
- package/server/application/workspace/session-commands.d.ts +24 -0
- package/server/application/workspace/session-commands.d.ts.map +1 -0
- package/server/application/workspace/session-commands.js +123 -0
- package/server/application/workspace/session-commands.js.map +1 -0
- package/server/application/workspace/session-queries.d.ts +14 -0
- package/server/application/workspace/session-queries.d.ts.map +1 -0
- package/server/application/workspace/session-queries.js +47 -0
- package/server/application/workspace/session-queries.js.map +1 -0
- package/server/application/workspace/worktree-commands.d.ts +98 -0
- package/server/application/workspace/worktree-commands.d.ts.map +1 -0
- package/server/application/workspace/worktree-commands.js +323 -0
- package/server/application/workspace/worktree-commands.js.map +1 -0
- package/server/application/workspace/worktree-local-files.d.ts +11 -0
- package/server/application/workspace/worktree-local-files.d.ts.map +1 -0
- package/server/application/workspace/worktree-local-files.js +223 -0
- package/server/application/workspace/worktree-local-files.js.map +1 -0
- package/server/application/workspace/worktree-reconcile.d.ts +21 -0
- package/server/application/workspace/worktree-reconcile.d.ts.map +1 -0
- package/server/application/workspace/worktree-reconcile.js +49 -0
- package/server/application/workspace/worktree-reconcile.js.map +1 -0
- package/server/auth/origin.d.ts +17 -0
- package/server/auth/origin.d.ts.map +1 -0
- package/server/auth/origin.js +93 -0
- package/server/auth/origin.js.map +1 -0
- package/server/auth/pairing-token.d.ts +28 -0
- package/server/auth/pairing-token.d.ts.map +1 -0
- package/server/auth/pairing-token.js +46 -0
- package/server/auth/pairing-token.js.map +1 -0
- package/server/auth/token-exchange.d.ts +11 -0
- package/server/auth/token-exchange.d.ts.map +1 -0
- package/server/auth/token-exchange.js +27 -0
- package/server/auth/token-exchange.js.map +1 -0
- package/server/auth/token.d.ts +18 -0
- package/server/auth/token.d.ts.map +1 -0
- package/server/auth/token.js +115 -0
- package/server/auth/token.js.map +1 -0
- package/server/bootstrap/create-app-server.d.ts +49 -0
- package/server/bootstrap/create-app-server.d.ts.map +1 -0
- package/server/bootstrap/create-app-server.js +154 -0
- package/server/bootstrap/create-app-server.js.map +1 -0
- package/server/bootstrap/project-runtime.d.ts +29 -0
- package/server/bootstrap/project-runtime.d.ts.map +1 -0
- package/server/bootstrap/project-runtime.js +253 -0
- package/server/bootstrap/project-runtime.js.map +1 -0
- package/server/bootstrap/pty-env.d.ts +3 -0
- package/server/bootstrap/pty-env.d.ts.map +1 -0
- package/server/bootstrap/pty-env.js +15 -0
- package/server/bootstrap/pty-env.js.map +1 -0
- package/server/bootstrap/reconcile-state.d.ts +16 -0
- package/server/bootstrap/reconcile-state.d.ts.map +1 -0
- package/server/bootstrap/reconcile-state.js +73 -0
- package/server/bootstrap/reconcile-state.js.map +1 -0
- package/server/bootstrap/runtime-loops.d.ts +51 -0
- package/server/bootstrap/runtime-loops.d.ts.map +1 -0
- package/server/bootstrap/runtime-loops.js +189 -0
- package/server/bootstrap/runtime-loops.js.map +1 -0
- package/server/bootstrap/runtime-port.d.ts +4 -0
- package/server/bootstrap/runtime-port.d.ts.map +1 -0
- package/server/bootstrap/runtime-port.js +52 -0
- package/server/bootstrap/runtime-port.js.map +1 -0
- package/server/bootstrap/safety-gate.d.ts +22 -0
- package/server/bootstrap/safety-gate.d.ts.map +1 -0
- package/server/bootstrap/safety-gate.js +43 -0
- package/server/bootstrap/safety-gate.js.map +1 -0
- package/server/bootstrap/shutdown-marker.d.ts +35 -0
- package/server/bootstrap/shutdown-marker.d.ts.map +1 -0
- package/server/bootstrap/shutdown-marker.js +100 -0
- package/server/bootstrap/shutdown-marker.js.map +1 -0
- package/server/bootstrap/shutdown-runtime.d.ts +62 -0
- package/server/bootstrap/shutdown-runtime.d.ts.map +1 -0
- package/server/bootstrap/shutdown-runtime.js +66 -0
- package/server/bootstrap/shutdown-runtime.js.map +1 -0
- package/server/bootstrap/startup-banner.d.ts +34 -0
- package/server/bootstrap/startup-banner.d.ts.map +1 -0
- package/server/bootstrap/startup-banner.js +114 -0
- package/server/bootstrap/startup-banner.js.map +1 -0
- package/server/bootstrap/wire-runtime.d.ts +42 -0
- package/server/bootstrap/wire-runtime.d.ts.map +1 -0
- package/server/bootstrap/wire-runtime.js +205 -0
- package/server/bootstrap/wire-runtime.js.map +1 -0
- package/server/cli/help.d.ts +3 -0
- package/server/cli/help.d.ts.map +1 -0
- package/server/cli/help.js +39 -0
- package/server/cli/help.js.map +1 -0
- package/server/cli/hook-client.d.ts +12 -0
- package/server/cli/hook-client.d.ts.map +1 -0
- package/server/cli/hook-client.js +81 -0
- package/server/cli/hook-client.js.map +1 -0
- package/server/cli/hook.d.ts +3 -0
- package/server/cli/hook.d.ts.map +1 -0
- package/server/cli/hook.js +152 -0
- package/server/cli/hook.js.map +1 -0
- package/server/cli/main.d.ts +2 -0
- package/server/cli/main.d.ts.map +1 -0
- package/server/cli/main.js +133 -0
- package/server/cli/main.js.map +1 -0
- package/server/cli/notify.d.ts +19 -0
- package/server/cli/notify.d.ts.map +1 -0
- package/server/cli/notify.js +77 -0
- package/server/cli/notify.js.map +1 -0
- package/server/cli/open.d.ts +2 -0
- package/server/cli/open.d.ts.map +1 -0
- package/server/cli/open.js +47 -0
- package/server/cli/open.js.map +1 -0
- package/server/cli/probe-daemon-version.d.ts +46 -0
- package/server/cli/probe-daemon-version.d.ts.map +1 -0
- package/server/cli/probe-daemon-version.js +167 -0
- package/server/cli/probe-daemon-version.js.map +1 -0
- package/server/cli/pty-host.d.ts +36 -0
- package/server/cli/pty-host.d.ts.map +1 -0
- package/server/cli/pty-host.js +390 -0
- package/server/cli/pty-host.js.map +1 -0
- package/server/cli/qr.d.ts +2 -0
- package/server/cli/qr.d.ts.map +1 -0
- package/server/cli/qr.js +70 -0
- package/server/cli/qr.js.map +1 -0
- package/server/cli/restart-confirm.d.ts +33 -0
- package/server/cli/restart-confirm.d.ts.map +1 -0
- package/server/cli/restart-confirm.js +107 -0
- package/server/cli/restart-confirm.js.map +1 -0
- package/server/cli/restart.d.ts +17 -0
- package/server/cli/restart.d.ts.map +1 -0
- package/server/cli/restart.js +145 -0
- package/server/cli/restart.js.map +1 -0
- package/server/cli/service-darwin.d.ts +70 -0
- package/server/cli/service-darwin.d.ts.map +1 -0
- package/server/cli/service-darwin.js +562 -0
- package/server/cli/service-darwin.js.map +1 -0
- package/server/cli/service-linux.d.ts +81 -0
- package/server/cli/service-linux.d.ts.map +1 -0
- package/server/cli/service-linux.js +412 -0
- package/server/cli/service-linux.js.map +1 -0
- package/server/cli/service.d.ts +33 -0
- package/server/cli/service.d.ts.map +1 -0
- package/server/cli/service.js +133 -0
- package/server/cli/service.js.map +1 -0
- package/server/cli/shim-installer.d.ts +35 -0
- package/server/cli/shim-installer.d.ts.map +1 -0
- package/server/cli/shim-installer.js +662 -0
- package/server/cli/shim-installer.js.map +1 -0
- package/server/cli/shim-open.d.ts +2 -0
- package/server/cli/shim-open.d.ts.map +1 -0
- package/server/cli/shim-open.js +128 -0
- package/server/cli/shim-open.js.map +1 -0
- package/server/cli/shutdown-deps.d.ts +41 -0
- package/server/cli/shutdown-deps.d.ts.map +1 -0
- package/server/cli/shutdown-deps.js +158 -0
- package/server/cli/shutdown-deps.js.map +1 -0
- package/server/cli/stop.d.ts +11 -0
- package/server/cli/stop.d.ts.map +1 -0
- package/server/cli/stop.js +123 -0
- package/server/cli/stop.js.map +1 -0
- package/server/cli/unknown-command.d.ts +8 -0
- package/server/cli/unknown-command.d.ts.map +1 -0
- package/server/cli/unknown-command.js +14 -0
- package/server/cli/unknown-command.js.map +1 -0
- package/server/debug/agent-status-recorder.d.ts +57 -0
- package/server/debug/agent-status-recorder.d.ts.map +1 -0
- package/server/debug/agent-status-recorder.js +209 -0
- package/server/debug/agent-status-recorder.js.map +1 -0
- package/server/debug/terminal-trace-recorder.d.ts +41 -0
- package/server/debug/terminal-trace-recorder.d.ts.map +1 -0
- package/server/debug/terminal-trace-recorder.js +112 -0
- package/server/debug/terminal-trace-recorder.js.map +1 -0
- package/server/fonts/catalog.d.ts +35 -0
- package/server/fonts/catalog.d.ts.map +1 -0
- package/server/fonts/catalog.js +76 -0
- package/server/fonts/catalog.js.map +1 -0
- package/server/fonts/installer.d.ts +45 -0
- package/server/fonts/installer.d.ts.map +1 -0
- package/server/fonts/installer.js +201 -0
- package/server/fonts/installer.js.map +1 -0
- package/server/fonts/routes.d.ts +4 -0
- package/server/fonts/routes.d.ts.map +1 -0
- package/server/fonts/routes.js +91 -0
- package/server/fonts/routes.js.map +1 -0
- package/server/fs/drops.d.ts +50 -0
- package/server/fs/drops.d.ts.map +1 -0
- package/server/fs/drops.js +137 -0
- package/server/fs/drops.js.map +1 -0
- package/server/fs/file-uploads.d.ts +57 -0
- package/server/fs/file-uploads.d.ts.map +1 -0
- package/server/fs/file-uploads.js +214 -0
- package/server/fs/file-uploads.js.map +1 -0
- package/server/fs/file-watcher.d.ts +22 -0
- package/server/fs/file-watcher.d.ts.map +1 -0
- package/server/fs/file-watcher.js +105 -0
- package/server/fs/file-watcher.js.map +1 -0
- package/server/fs/git-watcher.d.ts +76 -0
- package/server/fs/git-watcher.d.ts.map +1 -0
- package/server/fs/git-watcher.js +356 -0
- package/server/fs/git-watcher.js.map +1 -0
- package/server/fs/media.d.ts +35 -0
- package/server/fs/media.d.ts.map +1 -0
- package/server/fs/media.js +271 -0
- package/server/fs/media.js.map +1 -0
- package/server/fs/service.d.ts +97 -0
- package/server/fs/service.d.ts.map +1 -0
- package/server/fs/service.js +306 -0
- package/server/fs/service.js.map +1 -0
- package/server/fs/upload-staging.d.ts +76 -0
- package/server/fs/upload-staging.d.ts.map +1 -0
- package/server/fs/upload-staging.js +283 -0
- package/server/fs/upload-staging.js.map +1 -0
- package/server/fs/watcher-lifecycle.d.ts +24 -0
- package/server/fs/watcher-lifecycle.d.ts.map +1 -0
- package/server/fs/watcher-lifecycle.js +105 -0
- package/server/fs/watcher-lifecycle.js.map +1 -0
- package/server/index.d.ts +17 -0
- package/server/index.d.ts.map +1 -0
- package/server/index.js +510 -0
- package/server/index.js.map +1 -0
- package/server/ipc/socket-server.d.ts +28 -0
- package/server/ipc/socket-server.d.ts.map +1 -0
- package/server/ipc/socket-server.js +206 -0
- package/server/ipc/socket-server.js.map +1 -0
- package/server/lib/git-exec.d.ts +38 -0
- package/server/lib/git-exec.d.ts.map +1 -0
- package/server/lib/git-exec.js +96 -0
- package/server/lib/git-exec.js.map +1 -0
- package/server/lib/open-in-ide.d.ts +22 -0
- package/server/lib/open-in-ide.d.ts.map +1 -0
- package/server/lib/open-in-ide.js +90 -0
- package/server/lib/open-in-ide.js.map +1 -0
- package/server/lib/open-in-os.d.ts +20 -0
- package/server/lib/open-in-os.d.ts.map +1 -0
- package/server/lib/open-in-os.js +51 -0
- package/server/lib/open-in-os.js.map +1 -0
- package/server/lib/path.d.ts +2 -0
- package/server/lib/path.d.ts.map +1 -0
- package/server/lib/path.js +10 -0
- package/server/lib/path.js.map +1 -0
- package/server/lib/promise-mutex.d.ts +7 -0
- package/server/lib/promise-mutex.d.ts.map +1 -0
- package/server/lib/promise-mutex.js +26 -0
- package/server/lib/promise-mutex.js.map +1 -0
- package/server/lib/sd-notify.d.ts +8 -0
- package/server/lib/sd-notify.d.ts.map +1 -0
- package/server/lib/sd-notify.js +27 -0
- package/server/lib/sd-notify.js.map +1 -0
- package/server/net/local-machine.d.ts +7 -0
- package/server/net/local-machine.d.ts.map +1 -0
- package/server/net/local-machine.js +79 -0
- package/server/net/local-machine.js.map +1 -0
- package/server/net/reachable-host.d.ts +12 -0
- package/server/net/reachable-host.d.ts.map +1 -0
- package/server/net/reachable-host.js +25 -0
- package/server/net/reachable-host.js.map +1 -0
- package/server/network/endpoints.d.ts +14 -0
- package/server/network/endpoints.d.ts.map +1 -0
- package/server/network/endpoints.js +104 -0
- package/server/network/endpoints.js.map +1 -0
- package/server/network/qr.d.ts +16 -0
- package/server/network/qr.d.ts.map +1 -0
- package/server/network/qr.js +89 -0
- package/server/network/qr.js.map +1 -0
- package/server/port-forwarder/forwarder.d.ts +47 -0
- package/server/port-forwarder/forwarder.d.ts.map +1 -0
- package/server/port-forwarder/forwarder.js +159 -0
- package/server/port-forwarder/forwarder.js.map +1 -0
- package/server/port-scanner/scanner.d.ts +24 -0
- package/server/port-scanner/scanner.d.ts.map +1 -0
- package/server/port-scanner/scanner.js +193 -0
- package/server/port-scanner/scanner.js.map +1 -0
- package/server/pty/connection-lifecycle.d.ts +50 -0
- package/server/pty/connection-lifecycle.d.ts.map +1 -0
- package/server/pty/connection-lifecycle.js +113 -0
- package/server/pty/connection-lifecycle.js.map +1 -0
- package/server/pty/daemon-connect.d.ts +52 -0
- package/server/pty/daemon-connect.d.ts.map +1 -0
- package/server/pty/daemon-connect.js +62 -0
- package/server/pty/daemon-connect.js.map +1 -0
- package/server/pty/handshake-timeout-race.d.ts +22 -0
- package/server/pty/handshake-timeout-race.d.ts.map +1 -0
- package/server/pty/handshake-timeout-race.js +23 -0
- package/server/pty/handshake-timeout-race.js.map +1 -0
- package/server/pty/headless-replay-snapshot.d.ts +28 -0
- package/server/pty/headless-replay-snapshot.d.ts.map +1 -0
- package/server/pty/headless-replay-snapshot.js +285 -0
- package/server/pty/headless-replay-snapshot.js.map +1 -0
- package/server/pty/headless-terminal-state-cache.d.ts +31 -0
- package/server/pty/headless-terminal-state-cache.d.ts.map +1 -0
- package/server/pty/headless-terminal-state-cache.js +119 -0
- package/server/pty/headless-terminal-state-cache.js.map +1 -0
- package/server/pty/hello-ack-validator.d.ts +15 -0
- package/server/pty/hello-ack-validator.d.ts.map +1 -0
- package/server/pty/hello-ack-validator.js +30 -0
- package/server/pty/hello-ack-validator.js.map +1 -0
- package/server/pty/host-daemon/bootstrap.d.ts +100 -0
- package/server/pty/host-daemon/bootstrap.d.ts.map +1 -0
- package/server/pty/host-daemon/bootstrap.js +611 -0
- package/server/pty/host-daemon/bootstrap.js.map +1 -0
- package/server/pty/host-daemon/daemon.d.ts +111 -0
- package/server/pty/host-daemon/daemon.d.ts.map +1 -0
- package/server/pty/host-daemon/daemon.js +648 -0
- package/server/pty/host-daemon/daemon.js.map +1 -0
- package/server/pty/host-daemon/entry.d.ts +3 -0
- package/server/pty/host-daemon/entry.d.ts.map +1 -0
- package/server/pty/host-daemon/entry.js +72 -0
- package/server/pty/host-daemon/entry.js.map +1 -0
- package/server/pty/host-daemon/lockfile.d.ts +12 -0
- package/server/pty/host-daemon/lockfile.d.ts.map +1 -0
- package/server/pty/host-daemon/lockfile.js +120 -0
- package/server/pty/host-daemon/lockfile.js.map +1 -0
- package/server/pty/host-daemon/mode-marker.d.ts +77 -0
- package/server/pty/host-daemon/mode-marker.d.ts.map +1 -0
- package/server/pty/host-daemon/mode-marker.js +228 -0
- package/server/pty/host-daemon/mode-marker.js.map +1 -0
- package/server/pty/host-daemon/orphan-cleanup.d.ts +42 -0
- package/server/pty/host-daemon/orphan-cleanup.d.ts.map +1 -0
- package/server/pty/host-daemon/orphan-cleanup.js +84 -0
- package/server/pty/host-daemon/orphan-cleanup.js.map +1 -0
- package/server/pty/host-daemon/paths.d.ts +10 -0
- package/server/pty/host-daemon/paths.d.ts.map +1 -0
- package/server/pty/host-daemon/paths.js +56 -0
- package/server/pty/host-daemon/paths.js.map +1 -0
- package/server/pty/host-daemon/server-connection.d.ts +44 -0
- package/server/pty/host-daemon/server-connection.d.ts.map +1 -0
- package/server/pty/host-daemon/server-connection.js +100 -0
- package/server/pty/host-daemon/server-connection.js.map +1 -0
- package/server/pty/host-daemon/service-detection.d.ts +24 -0
- package/server/pty/host-daemon/service-detection.d.ts.map +1 -0
- package/server/pty/host-daemon/service-detection.js +16 -0
- package/server/pty/host-daemon/service-detection.js.map +1 -0
- package/server/pty/host-daemon/socket-ready.d.ts +22 -0
- package/server/pty/host-daemon/socket-ready.d.ts.map +1 -0
- package/server/pty/host-daemon/socket-ready.js +33 -0
- package/server/pty/host-daemon/socket-ready.js.map +1 -0
- package/server/pty/host-daemon/spawn-daemon.d.ts +45 -0
- package/server/pty/host-daemon/spawn-daemon.d.ts.map +1 -0
- package/server/pty/host-daemon/spawn-daemon.js +155 -0
- package/server/pty/host-daemon/spawn-daemon.js.map +1 -0
- package/server/pty/host-daemon/terminate-daemon.d.ts +16 -0
- package/server/pty/host-daemon/terminate-daemon.d.ts.map +1 -0
- package/server/pty/host-daemon/terminate-daemon.js +128 -0
- package/server/pty/host-daemon/terminate-daemon.js.map +1 -0
- package/server/pty/host-protocol/frames.d.ts +110 -0
- package/server/pty/host-protocol/frames.d.ts.map +1 -0
- package/server/pty/host-protocol/frames.js +255 -0
- package/server/pty/host-protocol/frames.js.map +1 -0
- package/server/pty/host-protocol/messages.d.ts +140 -0
- package/server/pty/host-protocol/messages.d.ts.map +1 -0
- package/server/pty/host-protocol/messages.js +117 -0
- package/server/pty/host-protocol/messages.js.map +1 -0
- package/server/pty/host.d.ts +273 -0
- package/server/pty/host.d.ts.map +1 -0
- package/server/pty/host.js +184 -0
- package/server/pty/host.js.map +1 -0
- package/server/pty/in-process-host.d.ts +224 -0
- package/server/pty/in-process-host.d.ts.map +1 -0
- package/server/pty/in-process-host.js +1183 -0
- package/server/pty/in-process-host.js.map +1 -0
- package/server/pty/osc7-lifecycle.d.ts +8 -0
- package/server/pty/osc7-lifecycle.d.ts.map +1 -0
- package/server/pty/osc7-lifecycle.js +22 -0
- package/server/pty/osc7-lifecycle.js.map +1 -0
- package/server/pty/osc7-parser.d.ts +23 -0
- package/server/pty/osc7-parser.d.ts.map +1 -0
- package/server/pty/osc7-parser.js +91 -0
- package/server/pty/osc7-parser.js.map +1 -0
- package/server/pty/remote-host.d.ts +188 -0
- package/server/pty/remote-host.d.ts.map +1 -0
- package/server/pty/remote-host.js +810 -0
- package/server/pty/remote-host.js.map +1 -0
- package/server/pty/request-correlator.d.ts +59 -0
- package/server/pty/request-correlator.d.ts.map +1 -0
- package/server/pty/request-correlator.js +75 -0
- package/server/pty/request-correlator.js.map +1 -0
- package/server/pty/scrollback-log.d.ts +130 -0
- package/server/pty/scrollback-log.d.ts.map +1 -0
- package/server/pty/scrollback-log.js +344 -0
- package/server/pty/scrollback-log.js.map +1 -0
- package/server/pty/scrollback-sanitize.d.ts +2 -0
- package/server/pty/scrollback-sanitize.d.ts.map +1 -0
- package/server/pty/scrollback-sanitize.js +54 -0
- package/server/pty/scrollback-sanitize.js.map +1 -0
- package/server/pty/session-mirror.d.ts +67 -0
- package/server/pty/session-mirror.d.ts.map +1 -0
- package/server/pty/session-mirror.js +112 -0
- package/server/pty/session-mirror.js.map +1 -0
- package/server/pty/session-policy.d.ts +85 -0
- package/server/pty/session-policy.d.ts.map +1 -0
- package/server/pty/session-policy.js +186 -0
- package/server/pty/session-policy.js.map +1 -0
- package/server/pty/version-mismatch-recovery.d.ts +71 -0
- package/server/pty/version-mismatch-recovery.d.ts.map +1 -0
- package/server/pty/version-mismatch-recovery.js +63 -0
- package/server/pty/version-mismatch-recovery.js.map +1 -0
- package/server/routes/debug-agent-status.d.ts +5 -0
- package/server/routes/debug-agent-status.d.ts.map +1 -0
- package/server/routes/debug-agent-status.js +22 -0
- package/server/routes/debug-agent-status.js.map +1 -0
- package/server/routes/debug-diagnostics.d.ts +8 -0
- package/server/routes/debug-diagnostics.d.ts.map +1 -0
- package/server/routes/debug-diagnostics.js +34 -0
- package/server/routes/debug-diagnostics.js.map +1 -0
- package/server/routes/debug-terminal-trace.d.ts +16 -0
- package/server/routes/debug-terminal-trace.d.ts.map +1 -0
- package/server/routes/debug-terminal-trace.js +545 -0
- package/server/routes/debug-terminal-trace.js.map +1 -0
- package/server/routes/drops.d.ts +13 -0
- package/server/routes/drops.d.ts.map +1 -0
- package/server/routes/drops.js +126 -0
- package/server/routes/drops.js.map +1 -0
- package/server/routes/file-uploads.d.ts +9 -0
- package/server/routes/file-uploads.d.ts.map +1 -0
- package/server/routes/file-uploads.js +119 -0
- package/server/routes/file-uploads.js.map +1 -0
- package/server/routes/files.d.ts +9 -0
- package/server/routes/files.d.ts.map +1 -0
- package/server/routes/files.js +441 -0
- package/server/routes/files.js.map +1 -0
- package/server/routes/filesystem.d.ts +6 -0
- package/server/routes/filesystem.d.ts.map +1 -0
- package/server/routes/filesystem.js +76 -0
- package/server/routes/filesystem.js.map +1 -0
- package/server/routes/git.d.ts +38 -0
- package/server/routes/git.d.ts.map +1 -0
- package/server/routes/git.js +585 -0
- package/server/routes/git.js.map +1 -0
- package/server/routes/healthz.d.ts +8 -0
- package/server/routes/healthz.d.ts.map +1 -0
- package/server/routes/healthz.js +24 -0
- package/server/routes/healthz.js.map +1 -0
- package/server/routes/hook.d.ts +14 -0
- package/server/routes/hook.d.ts.map +1 -0
- package/server/routes/hook.js +86 -0
- package/server/routes/hook.js.map +1 -0
- package/server/routes/ide-commands.d.ts +9 -0
- package/server/routes/ide-commands.d.ts.map +1 -0
- package/server/routes/ide-commands.js +23 -0
- package/server/routes/ide-commands.js.map +1 -0
- package/server/routes/lib/resolve-worktree.d.ts +30 -0
- package/server/routes/lib/resolve-worktree.d.ts.map +1 -0
- package/server/routes/lib/resolve-worktree.js +35 -0
- package/server/routes/lib/resolve-worktree.js.map +1 -0
- package/server/routes/open.d.ts +4 -0
- package/server/routes/open.d.ts.map +1 -0
- package/server/routes/open.js +21 -0
- package/server/routes/open.js.map +1 -0
- package/server/routes/pane-commands.d.ts +9 -0
- package/server/routes/pane-commands.d.ts.map +1 -0
- package/server/routes/pane-commands.js +23 -0
- package/server/routes/pane-commands.js.map +1 -0
- package/server/routes/projects.d.ts +15 -0
- package/server/routes/projects.d.ts.map +1 -0
- package/server/routes/projects.js +363 -0
- package/server/routes/projects.js.map +1 -0
- package/server/routes/server-notices.d.ts +4 -0
- package/server/routes/server-notices.d.ts.map +1 -0
- package/server/routes/server-notices.js +29 -0
- package/server/routes/server-notices.js.map +1 -0
- package/server/routes/service-config.d.ts +11 -0
- package/server/routes/service-config.d.ts.map +1 -0
- package/server/routes/service-config.js +64 -0
- package/server/routes/service-config.js.map +1 -0
- package/server/routes/sessions.d.ts +7 -0
- package/server/routes/sessions.d.ts.map +1 -0
- package/server/routes/sessions.js +218 -0
- package/server/routes/sessions.js.map +1 -0
- package/server/service/caffeinate.d.ts +33 -0
- package/server/service/caffeinate.d.ts.map +1 -0
- package/server/service/caffeinate.js +72 -0
- package/server/service/caffeinate.js.map +1 -0
- package/server/state/app-state.d.ts +167 -0
- package/server/state/app-state.d.ts.map +1 -0
- package/server/state/app-state.js +335 -0
- package/server/state/app-state.js.map +1 -0
- package/server/state/project-manager.d.ts +30 -0
- package/server/state/project-manager.d.ts.map +1 -0
- package/server/state/project-manager.js +128 -0
- package/server/state/project-manager.js.map +1 -0
- package/server/state/server-notices.d.ts +12 -0
- package/server/state/server-notices.d.ts.map +1 -0
- package/server/state/server-notices.js +32 -0
- package/server/state/server-notices.js.map +1 -0
- package/server/state/worktree-cache.d.ts +25 -0
- package/server/state/worktree-cache.d.ts.map +1 -0
- package/server/state/worktree-cache.js +53 -0
- package/server/state/worktree-cache.js.map +1 -0
- package/server/ws/events.d.ts +45 -0
- package/server/ws/events.d.ts.map +1 -0
- package/server/ws/events.js +134 -0
- package/server/ws/events.js.map +1 -0
- package/server/ws/keepalive.d.ts +27 -0
- package/server/ws/keepalive.d.ts.map +1 -0
- package/server/ws/keepalive.js +63 -0
- package/server/ws/keepalive.js.map +1 -0
- package/server/ws/terminal-attach.d.ts +13 -0
- package/server/ws/terminal-attach.d.ts.map +1 -0
- package/server/ws/terminal-attach.js +233 -0
- package/server/ws/terminal-attach.js.map +1 -0
- package/server/ws/terminal-flow.d.ts +17 -0
- package/server/ws/terminal-flow.d.ts.map +1 -0
- package/server/ws/terminal-flow.js +64 -0
- package/server/ws/terminal-flow.js.map +1 -0
- package/server/ws/terminal.d.ts +69 -0
- package/server/ws/terminal.d.ts.map +1 -0
- package/server/ws/terminal.js +311 -0
- package/server/ws/terminal.js.map +1 -0
- package/web/assets/EditorPane-CzzT3iYY.js +123 -0
- package/web/assets/SymbolsNerdFontMono-Regular-CwEZqMeU.woff2 +0 -0
- package/web/assets/TerminalPane-CjbYzePr.js +68 -0
- package/web/assets/TerminalPane-DkTCHfhq.css +1 -0
- package/web/assets/file-icons-JBi09j0r.js +6 -0
- package/web/assets/index-CTTkRpnn.css +2 -0
- package/web/assets/index-CmhewzMp.js +34 -0
- package/web/assets/session-resume-7f-tB-ZU.js +2 -0
- package/web/assets/terminal-trace-PuuFRybC.js +2803 -0
- package/web/assets/useVirtualKeyboard-DgJb9u9d.js +1 -0
- package/web/index.html +52 -0
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
import { Buffer } from "node:buffer";
|
|
2
|
+
import { existsSync, constants as fsConstants, readFileSync, realpathSync, } from "node:fs";
|
|
3
|
+
import { cp as fsCp, mkdir as fsMkdir, open as fsOpen, readFile as fsReadFile, realpath as fsRealpath, writeFile as fsWriteFile, readdir, stat, } from "node:fs/promises";
|
|
4
|
+
import { join, relative, resolve, sep } from "node:path";
|
|
5
|
+
import ignore from "ignore";
|
|
6
|
+
const HARD_EXCLUDES = new Set([".git", ".DS_Store", "Thumbs.db"]);
|
|
7
|
+
const BUILTIN_IGNORES = [
|
|
8
|
+
"node_modules",
|
|
9
|
+
"dist",
|
|
10
|
+
"build",
|
|
11
|
+
".next",
|
|
12
|
+
".nuxt",
|
|
13
|
+
".venv",
|
|
14
|
+
"venv",
|
|
15
|
+
"__pycache__",
|
|
16
|
+
".pytest_cache",
|
|
17
|
+
"target",
|
|
18
|
+
".turbo",
|
|
19
|
+
];
|
|
20
|
+
const MAX_FILE_SIZE = 1024 * 1024; // 1 MB
|
|
21
|
+
export class PathTraversalError extends Error {
|
|
22
|
+
constructor() {
|
|
23
|
+
super("Path traversal denied");
|
|
24
|
+
this.name = "PathTraversalError";
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
export class CopySourceNotFoundError extends Error {
|
|
28
|
+
constructor() {
|
|
29
|
+
super("Copy source not found");
|
|
30
|
+
this.name = "CopySourceNotFoundError";
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
export class CopyDestinationExistsError extends Error {
|
|
34
|
+
constructor() {
|
|
35
|
+
super("Copy destination already exists");
|
|
36
|
+
this.name = "CopyDestinationExistsError";
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
export class FilesystemService {
|
|
40
|
+
projectRoot;
|
|
41
|
+
ignoreInstance;
|
|
42
|
+
constructor(projectRoot) {
|
|
43
|
+
const resolved = resolve(projectRoot);
|
|
44
|
+
try {
|
|
45
|
+
this.projectRoot = realpathSync(resolved);
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
this.projectRoot = resolved;
|
|
49
|
+
}
|
|
50
|
+
this.ignoreInstance = this.loadIgnore();
|
|
51
|
+
}
|
|
52
|
+
async listDir(relPath) {
|
|
53
|
+
const absPath = this.resolve(relPath);
|
|
54
|
+
const ig = this.ignoreInstance;
|
|
55
|
+
const entries = [];
|
|
56
|
+
const dirEntries = await readdir(absPath, { withFileTypes: true });
|
|
57
|
+
for (const dirent of dirEntries) {
|
|
58
|
+
if (HARD_EXCLUDES.has(dirent.name))
|
|
59
|
+
continue;
|
|
60
|
+
const entryRelPath = relative(this.projectRoot, join(absPath, dirent.name));
|
|
61
|
+
const isDir = dirent.isDirectory();
|
|
62
|
+
const isGitignored = this.isIgnoredWith(ig, entryRelPath, isDir);
|
|
63
|
+
const isHidden = dirent.name.startsWith(".");
|
|
64
|
+
entries.push({
|
|
65
|
+
name: dirent.name,
|
|
66
|
+
path: entryRelPath,
|
|
67
|
+
type: isDir ? "directory" : "file",
|
|
68
|
+
...(isGitignored && { isGitignored: true }),
|
|
69
|
+
...(isHidden && { isHidden: true }),
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
entries.sort((a, b) => {
|
|
73
|
+
if (a.type !== b.type)
|
|
74
|
+
return a.type === "directory" ? -1 : 1;
|
|
75
|
+
return a.name.localeCompare(b.name);
|
|
76
|
+
});
|
|
77
|
+
return entries;
|
|
78
|
+
}
|
|
79
|
+
async readFile(relPath, maxBytes) {
|
|
80
|
+
const absPath = this.resolve(relPath);
|
|
81
|
+
const limit = maxBytes ?? MAX_FILE_SIZE;
|
|
82
|
+
try {
|
|
83
|
+
const stats = await stat(absPath);
|
|
84
|
+
if (stats.size > limit) {
|
|
85
|
+
throw new Error("File too large");
|
|
86
|
+
}
|
|
87
|
+
const content = await fsReadFile(absPath, "utf-8");
|
|
88
|
+
return content;
|
|
89
|
+
}
|
|
90
|
+
catch (err) {
|
|
91
|
+
if (err instanceof Error && err.message === "File too large")
|
|
92
|
+
throw err;
|
|
93
|
+
if (isNodeError(err) && err.code === "ENOENT")
|
|
94
|
+
return null;
|
|
95
|
+
throw err;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Stat a single file, returning `null` when missing. Wraps node `stat()`
|
|
100
|
+
* to surface `PathTraversalError` consistently and never leak ENOENT
|
|
101
|
+
* details to the route layer.
|
|
102
|
+
*/
|
|
103
|
+
async statFile(relPath) {
|
|
104
|
+
const absPath = this.resolve(relPath);
|
|
105
|
+
try {
|
|
106
|
+
return await stat(absPath);
|
|
107
|
+
}
|
|
108
|
+
catch (err) {
|
|
109
|
+
if (isNodeError(err) && err.code === "ENOENT")
|
|
110
|
+
return null;
|
|
111
|
+
throw err;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Open a regular file inside the project root for inline media serving.
|
|
116
|
+
* The leaf is opened with `O_NOFOLLOW` so a symlink swapped in between
|
|
117
|
+
* the parent-directory resolve and this open cannot redirect to a target
|
|
118
|
+
* outside the project tree. The returned `FileHandle` is the single
|
|
119
|
+
* authoritative reference: callers do `fstat`, magic-number sniff via
|
|
120
|
+
* `read`, and stream creation through the same handle so size limits and
|
|
121
|
+
* content-type detection apply to the exact bytes about to be served.
|
|
122
|
+
* The caller MUST `close()` the handle (or pass it to `createReadStream`
|
|
123
|
+
* with `autoClose: true`).
|
|
124
|
+
*
|
|
125
|
+
* `O_NONBLOCK` keeps `open()` from blocking when the path happens to be a
|
|
126
|
+
* FIFO/socket/character device (a `*.mp4` FIFO in a cloned repo would
|
|
127
|
+
* otherwise pin a libuv worker until a writer connects); the post-open
|
|
128
|
+
* `isFile()` check then rejects everything that isn't a regular file.
|
|
129
|
+
*
|
|
130
|
+
* `O_NOFOLLOW` only protects the leaf -- an attacker with FS write access
|
|
131
|
+
* can still swap a parent directory to a symlink between `resolve()`'s
|
|
132
|
+
* realpath check and this `open()`. We close that gap by re-resolving the
|
|
133
|
+
* path *after* open and comparing the canonical result's inode to the
|
|
134
|
+
* fd's inode. A mid-open swap leaves the fd bound to a file outside the
|
|
135
|
+
* project tree while the second realpath resolves to the legitimate
|
|
136
|
+
* (or missing) in-tree entry, so the inodes diverge and we reject.
|
|
137
|
+
*
|
|
138
|
+
* Returns `null` for ENOENT so missing files surface as 404 rather than
|
|
139
|
+
* leaking the absolute path. ELOOP (the leaf was a symlink) raises a
|
|
140
|
+
* `PathTraversalError` because following symlinks at the leaf is exactly
|
|
141
|
+
* what we are refusing.
|
|
142
|
+
*/
|
|
143
|
+
async openInlineFile(relPath) {
|
|
144
|
+
const absPath = this.resolve(relPath);
|
|
145
|
+
const NONBLOCK = fsConstants.O_NONBLOCK ?? 0;
|
|
146
|
+
let handle;
|
|
147
|
+
try {
|
|
148
|
+
handle = await fsOpen(absPath, fsConstants.O_RDONLY | fsConstants.O_NOFOLLOW | NONBLOCK);
|
|
149
|
+
}
|
|
150
|
+
catch (err) {
|
|
151
|
+
if (isNodeError(err) && err.code === "ENOENT")
|
|
152
|
+
return null;
|
|
153
|
+
if (isNodeError(err) && err.code === "ELOOP") {
|
|
154
|
+
throw new PathTraversalError();
|
|
155
|
+
}
|
|
156
|
+
throw err;
|
|
157
|
+
}
|
|
158
|
+
try {
|
|
159
|
+
const stats = await handle.stat();
|
|
160
|
+
if (!stats.isFile()) {
|
|
161
|
+
await handle.close();
|
|
162
|
+
return null;
|
|
163
|
+
}
|
|
164
|
+
let real;
|
|
165
|
+
try {
|
|
166
|
+
real = await fsRealpath(absPath);
|
|
167
|
+
}
|
|
168
|
+
catch (err) {
|
|
169
|
+
if (isNodeError(err) && err.code === "ENOENT") {
|
|
170
|
+
await handle.close();
|
|
171
|
+
return null;
|
|
172
|
+
}
|
|
173
|
+
throw err;
|
|
174
|
+
}
|
|
175
|
+
if (real !== this.projectRoot &&
|
|
176
|
+
!real.startsWith(this.projectRoot + sep)) {
|
|
177
|
+
await handle.close();
|
|
178
|
+
throw new PathTraversalError();
|
|
179
|
+
}
|
|
180
|
+
const pathStats = await stat(real);
|
|
181
|
+
if (pathStats.ino !== stats.ino || pathStats.dev !== stats.dev) {
|
|
182
|
+
await handle.close();
|
|
183
|
+
throw new PathTraversalError();
|
|
184
|
+
}
|
|
185
|
+
return { handle, stats };
|
|
186
|
+
}
|
|
187
|
+
catch (err) {
|
|
188
|
+
await handle.close().catch(() => { });
|
|
189
|
+
throw err;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Build a read stream from an already-open `FileHandle`, optionally clamped
|
|
194
|
+
* to a byte range. Uses `FileHandle.createReadStream` with `autoClose: true`
|
|
195
|
+
* so stream ownership of the handle is explicit -- closing the stream
|
|
196
|
+
* releases the underlying fd through the FileHandle, avoiding the
|
|
197
|
+
* double-close hazard of passing the raw `handle.fd` to `createReadStream`
|
|
198
|
+
* (where the FileHandle's own GC finalizer could close an fd the stream
|
|
199
|
+
* already returned to the OS). Pairs with `openInlineFile` -- callers must
|
|
200
|
+
* not reuse the handle after this call returns.
|
|
201
|
+
*/
|
|
202
|
+
createStreamFromHandle(handle, size, range) {
|
|
203
|
+
let start = 0;
|
|
204
|
+
let end = size === 0 ? 0 : size - 1;
|
|
205
|
+
if (range) {
|
|
206
|
+
start = range.start;
|
|
207
|
+
end = range.end;
|
|
208
|
+
}
|
|
209
|
+
const stream = size === 0
|
|
210
|
+
? handle.createReadStream({ autoClose: true })
|
|
211
|
+
: handle.createReadStream({ autoClose: true, start, end });
|
|
212
|
+
return { stream, start, end };
|
|
213
|
+
}
|
|
214
|
+
async writeFile(relPath, content) {
|
|
215
|
+
const byteLength = Buffer.byteLength(content, "utf-8");
|
|
216
|
+
if (byteLength > MAX_FILE_SIZE) {
|
|
217
|
+
throw new Error("File too large");
|
|
218
|
+
}
|
|
219
|
+
const absPath = this.resolve(relPath);
|
|
220
|
+
await fsWriteFile(absPath, content, "utf-8");
|
|
221
|
+
}
|
|
222
|
+
async mkdir(relPath) {
|
|
223
|
+
const absPath = this.resolve(relPath);
|
|
224
|
+
await fsMkdir(absPath, { recursive: true });
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Recursive copy of a file or directory inside the project root. Both
|
|
228
|
+
* sides are routed through `resolve()` so symlink-escape and `..` traversal
|
|
229
|
+
* remain blocked. Refuses to overwrite an existing destination -- callers
|
|
230
|
+
* pick a unique name (Finder-style "<n> copy", "<n> copy 2") before invoking.
|
|
231
|
+
*/
|
|
232
|
+
async cp(srcRelPath, destRelPath) {
|
|
233
|
+
const srcAbs = this.resolve(srcRelPath);
|
|
234
|
+
const destAbs = this.resolve(destRelPath);
|
|
235
|
+
try {
|
|
236
|
+
await stat(srcAbs);
|
|
237
|
+
}
|
|
238
|
+
catch (err) {
|
|
239
|
+
if (isNodeError(err) && err.code === "ENOENT") {
|
|
240
|
+
throw new CopySourceNotFoundError();
|
|
241
|
+
}
|
|
242
|
+
throw err;
|
|
243
|
+
}
|
|
244
|
+
if (existsSync(destAbs)) {
|
|
245
|
+
throw new CopyDestinationExistsError();
|
|
246
|
+
}
|
|
247
|
+
await fsCp(srcAbs, destAbs, {
|
|
248
|
+
recursive: true,
|
|
249
|
+
errorOnExist: true,
|
|
250
|
+
force: false,
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
reloadIgnore() {
|
|
254
|
+
this.ignoreInstance = this.loadIgnore();
|
|
255
|
+
}
|
|
256
|
+
isIgnored(relPath, isDir) {
|
|
257
|
+
if (!relPath || relPath === "." || relPath === "")
|
|
258
|
+
return false;
|
|
259
|
+
return this.isIgnoredWith(this.ignoreInstance, relPath, isDir);
|
|
260
|
+
}
|
|
261
|
+
resolve(relPath) {
|
|
262
|
+
// Normalize resolved path against canonical projectRoot
|
|
263
|
+
const resolved = resolve(this.projectRoot, relPath);
|
|
264
|
+
if (resolved !== this.projectRoot &&
|
|
265
|
+
!resolved.startsWith(this.projectRoot + sep)) {
|
|
266
|
+
throw new PathTraversalError();
|
|
267
|
+
}
|
|
268
|
+
// Symlink check: resolve real path if it exists
|
|
269
|
+
try {
|
|
270
|
+
const real = realpathSync(resolved);
|
|
271
|
+
if (real !== this.projectRoot &&
|
|
272
|
+
!real.startsWith(this.projectRoot + sep)) {
|
|
273
|
+
throw new PathTraversalError();
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
catch (err) {
|
|
277
|
+
if (err instanceof PathTraversalError)
|
|
278
|
+
throw err;
|
|
279
|
+
// ENOENT or other -- path doesn't exist yet, allow (ENOENT handled in callers)
|
|
280
|
+
}
|
|
281
|
+
return resolved;
|
|
282
|
+
}
|
|
283
|
+
loadIgnore() {
|
|
284
|
+
const ig = ignore();
|
|
285
|
+
ig.add(BUILTIN_IGNORES);
|
|
286
|
+
const gitignorePath = join(this.projectRoot, ".gitignore");
|
|
287
|
+
if (existsSync(gitignorePath)) {
|
|
288
|
+
try {
|
|
289
|
+
const content = readFileSync(gitignorePath, "utf-8");
|
|
290
|
+
ig.add(content);
|
|
291
|
+
}
|
|
292
|
+
catch {
|
|
293
|
+
// ignore read failures
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
return ig;
|
|
297
|
+
}
|
|
298
|
+
isIgnoredWith(ig, relPath, isDir) {
|
|
299
|
+
const testPath = isDir ? `${relPath}/` : relPath;
|
|
300
|
+
return ig.ignores(testPath);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
function isNodeError(err) {
|
|
304
|
+
return err instanceof Error && "code" in err;
|
|
305
|
+
}
|
|
306
|
+
//# sourceMappingURL=service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.js","sourceRoot":"","sources":["../../src/fs/service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validation failure for a sessionId that does not match the strict
|
|
3
|
+
* format. Carries the raw value as a property so log sinks can decide
|
|
4
|
+
* whether to record it; the human-readable `message` stays a fixed
|
|
5
|
+
* literal so journald / file logs cannot be ANSI/newline-injected by an
|
|
6
|
+
* attacker who controls the query string (reviewed for correctness).
|
|
7
|
+
*/
|
|
8
|
+
export declare class InvalidSessionIdError extends Error {
|
|
9
|
+
readonly reason: "empty" | "format";
|
|
10
|
+
/** Raw value as received. Not embedded in `message`. */
|
|
11
|
+
readonly value: string;
|
|
12
|
+
constructor(reason: "empty" | "format", value: string);
|
|
13
|
+
}
|
|
14
|
+
export interface UploadStagingOptions {
|
|
15
|
+
/**
|
|
16
|
+
* Base directory. Resolved through `realpath()` once at construction
|
|
17
|
+
* (macOS `/tmp` -> `/private/tmp`) so every later `startsWith(rootDir)`
|
|
18
|
+
* fence compares canonical paths. Defaults to `${tmpdir()}/parasor`.
|
|
19
|
+
*/
|
|
20
|
+
rootDir?: string;
|
|
21
|
+
/**
|
|
22
|
+
* Entries older than this in `sweepStale()` are removed. Default 24h.
|
|
23
|
+
*/
|
|
24
|
+
ttlMs?: number;
|
|
25
|
+
/**
|
|
26
|
+
* Test injection point. Defaults to `Date.now`.
|
|
27
|
+
*/
|
|
28
|
+
clock?: () => number;
|
|
29
|
+
}
|
|
30
|
+
export declare class UploadStaging {
|
|
31
|
+
/** Canonical absolute path of `<rootDir>/uploads`. */
|
|
32
|
+
readonly uploadsDir: string;
|
|
33
|
+
private readonly ttlMs;
|
|
34
|
+
private readonly clock;
|
|
35
|
+
constructor(options?: UploadStagingOptions);
|
|
36
|
+
/**
|
|
37
|
+
* Acquire (or re-use) a session-scoped upload directory. The directory
|
|
38
|
+
* name is `{sessionId}` -- opaque per-PTY, no timestamp suffix. Multiple
|
|
39
|
+
* concurrent callers for the same sessionId race-safely converge on the
|
|
40
|
+
* same directory because `mkdir({recursive:true})` is idempotent
|
|
41
|
+
* (prior `recursive:false` would 500 on EEXIST).
|
|
42
|
+
*/
|
|
43
|
+
acquire(sessionId: string): Promise<string>;
|
|
44
|
+
/**
|
|
45
|
+
* L1 cleanup. Removes the session's directory tree if any. Best-effort:
|
|
46
|
+
* a failure here is logged by the caller but never breaks shutdown.
|
|
47
|
+
*/
|
|
48
|
+
releaseSession(sessionId: string): Promise<void>;
|
|
49
|
+
/**
|
|
50
|
+
* L2 / L3 cleanup. Walks `uploadsDir` and removes every entry whose
|
|
51
|
+
* mtime is older than `ttlMs`. We stat instead of parsing the entry
|
|
52
|
+
* name so a future-dated suffix cannot keep an entry alive forever
|
|
53
|
+
* (reviewed for correctness). Returns the removed paths so callers can log
|
|
54
|
+
* a single-line summary.
|
|
55
|
+
*/
|
|
56
|
+
sweepStale(now?: number): Promise<{
|
|
57
|
+
swept: string[];
|
|
58
|
+
}>;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Best-effort removal of the legacy `.parasor/drops/` directory inside a
|
|
62
|
+
* project root. Upload staging isolation retires the in-tree drop layout entirely; on
|
|
63
|
+
* server boot the upload route's old dirs are deleted from every known
|
|
64
|
+
* project so the surface area for "stale screenshot in repo" goes to
|
|
65
|
+
* zero. Errors are swallowed (logged by caller) -- the legacy dir is
|
|
66
|
+
* already `.gitignore`d, so failure to delete is non-fatal.
|
|
67
|
+
*
|
|
68
|
+
* target is narrowed to `.parasor/drops/`. The
|
|
69
|
+
* parent `.parasor/` namespace is removed only when it ends up empty,
|
|
70
|
+
* so future code writing other entries under `.parasor/<other>` is
|
|
71
|
+
* not nuked by every server boot.
|
|
72
|
+
*/
|
|
73
|
+
export declare function removeLegacyDropsDir(projectRoot: string): Promise<{
|
|
74
|
+
removed: boolean;
|
|
75
|
+
}>;
|
|
76
|
+
//# sourceMappingURL=upload-staging.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upload-staging.d.ts","sourceRoot":"","sources":["../../src/fs/upload-staging.ts"],"names":[],"mappings":"AAoCA;;;;;;GAMG;AACH,qBAAa,qBAAsB,SAAQ,KAAK;IAC9C,QAAQ,CAAC,MAAM,EAAE,OAAO,GAAG,QAAQ,CAAC;IACpC,wDAAwD;IACxD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;gBACX,MAAM,EAAE,OAAO,GAAG,QAAQ,EAAE,KAAK,EAAE,MAAM;CAUtD;AAoBD,MAAM,WAAW,oBAAoB;IACnC;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,MAAM,CAAC;CACtB;AAED,qBAAa,aAAa;IACxB,sDAAsD;IACtD,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAe;gBAEzB,OAAO,GAAE,oBAAyB;IAwB9C;;;;;;OAMG;IACG,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAgBjD;;;OAGG;IACG,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOtD;;;;;;OAMG;IACG,UAAU,CAAC,GAAG,GAAE,MAAqB,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;CAqC3E;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,oBAAoB,CACxC,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC,CA2D/B"}
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
import { lstatSync, mkdirSync, realpathSync } from "node:fs";
|
|
2
|
+
import { lstat, mkdir, readdir, realpath, rm, rmdir, stat, } from "node:fs/promises";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { join, resolve, sep } from "node:path";
|
|
5
|
+
/**
|
|
6
|
+
* Image / file drops attached from the chat composer land here, NOT inside
|
|
7
|
+
* the user's project tree. The directory layout is:
|
|
8
|
+
*
|
|
9
|
+
* {rootDir}/uploads/{sessionId}/<filename>
|
|
10
|
+
*
|
|
11
|
+
* `{sessionId}` is opaque per-PTY (UUID). The directory is owned by the
|
|
12
|
+
* server process and exposed to the live PTY child via the per-session
|
|
13
|
+
* env var `PARASOR_UPLOAD_DIR` (set in `InProcessPtyHost.buildSessionEnv`)
|
|
14
|
+
* -- never as a shared root -- so the Claude wrapper's `--add-dir` only
|
|
15
|
+
* widens that PTY's allowlist to its own subdir, not its siblings'.
|
|
16
|
+
*
|
|
17
|
+
* Three-layer GC (upload staging isolation):
|
|
18
|
+
* L1 -- `releaseSession()` on PTY exit (immediate, in-process)
|
|
19
|
+
* L2 -- `sweepStale()` at server boot (handles SIGKILL leftovers)
|
|
20
|
+
* L3 -- `sweepStale()` on a 60-min interval (handles long-lived servers)
|
|
21
|
+
*/
|
|
22
|
+
const DEFAULT_TTL_MS = 24 * 60 * 60 * 1000;
|
|
23
|
+
const UPLOADS_SUBDIR = "uploads";
|
|
24
|
+
/** Owner-only -- drop dir contents may include unredacted screenshots. */
|
|
25
|
+
const DIR_MODE = 0o700;
|
|
26
|
+
/**
|
|
27
|
+
* Validation failure for a sessionId that does not match the strict
|
|
28
|
+
* format. Carries the raw value as a property so log sinks can decide
|
|
29
|
+
* whether to record it; the human-readable `message` stays a fixed
|
|
30
|
+
* literal so journald / file logs cannot be ANSI/newline-injected by an
|
|
31
|
+
* attacker who controls the query string (reviewed for correctness).
|
|
32
|
+
*/
|
|
33
|
+
export class InvalidSessionIdError extends Error {
|
|
34
|
+
reason;
|
|
35
|
+
/** Raw value as received. Not embedded in `message`. */
|
|
36
|
+
value;
|
|
37
|
+
constructor(reason, value) {
|
|
38
|
+
super(reason === "empty"
|
|
39
|
+
? "uploadStaging: empty sessionId"
|
|
40
|
+
: "uploadStaging: invalid sessionId format");
|
|
41
|
+
this.reason = reason;
|
|
42
|
+
this.value = value;
|
|
43
|
+
this.name = "InvalidSessionIdError";
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/** Reject session-id strings that could escape the upload root. */
|
|
47
|
+
function assertSafeSessionId(sessionId) {
|
|
48
|
+
if (sessionId.length === 0) {
|
|
49
|
+
throw new InvalidSessionIdError("empty", sessionId);
|
|
50
|
+
}
|
|
51
|
+
if (!/^[A-Za-z0-9_-]+$/.test(sessionId)) {
|
|
52
|
+
throw new InvalidSessionIdError("format", sessionId);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
function isNodeErrorWithCode(err, code) {
|
|
56
|
+
return (err instanceof Error &&
|
|
57
|
+
"code" in err &&
|
|
58
|
+
err.code === code);
|
|
59
|
+
}
|
|
60
|
+
export class UploadStaging {
|
|
61
|
+
/** Canonical absolute path of `<rootDir>/uploads`. */
|
|
62
|
+
uploadsDir;
|
|
63
|
+
ttlMs;
|
|
64
|
+
clock;
|
|
65
|
+
constructor(options = {}) {
|
|
66
|
+
const baseRaw = options.rootDir ?? join(tmpdir(), "parasor");
|
|
67
|
+
// mkdirSync runs before realpath because realpath() throws ENOENT on
|
|
68
|
+
// a missing path. The constructor is sync to keep `index.ts` boot
|
|
69
|
+
// ordering simple -- every subsequent operation is async.
|
|
70
|
+
mkdirSync(baseRaw, { recursive: true, mode: DIR_MODE });
|
|
71
|
+
const uploadsRaw = join(baseRaw, UPLOADS_SUBDIR);
|
|
72
|
+
mkdirSync(uploadsRaw, { recursive: true, mode: DIR_MODE });
|
|
73
|
+
// Reject if an attacker pre-planted a symlink at our root: realpath()
|
|
74
|
+
// would happily follow the link and we'd write under their target.
|
|
75
|
+
// lstat *before* realpath so the symlink itself is the thing we
|
|
76
|
+
// inspect (reviewed for correctness). uid is checked against geteuid()
|
|
77
|
+
// -- owning user only, no group/other writers.
|
|
78
|
+
assertOwnedRealDir(baseRaw);
|
|
79
|
+
assertOwnedRealDir(uploadsRaw);
|
|
80
|
+
// realpath resolves symlinks (notably macOS /tmp -> /private/tmp).
|
|
81
|
+
// Sync resolution keeps the public `uploadsDir` available for the
|
|
82
|
+
// `--add-dir` env injection without forcing the constructor to be
|
|
83
|
+
// async.
|
|
84
|
+
this.uploadsDir = realpathSync(uploadsRaw);
|
|
85
|
+
this.ttlMs = options.ttlMs ?? DEFAULT_TTL_MS;
|
|
86
|
+
this.clock = options.clock ?? (() => Date.now());
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Acquire (or re-use) a session-scoped upload directory. The directory
|
|
90
|
+
* name is `{sessionId}` -- opaque per-PTY, no timestamp suffix. Multiple
|
|
91
|
+
* concurrent callers for the same sessionId race-safely converge on the
|
|
92
|
+
* same directory because `mkdir({recursive:true})` is idempotent
|
|
93
|
+
* (prior `recursive:false` would 500 on EEXIST).
|
|
94
|
+
*/
|
|
95
|
+
async acquire(sessionId) {
|
|
96
|
+
assertSafeSessionId(sessionId);
|
|
97
|
+
const target = join(this.uploadsDir, sessionId);
|
|
98
|
+
// Defence in depth -- the sanitizer above already proves `sessionId`
|
|
99
|
+
// contains no separators, but the realpath-based fence catches a
|
|
100
|
+
// future regression of the validator.
|
|
101
|
+
if (!target.startsWith(this.uploadsDir + sep)) {
|
|
102
|
+
throw new Error("uploadStaging: target escaped uploadsDir");
|
|
103
|
+
}
|
|
104
|
+
// recursive:true converts EEXIST into a no-op success. The caller
|
|
105
|
+
// never sees an error if a sibling acquire() raced ahead, so two
|
|
106
|
+
// PTYs requesting the same sessionId both get the same dir back.
|
|
107
|
+
await mkdir(target, { recursive: true, mode: DIR_MODE });
|
|
108
|
+
return target;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* L1 cleanup. Removes the session's directory tree if any. Best-effort:
|
|
112
|
+
* a failure here is logged by the caller but never breaks shutdown.
|
|
113
|
+
*/
|
|
114
|
+
async releaseSession(sessionId) {
|
|
115
|
+
assertSafeSessionId(sessionId);
|
|
116
|
+
const target = join(this.uploadsDir, sessionId);
|
|
117
|
+
if (!target.startsWith(this.uploadsDir + sep))
|
|
118
|
+
return;
|
|
119
|
+
await rm(target, { recursive: true, force: true });
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* L2 / L3 cleanup. Walks `uploadsDir` and removes every entry whose
|
|
123
|
+
* mtime is older than `ttlMs`. We stat instead of parsing the entry
|
|
124
|
+
* name so a future-dated suffix cannot keep an entry alive forever
|
|
125
|
+
* (reviewed for correctness). Returns the removed paths so callers can log
|
|
126
|
+
* a single-line summary.
|
|
127
|
+
*/
|
|
128
|
+
async sweepStale(now = this.clock()) {
|
|
129
|
+
const cutoff = now - this.ttlMs;
|
|
130
|
+
const swept = [];
|
|
131
|
+
let entries;
|
|
132
|
+
try {
|
|
133
|
+
entries = await readdir(this.uploadsDir);
|
|
134
|
+
}
|
|
135
|
+
catch (err) {
|
|
136
|
+
if (isNodeErrorWithCode(err, "ENOENT"))
|
|
137
|
+
return { swept };
|
|
138
|
+
throw err;
|
|
139
|
+
}
|
|
140
|
+
for (const name of entries) {
|
|
141
|
+
const full = join(this.uploadsDir, name);
|
|
142
|
+
// Same fence as acquire: never act outside uploadsDir.
|
|
143
|
+
if (!full.startsWith(this.uploadsDir + sep))
|
|
144
|
+
continue;
|
|
145
|
+
try {
|
|
146
|
+
const st = await stat(full);
|
|
147
|
+
// Both birthtime (creation) and mtime (last write) must be old
|
|
148
|
+
// enough to retire -- a stale dir whose user keeps appending
|
|
149
|
+
// files stays alive while it's still in use.
|
|
150
|
+
const ageRef = Math.max(st.mtimeMs, st.birthtimeMs || 0);
|
|
151
|
+
if (ageRef > cutoff)
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
catch (err) {
|
|
155
|
+
if (isNodeErrorWithCode(err, "ENOENT"))
|
|
156
|
+
continue;
|
|
157
|
+
throw err;
|
|
158
|
+
}
|
|
159
|
+
try {
|
|
160
|
+
await rm(full, { recursive: true, force: true });
|
|
161
|
+
swept.push(full);
|
|
162
|
+
}
|
|
163
|
+
catch (err) {
|
|
164
|
+
if (isNodeErrorWithCode(err, "ENOENT"))
|
|
165
|
+
continue;
|
|
166
|
+
// Log + continue: a stuck entry must not block the rest of the
|
|
167
|
+
// sweep. Caller has no actionable response.
|
|
168
|
+
console.error("[upload-staging] sweep rm failed:", full, err);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return { swept };
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Best-effort removal of the legacy `.parasor/drops/` directory inside a
|
|
176
|
+
* project root. Upload staging isolation retires the in-tree drop layout entirely; on
|
|
177
|
+
* server boot the upload route's old dirs are deleted from every known
|
|
178
|
+
* project so the surface area for "stale screenshot in repo" goes to
|
|
179
|
+
* zero. Errors are swallowed (logged by caller) -- the legacy dir is
|
|
180
|
+
* already `.gitignore`d, so failure to delete is non-fatal.
|
|
181
|
+
*
|
|
182
|
+
* target is narrowed to `.parasor/drops/`. The
|
|
183
|
+
* parent `.parasor/` namespace is removed only when it ends up empty,
|
|
184
|
+
* so future code writing other entries under `.parasor/<other>` is
|
|
185
|
+
* not nuked by every server boot.
|
|
186
|
+
*/
|
|
187
|
+
export async function removeLegacyDropsDir(projectRoot) {
|
|
188
|
+
// Realpath the project root first so a project pointer like
|
|
189
|
+
// `~/projects/foo` (already expanded by caller) is canonicalized
|
|
190
|
+
// before the startsWith fence below.
|
|
191
|
+
let realProject;
|
|
192
|
+
try {
|
|
193
|
+
realProject = await realpath(projectRoot);
|
|
194
|
+
}
|
|
195
|
+
catch (err) {
|
|
196
|
+
if (isNodeErrorWithCode(err, "ENOENT"))
|
|
197
|
+
return { removed: false };
|
|
198
|
+
throw err;
|
|
199
|
+
}
|
|
200
|
+
const parasorDir = resolve(realProject, ".parasor");
|
|
201
|
+
const dropsDir = resolve(parasorDir, "drops");
|
|
202
|
+
// Reject if `.parasor` itself is a symlink -- refuse to follow into
|
|
203
|
+
// arbitrary territory. Using lstat (not stat) so the symlink itself
|
|
204
|
+
// is the thing we inspect.
|
|
205
|
+
try {
|
|
206
|
+
const parasorLst = await lstat(parasorDir);
|
|
207
|
+
if (parasorLst.isSymbolicLink())
|
|
208
|
+
return { removed: false };
|
|
209
|
+
}
|
|
210
|
+
catch (err) {
|
|
211
|
+
if (isNodeErrorWithCode(err, "ENOENT"))
|
|
212
|
+
return { removed: false };
|
|
213
|
+
throw err;
|
|
214
|
+
}
|
|
215
|
+
// Defence in depth: re-canonicalize and verify the drops path stays
|
|
216
|
+
// inside the project root. Catches a `.parasor/drops -> /etc` symlink
|
|
217
|
+
// even after the parent-dir lstat above passed.
|
|
218
|
+
let realDrops;
|
|
219
|
+
try {
|
|
220
|
+
realDrops = await realpath(dropsDir);
|
|
221
|
+
}
|
|
222
|
+
catch (err) {
|
|
223
|
+
if (isNodeErrorWithCode(err, "ENOENT"))
|
|
224
|
+
return { removed: false };
|
|
225
|
+
throw err;
|
|
226
|
+
}
|
|
227
|
+
if (realDrops !== resolve(realProject, ".parasor", "drops") ||
|
|
228
|
+
!realDrops.startsWith(realProject + sep)) {
|
|
229
|
+
return { removed: false };
|
|
230
|
+
}
|
|
231
|
+
await rm(realDrops, { recursive: true, force: true });
|
|
232
|
+
// Best-effort: clean the now-orphaned `.parasor/` shell, but only if
|
|
233
|
+
// empty. Other tooling that legitimately writes to `.parasor/<other>`
|
|
234
|
+
// (future features, user scripts) keeps its data.
|
|
235
|
+
try {
|
|
236
|
+
await rmdir(parasorDir);
|
|
237
|
+
}
|
|
238
|
+
catch (err) {
|
|
239
|
+
// ENOTEMPTY = other entries present (future namespace neighbours);
|
|
240
|
+
// ENOENT = removed concurrently. Both fine.
|
|
241
|
+
if (!isNodeErrorWithCode(err, "ENOTEMPTY") &&
|
|
242
|
+
!isNodeErrorWithCode(err, "ENOENT") &&
|
|
243
|
+
// Some platforms return EEXIST instead of ENOTEMPTY for non-empty
|
|
244
|
+
// rmdir (POSIX permits either).
|
|
245
|
+
!isNodeErrorWithCode(err, "EEXIST")) {
|
|
246
|
+
throw err;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
return { removed: true };
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Refuse to use `path` if its `lstat` reports it as a symlink, or its
|
|
253
|
+
* owner uid does not match the running process's effective uid. The
|
|
254
|
+
* latter check is skipped on Windows where `geteuid` is unavailable;
|
|
255
|
+
* elsewhere it ensures an attacker who pre-created the dir under a
|
|
256
|
+
* different user cannot trick us into writing secrets they can read.
|
|
257
|
+
*/
|
|
258
|
+
function assertOwnedRealDir(path) {
|
|
259
|
+
let st;
|
|
260
|
+
try {
|
|
261
|
+
st = lstatSync(path);
|
|
262
|
+
}
|
|
263
|
+
catch {
|
|
264
|
+
// Constructor only calls this after a successful mkdirSync so
|
|
265
|
+
// ENOENT here would be a TOCTOU race -- refuse to continue.
|
|
266
|
+
throw new Error(`uploadStaging: cannot lstat ${path}`);
|
|
267
|
+
}
|
|
268
|
+
if (st.isSymbolicLink()) {
|
|
269
|
+
throw new Error(`uploadStaging: refusing symlink at ${path}`);
|
|
270
|
+
}
|
|
271
|
+
if (!st.isDirectory()) {
|
|
272
|
+
throw new Error(`uploadStaging: not a directory: ${path}`);
|
|
273
|
+
}
|
|
274
|
+
// process.geteuid is undefined on Windows; skip the uid check there.
|
|
275
|
+
const geteuid = process.geteuid;
|
|
276
|
+
if (geteuid) {
|
|
277
|
+
const me = geteuid();
|
|
278
|
+
if (st.uid !== me) {
|
|
279
|
+
throw new Error(`uploadStaging: ${path} is owned by uid ${st.uid}, expected ${me}`);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
//# sourceMappingURL=upload-staging.js.map
|