summaryrefslogtreecommitdiff
path: root/docs/v9fs.md
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-09-29 19:25:00 -0300
committerGabriel Schneider <[email protected]>2026-10-01 00:12:17 -0300
commit57b30ba3e38153a4446626449b0fed5120da954c (patch)
tree7b9381327a05791181a855bd8d4ba3cfb4df5301 /docs/v9fs.md
parent0fd908eea63d04886b269438aa7529d3dd422256 (diff)
downloadpardes-57b30ba3e38153a4446626449b0fed5120da954c.tar.gz
pardes-57b30ba3e38153a4446626449b0fed5120da954c.zip
The docs and the 9P skill say each fact once, in the file that owns it, and say only what a live session does
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Diffstat (limited to 'docs/v9fs.md')
-rw-r--r--docs/v9fs.md130
1 files changed, 36 insertions, 94 deletions
diff --git a/docs/v9fs.md b/docs/v9fs.md
index a105fe06..26460658 100644
--- a/docs/v9fs.md
+++ b/docs/v9fs.md
@@ -1,114 +1,56 @@
-# Linux terminals with a kernel 9P mount
+# Tty9p: a terminal with a kernel 9P mount
-Execute `Tty9p`, or press `SPC n 9` in editor mode, to open a terminal below
-this pane with the current Pardes session mounted through Linux v9fs.
-
-The new pane asks for your sudo password when needed. After mounting, it starts
-your configured shell as your normal user, with your account's supplementary
-groups. The shell receives `PARDES_MOUNT`, the absolute mountpoint:
+On Linux, `Tty9p` (`SPC n 9`) opens a terminal below this pane with the
+session mounted through the kernel's v9fs. The pane asks for your sudo
+password, mounts, and starts your shell as your normal user (with your
+supplementary groups). The shell gets `PARDES_MOUNT`, the mountpoint:
```sh
-ls "$PARDES_MOUNT/pane"
cat "$PARDES_MOUNT/index"
-cat "$PARDES_MOUNT/README"
cat "$PARDES_MOUNT/pane/$PARDES_PANE/body"
echo 'Msg hello' > "$PARDES_MOUNT/exec"
n=$(cat "$PARDES_MOUNT/pane/new")
```
-**Opening** `pane/new` makes a pane, and reading that open file answers its
-serial; address the pane as `pane/<serial>` from then on. Each open makes
-another one, so read it once and keep the number. A *stat* makes nothing,
-which is why `new` can be listed at all: `ls`, `ls -l` and `find` over the
-whole mount create nothing, because none of them open it.
-
-The mount belongs to that pane's subprocess tree. Other panes and the editor
-core keep their original mount namespace. It works in native Linux TTY and SDL
-sessions, including detached sessions. A frontend attaching from elsewhere does
-not perform the mount; the session host starts the new terminal.
-
-## Build and setup
-
-The normal Linux build installs the ordinary `pardes-v9fs` executable beside
-`pardes` and `pardes-gui`:
-
-```sh
-zig build
-```
+The files are those of [fs.md](fs.md). The mount lives in that pane's
+private mount namespace: other panes and the editor do not see it, so a
+Look at a path under `$PARDES_MOUNT` opens nothing. Each `Tty9p` makes its
+own mount and takes one of the session's 16 Unix/TCP connection slots. It
+works in TTY, SDL and detached sessions (the session host starts the shell,
+not an attached frontend). Dump/Restore does not remake the mount.
-Start an updated editor to get the builtin. An already running core retains
-its old code. The host resolves the helper beside its own executable;
-`PARDES_V9FS_HELPER=/absolute/path/to/pardes-v9fs` overrides this for development
-builds whose editor and helper live in different build-cache directories.
+## Setup
-Linux must support `9p` and its Unix transport (`9pnet_fd`). v9fs mounting needs
-`CAP_SYS_ADMIN` in the initial user namespace, which sudo supplies. The launcher
-uses `sudo -E` to retain the shell environment; local sudo policy must allow
-that. It restores the caller's PATH after dropping privileges because sudo's
-`secure_path` can replace it even with `-E`.
+The build installs `pardes-v9fs` beside `pardes`; the host looks for it
+beside its own executable, or at `PARDES_V9FS_HELPER` (an absolute path).
+A running editor keeps the code it started with.
-No setuid installation, passwordless sudo policy, system group, or FUSE is
-installed. The helper currently accepts explicit mount paths and a command;
-it is not a restricted privilege broker. Do not grant it blanket passwordless
-access. A group-authorized helper would require a separate restricted design.
+Linux needs `9p` and its Unix transport (`9pnet_fd`); mounting needs
+`CAP_SYS_ADMIN`, which sudo supplies. The launcher runs `sudo -E` (local
+policy must allow it) and restores the caller's `PATH` after dropping
+privileges. Nothing setuid, no passwordless sudo rule and no FUSE is
+installed. The helper takes explicit mount paths and a command; it is not a
+restricted privilege broker, so do not grant it passwordless sudo.
-## Runtime organization
+## How it works
-`src/linux/v9fs.zig` builds `pardes-v9fs` and provides helper discovery to the
-native host. `Tty9p` marks the new pane for a mounted shell; `host_io.forkShell`
-starts the normal interactive shell and queues a quoted helper command. For
-bash and fish, the command waits for the shell's prompt-ready mark. The helper
-runs as a foreground shell job, so sudo uses the terminal like a manually run
-command. Authentication failure or cancellation returns to the original shell;
-exiting the mounted shell also returns there.
+`Tty9p` starts the normal shell and queues a quoted helper command, which
+bash and fish run once their prompt is ready, as a foreground job, so sudo
+uses the terminal. A failed or cancelled authentication returns to that
+shell, as does exiting the mounted one. The unprivileged launcher makes a
+private temporary mountpoint and runs sudo; the elevated helper makes a
+private mount namespace, mounts the session's socket with
+`trans=unix,version=9p2000,cache=none,access=any,nosuid,nodev,noexec`, drops
+every root id and capability, and executes the shell. The namespace, and
+the mount, go when its last process exits. Code: `src/linux/v9fs.zig`.
-The unprivileged launcher creates a private temporary mountpoint and invokes
-sudo inside the new PTY. The elevated helper creates a private mount namespace,
-makes propagation recursively private, and mounts the session's Unix socket
-with `version=9p2000,cache=none,access=any,nosuid,nodev,noexec`. It restores the
-calling user's account groups, drops all real/effective/saved root IDs and
-mount capabilities, and executes the shell. Ordinary commands such as sudo
-remain available for subsequent explicit authentication. The launcher waits for sudo,
-forwards termination signals, and removes its empty temporary directory on exit.
-Namespace destruction releases the mount when its last process exits.
-
-The core stays outside the mount namespace, which is the helper's private
-one: a path under `$PARDES_MOUNT` names nothing in the editor's own namespace,
-so a Look on one from that shell opens nothing.
-
-Each `Tty9p` currently creates its own mount and consumes a server connection;
-the session has four application connection slots across all transports. This
-is the explicit per-pane version. A shared launcher for all pane shells remains
-future work. Detached sessions retain the running mounted pane when frontends
-leave; Dump/Restore does not reconstruct mounted-shell namespaces. Descendants
-that deliberately outlive the terminal may retain their namespace until exit.
+Linux follows `O_TRUNC` with a `Twstat` of zero length and an `mtime` hint;
+pardes takes the truncation and drops the hint.
## Tests
```sh
-zig build v9fs-terminal-test -Dplatform=tty
-zig build v9fs-driver-test -Dplatform=tty
-zig build 9p-test -Dplatform=tty
-sudo -v
-zig build v9fs-test -Dplatform=tty
+zig build v9fs-terminal-test -Dplatform=tty # builtin, launcher, cleanup; a sudo stand-in, no mount
+zig build v9fs-driver-test -Dplatform=tty # the probe launcher, no privileges
+sudo -v; zig build v9fs-test -Dplatform=tty # a real kernel mount (sudo -n); fails, not skips, without it
```
-
-`v9fs-terminal-test` exercises the builtin, real launcher, PTY input, session
-environment, quoted helper paths, hidden password input, and core responsiveness
-using an unprivileged sudo stand-in. It checks that authentication failure and
-interruption clean up the temporary mountpoint and leave the original shell usable. It does not claim kernel-mount coverage.
-
-`v9fs-test` mounts through the same runtime helper. Its driver keeps the editor
-unprivileged and uses `sudo -n`, retaining the calling terminal's authorization.
-Missing authorization or kernel support fails the test instead of skipping it.
-It checks mount isolation, privilege dropping, inherited access, directory
-refresh, body reads and truncation, independent wire updates, addressed edits,
-shell redirection to name, Exec dispatch, rendered screen JSON, and OS-file reads.
-
-Linux follows `O_TRUNC` with a `Twstat` carrying zero length and an `mtime` hint.
-Pardes accepts this truncation without storing caller-selected timestamps;
-standalone timestamp, permission, and ownership changes remain unsupported.
-
-The initial kernel probe passed on this host on 2026-09-14. The broader
-`fs-test` has an existing syntax-bold assertion failure (now `test/fs.py:615`),
-also reproduced on the cached editor binary preceding the truncation fix.