Document native Landlock and persist session yolo
This commit is contained in:
parent
1915cf292d
commit
2ba9ba036c
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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. |
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
Loading…
Reference in New Issue