Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0c6ae449ea |
@@ -0,0 +1,285 @@
|
||||
# Pi sandbox requirements
|
||||
|
||||
Research scope: Pi `0.84.2`, Paseo's current direct Pi provider, and `pi-mcp-adapter` `2.27.0`. This note defines the smallest useful contract for a real `pi --mode rpc` process under gVisor. It covers the host-installed daemon and the official Paseo Docker image. It does not choose a sandbox launcher or implement the contract.
|
||||
|
||||
## Findings
|
||||
|
||||
### Process and image contents
|
||||
|
||||
Paseo spawns Pi as a JSONL child process with piped stdin, stdout, and stderr. A normal launch has this shape:
|
||||
|
||||
```text
|
||||
pi --mode rpc \
|
||||
--model <provider/model> \
|
||||
--thinking <level> \
|
||||
[--session <absolute-jsonl-path> | --no-session] \
|
||||
[--mcp-config <generated-file>] \
|
||||
--extension <generated-paseo-extension>
|
||||
```
|
||||
|
||||
Paseo sets the child cwd to the agent cwd and forwards the daemon environment plus provider overrides and `PASEO_AGENT_ID` and `PASEO_AGENT_CWD`. Pi adds `AI_AGENT=pi` and `PI_CODING_AGENT=true` for its descendants. Commands launched by Pi also receive `PI_SESSION_ID`, `PI_SESSION_FILE`, `PI_PROVIDER`, `PI_MODEL`, and `PI_REASONING_LEVEL`.[^paseo-launch] [^paseo-env] [^pi-env]
|
||||
|
||||
A minimum npm-based image needs:
|
||||
|
||||
| Content | Requirement |
|
||||
| --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Linux userspace | A glibc image such as Debian bookworm slim. The official Pi container example uses `node:24-bookworm-slim`.[^pi-container] |
|
||||
| Node | Node `>=22.19.0`, matching Pi's package engine. Copying only the `pi` script without Node and its package tree will not work.[^pi-package] |
|
||||
| Pi | The complete installed `@earendil-works/pi-coding-agent` package and its production dependency tree, or an official standalone Pi binary plus its adjacent assets. Pin the version in the sandbox image. |
|
||||
| TLS | `ca-certificates` and working DNS. Provider requests use HTTPS unless the selected model has a local or custom HTTP base URL. |
|
||||
| Shell | `bash`. Pi's built-in bash tool launches a configured shell, and the official Pi container installs bash.[^pi-container] [^pi-bash] |
|
||||
| Search helpers | Preinstall `rg` and `fd`/`fdfind`. Pi's `grep` and `find` tools otherwise download them from GitHub into `<agent-dir>/bin`, adding writable state and broad GitHub egress.[^pi-tools] |
|
||||
| Project tooling | `git` is part of Pi's official container recommendation and is needed for normal coding-agent work. Add only the compilers, package managers, SSH client, and project CLIs that the session is allowed to invoke. Pi does not provide them.[^pi-container] |
|
||||
| MCP adapter | Install and pin `pi-mcp-adapter` plus its production dependencies if the session must receive Paseo tools over MCP. Pi has no built-in MCP client.[^pi-readme] [^mcp-package] |
|
||||
|
||||
`pi-mcp-adapter` ships TypeScript source and Pi loads it through its extension loader. Copy its complete installed package tree, including the platform package for `@napi-rs/keyring`. Paseo disables both adapter OAuth and automatic auth for its own local HTTP server, so the local Paseo MCP path does not need an OS keyring. Other MCP servers that use OAuth or `bearerTokenStore` need a functioning OS credential store; the adapter fails closed when it cannot access one. Headless Linux usually needs a Secret Service session, and its keyring recovery path also expects `keyctl` and `node`.[^mcp-auth]
|
||||
|
||||
The image should set these defaults:
|
||||
|
||||
```text
|
||||
HOME=/home/sandbox
|
||||
PI_CODING_AGENT_DIR=/state/pi-agent
|
||||
PI_CODING_AGENT_SESSION_DIR=/state/pi-sessions
|
||||
PI_OFFLINE=1
|
||||
PATH=<fixed image paths plus explicitly allowed project tool paths>
|
||||
TMPDIR=/tmp
|
||||
```
|
||||
|
||||
`PI_OFFLINE=1` removes Pi's startup catalog/update traffic. It does not block model calls. Pi RPC otherwise starts a background model-catalog refresh. Disabling this traffic makes a network allowlist predictable; bake the required model catalog or project `models.json` into the state projection.[^pi-offline] [^pi-rpc-refresh]
|
||||
|
||||
### Files Pi reads
|
||||
|
||||
Pi resolves global state from `PI_CODING_AGENT_DIR`, defaulting to `~/.pi/agent`. Pointing it at a dedicated sandbox directory avoids any need to mount the daemon user's home.[^pi-paths]
|
||||
|
||||
| Path | Access | Required for the minimum contract | Treatment |
|
||||
| ----------------------------------------------------------------------- | ---------------------------------------------- | --------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `<agent-dir>/auth.json` | Read and sometimes write | One credential source, unless credentials arrive through environment variables or `--api-key` | Project only the selected provider credential. Keep writable when it contains OAuth because Pi refreshes and rewrites tokens under a file lock. API-key-only sessions can use a secret environment variable and omit the file.[^pi-providers] [^pi-auth-storage] |
|
||||
| `<agent-dir>/settings.json` | Read | A small generated file | Copy only settings that change runtime behavior: proxy, custom session directory, model defaults not supplied by Paseo, and the pinned MCP adapter package/resource declaration. Avoid copying unrelated extension/package declarations. |
|
||||
| `<agent-dir>/models.json` | Read | Only for custom providers/models | Copy read-only when the selected model depends on it. It may contain inline keys or command-backed key resolution, so treat it as a credential-bearing file.[^pi-providers] |
|
||||
| `<agent-dir>/models-store.json` | Read/write cache | Only for a dynamic catalog or offline cached model absent from the built-in catalog | Seed narrowly and permit cache writes, or omit when the selected model is built in. Pi stores refreshed catalogs here.[^pi-providers] [^pi-model-store] |
|
||||
| `<agent-dir>/trust.json` | Read | Only if project `.pi` settings/resources must load in non-interactive RPC mode | Copy a narrow decision for the mounted cwd, or set a generated global `defaultProjectTrust`. Do not inherit trust decisions for unrelated host paths.[^pi-trust] |
|
||||
| `<agent-dir>/mcp.json` | Read by Paseo before launch and by the adapter | Optional user-global MCP settings | Paseo merges it into the generated per-session MCP config. Copy only MCP entries approved for this sandbox. |
|
||||
| `<agent-dir>/mcp-cache.json` | Read/write | Adapter metadata optimization, direct-tool bootstrap | Persist in sandbox state if direct MCP tools or cached metadata matter. It contains tool metadata and config hashes, not the Paseo bearer token.[^mcp-cache] |
|
||||
| `<agent-dir>/mcp-npx-cache.json` and `agent-plugin-data/` | Read/write | Only for configured npx stdio servers or Agent Plugins | Persist only when those features are enabled. Their executables and data expand the sandbox contract. |
|
||||
| `<agent-dir>/extensions`, `skills`, `prompts`, `themes`, `npm`, `git` | Read; package manager may write | Only resources selected for the session | Bake pinned resources into the image read-only or copy an allowlisted subset. Pi extensions execute arbitrary code. Do not project the daemon user's complete package trees.[^pi-resources] [^pi-packages] |
|
||||
| `<agent-dir>/AGENTS.md`, `SYSTEM.md`, `APPEND_SYSTEM.md` | Read | Optional global prompt behavior | Copy only when Paseo promises parity with the user's Pi configuration. |
|
||||
| `<cwd>/.pi/*`, `<cwd>/.mcp.json`, `<cwd>/.agents/skills`, context files | Read, and project tools may write under cwd | Depends on project trust | These arrive through the workspace mount. RPC ignores project resources unless trust resolves to yes; `ask` cannot open a trust prompt in RPC mode.[^pi-trust] |
|
||||
|
||||
Pi also walks from cwd toward the filesystem root for `AGENTS.md`, `AGENTS.override.md`, or `CLAUDE.md`. A workspace-only mount will omit instructions stored above the workspace. The mount planner must either project the approved parent context files at their original paths or declare that sandboxed sessions load workspace-contained context only.[^pi-readme]
|
||||
|
||||
### State that must persist
|
||||
|
||||
Persist these objects independently instead of persisting a synthetic home directory:
|
||||
|
||||
1. **Pi session JSONL.** Normal Paseo Pi agents omit `--no-session`; Pi writes under `<session-dir>/<encoded-cwd>/`. Paseo stores the absolute JSONL path as `nativeHandle`, resumes with `--session <path>`, and scans the configured session directory for imports. The daemon and later sandboxes must see the same stable absolute path.[^pi-sessions] [^paseo-resume] [^paseo-import]
|
||||
2. **Mutable provider credentials.** Pi writes refreshed OAuth tokens back to `auth.json`. API keys delivered by environment do not require persistent credential files.[^pi-auth-storage]
|
||||
3. **Adapter metadata caches** when direct tools or fast lazy discovery matter. They can be discarded at the cost of reconnecting and repopulating metadata.[^mcp-cache]
|
||||
4. **Optional MCP secure-store state.** Only non-Paseo MCP servers using OAuth or adapter bearer storage need this. OS credential-store state is outside `<agent-dir>` and cannot be preserved by copying files alone.[^mcp-auth]
|
||||
|
||||
Keep the rest ephemeral. Give each sandbox a private writable `/tmp` for Pi bash spill files, image materialization, generated tool output, and MCP output/resource files. The adapter documents that some oversized MCP text spill files are not automatically deleted, so destroy the sandbox temp filesystem after the session.[^mcp-output]
|
||||
|
||||
### Workspace and project mounts
|
||||
|
||||
Mount the agent cwd read-write at the **same absolute path** recorded by Paseo. Pi writes that cwd into the session header, Paseo uses it in persistence metadata, and resume launches use it as the process cwd. Path translation would break import filtering, parent context discovery, absolute links in history, and commands saved in the transcript.[^paseo-resume] [^pi-sessions]
|
||||
|
||||
The minimum project mount set is:
|
||||
|
||||
- the cwd tree, read-write;
|
||||
- the linked worktree's actual Git metadata, when `.git` is a file or points outside cwd;
|
||||
- any explicit external directories that the product chooses to grant;
|
||||
- the persistent session and minimal agent-state mounts described above;
|
||||
- the two generated Paseo launch files, read-only, at the paths passed on argv.
|
||||
|
||||
Do not follow workspace symlinks into arbitrary host paths by mounting their targets. Let missing external targets fail unless a separate policy grants them. For Git linked worktrees, resolve `.git`, `commondir`, and object alternates before launch. Mount only the required Git dirs. They need write access for normal branch, index, object, and ref operations; a read-only Git mount supports inspection only.
|
||||
|
||||
### Paseo-generated extension and MCP config
|
||||
|
||||
For every Pi create or resume, Paseo creates two host temp directories:
|
||||
|
||||
- `paseo-pi-extension-*/paseo-integration.mjs`, passed with `--extension`. It appends Paseo's per-agent and daemon system prompts and emits session-tree markers over Pi extension UI notifications.
|
||||
- `paseo-pi-mcp-*/mcp.json`, passed with `--mcp-config` when Paseo detects `pi-mcp-adapter`. It starts from `<agent-dir>/mcp.json`, overlays injected servers, writes mode `0600`, and deletes the temp directory when the Pi session closes.[^paseo-generated]
|
||||
|
||||
The gVisor launcher must bind each file or its containing directory into the sandbox at the exact argv path. Do not share the daemon's `/tmp`. Mount these paths read-only. The generated MCP file contains the per-daemon-run Paseo bearer token in an `Authorization` header and must stay private to that sandbox. The generated extension can contain system-prompt text; change its creation mode to `0600` in the later implementation ticket.
|
||||
|
||||
Paseo detects adapter support by launching a scratch Pi RPC process for the same cwd and calling `get_commands`; it accepts an extension command named `mcp` with adapter source metadata. All Pi probes, including catalog fetches and this detection process, need the same image, state projection, cwd mounts, and sandbox policy as the real session. Otherwise the daemon can report a different provider capability than the session receives.[^paseo-detect]
|
||||
|
||||
For injected HTTP MCP servers, Paseo converts the entry to:
|
||||
|
||||
```json
|
||||
{
|
||||
"url": "http://<daemon-address>/mcp/agents?callerAgentId=<agent-id>",
|
||||
"headers": { "Authorization": "Bearer <per-daemon-run-token>" },
|
||||
"auth": false,
|
||||
"oauth": false
|
||||
}
|
||||
```
|
||||
|
||||
The adapter still reads standard user and project MCP layers around `--mcp-config`. The minimum Paseo contract should include only the injected `paseo` server. Supporting arbitrary user MCP config adds every referenced executable, cwd, environment secret, socket, remote host, package cache, and credential store to the contract.[^paseo-mcp] [^mcp-config]
|
||||
|
||||
### Local MCP connectivity
|
||||
|
||||
The current address generation assumes Pi shares the daemon network namespace. A daemon listening on `0.0.0.0` becomes `127.0.0.1`; an IPv6 wildcard becomes `::1`. A gVisor sandbox with its own network namespace resolves those addresses to itself, so current injected MCP URLs will fail.[^paseo-mcp-address]
|
||||
|
||||
The network ticket must provide a sandbox-specific MCP route and pass that route into runtime MCP config generation. Acceptable shapes include:
|
||||
|
||||
- a narrow host-gateway listener reachable only from the sandbox network;
|
||||
- a per-sandbox proxy that exposes only `/mcp/agents` and forwards to daemon loopback;
|
||||
- a Unix socket transport after both Paseo and the adapter support it for this server.
|
||||
|
||||
Do not expose the daemon's full `6767` listener to the sandbox network if a route-specific proxy can avoid it. Keep the per-daemon bearer token even on the private route. The token authorizes agent-scoped operations and rotates when the daemon restarts.[^paseo-mcp-auth]
|
||||
|
||||
### Egress contract
|
||||
|
||||
A real turn needs these network capabilities:
|
||||
|
||||
| Destination | Required | Policy |
|
||||
| ------------------------------------------------ | -------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Configured DNS resolver | Yes for hostname endpoints | Allow DNS only to the sandbox resolver. Do not allow arbitrary port 53 destinations. |
|
||||
| Selected model `baseUrl` | Yes, unless the model is local | Resolve the exact effective provider/model after Pi reads `auth.json`, `models.json`, and provider-scoped environment. Allow its host and port, normally HTTPS 443. Custom providers make a static global hostname list incomplete.[^pi-providers] |
|
||||
| Provider OAuth refresh/token endpoint | Only for subscription OAuth | Allow the selected provider's auth endpoints. A refreshed credential writes back to `auth.json`; read-only credentials will fail when tokens expire.[^pi-providers] |
|
||||
| Paseo Agent MCP route | Yes when Paseo tools are enabled | Allow the one private daemon/proxy address and path. It is local connectivity, not Internet egress. |
|
||||
| Other configured HTTP MCP servers | Only when explicitly enabled | Add each resolved MCP URL and its OAuth metadata/token endpoints. Paseo's injected server disables OAuth and needs no discovery.[^mcp-config] |
|
||||
| Stdio MCP descendants | Only when explicitly enabled | No network by default, but the child server may need its own egress. Treat each command as a separate workload policy. |
|
||||
| `pi.dev` | No for RPC operation | Set `PI_OFFLINE=1`. Pi's documented update and telemetry endpoints are not needed for model calls.[^pi-offline] |
|
||||
| GitHub API/releases | No when `rg` and `fd` are baked in | Pi downloads missing search helpers from GitHub. Preinstall them.[^pi-tools] |
|
||||
| npm and Git hosts | No when packages and MCP servers are pinned in the image | Disallow runtime package installation. `npx -y` MCP entries otherwise require registry and tarball egress and mutable npm caches. |
|
||||
| Arbitrary destinations from `bash` or extensions | Product decision | A coding agent can call `curl`, package managers, or custom extension code. Provider-only egress requires network enforcement below the process, not prompt instructions. |
|
||||
|
||||
Pass proxy variables only if the selected policy requires them. Pi supports `HTTP_PROXY` and `HTTPS_PROXY`, and a global `httpProxy` setting applies both. Ensure `NO_PROXY` covers the private Paseo MCP endpoint or route it through a proxy that can reach the daemon.[^pi-env]
|
||||
|
||||
## Explicit minimum sandbox contract
|
||||
|
||||
A sandboxed Paseo Pi session is ready only when the launcher satisfies all of these conditions:
|
||||
|
||||
1. **Identity:** run as a non-root uid/gid with no host capabilities, no daemon Docker socket, and a private process, IPC, temp, and mount namespace.
|
||||
2. **Image:** provide pinned Pi, Node `>=22.19.0`, production dependencies and assets, CA roots, bash, git, `rg`, and `fd`; add the pinned MCP adapter package when Paseo tools are enabled.
|
||||
3. **Cwd:** mount the exact agent cwd read-write at the same absolute path. Add only required external Git metadata and separately approved paths.
|
||||
4. **Agent state:** set `PI_CODING_AGENT_DIR` to a minimal host-visible state directory. Include only selected auth, settings, custom model files, and pinned resources. Do not mount `$HOME`, `/home/paseo`, `~/.pi`, `~/.ssh`, cloud config dirs, or the daemon's `$PASEO_HOME` wholesale.
|
||||
5. **Sessions:** set `PI_CODING_AGENT_SESSION_DIR` to a stable, host-visible, writable directory and preserve absolute session paths across launches. Scope it by daemon user or tenant; scope further by agent if cross-session import is not required.
|
||||
6. **Credentials:** prefer one selected-provider API key or a brokered secret. If Pi OAuth is required, give `auth.json` coordinated read-write persistence. Do not duplicate a mutable OAuth file into independent sandboxes without a refresh reconciliation design.
|
||||
7. **Generated files:** mount only the generated Paseo extension and MCP config read-only at their argv paths. Destroy them after the child exits.
|
||||
8. **MCP:** install the adapter, confirm its `mcp` command during a sandboxed probe, and give the sandbox a private route to `/mcp/agents`. Keep `auth: false`, `oauth: false`, and the per-run bearer header for the injected server.
|
||||
9. **Network:** allow the private Paseo MCP route, DNS to the configured resolver, the selected model endpoint, and any required provider token-refresh endpoints. Deny other egress by default. Set `PI_OFFLINE=1` and bake helpers/packages.
|
||||
10. **Lifecycle:** sandbox create, resume, import hydration, catalog probes, and adapter probes. Kill the process tree and remove ephemeral temp state when a Pi session closes.
|
||||
11. **Limits:** cap pids, memory, CPU, disk, file descriptors, output, and wall time. Pi and extensions can spawn children; stdio MCP and bash tools add more processes.
|
||||
|
||||
## Daemon topology implications
|
||||
|
||||
### Host-installed daemon
|
||||
|
||||
The daemon can bind the host workspace and persistent Pi state paths directly into the sandbox. It still must translate daemon loopback MCP connectivity because sandbox loopback is separate. A host gateway or path-limited proxy should be created per sandbox. Keep host `$HOME` outside the mount table.
|
||||
|
||||
Host-installed Pi may come from npm, Bun's global package tree, a version manager, or a standalone binary. Do not bind the discovered host installation into the sandbox as the production design. Build a pinned runtime image so the process cannot traverse the host package manager's global tree and so native dependencies match the sandbox libc and architecture.
|
||||
|
||||
### Official Docker Paseo daemon
|
||||
|
||||
The published daemon image runs as uid/gid `1000:1000`, sets `HOME=/home/paseo`, stores Paseo and agent state under `/home/paseo`, mounts workspaces at `/workspace`, and intentionally omits every agent CLI.[^paseo-docker]
|
||||
|
||||
A sibling gVisor sandbox cannot assume that `/workspace` inside the daemon container names a host bind source. The daemon-side launcher needs mount provenance: named volume identity or the original bind source plus destination. Bind the same workspace volume into the sandbox at the same in-container absolute path. Apply the same rule to persistent Pi sessions and minimal agent state.
|
||||
|
||||
Do not pass the official `/home/paseo` volume through to the sandbox. It contains `$PASEO_HOME`, daemon identity and config, logs, all provider credentials, and unrelated agent state. Create separate Pi credential/session volumes or copy approved files into sandbox-specific state. The official base image's Node and utilities also do not satisfy a sibling sandbox; the sandbox image owns its own runtime.
|
||||
|
||||
The Docker deployment ticket must also decide who owns gVisor container creation. Mounting a Docker/containerd socket into the Paseo daemon grants host-level control and conflicts with the sandbox goal. Prefer a narrow launcher service or runtime API that validates image, mounts, network, limits, and argv.
|
||||
|
||||
## What to copy, project, or persist
|
||||
|
||||
| Item | Strategy |
|
||||
| --------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- |
|
||||
| Pi, Node, MCP adapter, CA roots, bash, git, `rg`, `fd` | Bake read-only into the image. |
|
||||
| Workspace and required Git metadata | Bind explicit paths, cwd read-write, at stable absolute destinations. |
|
||||
| Paseo integration extension and merged MCP config | Bind two generated files read-only for one process. |
|
||||
| API keys | Inject as per-process secrets or provider env. Avoid broad inherited daemon env. |
|
||||
| Pi OAuth `auth.json` | Use one coordinated writable credential store or a broker. Persist and protect it independently. |
|
||||
| Pi JSONL sessions | Persist in a dedicated writable volume visible to daemon and future sandboxes. |
|
||||
| Minimal settings, custom model catalog, trust decision | Generate or copy an allowlisted subset. Prefer read-only unless Pi must refresh its model store. |
|
||||
| MCP metadata/npx caches | Persist only for enabled adapter features. They are rebuildable. |
|
||||
| User extensions/packages/skills/prompts | Bake pinned approved resources or bind explicit read-only trees. Omit ambient resources by default. |
|
||||
| `/tmp`, bash spill output, materialized images/MCP resources | Private writable ephemeral filesystem, destroyed on teardown. |
|
||||
| `$HOME`, `/home/paseo`, `$PASEO_HOME`, `.ssh`, cloud credential directories | Never mount wholesale. Grant individual files, sockets, or brokered credentials only. |
|
||||
|
||||
## Remaining uncertainties
|
||||
|
||||
1. **MCP adapter ownership and version.** Paseo detects an ambient `pi-mcp-adapter` but does not install or pin it. The sandbox image ticket must choose a supported version and define its upgrade compatibility with Pi and Paseo.
|
||||
2. **MCP route design.** Current loopback URL generation cannot cross a gVisor network namespace. The network ticket must select a route-specific proxy, gateway address, or future Unix socket transport and define token exposure.
|
||||
3. **OAuth concurrency.** Pi can rewrite `auth.json` during token refresh. The credential ticket must define locking and reconciliation across simultaneous sandboxes and daemon-side provider probes.
|
||||
4. **Project trust parity.** Decide whether sandboxed RPC sessions load project `.pi` resources and ancestor context files. A generated `defaultProjectTrust: "never"` is safer but changes current trusted-project behavior.
|
||||
5. **User extensions and MCP servers.** The minimum contract includes the Paseo extension and Paseo MCP only. Supporting ambient user Pi packages or arbitrary MCP config changes image contents, mounts, egress, subprocess policy, and credential requirements.
|
||||
6. **Git worktree mounts.** The mount ticket must specify how it resolves and grants linked-worktree gitdir, commondir, alternates, submodules, and LFS without exposing unrelated repositories.
|
||||
7. **Official Docker launcher authority.** The deployment ticket must choose a launcher architecture that avoids granting the daemon an unrestricted container runtime socket.
|
||||
8. **Path namespace and import UX.** Stable absolute paths simplify resume and import. If the product requires path remapping, Paseo needs an explicit host-to-sandbox path identity layer before sandboxing ships.
|
||||
9. **OS credential store in gVisor.** Adapter OAuth for non-Paseo MCP servers depends on a keyring service and native binding. Test whether the chosen gVisor image and launcher can provide a scoped Secret Service session; otherwise disable that feature or broker it.
|
||||
10. **Provider egress inventory.** Pi supports many built-in and custom providers. Generate policy from the effective selected model and credential type at launch; a hand-maintained host list will drift.
|
||||
|
||||
## Implications for follow-up tickets
|
||||
|
||||
- **Mount ticket:** introduce explicit mount descriptors for cwd, external Git metadata, persistent sessions, minimal agent state, generated launch files, and optional approved resources. Record Docker volume provenance.
|
||||
- **Security ticket:** isolate uid, namespaces, temp, process tree, secrets, and resource limits; reject broad home, runtime-socket, and daemon-state mounts; make the generated extension mode `0600`.
|
||||
- **Network ticket:** replace loopback MCP assumptions with a private sandbox route, generate provider-specific egress, enforce DNS policy, set offline mode, and keep package/helper downloads out of runtime.
|
||||
- **Credential ticket:** select env injection, a credential broker, or a coordinated writable Pi auth store. Cover OAuth refresh and adapter keyring behavior.
|
||||
- **Runtime image ticket:** pin Pi and adapter versions, bake their complete dependencies and assets, preinstall `rg`/`fd`, and test create, prompt, tool call, MCP call, close, resume, and import under both daemon topologies.
|
||||
|
||||
## Sources
|
||||
|
||||
Paseo repository sources use paths from this checkout. Upstream links point to the researched versions.
|
||||
|
||||
[^paseo-launch]: [`packages/server/src/server/agent/providers/pi/runtime.ts:75-139`](../../packages/server/src/server/agent/providers/pi/runtime.ts) and [`cli-runtime.ts:60-86`](../../packages/server/src/server/agent/providers/pi/cli-runtime.ts).
|
||||
|
||||
[^paseo-env]: [`packages/server/src/server/agent/agent-manager.ts:4767-4788`](../../packages/server/src/server/agent/agent-manager.ts) and [`paseo-env.ts:1-43`](../../packages/server/src/server/paseo-env.ts).
|
||||
|
||||
[^pi-env]: Pi 0.84.2, [Environment Variables](https://github.com/earendil-works/pi/blob/v0.84.2/packages/coding-agent/docs/environment-variables.md) and [`README.md`, environment table](https://github.com/earendil-works/pi/blob/v0.84.2/packages/coding-agent/README.md#environment-variables).
|
||||
|
||||
[^pi-container]: Pi 0.84.2, [Containerization, Plain Docker](https://github.com/earendil-works/pi/blob/v0.84.2/packages/coding-agent/docs/containerization.md#plain-docker).
|
||||
|
||||
[^pi-package]: Pi 0.84.2, [`packages/coding-agent/package.json`](https://github.com/earendil-works/pi/blob/v0.84.2/packages/coding-agent/package.json), `engines.node` and production dependencies.
|
||||
|
||||
[^pi-bash]: Pi 0.84.2, [`src/core/tools/bash.ts:83-106`](https://github.com/earendil-works/pi/blob/v0.84.2/packages/coding-agent/src/core/tools/bash.ts#L83-L106).
|
||||
|
||||
[^pi-tools]: Pi 0.84.2, [`src/utils/tools-manager.ts:15-116, 231-319`](https://github.com/earendil-works/pi/blob/v0.84.2/packages/coding-agent/src/utils/tools-manager.ts) and [`grep.ts:174-180`](https://github.com/earendil-works/pi/blob/v0.84.2/packages/coding-agent/src/core/tools/grep.ts#L174-L180), [`find.ts:222-232`](https://github.com/earendil-works/pi/blob/v0.84.2/packages/coding-agent/src/core/tools/find.ts#L222-L232).
|
||||
|
||||
[^pi-readme]: Pi 0.84.2, [`README.md`, Philosophy and MCP](https://github.com/earendil-works/pi/blob/v0.84.2/packages/coding-agent/README.md#philosophy).
|
||||
|
||||
[^mcp-package]: pi-mcp-adapter 2.27.0, [`package.json`](https://github.com/nicobailon/pi-mcp-adapter/blob/v2.27.0/package.json), including `pi.extensions`, dependencies, peer dependencies, and Node engine.
|
||||
|
||||
[^mcp-auth]: pi-mcp-adapter 2.27.0, [Remote/headless OAuth](https://github.com/nicobailon/pi-mcp-adapter/blob/v2.27.0/README.md#remoteheadless-oauth) and [`mcp-auth.ts:1-18, 274-391`](https://github.com/nicobailon/pi-mcp-adapter/blob/v2.27.0/mcp-auth.ts).
|
||||
|
||||
[^pi-offline]: Pi 0.84.2, [`README.md`, Telemetry and update checks](https://github.com/earendil-works/pi/blob/v0.84.2/packages/coding-agent/README.md#telemetry-and-update-checks).
|
||||
|
||||
[^pi-rpc-refresh]: Pi 0.84.2, [`src/main.ts:926-940`](https://github.com/earendil-works/pi/blob/v0.84.2/packages/coding-agent/src/main.ts#L926-L940).
|
||||
|
||||
[^pi-paths]: Pi 0.84.2, [`src/config.ts:494-565`](https://github.com/earendil-works/pi/blob/v0.84.2/packages/coding-agent/src/config.ts#L494-L565).
|
||||
|
||||
[^pi-providers]: Pi 0.84.2, [Providers](https://github.com/earendil-works/pi/blob/v0.84.2/packages/coding-agent/docs/providers.md), including credential resolution order, auth file writes, cloud credentials, and custom providers.
|
||||
|
||||
[^pi-auth-storage]: Pi 0.84.2, [`src/core/auth-storage.ts:47-188`](https://github.com/earendil-works/pi/blob/v0.84.2/packages/coding-agent/src/core/auth-storage.ts#L47-L188).
|
||||
|
||||
[^pi-model-store]: Pi 0.84.2, [`src/core/model-runtime.ts:171-212`](https://github.com/earendil-works/pi/blob/v0.84.2/packages/coding-agent/src/core/model-runtime.ts#L171-L212) and [`models-store.ts:49-53`](https://github.com/earendil-works/pi/blob/v0.84.2/packages/coding-agent/src/core/models-store.ts#L49-L53).
|
||||
|
||||
[^pi-trust]: Pi 0.84.2, [Settings, Project Trust](https://github.com/earendil-works/pi/blob/v0.84.2/packages/coding-agent/docs/settings.md#project-trust).
|
||||
|
||||
[^mcp-cache]: pi-mcp-adapter 2.27.0, [`metadata-cache.ts:39-79`](https://github.com/nicobailon/pi-mcp-adapter/blob/v2.27.0/metadata-cache.ts#L39-L79) and [Direct Tools](https://github.com/nicobailon/pi-mcp-adapter/blob/v2.27.0/README.md#direct-tools).
|
||||
|
||||
[^pi-resources]: Pi 0.84.2, [Settings, Resources](https://github.com/earendil-works/pi/blob/v0.84.2/packages/coding-agent/docs/settings.md#resources) and [Extensions, Security](https://github.com/earendil-works/pi/blob/v0.84.2/packages/coding-agent/docs/extensions.md#extension-locations).
|
||||
|
||||
[^pi-packages]: Pi 0.84.2, [Pi Packages, package sources and dependencies](https://github.com/earendil-works/pi/blob/v0.84.2/packages/coding-agent/docs/packages.md).
|
||||
|
||||
[^pi-sessions]: Pi 0.84.2, [`README.md`, Sessions](https://github.com/earendil-works/pi/blob/v0.84.2/packages/coding-agent/README.md#sessions) and [`session-manager.ts:474-487`](https://github.com/earendil-works/pi/blob/v0.84.2/packages/coding-agent/src/core/session-manager.ts#L474-L487).
|
||||
|
||||
[^paseo-resume]: [`packages/server/src/server/agent/providers/pi/agent.ts:467-527, 2462-2523`](../../packages/server/src/server/agent/providers/pi/agent.ts).
|
||||
|
||||
[^paseo-import]: [`packages/server/src/server/agent/providers/pi/session-descriptor.ts:72-145`](../../packages/server/src/server/agent/providers/pi/session-descriptor.ts).
|
||||
|
||||
[^mcp-output]: pi-mcp-adapter 2.27.0, [Output Guard](https://github.com/nicobailon/pi-mcp-adapter/blob/v2.27.0/README.md#output-guard) and [`mcp-output-guard.ts:358-363`](https://github.com/nicobailon/pi-mcp-adapter/blob/v2.27.0/mcp-output-guard.ts#L358-L363).
|
||||
|
||||
[^paseo-generated]: [`packages/server/src/server/agent/providers/pi/agent.ts:564-736`](../../packages/server/src/server/agent/providers/pi/agent.ts).
|
||||
|
||||
[^paseo-detect]: [`packages/server/src/server/agent/providers/pi/agent.ts:750-758, 2623-2653`](../../packages/server/src/server/agent/providers/pi/agent.ts).
|
||||
|
||||
[^paseo-mcp]: [`packages/server/src/server/agent/providers/pi/agent.ts:239-252, 512-527`](../../packages/server/src/server/agent/providers/pi/agent.ts) and [`runtime-mcp-config.ts:24-59`](../../packages/server/src/server/agent/runtime-mcp-config.ts).
|
||||
|
||||
[^mcp-config]: pi-mcp-adapter 2.27.0, [Config and precedence](https://github.com/nicobailon/pi-mcp-adapter/blob/v2.27.0/README.md#config) and [`config.ts:394-451`](https://github.com/nicobailon/pi-mcp-adapter/blob/v2.27.0/config.ts#L394-L451).
|
||||
|
||||
[^paseo-mcp-address]: [`packages/server/src/server/bootstrap.ts:243-260`](../../packages/server/src/server/bootstrap.ts).
|
||||
|
||||
[^paseo-mcp-auth]: [`packages/server/src/server/bootstrap.ts:631-638`](../../packages/server/src/server/bootstrap.ts), [`auth.ts:135-181`](../../packages/server/src/server/auth.ts), and [`runtime-mcp-config.ts:24-59`](../../packages/server/src/server/agent/runtime-mcp-config.ts).
|
||||
|
||||
[^paseo-docker]: [`docs/docker.md`](../../docs/docker.md) and [`docker/base/Dockerfile`](../../docker/base/Dockerfile).
|
||||
Reference in New Issue
Block a user