Documentation
¶
Overview ¶
Package workbenchdocker is a thin typed wrapper around the Docker Engine SDK (github.com/docker/docker/client), used to create/start/stop/remove the containers and volumes that back a single workbench (a per-user sandbox running the `claude` CLI inside a persistent tmux session).
This package talks to whichever daemon URL it's constructed with — one client per call, pointed at whichever docker_hosts row a given workbench is assigned to (resolved by internal/service/v1/workbench/workbench.go's resolveClient), not a single startup-time config value. See docs/workbench/02_docker_topology.md for why a docker host is expected to be a dedicated second dockerd process, not the daemon Artel's own containers run on. It intentionally does not create the `workbench-net` network itself (assumed to pre-exist on the configured daemon) and does not expose any inbound port on the containers it creates.
Index ¶
- type Client
- func (c *Client) CapturePane(ctx context.Context, containerID string) (string, error)
- func (c *Client) CreateContainer(ctx context.Context, opts CreateOpts) (string, error)
- func (c *Client) CreateVolume(ctx context.Context, name string) error
- func (c *Client) RemoveContainer(ctx context.Context, containerID string) error
- func (c *Client) RemoveVolume(ctx context.Context, name string) error
- func (c *Client) SendKeys(ctx context.Context, containerID string, keys string) error
- func (c *Client) StartContainer(ctx context.Context, containerID string, env map[string]string) error
- func (c *Client) StopContainer(ctx context.Context, containerID string) error
- type CreateOpts
- type TLSConfig
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client wraps the Docker SDK client with the narrow surface a workbench's container/volume lifecycle needs.
func New ¶
New constructs a Client talking to the Docker daemon at host (e.g. "unix:///var/run/docker-workbenches.sock", "tcp://host:2376" for a local/insecure daemon, or "tcp://host:2376" with a populated tlsCfg for a remote mTLS-secured daemon — see docs/workbench/02_docker_topology.md, "Option C"). API version negotiation is enabled so the client stays compatible with the daemon regardless of exactly which API version it speaks.
An empty tlsCfg reproduces exactly the pre-TLS behavior (plain client.WithHost, no custom HTTP client) — this must not regress the local unix-socket/dind path.
func (*Client) CapturePane ¶
CapturePane returns the current visible contents of the workbench's tmux pane (tmuxSessionName), via `tmux capture-pane -p`. Used to observe the subscription_login TUI flow (login URL, OAuth errors, ...) without disturbing it — see docs/workbench/03_auth_and_login_flow.md, "Mechanism (confirmed)".
func (*Client) CreateContainer ¶
CreateContainer creates (but does not start) a workbench container: the hardcoded workbench image, attached to the dedicated workbench-net network (assumed to pre-exist on the configured daemon — see docs/workbench/02_docker_topology.md), with opts.VolumeName mounted at workspaceMountPath, hardcoded CPU/memory limits, no exposed ports, and labeled for operational visibility.
func (*Client) CreateVolume ¶
CreateVolume creates a named Docker volume, labeled for operational visibility.
func (*Client) RemoveContainer ¶
RemoveContainer force-removes a workbench container. It does not remove the container's volume — call RemoveVolume separately.
func (*Client) RemoveVolume ¶
RemoveVolume force-removes a named Docker volume.
func (*Client) SendKeys ¶
SendKeys relays keys into the workbench's tmux pane (tmuxSessionName) via `tmux send-keys ... <keys> Enter`, followed by Enter as a separate key. keys is arbitrary, user-controlled input (an OAuth code or first-run keystrokes the user types/pastes) — it is passed as a single, literal argv element of ExecOptions.Cmd, never through a shell (`/bin/sh -c ...`), so there is no shell-metacharacter injection surface: the exec'd process is `tmux` itself, invoked directly, and keys is one opaque argument to it, not text that gets re-parsed as shell syntax. See docs/workbench/03_auth_and_login_flow.md, "Mechanism (confirmed)", step 4.
func (*Client) StartContainer ¶
func (c *Client) StartContainer(ctx context.Context, containerID string, env map[string]string) error
StartContainer starts an already-created workbench container and injects env into it.
The Docker Engine API has no way to attach environment variables to a container at `docker start` time — env is otherwise only settable at `docker create` time, which is deliberately too early here (see CreateOpts). Once started, env is instead propagated into the running container's tmux session (tmuxSessionName) via a docker exec, so the value only ever lives in the tmux server's in-memory session state — never baked into the image, never written to the mounted volume. See docs/workbench/03_auth_and_login_flow.md for the full login-flow design this is feeding into (unconfirmed/spike-flagged there as of this writing); this is the mechanism this client offers to keep that property intact.
type CreateOpts ¶
type CreateOpts struct {
// Name is the container name (e.g. "workbench-<vault_id>").
Name string
// VolumeName is the pre-created named volume to mount at workspaceMountPath.
VolumeName string
}
CreateOpts configures a new workbench container. Deliberately excludes any secret/env value — per docs/workbench/01_data_model_and_lifecycle.md, a workbench container is created with no auth env vars at all; those are only decided and supplied later, at StartContainer time.
type TLSConfig ¶
TLSConfig carries the decrypted, in-memory PEM-encoded TLS client credentials for connecting to a remote Docker daemon over TLS/mTLS — the docker_hosts.ca_cert_enc/client_cert_enc/ client_key_enc columns (migrations/062_docker_hosts_tls.sql), decrypted by dockerhosts.Repo.GetWithCreds. All three fields empty means "no TLS" — see New.