fix: allow group access to ctl, plan, fifo for frontend interaction

Changed from 0600 (owner only) to 0660 (owner + group):
- ctl: frontends need to send slash commands
- plan: frontends need to read/write plan
- fifo: frontends need to submit prompts via queue

The agent group includes frontends, so group permissions enable
frontend interaction while still maintaining ownership-based isolation.
This commit is contained in:
Levi Neely 2026-10-07 11:01:01 +02:00
parent d65c06f27b
commit b9026bb48b
2 changed files with 11 additions and 8 deletions

View File

@ -68,17 +68,20 @@
// # Per-Agent File Ownership
//
// Agent directories are owned by their agent ID (UID) with group "agent" (GID).
// Permissions enforce isolation:
// Permissions enforce isolation while allowing frontend access:
//
// - mode 0600: owner only (plan, ctl, fifo) — private to owning agent
// - mode 0640: owner rw, group r (cfg, name) — readable by other agents
// - mode 0440: owner r, group r (chat, log) — readable by other agents
// - mode 0660: owner + group rw (plan, ctl, fifo) — agent and frontend can access
// - mode 0640: owner rw, group r (cfg, name) — readable by frontend
// - mode 0440: owner r, group r (chat, log) — readable by frontend
// - mode 0444: world readable (state, id) — non-sensitive, observable
// - mode 0220: owner+group write (prompt) — CLI and owning agent can submit
// - mode 0220: owner + group write (prompt) — CLI and agent can submit
//
// Admin clients (empty uname, "admin", or server owner) bypass permission checks.
// This allows CLI tools and GUIs to manage all agents.
//
// The "agent" group includes all agents and frontends, allowing inter-agent
// visibility while maintaining ownership-based isolation for sensitive operations.
//
// # Blocking Reads
//
// Files like event block until their condition is met.

View File

@ -779,7 +779,7 @@ func buildAgentChildren(a *agent.Agent, s *session.Session) []virtfs.FsNodeDecl
return nil
}),
),
virtfs.FileNode("fifo", 0600, // owner only
virtfs.FileNode("fifo", 0660, // owner + group (frontend needs access)
virtfs.Write(func(data []byte) error {
input := strings.TrimSpace(string(data))
if input == "" {
@ -867,7 +867,7 @@ func buildAgentChildren(a *agent.Agent, s *session.Session) []virtfs.FsNodeDecl
return data, nil
}),
),
virtfs.FileNode("plan", 0600, // owner only
virtfs.FileNode("plan", 0660, // owner + group (frontend needs access)
virtfs.Read(func() ([]byte, error) {
return a.Plan(), nil
}),
@ -949,7 +949,7 @@ func buildAgentChildren(a *agent.Agent, s *session.Session) []virtfs.FsNodeDecl
}
return out, nil
}),
virtfs.FileNode("ctl", 0600, // owner only
virtfs.FileNode("ctl", 0660, // owner + group (frontend needs access)
virtfs.Rdwr(func(_ context.Context, data []byte) ([]byte, error) {
return dispatch([]ctlCmd{
{"kill", "destroy this agent", func(_ []string) ([]byte, error) {