Document native Landlock and persist session yolo

This commit is contained in:
Ollie Agent 2026-08-18 12:49:25 +02:00
parent 1915cf292d
commit 2ba9ba036c
8 changed files with 23 additions and 9 deletions

View File

@ -82,6 +82,8 @@ session/
## Providers, tools, and security
`session/new` accepts `name`, `remote`, `workflow`, `cwd`, and `yolo=true` key/value fields. Session-level `yolo` is persisted and applies to local or remote toolsrv startup; it disables native Landlock enforcement for explicit development use. Normal tools use the configured native Landlock policy, while approved escape requests go through the bypass broker.
Provider backends are the model-facing boundary; the agent loop is independent of vendor APIs. Tools are external executable programs served by the separate `toolsrv` 9P process. Their metadata is discovered and loaded lazily, so the model sees only the capabilities needed for a task.
Tool execution uses the configured native Landlock sandbox. Operations requiring an approved escape use the bypass namespace and broker, which applies policy and approval controls rather than providing an unrestricted escape.

View File

@ -257,6 +257,7 @@ func buildTreeSpec(cfg *Config) virtfs.FsNodeDecl {
virtfs.Rdwr(func(_ context.Context, data []byte) ([]byte, error) {
args := strings.Fields(string(data))
name, remote, workflow, cwd := "", "", "", ""
yolo := false
for _, arg := range args {
if k, v, ok := strings.Cut(arg, "="); ok {
switch k {
@ -268,13 +269,15 @@ func buildTreeSpec(cfg *Config) virtfs.FsNodeDecl {
workflow = v
case "cwd":
cwd = v
case "yolo":
yolo = v == "true"
}
}
}
if cwd == "" {
return nil, fmt.Errorf("cwd is required")
}
sess, err := session.CreateEmpty(name, remote)
sess, err := session.CreateEmpty(name, remote, yolo)
if err != nil {
return nil, err
}

View File

@ -21,6 +21,7 @@ type PersistedSession struct {
Name string `json:"name"`
CWD string `json:"cwd"`
Remote string `json:"remote,omitempty"`
Yolo bool `json:"yolo,omitempty"`
Paused bool `json:"paused,omitempty"`
Workflow string `json:"workflow,omitempty"`
Goal string `json:"goal,omitempty"`
@ -70,6 +71,7 @@ func PersistSession(name string) error {
Name: sess.Name(),
CWD: sess.Cwd(),
Remote: sess.Remote,
Yolo: sess.Yolo,
Paused: sess.IsPaused(),
Workflow: sess.Workflow(),
Goal: goalText,
@ -190,6 +192,7 @@ func restoreMultiAgentSession(ps *PersistedSession) (*RestoredSession, error) {
sess := NewEmpty(ps.ID, ctx, cancel)
sess.SetName(ps.Name)
sess.Remote = ps.Remote
sess.Yolo = ps.Yolo
if ps.Paused {
sess.mu.Lock()
sess.paused = true

View File

@ -284,7 +284,7 @@ func BuildAgentIndex(sess *Session) []byte {
}
// CreateEmpty creates an empty session (no agent) and registers it.
func CreateEmpty(name, remote string) (*Session, error) {
func CreateEmpty(name, remote string, yolo ...bool) (*Session, error) {
sessID := util.NewUUID()
if name == "" {
name = sessID
@ -304,6 +304,7 @@ func CreateEmpty(name, remote string) (*Session, error) {
sess := NewEmpty(sessID, ctx, cancel)
sess.SetName(name)
sess.Remote = remote
sess.Yolo = len(yolo) > 0 && yolo[0]
cwd, _ := os.Getwd()
infra, err := SetupToolServer(ToolServerConfig{
@ -311,7 +312,7 @@ func CreateEmpty(name, remote string) (*Session, error) {
CWD: cwd,
RemoteTarget: remote,
SessionID: sessID,
Yolo: pkgYolo,
Yolo: sess.Yolo,
})
if err != nil {
cancel()
@ -390,7 +391,7 @@ func buildAgent(sess *Session, p AgentParams) (*agent.Agent, error) {
CWD: cwd,
RemoteTarget: remote,
SessionID: sessID,
Yolo: pkgYolo,
Yolo: sess.Yolo,
ReuseFrom: reuseFrom,
})
if err != nil {

View File

@ -31,6 +31,7 @@ type Session struct {
Proc *toolclient.Process
Keeper *toolclient.ProcessKeeper
Remote string
Yolo bool
// Agent state
agents []*agent.Agent
@ -433,7 +434,7 @@ func (s *Session) Resume() error {
CWD: cwd,
RemoteTarget: s.Remote,
SessionID: s.ID,
Yolo: pkgYolo,
Yolo: s.Yolo,
})
if err != nil {
s.log.Error("Resume: toolsrv startup failed: %v", err)
@ -461,7 +462,7 @@ func (s *Session) Resume() error {
CWD: cwd,
RemoteTarget: s.Remote,
SessionID: s.ID,
Yolo: pkgYolo,
Yolo: s.Yolo,
})
if err != nil {
cancel()

View File

@ -55,7 +55,7 @@ echo '{"prompt":"explain recursion"}' | ollie-9p rdwr generate
| Path | Mode | Purpose |
|---|---:|---|
| `session/new` | rdwr | Create a session. Write `name=X [remote=Y]`; read the resulting name. |
| `session/new` | rdwr | Create a session. Write `name=X [remote=Y] [yolo=true]`; read the resulting name. |
| `session/idx` | r | Session index: `session-id\tsession-name\tpaused\tconnected\tremote\tcwd`. |
| `session/{sname}/env` | r | Session environment and runtime variables. |
| `session/{sname}/paused` | r | Pause state. |

View File

@ -36,7 +36,7 @@ Startup sequence:
1. Require the `serve` subcommand and a `--listen` path.
2. Expand `~` in `--cwd`.
3. Create the log sink and call `util.EnsureEnv()`.
4. Start the native Landlock sandbox helper for each restricted tool execution.
4. Start a short-lived child helper from the toolsrv binary for each restricted tool execution. The helper applies the configured Landlock ruleset directly with Linux system calls, then `exec`s the tool command.
5. Create the per-agent registry and the server state.
6. Apply `--yolo` to the server and process state.
7. Build the 9P tree from `server.Spec`.
@ -220,7 +220,7 @@ advanced:
add_exec: false
```
Paths support `{CWD}`, `{HOME}`, `{TMPDIR}`, XDG variables, and Ollie configuration/data variables. The loaded policy is passed to the sandbox wrapper. `--yolo` skips enforcement for explicit development use.
Paths support `{CWD}`, `{HOME}`, `{TMPDIR}`, XDG variables, and Ollie configuration/data variables. The policy is encoded by the parent toolsrv process and passed to its own short-lived helper mode; no separately installed sandbox executable or wrapper is required. On Linux, the helper sets `no_new_privs`, creates a Landlock ruleset, adds the configured path rules, restricts itself, and executes the tool. `--yolo` skips enforcement for explicit development use.
Sandbox validation rejects dangerous command patterns before execution. The execution service also rate-limits repeated validation failures. The bypass path is not a sandbox configuration override; it is a separately approved execution route.

View File

@ -29,6 +29,10 @@ Valid levels: `debug`, `info`, `warn`, `error`.
---
## Security and sandboxing
`toolsrv` applies the configured policy directly through native Landlock in a short-lived child helper; it does not depend on an external sandbox executable. On Linux, the helper creates and restricts a Landlock ruleset before executing the tool. Use `yolo=true` only for explicit development cases where enforcement should be disabled.
## `o` — Terminal CLI
`o` is a multi-call shell script that wraps the 9P namespace into a human-friendly interface.