Documentation
¶
Overview ¶
Package ipc is the console's local transport: a Unix domain socket in a directory private to the user (on Linux and macOS), newline-delimited JSON-RPC 2.0 framing capped at 1 MiB, and a peer check.
Index ¶
- Constants
- Variables
- func Compatible(major int) bool
- func Listen(path string) (net.Listener, error)
- func ListenShared(p kit.Product, path string, gid int) (net.Listener, error)
- func PeerAllowed(c net.Conn) (bool, error)
- func ReadMsg(r *bufio.Reader, v any) error
- func SharedSocketPath(dir, projectHash, profile string) (string, error)
- func SocketPath(p kit.Product, projectHash, profile string) (string, error)
- func WriteMsg(w io.Writer, v any) error
- type ChangeParams
- type ChangeResult
- type Cred
- type HelloParams
- type HelloResult
- type PIIAddParams
- type PIIListResult
- type RPCError
- type Request
- type Requester
- type Response
Constants ¶
const ( MethodHello = "hello" MethodStatus = "status" MethodPIIList = "pii.list" MethodPIIAdd = "pii.add" MethodChangeRequest = "change.request" MethodLogout = "logout" )
lockkit's own methods, served by every console. A product adds its own (its Backend's Methods). None of them loosens policy: change.request only queues a proposal that the console shows to the human.
const ( CodeRefused = -32001 // the policy refused the request CodeDenied = -32002 // the human denied CodeTimeout = -32003 // no answer within the approval timeout CodeNoSuchPlan = -32004 // unknown, used or expired plan id CodeConnLost = -32005 // the backend connection was lost CodePolicyPending = -32006 // a policy change awaits the human // CodeWrongRequester: in hub mode, a plan or ticket presented by // another agent than the one that made it (Requester.Token). CodeWrongRequester = -32007 // CodeWithdrawn: a hub ticket presented to a lock that now runs // without its hub (standalone): its tickets were withdrawn. Plan again; // the human approves on the lock's own terminal. CodeWithdrawn = -32008 CodeParseError = -32700 CodeInvalidRequest = -32600 CodeMethodNotFound = -32601 CodeInvalidParams = -32602 CodeInternal = -32603 )
Error codes. The -320xx range is reserved by JSON-RPC for implementation errors; the standard codes are kept for protocol faults.
const MaxMessage = 1 << 20
MaxMessage is the largest message, excluding the newline, in bytes.
const ProtocolMajor = 1
ProtocolMajor is exchanged in the hello handshake. A client and a console with different majors refuse to talk.
Variables ¶
var ErrAlreadyRunning = errors.New("ipc: a console is already running for this profile")
ErrAlreadyRunning means a live console already listens on the socket.
var ErrTooLarge = errors.New("ipc: message larger than 1 MiB")
ErrTooLarge means a message is over MaxMessage. After a read error the stream is out of step and the connection must be closed.
Functions ¶
func Compatible ¶
Compatible reports whether a peer's protocol major can talk to this one.
func Listen ¶
Listen opens the console socket at path. The parent directory is made private (0700 and owned by the user) and the socket is 0600. A socket left by a dead console is replaced; one with a live console gives ErrAlreadyRunning; any other kind of file at path is left alone and refused. Closing the listener removes the socket.
func ListenShared ¶
ListenShared opens a console socket of p in the shared socket directory of a separated setup (see package sysconf): the directory must already exist (the product's install creates it), belong to the console's user and to the client group gid, and give others no access; the socket is made read-write for that group only (0660). The peer check still decides who is served.
func PeerAllowed ¶
PeerAllowed reports whether the process at the other end of c runs as the same user as the console (SO_PEERCRED).
func ReadMsg ¶
ReadMsg reads one line of at most MaxMessage bytes (a trailing CR is dropped) and decodes it into v. It returns io.EOF at a clean end of stream and ErrTooLarge as soon as the line passes the cap, without buffering the rest.
func SharedSocketPath ¶
SharedSocketPath is SocketPath in the shared socket directory of a separated setup.
func SocketPath ¶
SocketPath returns the console socket of a project and profile of p: <p.RuntimeDir()>/<project-hash>-<profile>.sock (kit.Product.RuntimeDir: $<PREFIX>RUNTIME_DIR/<name> when set, else $XDG_RUNTIME_DIR/<name> on Linux or $TMPDIR/<name> on macOS, else /tmp/<name>-<uid>). A name that would exceed the OS socket path limit is replaced by <project-hash>-~<sha256(profile)[:16]>.sock, which is still stable, so the client and the console agree on it.
Types ¶
type ChangeParams ¶
type ChangeParams struct {
Change string `json:"change"`
}
ChangeParams queues a policy change proposal for the human.
type ChangeResult ¶
type ChangeResult struct {
Queued bool `json:"queued"`
}
ChangeResult answers change.request.
type Cred ¶
type Cred struct {
UID, GID, PID int
}
Cred is what the kernel says about the process at the other end of a socket. PID is -1 when the platform does not report it.
type HelloParams ¶
type HelloParams struct {
ProtocolMajor int `json:"protocol_major"`
Client string `json:"client,omitempty"`
}
HelloParams opens a session; Client is a free-form name and version.
type HelloResult ¶
type HelloResult struct {
ProtocolMajor int `json:"protocol_major"`
ConsoleVersion string `json:"console_version,omitempty"`
Profile string `json:"profile"`
}
HelloResult answers hello.
type PIIAddParams ¶
type PIIAddParams struct {
Pattern string `json:"pattern"`
}
PIIAddParams proposes a mask rule (its syntax is the product's).
type PIIListResult ¶
PIIListResult answers pii.list with the mask and allow rules in force.
type RPCError ¶
type RPCError struct {
Code int `json:"code"`
Message string `json:"message"`
Data *refusal.Info `json:"data,omitempty"`
}
RPCError is a JSON-RPC 2.0 error object. Message must never carry a secret; the console sanitises it. Data is set on CodeRefused only: the structured form of the refusal (code, retry, hint and span).
type Request ¶
type Request struct {
JSONRPC string `json:"jsonrpc"`
ID int64 `json:"id"`
Method string `json:"method"`
Params json.RawMessage `json:"params"`
}
Request is a JSON-RPC 2.0 request.
type Requester ¶ added in v0.3.0
type Requester struct {
Agent string `json:"agent,omitempty"`
Token string `json:"token,omitempty"`
}
Requester is the agent behind a request, as its MCP server reports it (mcpkit.RequesterFromEnv): the agent's name and the hash of its lea token (the raw token stays in the agent's process). Never write Token to the audit log, an approval screen or an error text. A product carries it in the params of its plan and run methods; in hub mode the console binds a plan to the token (stored hashed) and refuses it to another token with CodeWrongRequester. Agents of one UID can read each other's token: this catches mistakes, it is no security boundary.