daemon

package
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 13, 2026 License: Apache-2.0 Imports: 12 Imported by: 0

Documentation

Overview

Package daemon is the long-lived local server (§5).

Research sessions run past an hour; a bare stdio subprocess dies when the coding agent's session closes. So the daemon holds the session, claim and budget state, and a disposable shim forwards to it over a unix socket.

The socket is the trust boundary. §5's named-connector design keeps credentials out of the tool call by keeping them daemon-side — which only helps if reaching the daemon is itself privileged, so the listener setup in this file is a security control rather than plumbing (§3.5).

Index

Constants

View Source
const DefaultShutdownGrace = 30 * time.Second

DefaultShutdownGrace is how long a stopping daemon waits.

Long enough for a session to settle its open reservation, which is what the wait is for: exiting early leaves budget neither spent nor available until the next boot's sweep reclaims it (§9.4).

Variables

This section is empty.

Functions

This section is empty.

Types

type Handler

type Handler interface {
	Serve(ctx context.Context, conn net.Conn)
}

Handler serves one accepted connection. Slice 5 supplies the MCP one.

An interface rather than the MCP server directly, so the listener's security properties can be tested without a protocol, and so a future transport does not have to reimplement them.

type HandlerFunc

type HandlerFunc func(ctx context.Context, conn net.Conn)

HandlerFunc adapts a function to Handler.

func (HandlerFunc) Serve

func (f HandlerFunc) Serve(ctx context.Context, conn net.Conn)

type Server

type Server struct {
	// Socket is the path to listen on.
	Socket string
	// Supervisor runs the sessions. Shutdown stops it and waits for holds to be
	// released before returning.
	Supervisor *session.Supervisor
	Handler    Handler
	Log        *slog.Logger

	// ShutdownGrace bounds how long Serve waits for in-flight connections and
	// running sessions after its context is cancelled. Zero takes a default.
	ShutdownGrace time.Duration
	// contains filtered or unexported fields
}

Server accepts connections on a unix socket and hands them to a Handler.

func (*Server) Listen

func (s *Server) Listen() (net.Listener, error)

Listen creates the socket with the properties §3.5 requires.

Two independent controls, because each alone has a hole:

  • The parent directory is created 0700. net.Listen applies the process umask, so the socket can appear as 0755 and be connectable in the window between Listen and Chmod. A private directory closes that window, because the path is unreachable whatever the socket's own mode says.
  • The socket is then chmod 0600, so loosening the directory later — by a careless install script, or by putting the socket somewhere shared — does not silently expose it.

XDG_RUNTIME_DIR is already 0700 and user-owned on Linux, which is why §5.2 puts the socket there; this does not assume it.

func (*Server) Serve

func (s *Server) Serve(ctx context.Context, ln net.Listener) error

Serve accepts until ctx is cancelled, then shuts down.

Owns the listener: closes it on the way out and removes the socket file, so a clean stop does not leave a path that the next start has to reason about.

type SocketState

type SocketState struct {
	Path string
	// DirMode and DirOwned describe the parent directory — the control that
	// closes the window between net.Listen and Chmod.
	DirMode  os.FileMode
	DirOwned bool
	DirOK    bool
	// Present is whether a socket file exists at all; Live is whether something
	// accepts on it.
	Present bool
	Live    bool
	Mode    os.FileMode
	// Problems are the reasons this install would be refused or is exposed,
	// phrased for a user rather than a caller.
	Problems []string
	// Notes are true statements that are not problems.
	Notes []string
}

SocketState is what `mole doctor` can say about the MCP socket without starting a daemon.

func InspectSocket

func InspectSocket(path string) SocketState

InspectSocket reports the §3.5 properties of a socket path.

It calls the SAME checkPrivateDir the daemon enforces, rather than a second hand-written check beside it: `mole doctor` existed for two milestones saying socket permissions were "informational until M7 lands", M7 landed, and a check that is free to drift from the thing it gates is worth nothing. This is the M8 lesson (§12.1's "every crossing is logged" emitted nothing for a milestone) applied before it costs anything.

Reports rather than fixes. A directory that is not ours is not ours to chmod, and a user who pointed the socket somewhere shared should be told.

func (SocketState) OK

func (s SocketState) OK() bool

OK reports whether this install would be accepted.

func (SocketState) Summary

func (s SocketState) Summary() string

Summary is the one-line form for doctor.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL